在 Kubernetes 上搭建 EFK 日志收集系统(理论)
一、日志收集选型
Kubernetes 中比较流行的日志收集解决方案是 Elasticsearch、Fluentd 和 Kibana(EFK)技术栈,也是官方现在比较推荐的一种方案。
- EFK(es、fluentd、kibana)
Fluentd:
作为一个很好的 Logstash 替代品,Fluentd 是 DevOps 的最爱,特别是对于 Kubernetes 部署,因为它具有丰富的插件库。与 Logstash 一样,它可以将数据结构化为 JSON,并涉及日志数据处理的所有方面:收集、解析、缓冲和输出跨各种来源和目的地的数据。
主要特点
- 与库和Kubernetes的良好集成
- 大量的内置插件,很容易编写新的
chatgpt选择
现在你是架构师,做k8s日志收集的技术选型,请从 filebeat、Logstash 和 Fluentd选择一个采集工具,并给出理由 。
作为架构师,我建议选择 Fluentd 作为 Kubernetes 日志收集工具。以下是一些理由:
成熟稳定:Fluentd 是一个成熟且广泛使用的开源项目,已经在许多生产环境中得到验证。它有一个活跃的社区支持,并且有大量的插件和扩展可用。
灵活性和可定制性:Fluentd 提供了高度灵活的配置选项,可以根据需求进行定制。你可以通过配置文件定义日志的输入、过滤和输出规则,以适应各种复杂的日志处理场景。
多种输入和输出插件:Fluentd 支持多种输入和输出插件,可以与各种存储和分析系统集成。无论是将日志发送到 Elasticsearch、Kafka、S3 还是其他目标,都可以通过简单的配置实现。
跨平台支持:Fluentd 可以在不同的操作系统和云平台上运行,包括 Linux、Windows、Docker 和 Kubernetes。这使得它非常适合在多样化的环境中进行日志收集和处理。
社区支持和文档资源丰富:Fluentd 有一个活跃的社区,提供了大量的文档、教程和示例代码,可以帮助你快速上手和解决问题。
当然,选择适合的日志收集工具还要考虑你的具体需求和环境。如果你已经使用 Elastic Stack 或希望与 Elasticsearch 和 Kibana 集成,Logstash 也是一个不错的选择。而 Filebeat 则更适合简单地收集和发送日志文件。
综上所述,基于 Fluentd 的稳定性、灵活性和丰富的插件生态系统,我建议选择 Fluentd 作为 Kubernetes 日志收集工具。
二、k8s 集群应该采集哪些日志?
K8S 系统的组件日志:apiserver、scheduler、kubelet
K8S 集群里面部署的应用程序日志
在 Kubernetes 集群上运行多个服务和应用程序时,日志收集系统可以帮助你快速分类和分析由Pod 生成的大量日志数据。
Kubernetes 中比较流行的日志收集解决方案是 Elasticsearch、Fluentd 和 Kibana(EFK)技术栈,也是官方推荐的一种方案。
在 k8s 集群中应用一般有如下日志输出方式:
直接遵循 docker 官方建议把日志输出到标准输出或者标准错误输出输出日志到容器内指定目录中,应用直接发送日志给日志收集系统。
我们构建的带有elasticsearch插件的fluentd以DaemonSet的形式部署在每一个节点上,主要收集如下几种日志:
- containers log: /var/log/containers/*.log
- docker log: /var/log/docker.log
- kubelet log: /var/log/kubelet.log
- kube-proxy log: /var/log/kube-proxy.log
- kube-apiserver log: /var/log/kube-apiserver.log
- kube-controller-manager log: /var/log/kube-controller-manager.log
- kube-scheduler log: /var/log/kube-scheduler.log
三、实践
1、创建pv
创建 pv 文件
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
namespace: logging
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs-es
nfs:
path: /data/nfs_data
server: 172.26.40.165
第二步:执行yaml文件创建此PV;注意PV的成功跟后端存储正不正常没什么关系。
> kubectl apply -f es-pv.yaml
2、创建pvc
创建一个PVC挂载到Pod#
注意:pvc要和Pod在同一个命名空间,而pv不需要;因为都是在默认空间,就没指定,需要注意。
第一步:编写一个PVC的yaml文件,es-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: es-pv-claim
namespace: logging
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 3Gi # 小于等于pv
storageClassName: nfs-es
第二步:执行yaml文件创建PVC;从下面这个状态来看已经绑定成功了,绑定了pv-nfs,类型为nfs-es,都是前面指定的。
> kubectl apply -f es-pvc.yaml
> [root@master-165 k8sYaml]# kubectl get pv -n logging
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Bound logging/es-pv-claim nfs-es 15m
[root@master-165 k8sYaml]# kubectl get pvc -n logging
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
es-pv-claim Bound pv-nfs 5Gi RWO nfs-es 5m8s
第三步,创建pod,
es-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: es
namespace: logging
spec:
serviceName: elasticsearch
replicas: 3
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
nodeSelector:
es: log
initContainers:
- name: increase-vm-max-map
image: busybox
command: ["sysctl", "-w", "vm.max_map_count=262144"]
securityContext:
privileged: true
- name: increase-fd-ulimit
image: busybox
command: ["sh", "-c", "ulimit -n 65536"]
securityContext:
privileged: true
containers:
- name: elasticsearch
image: arm64v8/elasticsearch:7.17.10
ports:
- name: rest
containerPort: 9200
- name: inter
containerPort: 9300
resources:
limits:
cpu: 1000m
requests:
cpu: 1000m
volumeMounts:
- name: data-storage
mountPath: /usr/share/elasticsearch/data
env:
- name: cluster.name
value: k8s-logs
- name: node.name
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: cluster.initial_master_nodes
value: "es-0,es-1,es-2"
- name: discovery.zen.minimum_master_nodes
value: "2"
- name: discovery.seed_hosts
value: "elasticsearch"
- name: ES_JAVA_OPTS
value: "-Xms512m -Xmx512m"
- name: network.host
value: "0.0.0.0"
由于系统是 arm架构的,所以需要拉取arm架构的镜像:
# https://hub.docker.com/r/arm64v8/elasticsearch/
# docker pull arm64v8/elasticsearch:7.17.10
给部署节点打标签:
# ①、查看集群节点标签,确保node有这个labe
kubectl get nodes --show-labels | grep 'es=log'
# ②、添加集群节点标签(如果该节点不存在该标签,则需要手动添加)
kubectl label nodes master-165 es=log
kubectl label nodes node-166 es=log
kubectl label nodes bide-167 es=log
部署:
$ kubectl create -f es-statefulset.yaml
statefulset.apps/es created
$ kubectl get pods -n logging
添加成功后,可以看到 logging 命名空间下面的所有的资源对象:
root@master-165 k8sYaml]# kubectl get pods -n logging -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
es-0 1/1 Running 0 12m 10.244.69.156 master-165 <none> <none>
es-1 0/1 CrashLoopBackOff 3 3m19s 10.244.110.105 node-166 <none> <none>
es-2 1/1 Running 0 94s 10.244.27.16 bide-167 <none> <none>
# 查看日志
kubectl describe pod es-1 -n logging
单节点部署es
创建hostpath挂载目录:
# 在宿主机/节点创建
mkdir -p /data/es-data
# 赋予权限,否则启动会报错
chmod 777 /data/es-data
es.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: es-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: es-host
hostPath:
path: /data/es-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: es-pvc
namespace: logging
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
storageClassName: es-host
---
apiVersion: v1
kind: ConfigMap
metadata:
name: es
namespace: logging
data:
elasticsearch.yml: |
cluster.name: my-cluster
node.name: node-1
node.max_local_storage_nodes: 3
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["127.0.0.1", "[::1]"]
cluster.initial_master_nodes: ["node-1"]
http.cors.enabled: true
http.cors.allow-origin: /.*/
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: elasticsearch
namespace: logging
spec:
selector:
matchLabels:
name: elasticsearch
replicas: 1
template:
metadata:
labels:
name: elasticsearch
spec:
initContainers:
- name: init-sysctl
image: busybox
command:
- sysctl
- -w
- vm.max_map_count=262144
securityContext:
privileged: true
containers:
- name: elasticsearch
image: arm64v8/elasticsearch:7.17.10
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 1000m
memory: 2Gi
requests:
cpu: 100m
memory: 1Gi
env:
- name: ES_JAVA_OPTS
value: -Xms512m -Xmx512m
ports:
- containerPort: 9200
- containerPort: 9300
volumeMounts:
- name: elasticsearch-data
mountPath: /usr/share/elasticsearch/data/
- name: es-config
mountPath: /usr/share/elasticsearch/config/elasticsearch.yml
subPath: elasticsearch.yml
volumes:
- name: elasticsearch-data
persistentVolumeClaim:
claimName: es-pvc
# hostPath:
# path: /data/es
- name: es-config
configMap:
name: es
---
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
namespace: logging
labels:
name: elasticsearch
spec:
type: NodePort
ports:
- name: web-9200
port: 9200
targetPort: 9200
protocol: TCP
nodePort: 30105
- name: web-9300
port: 9300
targetPort: 9300
protocol: TCP
nodePort: 30106
selector:
name: elasticsearch
验证是否部署成功:
[root@master-165 k8sYaml]# kubectl get pods -n logging -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
elasticsearch-5867d7b46f-2vd8n 1/1 Running 6 9m50s 10.244.69.162 master-165 <none> <none>
[root@master-165 k8sYaml]# curl 10.244.69.162:9200
{
"name" : "node-1",
"cluster_name" : "my-cluster",
"cluster_uuid" : "EIGaunmRQ2-ZqA3YgKQ-DQ",
"version" : {
"number" : "7.17.10",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "fecd68e3150eda0c307ab9a9d7557f5d5fd71349",
"build_date" : "2023-04-23T05:33:18.138275597Z",
"build_snapshot" : false,
"lucene_version" : "8.11.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
[root@master-165 k8sYaml]#
看到上面的信息就表明我们名为my-cluster 的 Elasticsearch 集群成功创建了1个节点:node-1;
相关文章:
在 Kubernetes 上搭建 EFK 日志收集系统
详解 K8s 日志采集最佳实践
kubernetes 日志架构
9款日志采集和管理工具对比,选型必备!
K8S 生产实践-12-共享存储-PV、PVC 和 StorageClass
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)