iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0
DevOps

k8s 入門學習 30天系列 第 20

IT 鐵人賽 k8s 入門30天 -- day20 k8s Logging Architecture

前言

參考來源: https://kubernetes.io/docs/concepts/cluster-administration/logging/

這個章節會來研究關於 k8s 的 Log 架構

應用程式的 log 能夠幫助理解應用程式的運行狀態

對於容器化的應用程式最基礎的 log 方式就是透過 stream 的方式把 standard output 與 standard error 導出容器之外

然而只有應用程式層面的 log 對於容器狀態的管控還是不夠, 再跑容器時還想紀錄關於容器的失敗跑起來的紀錄

在 k8s 會想紀錄 Pod 的狀態在 Pod 要關閉時, 在結點死掉時

而要這樣做需要讓 log 的生命周期獨立於 nodes, pods, 還有 containers 並且具有額外的儲存空間

這種概念稱作 Cluster-level logging

Cluster-level logging 架構需要具有一個獨立於 Cluster 之外的後端去儲存, 分析, 跟查詢 logs.

k8s 本身不具有原生提供的儲存方案來處理 log 資料

目前有許多第三方 logging 方案有跟 k8s 整合

下面將依序說明這些方案

k8s 基礎的 logging

以下用一個範例來示範

設定 counter-pod.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)"; i=$((i+1)); sleep 1; done']

使用以下指令建立 Pod

kubectl apply -f counter-pod.yaml

察看 Pod 的 log 使用以下指令:

kubectl logs counter

在 node level 的 logging

container 引擎會把容器化應用的 stdout 跟 stderr 透過 stream 的方式導出

舉例來說, Docker Engine 會透過 logger driver 來處理 stdout, stderr 到 JSON format 的 file

在 k8s 中, 如果一個 container 重新啟動, kubelet 預設會保存該 container 的 log. 而如果一個 Pod 被從結點移除, 則所有相關的 Container 以及 log 都會被移除

在 node level 很重要的一個概念是要做 log rotation, 否則 log 將會隨著運行佔據太多空間

k8s 本身並不做這 log rotation 機制, 而是 Deployment 內部在 container 自行去設定各自的 log rotation

當使用一個 CRI container runtime, kubelet 會負責處理 log rotation 還有管理 logging 資料夾結構.

以下有兩個參數可以設定在 kubelet config:

containerLogMaxSize 這個設定用來決定每個 log 檔案大小

containerLogMaxFiles 這個設定用來決定最多幾個檔案

使用 kubelet logs 指令時, kubelet 會直接讀取 log 檔案來顯示

系統元件 log

k8s 的系統元件分為兩種: 跑在容器內與不跑在容器內的

舉例來說:

k8s scheduler 還有 kube-proxy 跑在一個容器內

k8s kubelet 還有 container runtime 不跑在容器內

在有 systemd 的機器上, kubelet 跟 container runtime 會把 log 寫入 journald

假設沒有 systemd, 則kubelet 跟 container runtime 會把 log 寫入 /var/log 下的 .log 黨內

而跑在容器內的元件則固定寫 log 到 /var/log 資料夾下

系統元件使用 klog 來當作 log 工具

系統元件有實作 log rotation 機制

Cluster-level 的 logging 架構

以下有幾種選項是可行的方案

使用一個 node-level logging agent 來跑在每個 node


建立一個 node-level logging agent 在每個 node

這個 logging agent 本身就是負責發送 log 到後端

一般來說, 這個 logging agent 會是一個 container 舉有一個資料架包含所有應用的log

因為這個 agent 要跑在所有 node, 建議使用 DaemonSet 來做佈署

這種做不需要影響到其他的應用

引用 sidecar container 在 application Pod 做 logging

sidecar container 可以有兩種作法:

1 sidecar container 直接串流應用程式的log 到自己的 stdout

使用 sidecar container 來建立 stdout, stderr stream, 就可以利用原本的 kubelet 以及 logging agent 功能

如此一來可以建立兩個 stream 分別不同 format 格式分開

舉例來說:

假設一個 Pod 跑在一個節點內要寫入兩個檔案已兩種不同的格式如下

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
  volumes:
  - name: varlog
    emptyDir: {}

因為有兩個檔案 所以不建議都用 stdout來顯示

這時候可以透過建立兩個 sidecar Container 來做處理

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-1
    image: busybox
    args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-2
    image: busybox
    args: [/bin/sh, -c, 'tail -n+1 -f /var/log/2.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}

可以分別針對不同格式做 log

2 sidecar container 跑一個 logging agent, logging agent 負責把 應用程式的 log 串接回來

當 node-level 的 logging agent 不夠彈性時, 就可以使用一個 sidecar container 來跑 logging agent

直接通過應用推送 log 到一個後端儲存

直接從應用推送 log 到後端


上一篇
IT 鐵人賽 k8s 入門30天 -- day19 k8s Task Coarse Parallel Processing Using a Work Queue
下一篇
IT 鐵人賽 k8s 入門30天 -- day21 k8s Task Deploying PHP Guestbook application with Redis
系列文
k8s 入門學習 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言