往期精彩文章 :
- 提升CKA考试胜算:一文带你全面了解RBAC权限控制!
- 揭秘高效运维:如何用kubectl top命令实时监控K8s资源使用情况?
- CKA认证必备:掌握k8s网络策略的关键要点
- 提高CKA认证成功率,CKA真题中的节点维护全攻略!
- 数据无忧,一学就会:掌握CKA认证必备的etcd备份与还原秘籍!
- 提升你的云技能:深入了解CKA认证之k8s升级秘籍!
- 揭秘CKA认证:Service四层代理的神秘面纱
- 提升CKA认证成功率:Kubernetes Ingress七层代理全攻略!
- CKA考生注意:这些Deployment要点能助你一臂之力!
- 从NodeSelector到NodeAffinity:探索Kubernetes节点亲和性的进化之路
- 提升CKA考试效率:精准统计Ready状态Node节点的实用攻略
- CKA考试必备:解锁Pod封装多容器的高级技巧!
- PV与PVC知多少?解锁CKA认证考点攻略!
- CKA备考攻略:掌握Pod日志收集,事半功倍的秘诀!
日志架构
应用日志可以让你了解应用内部的运行状况。日志对调试问题和监控集群活动非常有用。 大部分现代化应用都有某种日志记录机制。同样地,容器引擎也被设计成支持日志记录。 针对容器化应用,最简单且最广泛采用的日志记录方式就是写入标准输出和标准错误流。
但是,由容器引擎或运行时提供的原生功能通常不足以构成完整的日志记录方案。
例如,如果发生容器崩溃、Pod 被逐出或节点宕机等情况,你可能想访问应用日志。
在集群中,日志应该具有独立的存储,并且其生命周期与节点、Pod 或容器的生命周期相独立。 这个概念叫集群级的日志。
集群级日志架构需要一个独立的后端用来存储、分析和查询日志。 Kubernetes 并不为日志数据提供原生的存储解决方案。 相反,有很多现成的日志方案可以集成到 Kubernetes 中。
Pod和容器日志
Kubernetes 从正在运行的 Pod 中捕捉每个容器的日志。
此示例使用带有一个容器的 Pod 的清单,该容器每秒将文本写入标准输出一次。
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']
要运行此 Pod,请执行以下命令:
kubectl apply -f counter-pod.yaml
要获取这些日志,请执行以下 kubectl logs
命令:
kubectl logs counter
输出类似于:
节点的容器日志处理方式
容器运行时对写入到容器化应用程序的 stdout 和 stderr 流的所有输出进行处理和转发。 不同的容器运行时以不同的方式实现这一点;不过它们与 kubelet 的集成都被标准化为 CRI 日志格式。
默认情况下,如果容器重新启动,kubelet 会保留一个终止的容器及其日志。 如果一个 Pod 被逐出节点,所对应的所有容器及其日志也会被逐出。
kubelet 通过 Kubernetes API 的特殊功能将日志提供给客户端访问。 访问这个日志的常用方法是运行 kubectl logs
。
集群级日志架构
虽然 Kubernetes 没有为集群级日志记录提供原生的解决方案,但你可以考虑几种常见的方法。 以下是一些选项:
- 使用在每个节点上运行的节点级日志记录代理。
- 在应用程序的 Pod 中,包含专门记录日志的边车(Sidecar)容器。
- 将日志直接从应用程序中推送到日志记录后端。
使用节点级日志代理
你可以通过在每个节点上使用节点级的日志记录代理来实现集群级日志记录。 日志记录代理是一种用于暴露日志或将日志推送到后端的专用工具。 通常,日志记录代理程序是一个容器,它可以访问包含该节点上所有应用程序容器的日志文件的目录。
由于日志记录代理必须在每个节点上运行,推荐以 DaemonSet 的形式运行该代理。
节点级日志在每个节点上仅创建一个代理,不需要对节点上的应用做修改。
容器向标准输出和标准错误输出写出数据,但在格式上并不统一。 节点级代理收集这些日志并将其进行转发以完成汇总。
使用边车容器运行日志代理
你可以通过以下方式之一使用边车(Sidecar)容器:
- 边车容器将应用程序日志传送到自己的标准输出。
- 边车容器运行一个日志代理,配置该日志代理以便从应用容器收集日志。
传输数据流的边车容器
利用边车容器,写入到自己的 stdout 和 stderr 传输流, 你就可以利用每个节点上的 kubelet 和日志代理来处理日志。 边车容器从文件、套接字或 journald 读取日志。 每个边车容器向自己的 stdout 和 stderr 流中输出日志。
这种方法允许你将日志流从应用程序的不同部分分离开,其中一些可能缺乏对写入 stdout 或 stderr 的支持。重定向日志背后的逻辑是最小的,因此它的开销不大。 另外,因为 stdout 和 stderr 由 kubelet 处理,所以你可以使用内置的工具 kubectl logs。
具有日志代理功能的边车容器
如果节点级日志记录代理程序对于你的场景来说不够灵活, 你可以创建一个带有单独日志记录代理的边车容器,将代理程序专门配置为与你的应用程序一起运行。
CKA真题
真题截图
中文解析
Context
将一个现有的 Pod 集成到 Kubernetes 的内置日志记录体系结构中 (例如 kubectl logs)。添加 streaming sidecar 容器是实现此要求的一种好方法。
Task
使用 busybox lmage 来将名为 sidecar 的 sidecar 容器添加到现有的 Pod legacy-app 上,新的 sidecar 容器必须运行以下命令:
/bin/sh -c tail -n+1 -f /var/log/legacy-app.log
使用 volume 挂载
/var/log/
目录,确保sidecar
能访问/var/log/legacy-app.log
文件。
官方参考文档
做题解答
- 首先将题目中现有的 pod
legacy-app
的 yaml 导出
kubectl get pods legacy-app -o yaml > sidecar.yaml
- 删除一些导出的内容,结果如下
apiVersion: v1 kind: Pod metadata: name: legacy-app namespace: default spec: containers: - args: - /bin/sh - -c - "i=0; while true; do\n echo \"$(date) INFO $i\" >> /var/log/legacy-app.log;\n \ i=$((i+1));\n sleep 1;\ndone \n" image: busybox imagePullPolicy: Always name: count
- 在
sidecar.yaml
中添加sidecar
容器和volume
apiVersion: v1 kind: Pod metadata: name: legacy-app namespace: default spec: containers: - args: - /bin/sh - -c - "i=0; while true; do\n echo \"$(date) INFO $i\" >> /var/log/legacy-app.log;\n \ i=$((i+1));\n sleep 1;\ndone \n" - image: busybox imagePullPolicy: Always name: count volumeMouts: - name: logs mountPath: /var/log - image: busybox imagePullPolicy: Always name: sidecar args: [/bin/sh,-c,'tail -n+1 -f /var/log/legacy-app.log'] volumeMouts: - name: logs mountPath: /var/log volumes: - name: logs emptyDir: {}
- 先删除原有的Pod才能更新
controlplane $ kubectl delete pod legacy-app pod "legacy-app" deleted
- 提交更新
controlplane $ kubectl apply -f sidecar.yaml pod/legacy-app created
- 检查日志是否正常输出
controlplane $ kubectl logs legacy-app -c sidecar Mon Mar 11 03:49:35 UTC 2024 INFO 0 Mon Mar 11 03:49:36 UTC 2024 INFO 1 Mon Mar 11 03:49:37 UTC 2024 INFO 2 Mon Mar 11 03:49:38 UTC 2024 INFO 3