EFK 日志系统收集K8s日志 (一)

一、日志收集的需求背景:

• 业务发展越来越庞大,服务器越来越多

​ • 各种访问日志、应用日志、错误日志量越来越多

​ • 开发人员排查问题,需要到服务器上查日志,效率低、权限不好控制

​ • 运维需实时关注业务访问情况

二、容器特性给日志采集带来的难度:

​ • K8s弹性伸缩性:导致不能预先确定采集的目标​ • 容器隔离性:容器的文件系统与宿主机是隔离,导致日志采集器读取日志文件受阻

三、应用程序日志记录分为两类:

​ • 标准输出:输出到控制台,使用kubectl logs可以看到 (比如nginx 的日志就是输出到控制台)

​ • 日志文件:写到容器的文件系统的文件(比如tomcat的日志就是写入到容器中的文件系统的文件)

四、Kubernetes应用日志收集

EFK 日志系统收集K8s日志 (一)

针对标准输出:以DaemonSet方式在每个Node上部署一个日志收集程序,采集/var/lib/docker/containers/目录下所有容器日志

针对容器中日志文件:在Pod中增加一个容器运行日志采集器,使用emtyDir共享日志目录让日志采集器读取到日志文件

五、EFK Stack日志系统

EFK 日志系统收集K8s日志 (一)

EFK 是三个开源软件的缩写,提供一套完整的企业级日 志平台解决方案。 分别是:

• Elasticsearch:搜索、分析和存储数据

• Filebeat :是本地文件的日志数据采集器,可监控日志目录或特定日志文件,并将它们转发给Elasticsearch或Logstatsh进行索引、kafka等

• Kibana:数据可视化

六、部署ES 单点+ filebeat + kibana 实现Kubernetes应用日志收集

1、集群信息

主机名 IP地址 节点信息
Master 192.168.31.61 master 节点 8核8G
Node-1 192.168.31.63 node 节点 8核12G
Node-2 192.168.31.66 node 节点 8核12G
Node-3 192.168.31.67 node 节点 8核12G
NFS 192.168.31.100 nfs 存储节点 8核12G

2、软件版本

软件名 版本 备注
kubernetes v1.18.6
Elasticsearch v7.9.2 单点
Filebeat v7.9.2
Kibana v7.9.2
Nfs-client-provisioner v1.2.8 动态PV

3、部署NFS 服务

# 创建 NFS 存储目录
mkdir -p /home/elk
# 安装nfs服务
yum -y install nfs-utils rpcbind
# 修改配置文件
echo "/home/elk *(rw,sync,no_root_squash,no_subtree_check)" >> /etc/exports
# 启动服务
systemctl start nfs && systemctl start rpcbind
# 设置开机启动
systemctl enable nfs-server && systemctl enable rpcbind

4、集群所有节点都要安装nfs-utils

yum -y install nfs-utils

#记住,所有节点都要安装nfs-utils,否则无法使用pv

5、部署动态PV

5.1、创建NFS 动态PV专属命名空间

[root@master-1 ~]# kubectl create ns nfs
namespace/nfs created

5.2、使用Helm 部署nfs-client-provisioner

注意事项:
		(1)、nfs-client-provisioner部署到刚刚创建的nfs命名空间下
		(2)、storageClass.name #指定storageClassName名称,用于 PVC 自动绑定专属动态 PV 上
		(3)、需要指定NFS服务器的IP 地址(192.168.31.100),以及共享名称路径(/home/elk)
#添加helm charts repo
[root@master-1 es-single-node]# helm repo add helm-stable https://charts.helm.sh/stable        
[root@master-1 es-single-node]# helm repo update

cat >  elastic-client-nfs.yaml << EOF
# NFS 设置
nfs:
  server: 192.168.31.100
  path: /home/elk
storageClass:
  # 此配置用于绑定 PVC 和 PV
  name: elastic-nfs-client
  
  # 资源回收策略
#主要用于绑定的PVC删除后,资源释放后如何处理该PVC在存储设备上写入的数据。
#Retain:保留,删除PVC后,PV保留数据;
#Recycle:回收空间,删除PVC后,简单的清除文件;(NFS和HostPath存储支持)
#Delete:删除,删除PVC后,与PV相连接的后端存储会删除数据;(AWS EBS、Azure Disk、Cinder volumes、GCE PD支持)
  reclaimPolicy: Retain
# 使用镜像
image:
  repository: kubesphere/nfs-client-provisioner
