背景與問題
在容器化環(huán)境中,日志收集和查看是運(yùn)維工程師日常工作中最頻繁的操作之一。很多運(yùn)維工程師習(xí)慣性地進(jìn)入容器內(nèi)部使用 tail -f 命令查看日志,這種方式在小規(guī)模環(huán)境下勉強(qiáng)可用,但當(dāng)容器數(shù)量增加、工作負(fù)載增加時(shí),這種方式的效率低下且存在諸多問題。
本文系統(tǒng)講解 Kubernetes 環(huán)境下容器日志的正確查看方式、分布式日志收集架構(gòu)、以及常見日志問題的排障方法。本文基于 containerd 1.7.x 和 Kubernetes 1.29 環(huán)境,所有命令經(jīng)過實(shí)際驗(yàn)證。
一、容器日志的基礎(chǔ)機(jī)制
1.1 容器日志的存儲(chǔ)位置
在 containerd 環(huán)境中,容器日志默認(rèn)存儲(chǔ)在節(jié)點(diǎn)上的/var/log/pods/
查看容器日志文件:
# 查看節(jié)點(diǎn)的容器日志目錄 ls -la /var/log/pods/ # 查看特定 Pod 的日志 ls -la /var/log/pods/default_nginx-deployment-6d9f4c8b7-x2m9n_abc123/ # 查看特定容器的日志文件 ls -la /var/log/pods/default_nginx-deployment-6d9f4c8b7-x2m9n_abc123/nginx/ # 查看日志內(nèi)容 cat /var/log/pods/default_nginx-deployment-6d9f4c8b7-x2m9n_abc123/nginx/0.log
容器日志文件的命名規(guī)則:
1.2 kubelet 的日志處理
kubelet 負(fù)責(zé)將容器的主進(jìn)程 stdout 和 stderr 重定向到日志文件。當(dāng)容器主進(jìn)程向 stdout/stderr 寫入時(shí),Docker/containerd 會(huì)將這些輸出捕獲并寫入日志文件。
kubelet 還負(fù)責(zé)日志輪轉(zhuǎn),當(dāng)日志文件達(dá)到一定大小后會(huì)進(jìn)行輪轉(zhuǎn):
# 查看日志輪轉(zhuǎn)配置 cat /var/lib/kubelet/config.yaml | grep -A 5"logging" # 默認(rèn)配置 # containerLogMaxSize: 10Mi # containerLogMaxFiles: 5
1.3 containerd-shim 的作用
containerd-shim 是容器運(yùn)行時(shí)的一個(gè)中間進(jìn)程,它的作用是:
作為容器的父進(jìn)程,處理容器的退出信號(hào)。
保持容器在 kubelet 重啟后仍然運(yùn)行。
管理容器的 stdin/stdout 流。
查看 containerd-shim 進(jìn)程:
# 查看所有 containerd-shim 進(jìn)程 ps aux | grep containerd-shim # 查看 containerd-shim 管理的容器 sudo ctr -n k8s.io containers list
二、kubectl logs 的正確使用方式
2.1 基本用法
kubectl logs 是查看容器日志最常用的方式:
# 查看當(dāng)前最新的日志 kubectl logs nginx-deployment-6d9f4c8b7-x2m9n # 查看上一個(gè) terminated 容器的日志(容器重啟后) kubectl logs nginx-deployment-6d9f4c8b7-x2m9n --previous # 持續(xù)跟蹤日志(類似 tail -f) kubectl logs -f nginx-deployment-6d9f4c8b7-x2m9n # 查看最近 100 行日志 kubectl logs nginx-deployment-6d9f4c8b7-x2m9n --tail=100 # 查看指定時(shí)間范圍內(nèi)的日志 kubectl logs nginx-deployment-6d9f4c8b7-x2m9n --since=1h kubectl logs nginx-deployment-6d9f4c8b7-x2m9n --since-time="2026-01-01T0000Z"
2.2 多容器 Pod 的日志查看
當(dāng) Pod 包含多個(gè)容器時(shí),必須指定容器名稱:
# 查看多容器 Pod 中特定容器的日志 kubectl logs-c # 持續(xù)跟蹤特定容器的日志 kubectl logs -f -c # 同時(shí)查看所有容器的日志 kubectl logs --all-containers=true # 使用標(biāo)簽選擇器查看多個(gè) Pod 的日志 kubectl logs -l app=nginx --tail=100
2.3 常見錯(cuò)誤與解決方案
錯(cuò)誤一:Pod 未找到
kubectl logs nginx Error from server (NotFound): pods"nginx"not found # 解決:指定正確的命名空間 kubectl logs nginx -n production kubectl logs nginx -n production --all-namespaces
錯(cuò)誤二:容器未找到
kubectl logs multi-container-pod Error from server (BadRequest): a container name must be specifiedforpod multi-container-pod, choose one of: [nginx sidecar] # 解決:使用 -c 參數(shù)指定容器名 kubectl logs multi-container-pod -c nginx kubectl logs multi-container-pod -c sidecar
錯(cuò)誤三:Pod 處于 Terminating 狀態(tài)
kubectl logs nginx-deployment-6d9f4c8b7-x2m9n Error from server (NotFound): pods"nginx-deployment-6d9f4c8b7-x2m9n"not found # 解決:使用 --previous 查看上一個(gè)容器的日志 kubectl logs nginx-deployment-6d9f4c8b7-x2m9n --previous # 如果 Pod 已經(jīng)徹底刪除,查看節(jié)點(diǎn)上的日志文件 ssh"cat /var/log/pods/ / /0.log"
三、日志過濾與格式化
3.1 日志級(jí)別過濾
大多數(shù)應(yīng)用使用結(jié)構(gòu)化日志,支持不同的日志級(jí)別(DEBUG、INFO、WARN、ERROR):
# 查看 ERROR 級(jí)別的日志
kubectl logs nginx-deployment-6d9f4c8b7-x2m9n | grep ERROR
# 查看最近 1 小時(shí)的 ERROR 日志
kubectl logs nginx-deployment-6d9f4c8b7-x2m9n --since=1h | grep -E"ERROR|FATAL|CRITICAL"
# 統(tǒng)計(jì)各級(jí)別日志數(shù)量
kubectl logs nginx-deployment-6d9f4c8b7-x2m9n --since=24h | awk'{print $5}'| sort | uniq -c
3.2 時(shí)間戳過濾
# 提取特定時(shí)間范圍的日志 kubectl logs nginx-deployment-6d9f4c8b7-x2m9n --since=1h | awk -F'[] []''$2 " " $3 >= "2026-01-15 1000" && $2 " " $3 <= "2026-01-15 1100"' # 使用 sed 進(jìn)行時(shí)間范圍過濾 kubectl logs nginx-deployment-6d9f4c8b7-x2m9n | ? sed -n?'/2026-01-15 1000/,/2026-01-15 1100/p'
3.3 JSON 格式日志解析
如果應(yīng)用輸出 JSON 格式的日志,可以使用 jq 進(jìn)行解析:
# 安裝 jq(如果尚未安裝) kubectlexec-it-- apk add jq # 解析 JSON 日志 kubectl logs | jq -r'.level, .message' # 統(tǒng)計(jì)各錯(cuò)誤類型的數(shù)量 kubectl logs --since=24h | jq -r'.error // "no-error"'| sort | uniq -c | sort -rn # 提取特定字段 kubectl logs | jq -r'select(.level == "error") | .timestamp, .message'
四、節(jié)點(diǎn)級(jí)別的日志訪問
4.1 直接訪問日志文件
當(dāng) kubectl 無法使用時(shí),可以直接訪問節(jié)點(diǎn)上的日志文件:
# 連接到節(jié)點(diǎn) ssh# 查看 Pod 日志目錄 ls -la /var/log/pods/ # 使用 journalctl 查看容器日志 sudo journalctl -u kubelet --since"1 hour ago"| grep # 使用 ctr 查看容器信息 sudo ctr -n k8s.io containers list | grep sudo ctr -n k8s.io tasks logs
4.2 containerd 日志
containerd 自身的日志通常由 systemd 管理:
# 查看 containerd 日志 sudo journalctl -u containerd --since"1 hour ago"| grep -E"error|warn"--color=never # 查看 containerd 服務(wù)狀態(tài) sudo systemctl status containerd # 查看 containerd 配置文件 cat /etc/containerd/config.toml | grep -E"sandbox|log_level"
4.3 kubelet 日志
kubelet 日志對(duì)于診斷節(jié)點(diǎn)級(jí)別的問題非常重要:
# 查看 kubelet 日志 sudo journalctl -u kubelet --since"30 minutes ago"--no-pager # 查看 kubelet 日志中的錯(cuò)誤 sudo journalctl -u kubelet --since"1 hour ago"| grep -i error # 實(shí)時(shí)跟蹤 kubelet 日志 sudo journalctl -u kubelet -f
五、分布式日志收集架構(gòu)
5.1 EFK 日志架構(gòu)
EFK(Elasticsearch + Fluentd + Kibana)是 Kubernetes 環(huán)境中最常用的日志解決方案之一。
架構(gòu)組件:
Fluentd/Fluent Bit:日志收集器,運(yùn)行在每個(gè)節(jié)點(diǎn)上,負(fù)責(zé)收集容器日志并轉(zhuǎn)發(fā)到 Elasticsearch。
Elasticsearch:分布式搜索引擎,存儲(chǔ)和索引日志數(shù)據(jù)。
Kibana:可視化界面,用于查詢和分析日志。
5.1.1 Fluentd/Fluent Bit 部署
# DaemonSet 方式部署 Fluent Bit apiVersion:apps/v1 kind:DaemonSet metadata: name:fluent-bit namespace:kube-system spec: selector: matchLabels: k8s-app:fluent-bit template: metadata: labels: k8s-app:fluent-bit spec: containers: -name:fluent-bit image:fluent/fluent-bit:3.0.0 ports: -name:http containerPort:2020 volumeMounts: -name:varlog mountPath:/var/log readOnly:true -name:varlibdockercontainers mountPath:/var/lib/docker/containers readOnly:true -name:fluent-bit-config mountPath:/fluent-bit/etc volumes: -name:varlog hostPath: path:/var/log -name:varlibdockercontainers hostPath: path:/var/lib/docker/containers -name:fluent-bit-config configMap: name:fluent-bit-config --- apiVersion:v1 kind:ConfigMap metadata: name:fluent-bit-config namespace:kube-system data: fluent-bit.conf:| [SERVICE] Flush 5 Log_Level info Daemon off Parsers_File parsers.conf [INPUT] Name tail Path /var/log/containers/*.log Parser docker Tag kube.containers.* Refresh_Interval5 [OUTPUT] Name es Matchkube.containers.* Host elasticsearch.logging.svc Port 9200 Indexkubernetescontainers Type flb_type Retry_Limit 2 parsers.conf:| [PARSER] Name docker Format json Time_Key time Time_Format %Y-%m-%dT%H:%M:%S.%L
5.1.2 Fluent Bit 配置詳解
Fluent Bit 的核心配置包括:
INPUT:定義日志來源,tail 插件讀取容器日志文件。
FILTER:處理和轉(zhuǎn)換日志數(shù)據(jù),添加元信息。
OUTPUT:定義日志輸出目標(biāo)。
BUFFER:緩沖配置,指定內(nèi)存或磁盤緩沖策略。
# 添加 Kubernetes 元信息的 Filter [FILTER] Name kubernetes Match kube.containers.* Kube_URL https://kubernetes.default.svc:443 Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token Kube_Tag_Prefix kube.containers.var.log.containers. Merge_Log On Keep_Log Off K8S-Logging.ParserOn K8S-Logging.ExcludeOn
5.2 Loki 日志架構(gòu)
Loki 是 Grafana 實(shí)驗(yàn)室開發(fā)的日志聚合系統(tǒng),與 Prometheus 架構(gòu)類似,具有資源占用低、易于部署的優(yōu)點(diǎn)。
# Loki 部署示例
apiVersion:apps/v1
kind:Deployment
metadata:
name:loki
namespace:monitoring
spec:
replicas:2
selector:
matchLabels:
app:loki
template:
metadata:
labels:
app:loki
spec:
containers:
-name:loki
image:grafana/loki:3.0.0
ports:
-name:http
containerPort:3100
args:
--config.file=/etc/loki/local-config.yaml
--target=all
resources:
limits:
cpu:"2"
memory:4Gi
requests:
cpu:"500m"
memory:1Gi
---
# Promtail 配置(收集 Kubernetes 日志)
apiVersion:apps/v1
kind:DaemonSet
metadata:
name:promtail
namespace:monitoring
spec:
selector:
matchLabels:
app:promtail
template:
metadata:
labels:
app:promtail
spec:
containers:
-name:promtail
image:grafana/promtail:3.0.0
args:
--config.file=/etc/promtail/promtail.yaml
volumeMounts:
-name:config
mountPath:/etc/promtail
-name:varlog
mountPath:/var/log
-name:pods
mountPath:/var/log/pods
-name:dockercontainers
mountPath:/var/lib/docker/containers
volumes:
-name:config
configMap:
name:promtail-config
-name:varlog
hostPath:
path:/var/log
-name:pods
hostPath:
path:/var/log/pods
-name:dockercontainers
hostPath:
path:/var/lib/docker/containers
5.3 日志收集的最佳實(shí)踐
5.3.1 結(jié)構(gòu)化日志
應(yīng)用應(yīng)輸出結(jié)構(gòu)化日志(JSON 格式),便于后續(xù)解析和分析:
{
"timestamp":"2026-01-15T1000.123Z",
"level":"error",
"message":"Database connection failed",
"service":"user-api",
"request_id":"abc123",
"error_code":"DB_CONN_001",
"stack_trace":"..."
}
5.3.2 日志級(jí)別規(guī)范
ERROR:影響功能的問題,需要立即處理。
WARN:潛在問題或配置不當(dāng)。
INFO:重要的業(yè)務(wù)事件和狀態(tài)變更。
DEBUG:開發(fā)調(diào)試信息,生產(chǎn)環(huán)境應(yīng)關(guān)閉。
5.3.3 日志保留策略
根據(jù)合規(guī)要求和存儲(chǔ)成本制定日志保留策略:
熱存儲(chǔ)(Elasticsearch/Loki):7-30 天
溫存儲(chǔ)(對(duì)象存儲(chǔ)):30-90 天
冷存儲(chǔ)(歸檔):90 天以上
六、應(yīng)用日志的最佳實(shí)踐
6.1 應(yīng)用層日志配置
6.1.1 日志輸出到 stdout/stderr
容器環(huán)境的標(biāo)準(zhǔn)做法是將日志輸出到 stdout/stderr,由容器運(yùn)行時(shí)收集:
# Python 示例 importlogging importsys logging.basicConfig( level=logging.INFO, format='{"timestamp": "%(asctime)s", "level": "%(levelname)s", "message": "%(message)s"}', handlers=[logging.StreamHandler(sys.stdout)] )
6.1.2 日志輪轉(zhuǎn)配置
應(yīng)用層也應(yīng)配置日志輪轉(zhuǎn),避免單文件過大:
# Logback 配置示例(Java)/var/log/app/application.log /var/log/app/application.%d{yyyy-MM-dd}.log 30 10GB {"timestamp":"%d{ISO8601}","level":"%level","logger":"%logger","message":"%msg}%n
6.2 Sidecar 日志收集模式
對(duì)于需要特殊日志處理的應(yīng)用,可以使用 Sidecar 模式:
apiVersion:apps/v1
kind:Deployment
metadata:
name:app-with-sidecar
spec:
template:
spec:
containers:
-name:app
image:my-app:latest
volumeMounts:
-name:log-volume
mountPath:/var/log/myapp
-name:log-collector
image:fluent/fluent-bit:3.0.0
volumeMounts:
-name:log-volume
mountPath:/var/log/myapp
-name:fluent-bit-config
mountPath:/fluent-bit/etc
volumes:
-name:log-volume
emptyDir:{}
-name:fluent-bit-config
configMap:
name:fluent-bit-config
七、日志相關(guān)故障排查
7.1 kubectl logs 無響應(yīng)
# 檢查 API Server 是否正常 kubectl get componentstatuses # 檢查 API Server 日志 kubectl logs -n kube-system kube-apiserver---tail=100 # 檢查 kubelet 是否正常 ssh "systemctl status kubelet" # 繞過 API Server 直接查看日志文件 ssh "cat /var/log/pods/ _ _ / /0.log | tail -100"
7.2 日志丟失問題
7.2.1 容器重啟導(dǎo)致日志丟失
默認(rèn)情況下,容器重啟后舊日志會(huì)被刪除。解決方案:
配置日志持久化存儲(chǔ)
使用遠(yuǎn)程日志收集系統(tǒng)
啟用日志輪轉(zhuǎn)但增加保留文件數(shù)量
# 修改 kubelet 日志配置,增加保留文件數(shù) cat /var/lib/kubelet/config.yaml
apiVersion:kubelet.config.k8s.io/v1beta1 kind:KubeletConfiguration containerLogMaxFiles:10 containerLogMaxSize:50Mi
7.2.2 Fluent Bit/Fluentd 無法收集日志
# 檢查 Fluent Bit Pod 狀態(tài) kubectl get pod -n kube-system -l k8s-app=fluent-bit # 查看 Fluent Bit 日志 kubectl logs -n kube-system -l k8s-app=fluent-bit # 檢查 ConfigMap 配置是否正確 kubectl describe configmap fluent-bit-config -n kube-system # 測(cè)試 Fluent Bit 配置 kubectlexec-it -n kube-system fluent-bit-xxxx -- fluent-bit --test--parser=parsers.conf < /var/log/containers/*.log
7.3 日志文件過大的處理
# 查看大日志文件
find /var/log/pods -name"*.log"-size +100M -execls -lh {} ;
# 在節(jié)點(diǎn)上手動(dòng)壓縮日志
sudo gzip /var/log/pods//0.log
# 清理舊的日志文件
sudo find /var/log/pods -name"*.log.*"-mtime +7 -delete
# 監(jiān)控日志目錄大小
du -sh /var/log/pods/*
7.4 Pod 日志與容器日志不一致
某些情況下,kubectl logs 輸出的日志與實(shí)際容器日志文件可能存在差異:
# 比較兩者的差異 kubectl logs> /tmp/kubectl.log ssh "cat /var/log/pods/ / /0.log"> /tmp/file.log diff /tmp/kubectl.log /tmp/file.log # 可能的原因: # 1. 日志輪轉(zhuǎn)導(dǎo)致文件變化 # 2. 容器重啟,--previous 指向不同的日志文件 # 3. 日志編碼問題
八、日志監(jiān)控與告警
8.1 錯(cuò)誤日志監(jiān)控
配置 Prometheus 規(guī)則監(jiān)控錯(cuò)誤日志數(shù)量:
apiVersion:monitoring.coreos.com/v1
kind:PrometheusRule
metadata:
name:log-error-monitoring
namespace:monitoring
spec:
groups:
-name:application-logs
rules:
-alert:HighErrorRate
expr:|
sum(rate(container_log_messages_total{level="error"}[5m])) by (namespace, pod)
> 0.1
for:5m
labels:
severity:warning
annotations:
summary:"High error rate in{{ $labels.namespace }}/{{ $labels.pod }}"
description:"Error rate exceeds 10% over 5 minutes"
8.2 日志存儲(chǔ)容量監(jiān)控
-alert:LogStorageUsageHigh
expr:|
(node_filesystem_avail_bytes{mountpoint="/var/log"} / node_filesystem_size_bytes{mountpoint="/var/log"}) < 0.2
??for:?10m
??labels:
? ??severity:?warning
??annotations:
? ??summary:?"Log storage usage is above 80%"
九、實(shí)用命令參考
9.1 快速查看多個(gè) Pod 日志
# 查看標(biāo)簽為 app=nginx 的所有 Pod 日志 kubectl logs -l app=nginx --tail=50 # 查看最近 1 小時(shí)內(nèi)的錯(cuò)誤日志 kubectl logs -l app=nginx --since=1h | grep -E"ERROR|FATAL" # 統(tǒng)計(jì)錯(cuò)誤數(shù)量 kubectl logs -l app=nginx --since=24h | grep -c"ERROR"
9.2 實(shí)時(shí)查看多個(gè) Pod 日志
# 使用 stern 同時(shí)查看多個(gè) Pod 的日志 stern -n production app=nginx --since=10m # 只顯示包含 ERROR 的行 stern -n production app=nginx --filter=ERROR # 顯示帶有時(shí)間戳 stern -n production app=nginx --timestamp
9.3 日志分析常用命令
# 查看日志分布 kubectl logs| awk'{print $5}'| sort | uniq -c | sort -rn # 查看最常見的錯(cuò)誤 kubectl logs --since=24h | jq -r'.error // "no-error"'| sort | uniq -c | sort -rn | head -10 # 分析請(qǐng)求延遲 kubectl logs | jq -r'select(.type=="request") | .duration'| awk'{sum+=$1; count++} END {print "Average:", sum/count, "ms"}' # 查看特定時(shí)間段內(nèi)的日志 kubectl logs | awk -F'[] []''$2 >= "2026-01-15T1000" && $2 <= "2026-01-15T1100"'
總結(jié)
容器日志的正確處理方式分為三個(gè)層次:
基礎(chǔ)層:熟練使用 kubectl logs 命令,包括 --tail、--since、-f、--previous 等參數(shù)。多容器 Pod 必須指定容器名稱。
架構(gòu)層:理解容器日志的存儲(chǔ)機(jī)制(/var/log/pods 目錄)、日志輪轉(zhuǎn)配置、kubelet 的日志處理邏輯。
平臺(tái)層:建立分布式日志收集架構(gòu)(EFK、Loki),實(shí)現(xiàn)日志的集中存儲(chǔ)、搜索和分析。
運(yùn)維工程師應(yīng)避免進(jìn)入容器內(nèi)部查看日志的習(xí)慣,這不僅效率低下,還可能因?yàn)槿萜髦貑⒒蜻M(jìn)入調(diào)試狀態(tài)而影響業(yè)務(wù)。正確的做法是通過 kubectl logs 或日志收集系統(tǒng)查看日志。
日志的規(guī)范性同樣重要:結(jié)構(gòu)化輸出(JSON)、合理的日志級(jí)別、規(guī)范的字段命名,這些都為后續(xù)的日志分析和問題定位提供基礎(chǔ)。
-
容器
+關(guān)注
關(guān)注
0文章
536瀏覽量
23024 -
日志
+關(guān)注
關(guān)注
0文章
149瀏覽量
11095 -
kubernetes
+關(guān)注
關(guān)注
0文章
275瀏覽量
9530
原文標(biāo)題:容器日志該怎么看?別再進(jìn)容器里用 tail -f 硬查了
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
Kubernetes環(huán)境下容器日志的正確查看方式
評(píng)論