K8s Pod 神操作:用 Sidecar 容器拯救老应用,日志收集再也不用改代码!

“这破应用日志又丢了!” 运维小李第 N 次拍桌 —— 公司那套跑了 5 年的 legacy-app,每次 Pod 重启日志就清空,排查问题全靠猜。更头疼的是,开发早就离职,没人敢动代码加日志转发逻辑。

如果你也遇到过 “老应用难改造”“容器日志难收集” 的困境,今天这招Sidecar 容器模式绝对能救场。不用改一行业务代码,只需给 Pod “搭个副手”,就能轻松搞定日志、监控等附加功能。亲测有效,文末附完整实操代码!

一、为啥老应用的日志这么难搞?

先搞懂问题根源:容器的 “临时性” 是把双刃剑。

legacy-app 这类老应用,通常把日志直接写在容器内部的/var/log目录 —— 但容器一旦重启、迁移或删除,目录里的日志会跟着消失。更麻烦的是:

  • 改代码加日志转发?没人敢动老应用,怕出生产事故;
  • 直接挂载 hostPath?耦合节点存储,Pod 换节点日志就断;
  • 用日志代理抓取?容器内日志路径不统一,配置繁琐还容易漏。

其实 K8s 早就给出了完美解法:在同一个 Pod 里加个 “辅助容器”(Sidecar),让它帮主容器干活

二、Sidecar 容器:Pod 里的 “全能副手”

1. 什么是 Sidecar?

Sidecar 直译是 “边车”,就像摩托车的边斗 —— 它和主容器(legacy-app)跑在同一个 Pod 里,共享网络、存储资源,但各司其职:

  • 主容器:专心跑业务(比如 legacy-app);
  • Sidecar 容器:专门干辅助活(比如收集日志、同步配置、监控指标)。

最关键的是:不用改主容器代码,只需新增 Sidecar 配置,零侵入改造老应用!

2. 核心原理:用 emptyDir 实现数据共享

Sidecar 能帮主容器收集日志,靠的是 K8s 的emptyDir卷 —— 一种和 Pod 同生命周期的临时存储,同一 Pod 里的容器都能访问。

整个流程像这样:

主容器把日志写进挂载了emptyDir的/var/log,Sidecar 从同一个路径读日志,完美实现 “生产端” 和 “收集端” 的解耦。

三、实操:给老应用加日志收集 Sidecar(附完整代码)

接下来手把手教你改造 legacy-app,全程不到 10 分钟,新手也能搞定。

前置条件

  • 已有运行中的 Pod:legacy-app(用 busybox 模拟老应用);
  • 掌握基础 kubectl 命令,能编辑 YAML 文件。

步骤 1:导出原有 Pod 配置,留好备份

先把现有 Pod 的配置导出来,避免从零写 YAML:


# 切换到目标集群(必做!避免操作错集群)

kubectl config use-context kubernetes-admin@kubernetes

# 导出现有Pod的YAML配置

kubectl get pod legacy-app -o yaml > sidecar.yaml

# 创建备份,改崩了能回滚

cp sidecar.yaml sidecar.yaml.bk

此时sidecar.yaml里是 legacy-app 的原始配置,重点看spec.containers—— 只有一个主容器。

步骤 2:修改 YAML,添加 Sidecar 和共享卷

用 vim 打开sidecar.yaml,重点改 3 处:主容器挂载卷、加 Sidecar 容器、定义 emptyDir 卷

完整修改后配置(关键处标红)

apiVersion: v1

kind: Pod

metadata:

name: legacy-app # 保持原Pod名称,重建后替换旧Pod

spec:

containers:

# 1. 原有主容器:添加日志卷挂载

- name: legacy-main # 主容器名称(可自定义)

image: busybox

args: [/bin/sh, -c, 'while true; do echo "`date` 业务日志" >> /var/log/legacy-app.log; sleep 5; done'] # 模拟日志输出

volumeMounts:

- name: logs # 挂载共享卷

mountPath: /var/log # 挂载到容器内/var/log,和Sidecar一致

# 2. 新增Sidecar容器:负责收集日志

- name: log-collector # Sidecar名称,清晰易懂

image: busybox # 轻量镜像,节省资源

args: [/bin/sh, -c, 'tail -n+1 -f /var/log/legacy-app.log'] # 实时跟踪日志

volumeMounts:

- name: logs # 挂载同一个共享卷

mountPath: /var/log # 路径和主容器保持一致,实现数据共享

# 3. 定义共享卷(emptyDir类型)

volumes:

- name: logs # 卷名称,和容器挂载的name一致

emptyDir: {} # 临时共享卷,Pod删除时自动清理

