Linux中國

Kubernetes 集群日誌基礎

伺服器和應用程序日誌記錄是開發人員、運維人員和安全團隊了解應用程序在其生產環境中運行狀態的重要工具。

日誌記錄使運維人員能夠確定應用程序和所需組件是否運行平穩,並檢測是否發生了異常情況,以便他們能夠對這種情況做出反應。

對於開發人員,日誌記錄提供了在開發期間和之後對代碼進行故障排除的可見性。在生產環境中,開發人員通常依賴於沒有調試工具的日誌記錄工具。在加上系統的日誌記錄,開發人員可以與運維人員攜手合作,有效地解決問題。

日誌記錄工具最重要的受益者是安全團隊,尤其是在雲原生的環境中。能夠從應用程序和系統日誌中收集信息使得安全團隊能夠分析來自身份驗證、應用程序訪問惡意軟體活動的數據,並在需要時進行響應。

Kubernetes 是領先的容器平台,越來越多的應用程序通過 Kubernetes 部署到生產環境。我相信了解 Kubernetes 的日誌架構是一項非常重要的工作,每個開發、運維和安全團隊都需要認真對待。

在本文中,我將討論 Kubernetes 中不同容器日誌記錄模式的工作原理。

系統日誌記錄和應用日誌記錄

在深入研究 Kubernetes 日誌記錄架構之前,我想探索不同的日誌記錄方法以及這兩種功能如何成為 Kubernetes 日誌記錄的關鍵特性。

有兩種類型的系統組件:在容器中運行的組件和不在容器中運行的組件。例如:

  • Kubernetes 調度者和 kube-proxy 運行在容器中。
  • kubelet 和容器運行時不在容器中運行。

與容器日誌類似,系統容器日誌存儲在 /var/log 目錄中,你應該定期輪換它們。

在這裡,我研究的是容器日誌記錄。首先,我看一下集群級別的日誌記錄以及為什麼它對集群運維人員很重要。集群日誌提供有關集群如何執行的信息。諸如為什麼 吊艙 Pod 被下線或節點死亡之類的信息。集群日誌記錄還可以捕獲諸如集群和應用程序訪問以及應用程序如何利用計算資源等信息。總體而言,集群日誌記錄工具為集群運維人員提供操作集群和安全有用的信息。

捕獲容器日誌的另一種方法是通過應用程序的本機日誌記錄工具。現代應用程序設計很可能具有日誌記錄機制,可幫助開發人員通過標準輸出 (stdout) 和錯誤流 (stderr) 解決應用程序性能問題。

為了擁有有效的日誌記錄工具,Kubernetes 實現需要應用程序和系統日誌記錄組件。

Kubernetes 容器日誌的 3 種類型

如今,在大多數的 Kubernetes 實現中,你可以看到三種主要的集群級日誌記錄方法。

  1. 節點級日誌代理
  2. 用於日誌記錄的 挎斗 Sidecar 容器應用程序
  3. 將應用程序日誌直接暴露給日誌後端

節點級日誌代理

我想考慮節點級日誌代理。你通常使用 DaemonSet 作為部署策略來實現這些,以便在所有 Kubernetes 節點中部署一個吊艙(充當日誌代理)。然後,該日誌代理被配置為從所有 Kubernetes 節點讀取日誌。你通常將代理配置為讀取節點 /var/logs 目錄捕獲 stdout/stderr 流並將其發送到日誌記錄後端存儲。

下圖顯示了在所有節點中作為代理運行的節點級日誌記錄。

![Node-level logging agent](/data/attachment/album/202201/02/105823jz5e65z3cb6e6iv0.png "Node-level logging agent")

以使用 fluentd 方法為例設置節點級日誌記錄,你需要執行以下操作:

1、首先,你需要創建一個名為 fluentdd 的服務賬戶。Fluentd 吊艙使用此服務賬戶來訪問 Kubernetes API,你需要在日誌命名空間中使用標籤 app: fluentd 創建它們:

#fluentd-SA.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd
  namespace: logging
  labels:
    app: fluentd  

你可以在此 倉庫 中查看完整示例。

2、接著,你需要創建一個名稱為 fluentd-configmap 的 ConfigMap。這為 fluentd daemonset 提供了一個配置文件,其中包含所有必需的屬性。

#fluentd-daemonset.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: logging
  labels:
    app: fluentd
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    matchLabels:
      app: fluentd
      kubernetes.io/cluster-service: "true"
  template:
    metadata:
      labels:
        app: fluentd
        kubernetes.io/cluster-service: "true"
    spec:
      serviceAccount: fluentd
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-elasticsearch7-1.0
        env:
          - name: FLUENT_ELASTICSEARCH_HOST
            value: "elasticsearch.logging.svc.cluster.local"
          - name: FLUENT_ELASTICSEARCH_PORT
            value: "9200"
          - name: FLUENT_ELASTICSEARCH_SCHEME
            value: "http"
          - name: FLUENT_ELASTICSEARCH_USER
            value: "elastic"
          - name: FLUENT_ELASTICSEARCH_PASSWORD
            valueFrom:
              secretKeyRef:
                name: efk-pw-elastic
                key: password
          - name: FLUENT_ELASTICSEARCH_SED_DISABLE
            value: "true"
        resources:
          limits:
            memory: 512Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: fluentconfig
          mountPath: /fluentd/etc/fluent.conf
          subPath: fluent.conf
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: fluentconfig
        configMap:
          name: fluentdconf

