环境目标:
- 基于K8S搭建一套简单的EFK(Elasticsearch+Kibana+Filebeat)
- 收集K8S集群中容器的应用日志(如web访问日志)
- 收集K8S集群中容器的标准输出日志
- 审计K8S中通过apiserver进行的操作
- K8S标配Dashboard
1 准备工作
K8S Master、K8S Node1、K8S Node2:Ubuntu18.04,共计三台主机
修改每台主机上的APT源并更新
编辑/etc/apt/source.list,修改为如下内容。
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main
添加密钥
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add
更新安装源
apt update
关闭swap
修改文件/etc/fstab
,将最后一行内容注释,然后重启主机。
安装docker
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
2 K8S Master节点搭建
安装https和k8s
apt-get update && apt-get install -y apt-transport-https curl
apt-get install -y kubelet kubeadm kubectl --allow-unauthenticated
将k8s相关服务设置为开机自启动
sudo systemctl enable kubelet && systemctl start kubelet
执行命令kubeadm version
检查版本,如图为1.26.2
初始化master节点
kubeadm init --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --v=5
这里使用到三个参数:
-
--image-repository
:指定镜像源为国内镜像 -
--pod-network-cidr
:k8s内部pod节点之间网络可以使用的IP段 -
--service-cidr
:服务之间网络可以使用的IP段
可选参数--v=5
,用于回显。
执行后报错:
[ERROR CRI]: container runtime is not running: output: time="2023-03-09T02:27:26Z" level=fatal msg="validate service connection: CRI v1 runtime API is not implemented for endpoint \"unix:///var/run/containerd/containerd.sock\": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService"
, error: exit status 1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1hRl8tSM-1678356658785)(https://l7dia-images.oss-cn-hangzhou.aliyuncs.com/images/202303091028750.png)]
删除/etc/containerd/config.toml
,重启containerd
服务
rm -rf /etc/containerd/config.toml
systemctl restart containerd
执行kubeadm reset
清除之前安装错误时产生的文件,不然后面再次安装时可能会报错。
再次执行初始化命令,又报错
检查关联的kubelet服务喝和containerd服务,在containerd中看到报错信息。
failed to do request: Head \"https://asia-east1-docker.pkg.dev/v2/k8s-artifa……
生成containerd的配置文件
containerd config default > /etc/containerd/config.toml
将SystemdCgroup
的值修改为true
,将sandbox_image
的值修改为国内镜像registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7
重启containerd
服务
systemctl restart containerd
执行kubeadm reset
,然后重新执行kubeadm初始化命令即可,可以看到安装成功的信息。
记录最后的命令
kubeadm join 192.168.17.24:6443 --token 0s924y.gpsmhmsqpwzrr580 \
--discovery-token-ca-cert-hash sha256:caabac919ca3dfb2376e042cde917541fcc0001baf163ba8ff8d7ced2a75e1c0
设置配置文件
mkdir -p /root/.kube
cp -i /etc/kubernetes/admin.conf /root/.kube/config
chown root:root /root/.kube/config
安装网络插件flannel
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
3 K8S Node节点加入
本次搭建使用了两个node节点,对于node节点执行以下安装步骤:
-
完成准备工作中的内容
-
安装https和k8s
apt-get update && apt-get install -y apt-transport-https curl apt-get install -y kubelet kubeadm kubectl --allow-unauthenticated
将k8s相关服务设置为开机自启动
sudo systemctl enable kubelet && systemctl start kubelet
创建.kube文件夹
mkdir .kube
将master节点上生成的config文件夹拷贝到本地的.kube
文件夹中,并修改权限
chown root:root /root/.kube/config
接着,执行master节点安装完成后回显的命令,让node节点加入集群。
kubeadm join 192.168.17.24:6443 --token 0s924y.gpsmhmsqpwzrr580 \
--discovery-token-ca-cert-hash sha256:caabac919ca3dfb2376e042cde917541fcc0001baf163ba8ff8d7ced2a75e1c0
同样报错,使用之前描述过的相同的解决方法,完成节点的加入
此时还需要配置containerd服务中的内容,否则后续将pod部署到node节点上时同样会发生无法拉去容器镜像的情况。方法步骤与之前相同,首先生成containerd的配置文件
containerd config default > /etc/containerd/config.toml
将SystemdCgroup
的值修改为true
,将sandbox_image
的值修改为国内镜像registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7
重启containerd
服务
systemctl restart containerd
当所有node节点加入完成后,可以在任意节点上执行命令查看节点情况
kubectl get nodes
最后,在每个节点上的/etc/hosts
文件中加入IP地址和主机名的映射关系。
4 部署Dashboard
Dashboard的部署其实可有可无,主要看场景需求。
在任意节点上执行如下命令。其中-f
指定文件,使用官方的dashboard配置文件部署。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
由于K8S中使用RBAC机制进行访问控制,所以我们要创建用户,然后为用户绑定角色。创建超级管理员账户k8sadmin
kubectl create serviceaccount k8sadmin -n kubernetes-dashboard
kubectl create clusterrolebinding k8sadmin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:k8sadmin
创建token,这里生成token的默认有效时间为10min
kubectl -n kubernetes-dashboard create token k8sadmin
此时,仍然无法从外部访问dashboard,因为默认的访问方式为ClusterIP,所以需要修改访问方式
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
将type:ClusterIP
修改为type:NodePort
,也可以指定端口nodePort
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nrtSR9eT-1678356658791)(https://l7dia-images.oss-cn-hangzhou.aliyuncs.com/images/202303091224659.png)]
查看服务情况,检查端口映射关系
kubectl get svc -n kubernetes-dashboard
浏览器访问映射出来的端口32088,得到如下页面。输入之前生成的token即可登录。
5 配置K8S审计日志
k8s的审计日志主要针对apiserver,也就是对apiserver进行相关设置。
首先,准备审计策略文件audit-policy.yaml,官方给到的样例如下:
apiVersion: audit.k8s.io/v1 # 这是必填项。
kind: Policy
# 不要在 RequestReceived 阶段为任何请求生成审计事件。
omitStages:
- "RequestReceived"
rules:
# 在日志中用 RequestResponse 级别记录 Pod 变化。
- level: RequestResponse
resources:
- group: ""
# 资源 "pods" 不匹配对任何 Pod 子资源的请求,
# 这与 RBAC 策略一致。
resources: ["pods"]
# 在日志中按 Metadata 级别记录 "pods/log"、"pods/status" 请求
- level: Metadata
resources:
- group: ""
resources: ["pods/log", "pods/status"]
# 不要在日志中记录对名为 "controller-leader" 的 configmap 的请求。
- level: None
resources:
- group: ""
resources: ["configmaps"]
resourceNames: ["controller-leader"]
# 不要在日志中记录由 "system:kube-proxy" 发出的对端点或服务的监测请求。
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: "" # core API 组
resources: ["endpoints", "services"]
# 不要在日志中记录对某些非资源 URL 路径的已认证请求。
- level: None
userGroups: ["system:authenticated"]
nonResourceURLs:
- "/api*" # 通配符匹配。
- "/version"
# 在日志中记录 kube-system 中 configmap 变更的请求消息体。
- level: Request
resources:
- group: "" # core API 组
resources: ["configmaps"]
# 这个规则仅适用于 "kube-system" 名字空间中的资源。
# 空字符串 "" 可用于选择非名字空间作用域的资源。
namespaces: ["kube-system"]
# 在日志中用 Metadata 级别记录所有其他名字空间中的 configmap 和 secret 变更。
- level: Metadata
resources:
- group: "" # core API 组
resources: ["secrets", "configmaps"]
# 在日志中以 Request 级别记录所有其他 core 和 extensions 组中的资源操作。
- level: Request
resources:
- group: "" # core API 组
- group: "extensions" # 不应包括在内的组版本。
# 一个抓取所有的规则,将在日志中以 Metadata 级别记录所有其他请求。
- level: Metadata
# 符合此规则的 watch 等长时间运行的请求将不会
# 在 RequestReceived 阶段生成审计事件。
omitStages:
- "RequestReceived"
其中使用level
指定日志等级,共有四个级别:
None
- 符合这条规则的日志将不会记录。Metadata
- 记录请求的元数据(请求的用户、时间戳、资源、动词等等), 但是不记录请求或者响应的消息体。Request
- 记录事件的元数据和请求的消息体,但是不记录响应的消息体。 这不适用于非资源类型的请求。RequestResponse
- 记录事件的元数据,请求和响应的消息体。这不适用于非资源类型的请求。
在什么时候进行日志记录同样也分为了四个阶段:
RequestReceived
- 此阶段对应审计处理器接收到请求后,并且在委托给 其余处理器之前生成的事件。ResponseStarted
- 在响应消息的头部发送后,响应消息体发送前生成的事件。 只有长时间运行的请求(例如 watch)才会生成这个阶段。ResponseComplete
- 当响应消息体完成并且没有更多数据需要传输的时候。Panic
- 当 panic 发生时生成。
接着,需要在apiserver的配置文件中应用该日志策略。默认配置文件为/etc/kubernetes/manifests/kube-apiserver.yaml
在参数部分需要添加如下内容:
- --audit-policy-file=/etc/kubernetes/manifests/audit-policy.yaml
- --audit-log-path=/var/log/kubernetes/audit.log
- --audit-log-maxage=365
- --audit-log-maxbackup=10
- --audit-log-maxsize=100
--audit-log-path
指定用来写入审计事件的日志文件路径,需要精确到文件名。不指定此标志会禁用日志后端。--audit-log-maxage
定义保留旧审计日志文件的最大天数--audit-log-maxbackup
定义要保留的审计日志文件的最大数量--audit-log-maxsize
定义审计日志文件轮转之前的最大大小(兆字节)--audit-policy-file
指定刚才创建的审计策略文件
基于以上配置,当单个日志文件大小达到100MB
时就会自动分片
由于需要在apiserver容器内部使用策略文件,所以还需要将策略文件和日志文件映射到内部
volumeMounts:
- name: audit
mountPath: /etc/kubernetes/manifests/audit-policy.yaml
readOnly: true
- mountPath: /var/log/kubernetes
name: audit-log
readOnly: false
volumes:
- hostPath:
path: /etc/kubernetes/manifests/audit-policy.yaml
type: File
name: audit
- hostPath:
path: /var/log/kubernetes
type: DirectoryOrCreate
name: audit-log
在进行日志文件映射时,指定到路径即可。
重启kubelet服务,就可以看到生成的审计日志,默认为json格式。
关于审计日志的配置策略,当前大多数会遵循以下规则:
-
在收到请求后不立即记录日志,当返回体header发送后才开始记录。
-
对于大量冗余的kube-proxy watch请求,kubelet和system:nodes对于node的get请求,kube组件在kube-system下对于endpoint的操作,以及apiserver对于namespaces的get请求等不作审计。
-
对于/healthz*,/version*, /swagger*等只读url不作审计。
-
对于可能包含敏感信息或二进制文件的secrets,configmaps,tokenreviews接口的日志等级设为metadata,该level只记录请求事件的用户、时间戳、请求资源和动作,而不包含请求体和返回体。
-
对于一些如authenticatioin、rbac、certificates、autoscaling、storage等敏感接口,根据读写记录相应的请求体和返回体。
6 配置EFK
日志采集使用Elasticsearch+Filebeat+Kibana,根据实际需求可以将Filebeat替换为Fluentd或者再加上Logstash
6.1 创建命名空间
使用单独的命名空间来运行EFK及相关内容
kubectl create namespace elastic-system
6.2 创建持久化存储
在使用ES的过程中,涉及到数据存储的问题,除了常规使用映射的方式外,建议使用K8S中的持久化存储进行数据的存留
本次搭建将在node1上进行数据存储,所以先在node1上创建/data文件夹
首先,创建持久化存储类StorageClass
。创建yaml文件,指定kind
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
reclaimPolicy: Retain
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
保存文件后创建或应用
创建持久卷PersistentVolume
,其中可以指定存储空间大小(spec.storage)、关联存储类名称(spec.storageClassName)、物理路径(spec.local.path),使用nodeAffinity
将PV绑定到node1节点上。
apiVersion: v1
kind: PersistentVolume
metadata:
name: es-local-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /data
claimRef:
name: es-pv-claim
namespace: elastic-system
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node1
创建持久卷申领PersistentVolumeClaim
,将PVC绑定到持久化存储上。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: es-pv-claim
namespace: elastic-system
spec:
storageClassName: local-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
创建完存储类、PV、PVC后,检查是否成功绑定。需要确保PVC已经绑定到PV上,如果显示为Pending状态,则删除刚才创建的storageclass、pv、pvc,然后重新创建。
6.3 创建Elasticsearch和Kibana
准备es和kibana的配置文件。这里没有配置相关用户名和密码。
es的配置文件如下,存储yml文件,文件名必须为elasticsearch.yml
,否则后续会报错。
cluster.name: my-es
node.name: "node1"
path.data: /usr/share/elasticsearch/data
bootstrap.memory_lock: false
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["127.0.0.1", "[::1]"]
cluster.initial_master_nodes: ["node1"]
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type
xpack.security.enabled: false
kibana的配置文件如下,存储为yaml文件。其中,指定了es的路径,采取域名的形式。在k8s中,访问创建的服务(service)中的pod可以使用如下域名格式:...svc.cluster.local。
server.name: kibana
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: "http://es-kibana-0.es-kibana.elastic-system.svc.cluster.local:9200"
xpack.reporting.roles.enabled: false
将配置文件转化为k8s中的configmap,需要使用-n命令指定命名空间。
kubectl create configmap es-config -n elastic-system --from-file=elasticsearch.yml
kubectl create configmap kibana-config -n elastic-system --from-file=kibana.yml
创建StatefulSet
类型的es和kibana
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: es-kibana
name: es-kibana
namespace: elastic-system
spec:
replicas: 1
selector:
matchLabels:
app: es-kibana
serviceName: "es-kibana"
template:
metadata:
labels:
app: es-kibana
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- image: elasticsearch:8.6.2
imagePullPolicy: IfNotPresent
name: elasticsearch
resources:
requests:
memory: "800Mi"
cpu: "1000m"
limits:
memory: "1Gi"
cpu: "1000m"
ports:
- containerPort: 9200
- containerPort: 9300
volumeMounts:
- name: es-config
mountPath: /usr/share/elasticsearch/config/elasticsearch.yml
subPath: elasticsearch.yml
- name: es-persistent-storage
mountPath: data
env:
- name: TZ
value: Asia/Shanghai
- name: "ES_JAVA_OPTS"
value: "-Xms256m -Xmx256m"
- image: kibana:8.6.2
imagePullPolicy: IfNotPresent
name: kibana
resources:
requests:
memory: 1Gi
cpu: 50m
limits:
memory: 1Gi
cpu: 1000m
ports:
- containerPort: 5601
env:
- name: TZ
value: Asia/Shanghai
volumeMounts:
- name: kibana-config
mountPath: /usr/share/kibana/config/kibana.yml
subPath: kibana.yml
initContainers:
- name: increase-vm-max-map
image: busybox
command: ["sysctl", "-w", "vm.max_map_count=262144"]
securityContext:
privileged: true
volumes:
- name: es-config
configMap:
name: es-config
- name: kibana-config
configMap:
name: kibana-config
- name: es-persistent-storage
persistentVolumeClaim:
claimName: es-pv-claim
对其中一些内容解释如下:
spec.replicas
:冗余数量,为了节省资源,使用1
spec.template.spec.containers
:使用的容器模板,在资源部分可以指定申请的资源和资源限制,可以自行设置。这里cpu的单位为m
,表示毫核。创建容器时将刚才创建的configmap挂载到容器中。
spec.template.spec.initContainers
:使用busybox修改es中的配置
spec.template.spec.volumes
:挂载configmap和申领的PVC
然后执行kubectl create -f es-kibana-statefulset.yaml
创建即可。首次创建的时间会略长。
创建完成后检查pod,能够看到处于running状态。
此时的es跟kibana还不能够通过外部网络访问,同样要创建对应的service才可以。
apiVersion: v1
kind: Service
metadata:
labels:
app: es-kibana
name: es-kibana-svc
namespace: elastic-system
spec:
ports:
- name: 9200-9200
port: 9200
protocol: TCP
targetPort: 9200
nodePort: 30200
- name: 5601-5601
port: 5601
protocol: TCP
targetPort: 5601
nodePort: 30601
selector:
app: es-kibana
type: NodePort
检查对应的service
创建完成后可以访问到es和kibana
6.4 配置Filebeat
去除master上的污点
kubectl taint node master node-role.kubernetes.io/control-plane:NoSchedule-
filebeat的配置直接使用了官方的配置文件
apiVersion: v1
kind: ServiceAccount
metadata:
name: filebeat
namespace: elastic-system
labels:
k8s-app: filebeat
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: filebeat
labels:
k8s-app: filebeat
rules:
- apiGroups: [""] # "" indicates the core API group
resources:
- namespaces
- pods
- nodes
verbs:
- get
- watch
- list
- apiGroups: ["apps"]
resources:
- replicasets
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources:
- jobs
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: filebeat
# should be the namespace where filebeat is running
namespace: elastic-system
labels:
k8s-app: filebeat
rules:
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs: ["get", "create", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: filebeat-kubeadm-config
namespace: elastic-system
labels:
k8s-app: filebeat
rules:
- apiGroups: [""]
resources:
- configmaps
resourceNames:
- kubeadm-config
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: filebeat
subjects:
- kind: ServiceAccount
name: filebeat
namespace: elastic-system
roleRef:
kind: ClusterRole
name: filebeat
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: filebeat
namespace: elastic-system
subjects:
- kind: ServiceAccount
name: filebeat
namespace: elastic-system
roleRef:
kind: Role
name: filebeat
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: filebeat-kubeadm-config
namespace: elastic-system
subjects:
- kind: ServiceAccount
name: filebeat
namespace: elastic-system
roleRef:
kind: Role
name: filebeat-kubeadm-config
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-config
namespace: elastic-system
labels:
k8s-app: filebeat
data:
filebeat.yml: |-
filebeat.inputs:
- type: container
paths:
- /var/log/containers/*.log
processors:
- add_kubernetes_metadata:
host: ${NODE_NAME}
matchers:
- logs_path:
logs_path: "/var/log/containers/"
fields:
source: container
- type: filestream
paths:
- /var/log/kubernetes/audit*.log
parsers:
- ndjson:
target: ""
add_error_key: true
fields:
source: k8s-audit
processors:
- add_cloud_metadata:
- add_host_metadata:
# cloud.id: ${ELASTIC_CLOUD_ID}
# cloud.auth: ${ELASTIC_CLOUD_AUTH}
setup.template.settings:
index.number_of_shards: 1
setup.template.enabled: true
setup.template.fields: fields.yml
setup.template.name: "filebeat"
setup.template.pattern: "filebeat-*"
setup.ilm.enabled: false
output.elasticsearch:
hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
index: "filebeat-%{[fields.source]}-*"
indices:
- index: "filebeat-container-%{+yyyy.MM}"
when.equals:
fields:
source: "container"
- index: "filebeat-k8s-audit-%{+yyyy.MM}"
when.equals:
fields:
source: "k8s-audit"
# username: ${ELASTICSEARCH_USERNAME}
# password: ${ELASTICSEARCH_PASSWORD}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat
namespace: elastic-system
labels:
k8s-app: filebeat
spec:
selector:
matchLabels:
k8s-app: filebeat
template:
metadata:
labels:
k8s-app: filebeat
spec:
serviceAccountName: filebeat
terminationGracePeriodSeconds: 30
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: filebeat
image: docker.elastic.co/beats/filebeat:8.6.2
args: [
"-c", "/etc/filebeat.yml",
"-e",
]
env:
- name: ELASTICSEARCH_HOST
value: es-kibana-svc.elastic-system.svc.cluster.local
- name: ELASTICSEARCH_PORT
value: "9200"
# - name: ELASTICSEARCH_USERNAME
# value: elastic
# - name: ELASTICSEARCH_PASSWORD
# value: changeme
# - name: ELASTIC_CLOUD_ID
# value:
# - name: ELASTIC_CLOUD_AUTH
# value:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
securityContext:
runAsUser: 0
# If using Red Hat OpenShift uncomment this:
#privileged: true
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
volumeMounts:
- name: config
mountPath: /etc/filebeat.yml
readOnly: true
subPath: filebeat.yml
- name: data
mountPath: /usr/share/filebeat/data
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: varlog
mountPath: /var/log
readOnly: true
- name: varlogkube
mountPath: /var/log/kubernetes
readOnly: true
volumes:
- name: config
configMap:
defaultMode: 0640
name: filebeat-config
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: varlog
hostPath:
path: /var/log
- name: varlogkube
hostPath:
path: /var/log/kubernetes
# data folder stores a registry of read status for all files, so we don't send everything again on a Filebeat pod restart
- name: data
hostPath:
# When filebeat runs as non-root user, this directory needs to be writable by group (g+w).
path: /var/lib/filebeat-data
type: DirectoryOrCreate
---
同样理解一下其中的关键配置。首先,Filebeat需要绑定RBAC角色才能够使用,也就是创建ServiceAccount、ClusterRole、Role、ClusterRoleBinding和RoleBinding,主要是为filebeat赋予权限。
在上述配置文件中,创建了configmap,指定了filebeat配置文件的内容
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-config
namespace: elastic-system
labels:
k8s-app: filebeat
data:
filebeat.yml: |-
filebeat.inputs:
- type: container
paths:
- /var/log/containers/*.log
processors:
- add_kubernetes_metadata:
host: ${NODE_NAME}
matchers:
- logs_path:
logs_path: "/var/log/containers/"
fields:
source: container
- type: filestream
paths:
- /var/log/kubernetes/audit*.log
parsers:
- ndjson:
target: ""
add_error_key: true
fields:
source: k8s-audit
processors:
- add_cloud_metadata:
- add_host_metadata:
# cloud.id: ${ELASTIC_CLOUD_ID}
# cloud.auth: ${ELASTIC_CLOUD_AUTH}
setup.template.settings:
index.number_of_shards: 1
setup.template.enabled: true
setup.template.fields: fields.yml
setup.template.name: "filebeat"
setup.template.pattern: "filebeat-*"
setup.ilm.enabled: false
output.elasticsearch:
hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
index: "filebeat-%{[fields.source]}-*"
indices:
- index: "filebeat-container-%{+yyyy.MM}"
when.equals:
fields:
source: "container"
- index: "filebeat-k8s-audit-%{+yyyy.MM}"
when.equals:
fields:
source: "k8s-audit"
# username: ${ELASTICSEARCH_USERNAME}
# password: ${ELASTICSEARCH_PASSWORD}
filebeat.inputs
中指定日志来源,一个filebeat配置文件中只能有一个inputs,但是一个inputs中可以指定多个日志源。在指定日志源时,需要使用filebeat指定的日志源格式,对于json格式的日志,可以使用parsers
对其进行解析。
在设置inputs中的日志源时,加上了fields
字段,可以用于后续自定义内容的添加。
在输出设置方面,指定了输出对象为es,如果用了logstash,则指定为logstash即可。
通过indices指定不同日志源在es中存储的datastream名称,这里用到之前定义的fields字段进行区分。
对于一些不在filebeat默认输入流中的日志格式,可以自己定义pipeline进行处理,在pipeline中设计grok语法进行解析即可。当处理规则复杂时,建议用logstash。
创建filebeat,可以看到对应的pod和daemonset
在kibana的Discover
中创建dataview就可以看到对应的日志