关键配置解析
  1. 主容器挂载卷

在volumeMounts里加logs卷,让主容器的/var/log指向共享卷 —— 从此写日志就是写进共享存储,不是容器内部。

  1. Sidecar 容器配置
    • 用tail -f命令实时跟踪日志,也能换成filebeat镜像转发到 ELK;
    • 必须挂载同一个logs卷,且mountPath和主容器一致,否则读不到日志。
  1. emptyDir 卷

无需提前创建存储,K8s 会在 Pod 启动时自动生成,适合临时共享场景。

步骤 3:重建 Pod,让配置生效

K8s 的 Pod 创建后不能直接修改容器列表,必须先删旧的再建新的:


# 删除原有Pod(数据已通过emptyDir暂存?不,emptyDir随Pod删除,生产环境需用PV持久化日志)

kubectl delete pod legacy-app

# 用修改后的YAML重建Pod

kubectl create -f sidecar.yaml

# 检查Pod状态:READY显示2/2才正常(主容器+Sidecar都启动)

kubectl get pod legacy-app

正常输出长这样:


NAME READY STATUS RESTARTS AGE

legacy-app 2/2 Running 0 30s

步骤 4:验证日志收集是否生效

来测试下 Sidecar 是不是真的能抓到日志:


# 查看Sidecar容器的输出(-c指定容器名)

kubectl logs legacy-app -c log-collector

会看到实时滚动的日志:


2024-05-20 10:00:00 业务日志

2024-05-20 10:00:05 业务日志

2024-05-20 10:00:10 业务日志

成功了!主容器写日志,Sidecar 读日志,全程没改一行业务代码。

四、进阶玩法:Sidecar 不只是收集日志

Sidecar 的能力远不止于此,这 3 个场景闭眼能用:

1. 日志转发到 ELK

把 Sidecar 的镜像换成elastic/filebeat,配置文件挂载进去,就能自动把日志推到 Elasticsearch:


- name: filebeat-sidecar

image: elastic/filebeat:8.10.0

volumeMounts:

- name: logs

mountPath: /var/log

- name: filebeat-config

mountPath: /usr/share/filebeat/filebeat.yml

subPath: filebeat.yml

2. 配置自动同步

老应用没有配置中心?加个 Sidecar 定期从 NFS 拉取配置,再通过共享卷同步给主容器:


- name: config-sync

image: busybox

args: [/bin/sh, -c, 'while true; do cp /nfs-config/app.conf /config/app.conf; sleep 300; done']

volumeMounts:

- name: app-config

mountPath: /config

- name: nfs-vol

mountPath: /nfs-config

3. 健康检查代理

老应用不支持 HTTP 健康检查?Sidecar 监听主容器的端口,转为 K8s 能识别的健康检查接口:


- name: health-proxy

image: nginx

ports:

- containerPort: 8080

args: [/bin/sh, -c, 'while true; do if nc -z localhost 80; then echo "OK"; else echo "ERROR"; fi; sleep 10; done']

五、避坑指南:Sidecar 模式的 5 个注意事项

  1. 资源限制别忘加:Sidecar 会占用资源,一定要在resources里设requests和limits,避免抢主容器资源:

resources:

requests:

cpu: 10m

memory: 20Mi

limits:

cpu: 50m

memory: 50Mi

  1. 日志持久化用 PV:emptyDir 随 Pod 删除,生产环境要把日志卷换成 PV(如 NFS),避免日志丢失。
  1. Sidecar 别太 “重”:优先用 busybox、alpine 这类轻量镜像,减少启动时间和资源消耗。
  1. 容器启动顺序控制:如果 Sidecar 要先启动,加initContainers或readinessProbe控制顺序。
  1. 避免 “Sidecar 膨胀”:一个 Sidecar 只干一件事(如日志收集),多个功能就加多个 Sidecar,保持职责单一。

六、总结:Sidecar 为啥是老应用的 “救星”?

今天的实操让我们看清:Sidecar 模式的核心是 **“解耦”**—— 把业务逻辑和辅助功能拆分开,老应用不用改代码,就能享受到 K8s 的生态能力。

无论是日志收集、配置同步还是监控代理,Sidecar 都能像 “外挂” 一样给应用赋能。这种零侵入、高灵活的改造方式,正是 K8s “声明式 API” 和 “容器编排” 思想的最佳体现。

最后再送你一句口诀:“主容器干主业,Sidecar 打辅助,共享卷传数据,零改造解难题”。下次遇到老应用改造,直接用这招准没错!

本文配套的 YAML 配置已上传 GitHub:github.com/xxx/k8s-sidecar-demo,需要的直接拿~

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