侧边栏壁纸
博主头像
小周的知识站 博主等级

行动起来,活在当下

  • 累计撰写 80 篇文章
  • 累计创建 12 个标签
  • 累计收到 8 条评论

目 录CONTENT

文章目录
K8S

K8S 日志收集 ELK

Administrator
2024-07-19 / 0 评论 / 0 点赞 / 35 阅读 / 0 字

K8S 日志收集ELK

收集日志可以用于分析用户行为,监控服务器状态,增强系统或应用安全性等。

1 常见的日志收集方案

ELK简介:ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana。

  • Elasticsearch:是个开源分布式搜索引擎,提供搜集、分析、存储数据三大功能。

  • Logstash:主要是用来做日志的分析、过滤等处理工作。

  • Kibana:可以为 Logstash 和 ElasticSearch 提供的日志提供友好的 Web 界面,可以帮助汇总、分析和搜索重要数据日志。

  • 新增了一个FileBeat,它是一个轻量级的日志收集处理工具(Agent),Filebeat占用资源少,适合于在各个服务器上搜集日志后传输给Logstash。

传统服务日志收集方案:Elasticsearch、Logstash、Kibana(ELKB) + Filebeat

传统服务日志收集与K8s服务日志收集区别:

  • 传统日志收集:传统服务部署在固定的服务器,而日志也固定服务器中的具体目录中,即便服务器重启,应用依然在固定的节点,对日志收集系统来讲,也不需要重新指定日志的所在位置。

  • K8s日志收集:在K8s集群中,服务通常不会固定在某一个节点,如果服务重启、弹性伸缩,那么服务可能会漂移到其他的节点,所以对于K8s中日志的收集与传统的方式不太一样。

容器日志收集方案:Elasticsearch、fluentd、Kibana(EFK)

Fluentd这种需要我们在每个 Pod 中都附带一个Agent容器来进行本 Pod 内部容器的日志采集,

一般采用共享卷的方式,但是对于这一种模式来说,很明显的一个问题就是占用的资源比较多,尤其是在集群规模比较大的情况下,或者说单个节点上容器特别多的情况下,它会占用过多的系统资源,同时也对日志存储后端占用过多的连接数。当我们的集群规模越大,这种部署模式引发的潜在问题就越大。

2 破解利器 Log-Pilot

轻量级:Log-Pilot采用节点模式(每个Node节点仅会部署一个Agent)进行日志采集,对比与上述fluentd(每个Pod中部署一个Agent)更加的节约资源,同样在集群规模比较大的情况下表现出的优势越明显。

自动检测:Log-Pilot 能够自动感知宿主机上容器的创建删除事件,进而动态配置容器日志采集配置文件。

句柄保持机制:Log-Pilot 内部会实时跟踪日志采集偏移量,然后维持日志文件信息与偏移量的映射关系,最后定期地持久化到磁盘中。采用偏移量的方式我们可以避免日志采集丢失和重复的问题,同时即使当采集工具宕掉再起来,它可以通过加载持久化在磁盘上的元数据信息,然后从指定的日志偏移位置上继续采集日志。

自动数据打标:Log-Pilot 在采集容器日志的时候,同时也会收集容器的元数据信息,包括容器的名称,容器所属的服务名称以及容器所属的应用名称,同时在 Kubernetes 里面也会采集容器所属的 Pod 信息,包括 Pod 的名称,Pod 所属的 namespace 以及 Pod 所在的节点信息。这样我们排查问题时,就可以很方便地知道这个日志数据是来源于哪个节点上的哪个应用容器。

支持高级特性:Log-Pilot 除了提供前面的几个特性外,还支持一些其他的高级特性,比如低资源消耗,支持自定义 tag,支持多种日志解析格式,支持自定义日志输出 target 以及支持 fluentd 和 filebeat 等插件,最后支持对接到多种日志存储后端。

支持自定义Tag:我们可以在容器的标签或者环境变量里配置 aliyun.logs.$name.tags: k=v 那么在采集日志的时候也会将k=v采集到容器的日志输出中。

比如我们有一种场景,有一个开发环境和测试环境,应用日志都会被采集到统一的一个日志存储后端,假设是一个 ElasticSearch 集群,但是我们在 ElasticSearch 中查询日志的时候又想区分出来,具体某条日志记录到底来源于生产环境,还是测试环境。那么我们就可以通过给测试环境的容器打上 stage=dev 的 tag给生产环境的容器打上 stage=pro 的 tag,Log-Pilot 在采集容器日志的时候,同时会将这些 tag 随容器日志一同采集到日志存储后端中,那么当我们在查询日志的时候,就可以通过 stage=dev 或者 stage=pro 能明确地区分出某条日志是来源于生产环境的应用容器所产生,还是测试环境应用容器所产生的。

另外通过自定义 tag 的方式我们还可以进行日志统计、日志路由和日志过滤。

3 Log-Pilot 环境准备

本案例在K8s集群内部署日志收集系统ELK,所有节点先增加2G内存。

4 创建 Service Account

创建es的Service Account,ServiceAccount在K8s中可用于存储服务的账号信息,用于给运行在Pod里面的进程提供必要的身份证明。

[root@master01 ~]# kubectl create sa es-admin -n kube-system
[root@master01 ~]# kubectl create clusterrolebinding es-admin --clusterrole=cluster-admin --serviceaccount=kube-system:es-admin


当serviceaccout创建时K8s会默认创建对应的secret用于存储账号的token信息
[root@master01 ~]# kubectl get secrets -n kube-system | grep es-admin

5 部署 Elasticsearch 集群