# 副本数量
replicaCount: 3
EOF

#helm 部署 nfs-client-provisioner
[root@master-1 es-single-node]# helm install elastic-nfs-storage -n nfs --values elastic-client.yaml helm-stable/nfs-client-provisioner --version 1.2.8

5.3、查看 nfs-client-provisioner Pod 运行状态

[root@master-1 es-single-node]# kubectl get pods -n nfs
NAME                                                          READY   STATUS    RESTARTS   AGE
elastic-nfs-storage-nfs-client-provisioner-78c7754777-8kvlg   1/1     Running   0          28m
elastic-nfs-storage-nfs-client-provisioner-78c7754777-vtpn8   1/1     Running   0          28m
elastic-nfs-storage-nfs-client-provisioner-78c7754777-zbx8s   1/1     Running   0          28m

6、部署单节点Elasticsearch数据库

6.1、创建EFK 专属命名空间

[root@master-1 es-single-node]# kubectl create ns ops
namespace/ops created

6.2、创建elasticsearch.yaml

cat >  elasticsearch.yaml  << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
  namespace: ops
  labels:
    k8s-app: elasticsearch
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: elasticsearch
  template:
    metadata:
      labels:
        k8s-app: elasticsearch
    spec:
      containers:
      - image: elasticsearch:7.9.2
        name: elasticsearch
        resources:
          limits:
            cpu: 2
            memory: 3Gi
          requests:
            cpu: 0.5 
            memory: 500Mi
        env:
          - name: "discovery.type"
            value: "single-node"
          - name: ES_JAVA_OPTS
            value: "-Xms512m -Xmx2g" 
        ports:
        - containerPort: 9200
          name: db
          protocol: TCP
        volumeMounts:
        - name: elasticsearch-data
          mountPath: /usr/share/elasticsearch/data
      volumes:
      - name: elasticsearch-data
        persistentVolumeClaim:
          claimName: es-pvc

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: es-pvc
  namespace: ops
spec:
#指定动态PV 名称
  storageClassName: "elastic-nfs-client"
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

---

apiVersion: v1
kind: Service
metadata:
  name: elasticsearch
  namespace: ops
spec:
  ports:
  - port: 9200
    protocol: TCP
    targetPort: 9200
  selector:
    k8s-app: elasticsearch
EOF

[root@master-1 es-single-node]# kubectl apply -f elasticsearch.yaml 
deployment.apps/elasticsearch create
persistentvolumeclaim/es-pvc create
service/elasticsearch create

6.3、查看elasticsearch pod,service 运行状态

[root@master-1 es-single-node]# kubectl get pod -n ops -l k8s-app=elasticsearch
NAME                            READY   STATUS    RESTARTS   AGE
elasticsearch-97f7d74f5-qr6d4   1/1     Running   0          2m41s


[root@master-1 es-single-node]# kubectl get service -n ops
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)             AGE
elasticsearch        ClusterIP   10.0.0.126   <none>        9200/TCP            2m41s

7、部署kibana 可视化展示

7.1、创建kibana.yaml

cat >  kibana.yaml  << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kibana
  namespace: ops
  labels:
    k8s-app: kibana
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: kibana
  template:
    metadata:
      labels:
        k8s-app: kibana
    spec:
      containers:
      - name: kibana
        image: kibana:7.9.2
        resources:
          limits:
            cpu: 2
            memory: 4Gi
          requests:
            cpu: 0.5 
            memory: 500Mi
        env:
          - name: ELASTICSEARCH_HOSTS
#指定elasticsearch的servicesname,记得加上命名空间.ops
            value: http://elasticsearch.ops:9200
          - name: I18N_LOCALE
            value: zh-CN
        ports:
        - containerPort: 5601
          name: ui
          protocol: TCP

---
apiVersion: v1
kind: Service
metadata:
  name: kibana
  namespace: ops
spec:
  type: NodePort
  ports:
  - port: 5601
    protocol: TCP
    targetPort: ui
    nodePort: 30601
  selector:
    k8s-app: kibana
EOF


[root@master-1 es-single-node]# kubectl apply -f kibana.yaml 
deployment.apps/kibana create
service/kibana create

7.2、查看kibana pod,service 运行状态

[root@master-1 es-single-node]# kubectl get pod -n ops -l k8s-app=kibana
NAME                      READY   STATUS    RESTARTS   AGE
kibana-5c96d89b65-zgphp   1/1     Running   0          7m

