从零到一:EFK在K8S环境下的日志收集实战部署
1. 为什么需要EFK日志系统在Kubernetes集群中日志管理是个让人头疼的问题。想象一下你有几十个Pod在集群里跑着每个Pod都在不断产生日志。当某个服务出现问题时你需要像大海捞针一样去各个容器里翻找日志这效率实在太低了。我刚开始接触K8S时就经常遇到这种情况每次排查问题都要花大量时间在日志收集上。EFKElasticsearch Fluentd Kibana这套组合拳正好能解决这个问题。Elasticsearch负责存储和检索日志Fluentd负责收集和转发日志Kibana则提供可视化界面。把它们部署在K8S环境里就像给集群装上了行车记录仪所有服务的运行状况一目了然。实测下来这套方案对资源占用也很友好在我们测试环境中单个Fluentd容器内存占用不到300MB。2. 环境准备与基础组件安装2.1 搭建基础环境首先确保你已经有一个可用的Kubernetes集群。我用的是Kubeadm搭建的v1.25版本集群节点配置为4核8G。如果你只是想测试Minikube也是不错的选择。这里有个小技巧在安装前先检查节点资源Elasticsearch比较吃内存建议预留至少2G内存。安装Docker是必须的因为我们要用容器化方式部署组件。在Ubuntu系统上可以这样安装sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io sudo systemctl enable docker2.2 部署ElasticsearchElasticsearch是整个日志系统的存储核心。我推荐使用官方镜像版本选择8.x系列因为7.x即将停止维护。这里有个坑要注意Elasticsearch默认开启安全认证为了方便测试我们可以先关闭它。先创建数据目录和配置文件mkdir -p /data/es/{config,data,plugins} chmod 777 -R /data/es然后编写elasticsearch.yml配置文件# /data/es/config/elasticsearch.yml cluster.name: k8s-logs network.host: 0.0.0.0 xpack.security.enabled: false discovery.type: single-node启动容器时我建议限制JVM堆大小避免占用过多内存docker run -d \ --name elasticsearch \ -p 9200:9200 \ -p 9300:9300 \ -v /data/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \ -v /data/es/data:/usr/share/elasticsearch/data \ -v /data/es/plugins:/usr/share/elasticsearch/plugins \ -e ES_JAVA_OPTS-Xms1g -Xmx1g \ elasticsearch:8.11.0启动后可以用curl测试是否正常curl http://localhost:92002.3 部署KibanaKibana是日志的可视化工具版本需要与Elasticsearch保持一致。先准备配置mkdir -p /data/kibana/config cat /data/kibana/config/kibana.yml EOF server.host: 0.0.0.0 elasticsearch.hosts: [http://elasticsearch:9200] EOF启动Kibana容器时记得把它和Elasticsearch放在同一个网络docker network create es-network docker run -d \ --name kibana \ --network es-network \ -p 5601:5601 \ -v /data/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml \ kibana:8.11.0等个一两分钟访问http://localhost:5601就能看到Kibana界面了。3. 在K8S中部署Fluentd3.1 准备Fluentd镜像官方提供了针对Kubernetes的Fluentd镜像我们可以直接使用。如果需要自定义插件可以基于这个镜像构建FROM fluentd-kubernetes-daemonset:v1.16-debian-elasticsearch8-1 RUN gem install fluent-plugin-slack3.2 配置RBAC权限Fluentd需要读取Pod日志和元数据所以要配置适当的RBAC权限。这是我调整过的配置比原始文章的更安全# fluentd-rbac.yaml apiVersion: v1 kind: ServiceAccount metadata: name: fluentd namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: fluentd rules: - apiGroups: [] resources: [pods, namespaces] verbs: [get, list, watch] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: fluentd roleRef: kind: ClusterRole name: fluentd apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: fluentd namespace: kube-system应用配置kubectl apply -f fluentd-rbac.yaml3.3 部署DaemonSetFluentd需要以DaemonSet方式运行确保每个节点都有日志收集器。这是我的优化版配置增加了资源限制和容器日志解析设置# fluentd-daemonset.yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd namespace: kube-system labels: app: fluentd spec: selector: matchLabels: app: fluentd template: metadata: labels: app: fluentd spec: serviceAccountName: fluentd tolerations: - key: node-role.kubernetes.io/control-plane effect: NoSchedule containers: - name: fluentd image: fluentd-kubernetes-daemonset:v1.16-debian-elasticsearch8-1 env: - name: FLUENT_ELASTICSEARCH_HOST value: elasticsearch.default.svc.cluster.local - name: FLUENT_ELASTICSEARCH_PORT value: 9200 - name: FLUENT_CONTAINER_TAIL_PARSER_TYPE value: cri resources: limits: memory: 500Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: containers mountPath: /var/log/containers readOnly: true volumes: - name: varlog hostPath: path: /var/log - name: containers hostPath: path: /var/log/containers部署后检查Pod状态kubectl get pods -n kube-system -l appfluentd4. 配置与优化技巧4.1 日志过滤与处理默认情况下Fluentd会收集所有日志这可能会导致Elasticsearch存储压力过大。我们可以通过配置只收集特定命名空间或带特定标签的Pod日志。在Fluentd配置中添加filter kubernetes.** type grep exclude key $.kubernetes.namespace_name pattern ^(kube-system|default)$ /exclude /filter4.2 性能调优在大规模集群中Fluentd可能会成为性能瓶颈。我总结了几个优化点调整缓冲区配置减少IO压力buffer type file path /var/log/fluentd-buffer flush_mode interval flush_interval 5s chunk_limit_size 2M queue_limit_length 32 /buffer使用多线程处理- name: FLUENTD_WORKERS value: 4对于高流量日志考虑使用Kafka作为缓冲层4.3 Kibana仪表板配置登录Kibana后需要配置索引模式才能查看日志。进入Management Stack Management Index Patterns创建名为logstash-*的索引模式时间字段选择timestamp保存后就可以在Discover页面查看日志了我建议创建几个常用仪表板错误日志监控过滤ERROR级别日志服务请求统计按服务统计请求量资源使用TopN显示资源占用最高的Pod5. 常见问题排查5.1 Fluentd无法收集日志首先检查DaemonSet是否正常运行kubectl logs -n kube-system fluentd-pod-name常见问题包括权限不足检查RBAC配置是否正确网络不通测试Fluentd能否访问Elasticsearch服务存储卷挂载失败检查/var/log/containers目录是否存在5.2 Elasticsearch磁盘占用过大可以通过Kibana的Index Management功能设置合理的索引生命周期策略配置按日期自动删除旧索引调整日志保留天数5.3 日志格式混乱如果是容器日志确保配置了正确的解析器- name: FLUENT_CONTAINER_TAIL_PARSER_TYPE value: cri对于应用日志建议在应用中使用JSON格式输出这样便于后续分析和过滤。6. 生产环境建议经过几个项目的实践我总结了一些生产环境部署经验高可用部署Elasticsearch至少部署3个节点使用StatefulSet管理资源隔离将日志系统部署到独立节点避免影响业务Pod监控告警监控EFK组件本身的状态设置磁盘使用率等告警备份策略定期备份Elasticsearch的重要索引安全加固在生产环境开启Elasticsearch的安全认证对于中小规模集群这套配置完全够用。当集群规模超过100个节点时可能需要考虑引入日志采样或者分布式收集方案。