Kubernetes EFK(8.6.2)搭建

环境目标:

  • 基于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

image-20230309100709142

更新安装源

apt update

关闭swap

修改文件/etc/fstab,将最后一行内容注释,然后重启主机。

image-20230202114654383

安装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

image-20230309101805231

初始化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清除之前安装错误时产生的文件,不然后面再次安装时可能会报错。

image-20230309103045193

再次执行初始化命令,又报错

image-20230309114115406

检查关联的kubelet服务喝和containerd服务,在containerd中看到报错信息。

failed to do request: Head \"https://asia-east1-docker.pkg.dev/v2/k8s-artifa……

image-20230309114157312

生成containerd的配置文件

containerd config default > /etc/containerd/config.toml

SystemdCgroup的值修改为true,将sandbox_image的值修改为国内镜像registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7

image-20230202151335539

image-20230202151505808

重启containerd服务

systemctl restart containerd

执行kubeadm reset,然后重新执行kubeadm初始化命令即可,可以看到安装成功的信息。

image-20230309114457091

记录最后的命令

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

image-20230309114900311

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

image-20230309115130194

接着,执行master节点安装完成后回显的命令,让node节点加入集群。

kubeadm join 192.168.17.24:6443 --token 0s924y.gpsmhmsqpwzrr580 \
        --discovery-token-ca-cert-hash sha256:caabac919ca3dfb2376e042cde917541fcc0001baf163ba8ff8d7ced2a75e1c0

同样报错,使用之前描述过的相同的解决方法,完成节点的加入

image-20230309123017976

此时还需要配置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

image-20230202151335539

image-20230202151505808

重启containerd服务

systemctl restart containerd

当所有node节点加入完成后,可以在任意节点上执行命令查看节点情况

kubectl get nodes

image-20230309122257495

最后,在每个节点上的/etc/hosts文件中加入IP地址和主机名的映射关系。

image-20230309143802307

4 部署Dashboard

Dashboard的部署其实可有可无,主要看场景需求。

在任意节点上执行如下命令。其中-f指定文件,使用官方的dashboard配置文件部署。

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

image-20230203110643762

image-20230203110731671

由于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

image-20230203113805822

此时,仍然无法从外部访问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

image-20230309123547047

浏览器访问映射出来的端口32088,得到如下页面。输入之前生成的token即可登录。

image-20230309123825051
image-20230309124242967

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

image-20230216101743429

  • --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格式。

image-20230309142052704

关于审计日志的配置策略,当前大多数会遵循以下规则:

  • 在收到请求后不立即记录日志,当返回体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

image-20230309142322354

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

保存文件后创建或应用

image-20230309142616165

创建持久卷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

image-20230309144016374

创建持久卷申领PersistentVolumeClaim,将PVC绑定到持久化存储上。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: es-pv-claim
  namespace: elastic-system
spec:
  storageClassName: local-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

image-20230309144227144

创建完存储类、PV、PVC后,检查是否成功绑定。需要确保PVC已经绑定到PV上,如果显示为Pending状态,则删除刚才创建的storageclass、pv、pvc,然后重新创建。

image-20230309161128218

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状态。

image-20230309162818866

此时的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

image-20230309162957269

创建完成后可以访问到es和kibana

image-20230309164755267

image-20230309164814464

6.4 配置Filebeat

去除master上的污点

kubectl taint node master node-role.kubernetes.io/control-plane:NoSchedule-

image-20230309172252678

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

image-20230309172347353

在kibana的Discover中创建dataview就可以看到对应的日志

image-20230309172452098

image-20230309172636358

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值