日志架構(gòu)
應(yīng)用日志可以讓你了解應(yīng)用內(nèi)部的運(yùn)行狀況。日志對(duì)調(diào)試問(wèn)題和監(jiān)控集群活動(dòng)非常有用。 大部分現(xiàn)代化應(yīng)用都有某種日志記錄機(jī)制。同樣地,容器引擎也被設(shè)計(jì)成支持日志記錄。 針對(duì)容器化應(yīng)用,最簡(jiǎn)單且最廣泛采用的日志記錄方式就是寫入標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤流。
但是,由容器引擎或運(yùn)行時(shí)提供的原生功能通常不足以構(gòu)成完整的日志記錄方案。
例如,如果發(fā)生容器崩潰、Pod 被逐出或節(jié)點(diǎn)宕機(jī)等情況,你可能想訪問(wèn)應(yīng)用日志。
在集群中,日志應(yīng)該具有獨(dú)立的存儲(chǔ),并且其生命周期與節(jié)點(diǎn)、Pod 或容器的生命周期相獨(dú)立。 這個(gè)概念叫集群級(jí)的日志。
集群級(jí)日志架構(gòu)需要一個(gè)獨(dú)立的后端用來(lái)存儲(chǔ)、分析和查詢?nèi)罩尽?Kubernetes 并不為日志數(shù)據(jù)提供原生的存儲(chǔ)解決方案。 相反,有很多現(xiàn)成的日志方案可以集成到 Kubernetes 中。 下面各節(jié)描述如何在節(jié)點(diǎn)上處理和存儲(chǔ)日志。
Pod 和容器日志
Kubernetes 從正在運(yùn)行的 Pod 中捕捉每個(gè)容器的日志。
此示例使用帶有一個(gè)容器的?Pod
?的清單,該容器每秒將文本寫入標(biāo)準(zhǔn)輸出一次。
?debug/counter-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox:1.28
args: [/bin/sh, -c,
'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
要運(yùn)行此 Pod,請(qǐng)執(zhí)行以下命令:
kubectl apply -f https://k8s.io/examples/debug/counter-pod.yaml
輸出為:
pod/counter created
要獲取這些日志,請(qǐng)執(zhí)行以下?kubectl logs
?命令:
kubectl logs counter
輸出類似于:
0: Fri Apr 1 11:42:23 UTC 2022
1: Fri Apr 1 11:42:24 UTC 2022
2: Fri Apr 1 11:42:25 UTC 2022
你可以使用?kubectl logs --previous
?從容器的先前實(shí)例中檢索日志。 如果你的 Pod 有多個(gè)容器,請(qǐng)如下通過(guò)將容器名稱追加到該命令并使用?-c
?標(biāo)志來(lái)指定要訪問(wèn)哪個(gè)容器的日志:
kubectl logs counter -c count
節(jié)點(diǎn)的容器日志處理方式
容器運(yùn)行時(shí)對(duì)寫入到容器化應(yīng)用程序的?stdout
?和?stderr
?流的所有輸出進(jìn)行處理和轉(zhuǎn)發(fā)。 不同的容器運(yùn)行時(shí)以不同的方式實(shí)現(xiàn)這一點(diǎn);不過(guò)它們與 kubelet 的集成都被標(biāo)準(zhǔn)化為?CRI 日志格式。
默認(rèn)情況下,如果容器重新啟動(dòng),kubelet 會(huì)保留一個(gè)終止的容器及其日志。 如果一個(gè) Pod 被逐出節(jié)點(diǎn),所對(duì)應(yīng)的所有容器及其日志也會(huì)被逐出。
kubelet 通過(guò) Kubernetes API 的特殊功能將日志提供給客戶端訪問(wèn)。 訪問(wèn)這個(gè)日志的常用方法是運(yùn)行?kubectl logs
。
日志輪轉(zhuǎn)
特性狀態(tài):?Kubernetes v1.21 [stable]
你可以配置 kubelet 令其自動(dòng)輪轉(zhuǎn)日志。
如果配置輪轉(zhuǎn),kubelet 負(fù)責(zé)輪轉(zhuǎn)容器日志并管理日志目錄結(jié)構(gòu)。 kubelet(使用 CRI)將此信息發(fā)送到容器運(yùn)行時(shí),而運(yùn)行時(shí)則將容器日志寫到給定位置。
你可以使用?kubelet 配置文件配置兩個(gè) kubelet?配置選項(xiàng)、?containerLogMaxSize?和?containerLogMaxFiles。 這些設(shè)置分別允許你分別配置每個(gè)日志文件大小的最大值和每個(gè)容器允許的最大文件數(shù)。
當(dāng)類似于基本日志示例一樣運(yùn)行?kubectl logs?時(shí), 節(jié)點(diǎn)上的 kubelet 會(huì)處理請(qǐng)求并直接從日志文件讀取。kubelet 將返回該日志文件的內(nèi)容。
說(shuō)明:
只有最新的日志文件的內(nèi)容可以通過(guò)?kubectl logs
?獲得。
例如,如果 Pod 寫入 40 MiB 的日志,并且 kubelet 在 10 MiB 之后輪轉(zhuǎn)日志, 則運(yùn)行?kubectl logs
?將最多返回 10 MiB 的數(shù)據(jù)。
系統(tǒng)組件日志
系統(tǒng)組件有兩種類型:通常在容器中運(yùn)行的組件和直接參與容器運(yùn)行的組件。例如:
- kubelet 和容器運(yùn)行時(shí)不在容器中運(yùn)行。kubelet 運(yùn)行你的容器 (一起按?Pod?分組)
- Kubernetes 調(diào)度器、控制器管理器和 API 服務(wù)器在 Pod 中運(yùn)行 (通常是靜態(tài) Pod。 etcd 組件在控制平面中運(yùn)行,最常見(jiàn)的也是作為靜態(tài) Pod。 如果你的集群使用 kube-proxy,則通常將其作為?DaemonSet?運(yùn)行。
日志位置
kubelet 和容器運(yùn)行時(shí)寫入日志的方式取決于節(jié)點(diǎn)使用的操作系統(tǒng):
- Linux
- Windows
在使用 systemd 的 Linux 節(jié)點(diǎn)上,kubelet 和容器運(yùn)行時(shí)默認(rèn)寫入 journald。 你要使用?journalctl?來(lái)閱讀 systemd 日志;例如:journalctl -u kubelet。
如果 systemd 不存在,kubelet 和容器運(yùn)行時(shí)將寫入到?/var/log?目錄中的?.log?文件。 如果你想將日志寫入其他地方,你可以通過(guò)輔助工具?kube-log-runner?間接運(yùn)行 kubelet, 并使用該工具將 kubelet 日志重定向到你所選擇的目錄。
kubelet 始終指示你的容器運(yùn)行時(shí)將日志寫入?/var/log/pods?中的目錄。
有關(guān)?kube-log-runner?的更多信息,請(qǐng)閱讀系統(tǒng)日志。
對(duì)于在 Pod 中運(yùn)行的 Kubernetes 集群組件,其日志會(huì)寫入?/var/log
?目錄中的文件, 相當(dāng)于繞過(guò)默認(rèn)的日志機(jī)制(組件不會(huì)寫入 systemd 日志)。 你可以使用 Kubernetes 的存儲(chǔ)機(jī)制將持久存儲(chǔ)映射到運(yùn)行該組件的容器中。
同樣,你可以使用 Kubernetes 的存儲(chǔ)機(jī)制將持久存儲(chǔ)映射到運(yùn)行該組件的容器中。
說(shuō)明:
如果你部署 Kubernetes 集群組件(例如調(diào)度器)以將日志記錄到從父節(jié)點(diǎn)共享的卷中, 則需要考慮并確保這些日志被輪轉(zhuǎn)。?Kubernetes 不管理這種日志輪轉(zhuǎn)。
你的操作系統(tǒng)可能會(huì)自動(dòng)實(shí)現(xiàn)一些日志輪轉(zhuǎn)。例如,如果你將目錄?/var/log
?共享到一個(gè)組件的靜態(tài) Pod 中, 則節(jié)點(diǎn)級(jí)日志輪轉(zhuǎn)會(huì)將該目錄中的文件視同為 Kubernetes 之外的組件所寫入的文件。
一些部署工具會(huì)考慮日志輪轉(zhuǎn)并將其自動(dòng)化;而其他一些工具會(huì)將此留給你來(lái)處理。
集群級(jí)日志架構(gòu)
雖然 Kubernetes 沒(méi)有為集群級(jí)日志記錄提供原生的解決方案,但你可以考慮幾種常見(jiàn)的方法。 以下是一些選項(xiàng):
- 使用在每個(gè)節(jié)點(diǎn)上運(yùn)行的節(jié)點(diǎn)級(jí)日志記錄代理。
- 在應(yīng)用程序的 Pod 中,包含專門記錄日志的邊車(Sidecar)容器。
- 將日志直接從應(yīng)用程序中推送到日志記錄后端。
使用節(jié)點(diǎn)級(jí)日志代理
你可以通過(guò)在每個(gè)節(jié)點(diǎn)上使用節(jié)點(diǎn)級(jí)的日志記錄代理來(lái)實(shí)現(xiàn)集群級(jí)日志記錄。 日志記錄代理是一種用于暴露日志或?qū)⑷罩就扑偷胶蠖说膶S霉ぞ摺?通常,日志記錄代理程序是一個(gè)容器,它可以訪問(wèn)包含該節(jié)點(diǎn)上所有應(yīng)用程序容器的日志文件的目錄。
由于日志記錄代理必須在每個(gè)節(jié)點(diǎn)上運(yùn)行,推薦以?DaemonSet
?的形式運(yùn)行該代理。
節(jié)點(diǎn)級(jí)日志在每個(gè)節(jié)點(diǎn)上僅創(chuàng)建一個(gè)代理,不需要對(duì)節(jié)點(diǎn)上的應(yīng)用做修改。
容器向標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出寫出數(shù)據(jù),但在格式上并不統(tǒng)一。 節(jié)點(diǎn)級(jí)代理收集這些日志并將其進(jìn)行轉(zhuǎn)發(fā)以完成匯總。
使用邊車容器運(yùn)行日志代理
你可以通過(guò)以下方式之一使用邊車(Sidecar)容器:
- 邊車容器將應(yīng)用程序日志傳送到自己的標(biāo)準(zhǔn)輸出。
- 邊車容器運(yùn)行一個(gè)日志代理,配置該日志代理以便從應(yīng)用容器收集日志。
傳輸數(shù)據(jù)流的邊車容器
利用邊車容器,寫入到自己的?stdout
?和?stderr
?傳輸流, 你就可以利用每個(gè)節(jié)點(diǎn)上的 kubelet 和日志代理來(lái)處理日志。 邊車容器從文件、套接字或 journald 讀取日志。 每個(gè)邊車容器向自己的?stdout
?和?stderr
?流中輸出日志。
這種方法允許你將日志流從應(yīng)用程序的不同部分分離開(kāi),其中一些可能缺乏對(duì)寫入?stdout
?或?stderr
?的支持。重定向日志背后的邏輯是最小的,因此它的開(kāi)銷不大。 另外,因?yàn)?stdout
?和?stderr
?由 kubelet 處理,所以你可以使用內(nèi)置的工具?kubectl logs
。
例如,某 Pod 中運(yùn)行一個(gè)容器,且該容器使用兩個(gè)不同的格式寫入到兩個(gè)不同的日志文件。 下面是這個(gè) Pod 的清單:
?admin/logging/two-files-counter-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox:1.28
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: {}
不建議在同一個(gè)日志流中寫入不同格式的日志條目,即使你成功地將其重定向到容器的?stdout
?流。 相反,你可以創(chuàng)建兩個(gè)邊車容器。每個(gè)邊車容器可以從共享卷跟蹤特定的日志文件, 并將文件內(nèi)容重定向到各自的?stdout
?流。
下面是運(yùn)行兩個(gè)邊車容器的 Pod 的清單:
?admin/logging/two-files-counter-pod-streaming-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox:1.28
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:1.28
args: [/bin/sh, -c, 'tail -n+1 -F /var/log/1.log']
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-2
image: busybox:1.28
args: [/bin/sh, -c, 'tail -n+1 -F /var/log/2.log']
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
現(xiàn)在當(dāng)你運(yùn)行這個(gè) Pod 時(shí),你可以運(yùn)行如下命令分別訪問(wèn)每個(gè)日志流:
kubectl logs counter count-log-1
輸出類似于:
0: Fri Apr 1 11:42:26 UTC 2022
1: Fri Apr 1 11:42:27 UTC 2022
2: Fri Apr 1 11:42:28 UTC 2022
...
kubectl logs counter count-log-2
輸出類似于:
Fri Apr 1 11:42:29 UTC 2022 INFO 0
Fri Apr 1 11:42:30 UTC 2022 INFO 0
Fri Apr 1 11:42:31 UTC 2022 INFO 0
...
如果你在集群中安裝了節(jié)點(diǎn)級(jí)代理,由代理自動(dòng)獲取上述日志流,而無(wú)需任何進(jìn)一步的配置。 如果你愿意,你可以將代理配置為根據(jù)源容器解析日志行。
即使對(duì)于 CPU 和內(nèi)存使用率較低的 Pod(CPU 為幾毫核,內(nèi)存為幾兆字節(jié)),將日志寫入一個(gè)文件, 將這些日志流寫到?stdout
?也有可能使節(jié)點(diǎn)所需的存儲(chǔ)量翻倍。 如果你有一個(gè)寫入特定文件的應(yīng)用程序,則建議將?/dev/stdout
?設(shè)置為目標(biāo)文件,而不是采用流式邊車容器方法。
邊車容器還可用于輪轉(zhuǎn)應(yīng)用程序本身無(wú)法輪轉(zhuǎn)的日志文件。 這種方法的一個(gè)例子是定期運(yùn)行?logrotate
?的小容器。 但是,直接使用?stdout
?和?stderr
?更直接,而將輪轉(zhuǎn)和保留策略留給 kubelet。
集群中安裝的節(jié)點(diǎn)級(jí)代理會(huì)自動(dòng)獲取這些日志流,而無(wú)需進(jìn)一步配置。 如果你愿意,你也可以配置代理程序來(lái)解析源容器的日志行。
注意,盡管 CPU 和內(nèi)存使用率都很低(以多個(gè) CPU 毫核指標(biāo)排序或者按內(nèi)存的兆字節(jié)排序), 向文件寫日志然后輸出到?stdout
?流仍然會(huì)成倍地增加磁盤使用率。 如果你的應(yīng)用向單一文件寫日志,通常最好設(shè)置?/dev/stdout
?作為目標(biāo)路徑, 而不是使用流式的邊車容器方式。
如果應(yīng)用程序本身不能輪轉(zhuǎn)日志文件,則可以通過(guò)邊車容器實(shí)現(xiàn)。 這種方式的一個(gè)例子是運(yùn)行一個(gè)小的、定期輪轉(zhuǎn)日志的容器。 然而,還是推薦直接使用?stdout
?和?stderr
,將日志的輪轉(zhuǎn)和保留策略交給 kubelet。
具有日志代理功能的邊車容器
如果節(jié)點(diǎn)級(jí)日志記錄代理程序?qū)τ谀愕膱?chǎng)景來(lái)說(shuō)不夠靈活, 你可以創(chuàng)建一個(gè)帶有單獨(dú)日志記錄代理的邊車容器,將代理程序?qū)iT配置為與你的應(yīng)用程序一起運(yùn)行。
說(shuō)明:
在邊車容器中使用日志代理會(huì)帶來(lái)嚴(yán)重的資源損耗。 此外,你不能使用?kubectl logs
?訪問(wèn)日志,因?yàn)槿罩静](méi)有被 kubelet 管理。
下面是兩個(gè)配置文件,可以用來(lái)實(shí)現(xiàn)一個(gè)帶日志代理的邊車容器。 第一個(gè)文件包含用來(lái)配置 fluentd 的?ConfigMap。
admin/logging/fluentd-sidecar-config.yaml?
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentd-config
data:
fluentd.conf: |
<source>
type tail
format none
path /var/log/1.log
pos_file /var/log/1.log.pos
tag count.format1
</source>
<source>
type tail
format none
path /var/log/2.log
pos_file /var/log/2.log.pos
tag count.format2
</source>
<match **>
type google_cloud
</match>
說(shuō)明:
你可以將此示例配置中的 fluentd 替換為其他日志代理,從應(yīng)用容器內(nèi)的其他來(lái)源讀取數(shù)據(jù)。
第二個(gè)清單描述了一個(gè)運(yùn)行 fluentd 邊車容器的 Pod。 該 Pod 掛載一個(gè)卷,flutend 可以從這個(gè)卷上揀選其配置數(shù)據(jù)。
?admin/logging/two-files-counter-pod-agent-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox:1.28
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-agent
image: registry.k8s.io/fluentd-gcp:1.30
env:
- name: FLUENTD_ARGS
value: -c /etc/fluentd-config/fluentd.conf
volumeMounts:
- name: varlog
mountPath: /var/log
- name: config-volume
mountPath: /etc/fluentd-config
volumes:
- name: varlog
emptyDir: {}
- name: config-volume
configMap:
name: fluentd-config
從應(yīng)用中直接暴露日志目錄
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-539049.html
從各個(gè)應(yīng)用中直接暴露和推送日志數(shù)據(jù)的集群日志機(jī)制已超出 Kubernetes 的范圍。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-539049.html
到了這里,關(guān)于Kubernetes —Pod 和容器日志的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!