0 前言

基于 centos7.9docker-ce-20.10.18kubelet-1.22.3-0

kubelet logs 命令的流程

kubectl logs --请求--> apiserver --请求--> kubelet --读取--> container日志

k8s 日志包含两大类:

  • k8s 系统的组件日志
  • k8s 集群中部署的应用程序的日志
    • 标准输出
    • 日志文件

1 组件日志

journalctl -u kubelet
kubectl logs kube-proxy -n kube-system
/var/log/messages

2 pod 日志

2.1 标准输出

实时查看 pod 标准输出日志

kubectl logs [options] <podname>
kubectl logs -f <podname>
kubectl logs -f <podname> -c <containername>
kubectl logs --previous <podname> # 查看pod上次重启的日志

k8s 会将每个 pod 中每个 container 的日志记录到 pod 所在 node 的 /var/log/pods 目录中, 日志文件其实是 docker 保存的日志文件的一个软连接.

k8s 会为每个 pod 的每个 container 日志保留 2 份, 一份为 container 当前状态的日志, 另一份是 container 上一次生命周期的日志, 日志保留数量应该是由 k8s 的 gc 机制管控.

# k8s 日志
/var/log/pods/<pod namespace>_<pod name>_<pod uid>/<容器名称>/容器重启次数.log
# docker日志
/var/lib/docker/containers/<container-id>/<container-id>-json.log

示例

# 可以看到 calico-kube-controllers 这个 pod 重启了 7 次
[root@k8s-node1 ~]# kubectl get pods -n kube-system -l k8s-app=calico-kube-controllers
NAME                                       READY   STATUS    RESTARTS      AGE
calico-kube-controllers-6c76574f75-69flf   1/1     Running   7 (41h ago)   4d1h

# k8s 分别保存了编号 6 和 7 两个日志文件
[root@k8s-node3 ~]# ls -l /var/log/pods/kube-system_calico-kube-controllers-6c76574f75-69flf_066e1042-97a4-4547-8d2d-6580cbad40c5/calico-kube-controllers/
lrwxrwxrwx. 1 root root 165 Apr 20 14:31 6.log -> /var/lib/docker/containers/8ed4865daa5d984d9b7e3412f61251ce1a5e12e295fce1f14ee341c3f79b1afe/8ed4865daa5d984d9b7e3412f61251ce1a5e12e295fce1f14ee341c3f79b1afe-json.log
lrwxrwxrwx. 1 root root 165 Apr 23 10:23 7.log -> /var/lib/docker/containers/c30d353ee464efd853968dcd1524933aa214294303e5a7cd7828b0e86f0e94ec/c30d353ee464efd853968dcd1524933aa214294303e5a7cd7828b0e86f0e94ec-json.log

# 7 号日志文件是当前生命周期的日志
[root@k8s-node1 ~]# kubectl logs --tail=1 calico-kube-controllers-6c76574f75-69flf -n kube-system
2023-04-23 03:05:54.256 [INFO][1] resources.go 350: Main client watcher loop
[root@k8s-node3 calico-kube-controllers]# tail -n 1 7.log | python -m json.tool
{
    "log": "2023-04-23 03:05:54.256 [INFO][1] resources.go 350: Main client watcher loop\n",
    "stream": "stderr",
    "time": "2023-04-23T03:05:54.257447874Z"
}

# 6 号日志文件是上一次生命周期的日志
[root@k8s-node1 ~]# kubectl logs --tail=1 --previous calico-kube-controllers-6c76574f75-69flf -n kube-system
2023-04-21 08:57:20.637 [INFO][1] resources.go 350: Main client watcher loop
[root@k8s-node3 calico-kube-controllers]# tail -n 1 6.log | python -m json.tool
{
    "log": "2023-04-21 08:57:20.637 [INFO][1] resources.go 350: Main client watcher loop\n",
    "stream": "stderr",
    "time": "2023-04-21T08:57:20.637780663Z"
}

2.2 日志文件

比如 nginx 应用的日志一般保存在 accesss.log 和 error.log 日志中,这些日志是不会输出到标准输出的,可以采用如下两种方式进行采集

2.2.1 emptyDir 数据卷

创建 pod 时挂载 emptyDIr 类型的数据卷,用以持久化自定义的日志文件

需要先找到 pod 分配的节点

Kubectl get pods -o wide

再查看 pod 的 id

docker ps | grep pod-name 
# 或者
kubectl get pod <podname> -n <namespace> -o jsonpath='{.metadata.uid}'

pod 日志文件路径

/var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~empty-dir

示例

apiVersion: v1
kind: Pod
metadata:
  name: pod-logs-emptydir
spec:
  containers:
  - name: web
    image: nginx
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx/
  volumes:
  - name: logs
    emptyDir: {}

2.2.2 sidecar 边车容器

通过创建边车容器实现将应用原本的日志文件输出到标准输出

示例:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: web
    image: nginx:1.22.1
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx/
  - name: accesslog
    image: busybox:1.28
    command: ['/bin/sh', '-c', 'tail -f /opt/access.log']
    volumeMounts:
    - name: logs
      mountPath: /opt
  volumes:
  - name: logs
    emptyDir: {}

以上