你可以在此 倉庫 中查看完整示例。

現在,我們來看看如何將 fluentd daemonset 部署為日誌代理的代碼。

#fluentd-daemonset.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: logging
  labels:
    app: fluentd
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    matchLabels:
      app: fluentd
      kubernetes.io/cluster-service: "true"
  template:
    metadata:
      labels:
        app: fluentd
        kubernetes.io/cluster-service: "true"
    spec:
      serviceAccount: fluentd
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-elasticsearch7-1.0
        env:
          - name: FLUENT_ELASTICSEARCH_HOST
            value: "elasticsearch.logging.svc.cluster.local"
          - name: FLUENT_ELASTICSEARCH_PORT
            value: "9200"
          - name: FLUENT_ELASTICSEARCH_SCHEME
            value: "http"
          - name: FLUENT_ELASTICSEARCH_USER
            value: "elastic"
          - name: FLUENT_ELASTICSEARCH_PASSWORD
            valueFrom:
              secretKeyRef:
                name: efk-pw-elastic
                key: password
          - name: FLUENT_ELASTICSEARCH_SED_DISABLE
            value: "true"
        resources:
          limits:
            memory: 512Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: fluentconfig
          mountPath: /fluentd/etc/fluent.conf
          subPath: fluent.conf
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: fluentconfig
        configMap:
          name: fluentdconf

將這些放在一起執行:

kubectl apply -f fluentd-SA.yaml 
              -f fluentd-configmap.yaml 
              -f fluentd-daemonset.yaml

用於日誌記錄的挎斗容器應用程序

另一種方法是使用帶有日誌代理的專用挎斗容器。容器最常見的實現是使用 Fluentd 作為日誌收集器。在企業部署中(你無需擔心一點計算資源開銷),使用 fluentd(或類似)實現的挎斗容器提供了集群級日誌記錄的靈活性。這是因為你可以根據需要捕獲的日誌類型、頻率和其它可能的調整來調整和配置收集器代理。

下圖展示了作為日誌代理的挎斗容器。

![Sidecar container as logging agent](/data/attachment/album/202201/02/105823jgueyuw38e3oawua.png "Sidecar container as logging agent")

例如,一個吊艙運行單個容器,容器使用兩種不同的格式寫入兩個不同的日誌文件。吊艙的配置文件如下:

#log-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox
    args:
   - /bin/sh
    - -c
    - >
     i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log
    image: busybox
    args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}

把它們放在一起,你可以運行這個吊艙:

$ kubectl apply -f log-sidecar.yaml

要驗證挎斗容器是否用作日誌代理,你可以執行以下操作:

$ kubectl logs counter count-log

預期的輸出如下所示:

$ kubectl logs counter count-log-1

Thu 04 Nov 2021 09:23:21 NZDT
Thu 04 Nov 2021 09:23:22 NZDT
Thu 04 Nov 2021 09:23:23 NZDT
Thu 04 Nov 2021 09:23:24 NZDT

將應用程序日誌直接暴露給日誌後端

第三種方法(在我看來)是 Kubernetes 容器和應用程序日誌最靈活的日誌記錄解決方案,是將日誌直接推送到日誌記錄後端解決方案。儘管此模式不依賴於原生 Kubernetes 功能,但它提供了大多數企業需要的靈活性,例如:

  1. 擴展對網路協議和輸出格式的更廣泛支持。
  2. 提供負載均衡能力並提高性能。
  3. 可配置為通過上游聚合接受複雜的日誌記錄要求。

因為這第三種方法通過直接從每個應用程序推送日誌來依賴非 Kubernetes 功能,所以它超出了 Kubernetes 的範圍。

結論

Kubernetes 日誌記錄工具是企業部署 Kubernetes 集群的一個非常重要的組件。我討論了三種可能的可用模式。你需要找到適合你需求的模式。

如上所述,使用 daemonset 的節點級日誌記錄是最容易使用的部署模式,但它也有一些限制,可能不適合你的組織的需要。另一方面,挎斗 模式提供了靈活性和自定義,允許你自定義要捕獲的日誌類型,但是會提高計算機的資源開銷。最後,將應用程序日誌直接暴露給後端日誌工具是另一種允許進一步定製的誘人方法。

選擇在你,你只需要找到適合你組織要求的方法。

via: https://opensource.com/article/21/11/cluster-logging-kubernetes

作者:Mike Calizo 選題:lujun9972 譯者:perfiffer 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國