DevOps 实验项目阶段 8 笔记: Kafka + ELK 日志系统部署与问题处理

阶段目标

在已有 Kubernetes + Jenkins + Harbor CI/CD 平台基础上,引入完整日志链路:

Spring Boot Pod -> stdout -> /var/log/containers/*.log
-> Filebeat DaemonSet -> Kafka -> Logstash -> Elasticsearch -> Kibana

最终实现:Kubernetes 中的 SpringBoot 应用日志自动采集、缓存、处理、存储,并在 Kibana 展示。


环境规划

节点规划

IPhostname服务
192.168.205.141k8s-masterKubernetes Control Plane
192.168.205.142k8s-node1Worker
192.168.205.143k8s-node2Worker
192.168.205.144devopsAnsible + Jenkins
192.168.205.145elkKafka + Elasticsearch + Logstash + Kibana
192.168.205.146infraHarbor + MySQL

二、阶段 8 整体流程

最终日志链路:

Spring Boot (Kubernetes stdout)
  -> /var/log/containers/*.log
    -> Filebeat DaemonSet
      -> Kafka topic: springboot-log
        -> Logstash
          -> Elasticsearch index
            -> Kibana Discover

三、阶段 8.1 Kafka 部署 (KRaft 模式)

目标

替代传统 Kafka + Zookeeper,采用 Kafka KRaft,无需 Zookeeper。

部署节点

192.168.205.145 elk

目录

ansible/files/kafka/
  - docker-compose.yml

Kafka 启动

进入 elk:

cd /opt/kafka

启动:

docker compose up -d

创建测试 Topic

进入 Kafka 容器:

docker exec -it kafka bash

创建:

/opt/kafka/bin/kafka-topics.sh \
  --create \
  --topic springboot-log \
  --bootstrap-server localhost:9092 \
  --partitions 3 \
  --replication-factor 1

查看:

/opt/kafka/bin/kafka-topics.sh \
  --list \
  --bootstrap-server localhost:9092

结果:

springboot-log

Kafka 消费测试

消费者:

/opt/kafka/bin/kafka-console-consumer.sh \
  --topic springboot-log \
  --bootstrap-server localhost:9092 \
  --from-beginning

生产者:

/opt/kafka/bin/kafka-console-producer.sh \
  --topic springboot-log \
  --bootstrap-server localhost:9092

输入:

hello kafka elk

消费者收到:

hello kafka elk

Kafka 部署成功。


四、阶段 8.2 Elasticsearch 部署

节点

192.168.205.145 elk

版本

Elasticsearch 8.15.3

Docker Compose

目录:

ansible/files/elasticsearch/

部署:

ansible-playbook elasticsearch.yml -K

验证

访问:

curl http://192.168.205.145:9200

返回:

{"name":"es-node","cluster_name":"devops-es","version":{"number":"8.15.3"}}

说明:Elasticsearch OK


五、阶段 8.3 Logstash 部署

作用

负责:Kafka -> Logstash -> ES

文件结构

ansible/files/logstash/
  - docker-compose.yml
  - logstash.conf

初始问题 1: Logstash 无法连接 ES

错误:

elasticsearch: Temporary failure in name resolution

原因:配置 hosts => ["http://elasticsearch:9200"],但 Docker compose 不存在该 hostname。

解决

修改:

output {
  elasticsearch {
    hosts => ["http://192.168.205.145:9200"]
  }
}

重新启动:

docker compose down
docker compose up -d

验证

查看:

docker logs -f logstash

正常输出:

Subscribed to topic(s): springboot-log

六、阶段 8.4 Kibana 部署

部署

节点:192.168.205.145

目录:

ansible/files/kibana/

执行:

ansible-playbook kibana.yml -K

访问:

http://192.168.205.145:5601

创建 Data View

Kibana -> Discover -> Create data view -> springboot-log*

时间字段:@timestamp


七、阶段 8.5 Filebeat Kubernetes 日志采集

目标

采集:Pod stdout

发送:Kafka

文件结构

devops 节点:

ansible/files/filebeat/
  - filebeat.yml
  - filebeat-rbac.yml
  - filebeat-daemonset.yml

八、Filebeat 配置

文件:filebeat.yml

核心:

filebeat.inputs:
  - type: container
    enabled: true
    paths:
      - /var/log/containers/*.log
    processors:
      - add_kubernetes_metadata: ~

九、部署 Filebeat

注意:不是在 devops 部署 K8S 资源,正确操作如下:

RBAC

创建:

kubectl apply -f filebeat-rbac.yml

ConfigMap

创建:

kubectl create configmap filebeat-config \
  --from-file=filebeat.yml=/tmp/filebeat.yml \
  -n default \
  --dry-run=client -o yaml | kubectl apply -f -

DaemonSet

部署:

kubectl apply -f filebeat-daemonset.yml

验证

kubectl get pods -l app=filebeat -o wide

结果:

filebeat   Running   node1
filebeat   Running   node2

说明:Filebeat 成功。


十、完整链路测试

1. Spring Boot 接口测试

访问:

curl http://192.168.205.142:30881/api/users

2. 查看 Pod 日志

kubectl logs -l app=devops-demo --tail=50

3. Kafka 消费

elk 节点:

docker exec -it kafka bash

消费:

/opt/kafka/bin/kafka-console-consumer.sh \
  --topic springboot-log \
  --bootstrap-server localhost:9092 \
  --from-beginning

收到日志。

4. Kibana 查看

进入 Discover,看到 springboot-log 日志出现。


十一、阶段遇到的问题总结

问题 1: Kafka 镜像不存在

错误:

manifest for bitnami/kafka:3.9 not found

原因: 镜像 tag 不存在。

解决: 更换存在版本,例如 bitnami/kafka:3.8,然后重新:

docker compose pull
docker compose up -d

问题 2: Ansible playbook 语法错误

错误:

Unable to parse argument string line xx-name: Start Elasticsearch

原因: YAML 缩进错误。

解决: 检查并修正缩进:

ansible-playbook xxx.yml --syntax-check

问题 3: Logstash 连接 ES 失败

错误:

elasticsearch:9200 DNS failure

原因: Docker 内部 hostname 不存在。

解决: 修改为:

hosts => ["http://192.168.205.145:9200"]

问题 4: Filebeat 部署后 kubectl 连接 localhost

错误:

failed to download openapi, localhost:8080 connection refused

原因: 执行 kubectl 的机器没有 Kubeconfig。错误在 devops 直接执行 kubectl

解决: 让 Ansible 远程 master 执行:

ansible k8s_control_plane -a "kubectl get nodes"

成功输出:

k8s-master   Ready
k8s-node1    Ready
k8s-node2    Ready

问题 5: Harbor 突然不可用

现象:

docker login 192.168.205.146

错误:

Get https://192.168.205.146/v2/: 443 connection refused

原因: Docker 配置丢失 insecure-registries。Docker 默认使用 HTTPS 443,但 Harbor 使用 HTTP 80。

根因: docker-install.sh 中的 cat > /etc/docker/daemon.json 覆盖了配置。

解决: 加入:

"insecure-registries": ["192.168.205.146"]

统一由 Ansible 管理。

验证:

docker info | grep -A3 "Insecure Registries"

结果:

192.168.205.146

问题 6: cri-dockerd 重复安装问题

现象: 每次执行 ansible-playbook kubernetes.yml 都会重新下载 cri-dockerd

原因: 脚本没有判断是否已安装。

优化: 增加幂等判断:

if command -v cri-dockerd >/dev/null
then
  echo "already installed"
  exit 0
fi

十二、当前完成状态

阶段状态
阶段1 基础环境
阶段2 Ansible
阶段3 Docker
阶段4 Kubernetes
阶段5 Spring Boot
阶段6 Harbor/MySQL
阶段7 Jenkins CI/CD
阶段8.1 Kafka
阶段8.2 Elasticsearch
阶段8.3 Logstash
阶段8.4 Kibana
阶段8.5 Filebeat

更多推荐