[root@master-1 es-single-node]# kubectl get service -n ops
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)             AGE
kibana               NodePort    10.0.0.164   <none>        5601:30601/TCP      7m

7.3、查看kibana dashboard

输入kibana 地址: http://nodeIP:30601

EFK 日志系统收集K8s日志 (一)

8、日志收集

8.1、收集容器标准输出日志

EFK 日志系统收集K8s日志 (一)

大致思路:

​ 以DaemonSet方式在每个Node上部署一个Filebeat 的日志收集程序的Pod,采用hostPath 方式把 /var/lib/docker/containers 挂载到Filebeat 容器中,/var/lib/docker/containers 目录下的就是每个容器标准输出的日志

8.1.1 创建 filebeat-kubernetes.yaml

cat >  filebeat-kubernetes.yaml << EOF
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: ops
  labels:
    k8s-app: filebeat
data:
  filebeat.yml: |- filebeat.config: inputs: # Mounted `filebeat-inputs` configmap: path: ${path.config}/inputs.d/*.yml # Reload inputs configs as they change: reload.enabled: false modules: path: ${path.config}/modules.d/*.yml # Reload module configs as they change: reload.enabled: false 
    output.elasticsearch:
      hosts: ['elasticsearch.ops:9200']
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-inputs
  namespace: ops
  labels:
    k8s-app: filebeat
data:
  kubernetes.yml: |- - type: docker containers.ids: - "*" processors: - add_kubernetes_metadata: in_cluster: true ---
apiVersion: apps/v1 
kind: DaemonSet
metadata:
  name: filebeat
  namespace: ops
  labels:
    k8s-app: filebeat
spec:
  selector:
    matchLabels:
      k8s-app: filebeat
  template:
    metadata:
      labels:
        k8s-app: filebeat
    spec:
      serviceAccountName: filebeat
      terminationGracePeriodSeconds: 30
      containers:
      - name: filebeat
        image: elastic/filebeat:7.9.2
        args: [
          "-c", "/etc/filebeat.yml",
          "-e",
        ]
        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: inputs
          mountPath: /usr/share/filebeat/inputs.d
          readOnly: true
        - name: data
          mountPath: /usr/share/filebeat/data
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      volumes:
      - name: config
        configMap:
          defaultMode: 0600
          name: filebeat-config
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: inputs
        configMap:
          defaultMode: 0600
          name: filebeat-inputs
      # 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:
          path: /var/lib/filebeat-data
          type: DirectoryOrCreate
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: filebeat
subjects:
- kind: ServiceAccount
  name: filebeat
  namespace: ops
roleRef:
  kind: ClusterRole
  name: filebeat
  apiGroup: rbac.authorization.k8s.io
---
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
  verbs:
  - get
  - watch
  - list
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: filebeat
  namespace: ops
  labels:
    k8s-app: filebeat
EOF

[root@master-1 es-single-node]# kubectl apply -f filebeat-kubernetes.yaml 
configmap/filebeat-config create
configmap/filebeat-inputs create
daemonset.apps/filebeat create
clusterrolebinding.rbac.authorization.k8s.io/filebeat create
clusterrole.rbac.authorization.k8s.io/filebeat create
serviceaccount/filebeat create

8.1.2 查看Filebeat pod 运行状态

[root@master-1 es-single-node]# kubectl get pods -n ops -l k8s-app=node-exporter
NAME                  READY   STATUS    RESTARTS   AGE
node-exporter-j72cb   1/1     Running   10         13d
node-exporter-k6d7v   1/1     Running   10         13d
node-exporter-vhgns   1/1     Running   10         13d

8.1.3 登陆kibana 管理索引, 添加索引模式

索引管理:

(一般只要有数据入到ES中就会有索引出现 ,如果没有出现可以试着访问下业务使其产生日志输出到ES中)

点击 左边的 Stack Management 中的 索引管理 可以看到一个名词为filebeat-7.9.2-2021.03.01-000001的索引,状态为open

EFK 日志系统收集K8s日志 (一)

添加索引模式:

点击 左边的 Stack Management 中的索引模式,创建索引模式

EFK 日志系统收集K8s日志 (一)

输入索引模式名称: filebeat-7.9.2-*

表示可以匹配到上面的索引 filebeat-7.9.2-2021.03.01-000001

EFK 日志系统收集K8s日志 (一)

选择@timestamp 时间字段