es集群采用StatefulSet控制器部署,StatefulSet本质上是Deployment的一种变体,用于部署有状态服务,它所管理的Pod拥有固定的Pod名称,启停顺序。

[root@master01 logs]# kubectl create -f elasticsearch.yaml


查看StatefulSet信息(缩写:sts)
[root@master01 logs]# kubectl get sts -n kube-system


查看es的Pod
[root@master01 ~]# kubectl get pod -n kube-system -o wide | grep elastic


查看es的svc端口
[root@master01 logs]# kubectl get svc -n kube-system
elasticsearch-0                    1/1     Running       0              22m
elasticsearch-1                    1/1     Running       0              22m
elasticsearch-2                    1/1     Running       0              21m

6 部署 Log-Pilot

为了保证集群每个节点都能够采集到日志信息,Log-Pilot采用DaemonSet控制器创建,DaemonSet可以保证集群的每个节点都存在一个相同的副本。

[root@master01 logs]# kubectl apply -f log-pilot.yaml

[root@master01 ~]# kubectl get pod -n kube-system | grep log-pilot
log-pilot-c4kvk                    1/1     Running       0              2m32s
log-pilot-s78h8                    1/1     Running       0              2m32s
log-pilot-xlclz                    1/1     Running       0              2m32s
log-pilot-xzwps                    1/1     Running       0              2m32s

7 部署 Kibana

kibana提供web页面展示,采用Deploy控制器部署。

[root@master01 logs]# kubectl apply -f kibana.yaml

[root@master01 logs]# kubectl get deploy -n kube-system
kibana    1/1     1            1           82s

[root@master01 logs]# kubectl get ing -n kube-system
NAME     CLASS    HOSTS            ADDRESS        PORTS   AGE
kibana   <none>   www.kibana.com   192.168.0.13   80      4m2s

配置域名解析:C:\Windows\System32\drivers\etc

192.168.0.13 www.kibana.com

访问测试:在访问测试时,通过域名与ingress对外暴露的端口进行访问

查看ingress-nginx暴露的端口
[root@master01 logs]# kubectl get svc -n ingress-nginx

NAME                       TYPE      CLUSTER-IP     EXTERNAL-IP   
ingress-nginx-controller   NodePort  10.111.226.197 <none>        80:31681/TCP,443:31150/TCP   22m

访问测试:注意80对应的是HTTP端口,443对应的是HTTPS端口

部署应用并采集日志

[root@master01 ~]# vim elk.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  namespace: test

spec:
  selector:
    matchLabels:
      app: deploy-nginx

  template:
    metadata:
      labels:
        app: deploy-nginx

    spec:
      containers:
      - name: nginx
        image: nginx:1.18.0
        ports:
        - containerPort: 80

        env:
        - name: aliyun_logs_nginx  #变量名称开头固定为aliyun_logs(变量名称用于创建kibana索引)
          value: "stdout"
        - name: aliyun_logs_nginxlogs  #变量名称开头固定为aliyun_logs(变量名称用于创建kibana索引)
          value: "/var/log/nginx/*"

        volumeMounts:
        - mountPath: /var/log/nginx/
          name: nginxlogs
      volumes:
      - name: nginxlogs
        emptyDir: {}


---
apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
  namespace: test

spec:
  selector:
    app: deploy-nginx
  clusterIP: None
  type: ClusterIP         #service类型              
  ports:
    - port: 80
      targetPort: 80
      
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-tomcat
  namespace: test

spec:
  selector:
    matchLabels:
      app: deploy-tomcat

  template:
    metadata:
      labels:
        app: deploy-tomcat

    spec:
      containers:
      - name: tomcat
        image: tomcat:8.5-jre10-slim
        ports:
        - containerPort: 8080

        env:
        - name: aliyun_logs_tomcat   #变量名称开头固定为aliyun_logs(变量名称用于创建kibana索引)
          value: "stdout"
        - name: aliyun_logs_tomcatlogs  #变量名称开头固定为aliyun_logs(变量名称用于创建kibana索引)
          value: "/usr/local/tomcat/logs/*"

        volumeMounts:
        - mountPath: /usr/local/tomcat/logs
          name: tomcatlogs
      volumes:
      - name: tomcatlogs
        emptyDir: {}

---
apiVersion: v1
kind: Service
metadata:
  name: svc-tomcat
  namespace: test
spec:
  selector:
    app: deploy-tomcat
  clusterIP: None
  type: ClusterIP         #service类型              
  ports:
    - port: 8080
      targetPort: 8080

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-http                   #自定义ingress名称
  namespace: test
  annotations:
    ingressclass.kubernetes.io/is-default-class: "true"
    kubernetes.io/ingress.class: nginx  #注释名称需为nginx(不可省略)

spec:
  rules:                         #定义主机列表
  - host: www.nginx.com          #自定义域名
    http:
      paths:                     
      - pathType: Prefix         #路径类型
        path: "/"                #定义站点路径
        backend:                 #定义后端引用的服务
          service:               #关联service
            name: svc-nginx      #对应上面创建的service名称
            port:
              number: 80          #service端口


  - host: www.tomcat.com          #自定义域名
    http:
      paths:
      - pathType: Prefix         #路径类型            
        path: "/"                #定义站点路径
        backend:                 #定义后端引用的服务
          service:               #关联service
            name: svc-tomcat      #对应上面创建的service名称
            port:
              number: 8080          #service端口



创建Pod
[root@master01 ~]# kubectl create -f elk.yml

添加索引:索引名称对应环境变量名称

0
K8S
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区