16.2 Sidecar、Ambassador、Adapter 与故障实验
辅助容器模式把与主应用生命周期密切相关、但不属于核心业务的能力放进同一个 Pod。同一 Pod 的容器共享网络,文件只有挂载共同卷时才共享。它们作为一个 Pod 调度和扩缩;单个容器可以独立重启,Pod 被驱逐或节点故障则会影响整组。
这种耦合有时正是目的,但不是“把平台功能全部塞进 sidecar”的理由。
Sidecar:伴随主容器的辅助能力
典型 Sidecar 包括日志转发、代理、配置刷新或本地同步器。下面使用 Kubernetes 1.33 起稳定的原生 Sidecar:放在 initContainers 下,并设置容器级 restartPolicy: Always。这是配置示意,两个镜像名与摘要都是占位符,不能直接部署;实际镜像须约定日志路径、权限、转发目的地,并补齐资源和探针配置:
apiVersion: v1
kind: Pod
metadata:
name: scoring-example
spec:
initContainers:
- name: log-forwarder
restartPolicy: Always
image: "registry.example/log-forwarder@sha256:<forwarder-digest>"
volumeMounts:
- name: logs
mountPath: /var/log/app
readOnly: true
containers:
- name: app
image: "registry.example/scoring@sha256:<app-digest>"
volumeMounts:
- name: logs
mountPath: /var/log/app
volumes:
- name: logs
emptyDir: {}emptyDir 可以跨同一 Pod 内的容器重启保留,但 Pod 删除后不会保留日志;它不是持久日志备份。
评估时要计算每个 Pod 额外的 CPU、内存、启动时间和攻击面。1000 个应用副本意味着 1000 个 Sidecar;假设每个额外占用 50 MiB,合计约 48.8 GiB,代理并不会因为个头小就免交资源账单。
Ambassador:代表应用处理外部通信
Ambassador 是面向外部依赖的本地代理,可负责 TLS、服务发现、连接池和部分重试:
Application → localhost proxy → External Service应用得到稳定的本地端点,但代理配置必须与业务语义一致。若代理自动重试非幂等写入,主应用甚至可能不知道重复发生。
服务网格数据平面常以 Sidecar 或节点代理实现类似职责,但它不能替代业务级 deadline、幂等键和降级政策。
Adapter:标准化主应用输出
Adapter 容器把应用特有格式转换成平台统一格式,例如把自定义指标转成 Prometheus 暴露格式,或把遗留日志转换成结构化事件。
如果能够直接修改应用使用标准协议,长期通常更简单。Adapter 更适合遗留程序、第三方镜像或迁移阶段。
普通 Init Container 与原生 Sidecar
普通 Init Container 必须成功退出,后续初始化和主应用才会继续;原生 Sidecar 则在启动后持续运行。主应用若依赖代理真正可用,应给代理配置 startupProbe,不能把“进程已启动”当作“连接已建立”。把辅助容器直接放进 containers 仍是合法的传统多容器模式,但不会自动获得这种启动、终止顺序。
数据库 schema 迁移不宜让每个副本的 Init Container 同时竞争执行。它应是有锁、有审计、可单独观察的发布步骤,并事先定义兼容回退或前向修复办法;删列之后没有通用的自动还原按钮。
健康和终止要按整体设计
辅助容器引入新的生命周期问题:
- 主应用就绪但代理尚未就绪;
- 主应用退出后,日志转发器尚未排空;
- Sidecar 崩溃但 Pod 仍被视为可服务;
- 网格代理阻止或延迟应用优雅终止。
原生 Sidecar 的就绪探针会参与 Pod 就绪判断。终止时 kubelet 先等待主容器退出,再按声明的逆序终止这些 Sidecar,但它们共享 Pod 的终止宽限期;主容器耗光时间,日志转发器仍可能来不及排空。原生 Sidecar 文档说明了这套顺序。readiness、探针、终止宽限期和排空协议仍需在实际环境验证。
混沌工程先从假设开始
混沌工程不是随机“搞坏生产”,而是通过受控实验检验稳态假设:
示例假设:终止一个计分实例后,实验窗口内按逻辑结算请求计算的成功率仍高于 99.9%,且 p99 延迟在 2 分钟内恢复到约定的基线范围。
这不是测量结果。实验前需固定流量、统计窗口和基线容差,把重试合并回同一个逻辑请求,并规定样本不足时不作成功结论。
一个实验包含:
- 定义可观测稳态;
- 提出具体故障假设;
- 选择最小爆炸半径;
- 设置自动中止条件;
- 注入实例终止、网络延迟、依赖错误或资源压力;
- 记录发现并修复,再针对原假设复验。
例如只选择一个测试租户、一个实例和最多两分钟的延迟注入;若结算失败率超过预设阈值,就停止继续注入并观察恢复。中止注入不会撤回已经丢失的请求或回滚业务数据,恢复步骤也必须事先准备。
先在测试环境验证工具和保护,再逐步进入生产的小流量、非关键范围。没有监控、回滚和事件负责人时,不应扩大实验。
应验证的真实问题
- 代理超时是否小于调用方 deadline?
- 重试是否在多个层级叠加?
- Sidecar 资源耗尽会怎样影响主容器?
- 实例终止时在途请求和消息是否安全处理?
- 区域或依赖故障时,系统是快速拒绝还是无界排队?
- 告警是否在用户影响之前或同时触发?
参考资料
- Kubernetes, Pods
- Kubernetes, Volumes: emptyDir
- Kubernetes, Sidecar Containers
- Principles of Chaos Engineering, Principles