EFK 日志系统收集K8s日志 (一)

EFK 日志系统收集K8s日志 (一)

8.1.4 启动一个nginx 的Pod,验证日志数据

cat >  app-log-stdout.yaml  << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-log-stdout
spec:
  replicas: 3
  selector:
    matchLabels:
      project: stdout-test
      app: nginx-stdout
  template:
    metadata:
      labels:
        project: stdout-test
        app: nginx-stdout
    spec:
      containers:
      - name: nginx 
        image: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: app-log-stdout
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    project: stdout-test
    app: nginx-stdout
EOF


[root@master-1 es-single-node]# kubectl apply -f app-log-stdout.yaml 
deployment.apps/app-log-stdout created
service/app-log-stdout created

8.1.5 查看nginx pod,service 状态

[root@master-1 es-single-node]# kubectl get pods -l app=nginx-stdout
NAME                              READY   STATUS    RESTARTS   AGE
app-log-stdout-76fb86fcf6-cjch4   1/1     Running   0          2m34s
app-log-stdout-76fb86fcf6-wcfqm   1/1     Running   0          2m34s
app-log-stdout-76fb86fcf6-zgzcc   1/1     Running   0          2m34s

[root@master-1 es-single-node]# kubectl get service
NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
app-log-stdout   ClusterIP   10.0.0.167   <none>        80/TCP    2m41s
kubernetes       ClusterIP   10.0.0.1     <none>        443/TCP   63d

8.1.6 访问nginx 的Pod 使其产生nginx 日志

[root@node-1 ~]# curl 10.0.0.167

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

8.1.7 登陆kibana dashboard 检索nginx 日志

检索的语句: kubernetes.namespace : “default” and message : “curl”

可以看到有1个 日志被命中了

EFK 日志系统收集K8s日志 (一)

本期的分享先分享到这里,下期接着分享 EFK 日志系统收集K8s日志之 容器中日志文件

文章来源:https://www.cnaaa.net,转载请注明出处:https://www.cnaaa.net/archives/7112

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年2月7日 下午5:43
下一篇 2023年2月8日 下午6:09

相关推荐

  • 如何处理CentOS Failed to load SELinux policy

    CentOS 7在启动时,卡在进度条界面一直进不去系统,如下图所示: 我们可以通过按键盘的左右方向键,可以看到提示“Failed to load SELinux policy.”,这就是造成系统一直卡住无法正常启动的原因。 原因 是因为没有正确修改系统的selinux的配置,导致系统在启动时报selinux的错误 解决方案 第一步:先重启CentOS7操作系…

    2022年6月15日
    29800
  • CentOS 7 磁盘挂载教程

    mount命令是经常会使用到的命令,它用于挂载Linux系统外的文件 进行挂载操作后,用户便可以在挂载目录中使用硬盘资源了。默认情况下Linux系统并不会像Windows系统那样自动的挂载光盘和U盘设备,需要自行完成。 语法 语法格式:mount [参数] [设备] [挂载点] 常用参数 -t 指定文件系统,即挂载类型 -l 显示已加载的文件系统列表 -h …

    2022年6月9日
    32910
  • mysql5.7忘记密码时,修改root密码

    推荐方法二 方法一: 1、修改mysql 配置文件,添加 skip-grant-tables vim /etc/my.cnf [myslqd] ……………….skip-grant-tables………………….

    2023年3月7日
    3600
  • 使用ovftool工具实现exsi上主机的导入导出

    需求: EXSI上虚机需要迁移到另外一台EXSI服务器上,需要批量下发系统或者是导入导出模板的功能 环境: ESXi版本: 6.7.0 VMware-ovftool: 4.3.0 一、下载VMware-ovftool 工具并安装 下载地址: https://customerconnect.vmware.com/zh/downloads/details?dow…

    2023年2月2日
    6300
  • K8S 部署redis单节点&rdb数据持久化&故障演练恢复

    K8S 部署redis单节点&rdb数据持久化&故障演练恢复   环境: 背景: 采用NFS存储卷的方式 持久化存储redis 需要保存的文件 一、部署NFS服务器 #服务器安装nfs服务,提供nfs存储功能 1、安装nfs-utils yum install nfs-utils (centos) 或者 apt-get instal…

    2023年2月7日
    5700

在线咨询: QQ交谈

邮件:712342017@qq.com

工作时间:周一至周五,8:30-17:30,节假日休息

关注微信