IT策士 10余年一线大厂经验专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章助你少走弯路。在第 21 篇中我们学习了 Pod 的 YAML 结构和多容器共享网络第 22 篇深入了 Pod 的生命周期和重启策略。回顾第 21 篇我们部署过一个包含 Flask 和 Redis 两个容器的 Pod通过localhost共享网络。那篇文章的核心是“怎么用”今天我们要回答的是“为什么要这样设计”——把多个容器放进同一个 Pod到底能解决哪些实际问题这背后是 Kubernetes 社区经过大量生产实践总结出的三种经典设计模式Sidecar边车、Adapter适配器、Ambassador大使。这三种模式在 Compose 时代你几乎不会用到因为单机编排天然缺乏 Pod 这种“多个容器共享命运”的抽象。而到了 K8s 阶段合理地组织多容器 Pod 直接决定了你的应用架构是否优雅、可维护、可观测。一、为什么要在 Pod 里放多个容器先明确一点大部分 Pod 只需要一个容器。多容器 Pod 不是默认选择而是为了解决特定问题。哪些问题扩展或增强主容器功能但不修改主应用代码——比如自动采集日志、统一监控指标格式。在主容器和外部系统之间做代理或适配——比如连接外部数据库时需要客户端证书认证用一个边车容器专门处理 TLS。将辅助进程与主进程紧密绑定——它们必须共享同一个网络命名空间、同一个 IP、同一组存储卷。Kubernetes 官方文档总结了三种经典模式Sidecar边车、Adapter适配器、Ambassador大使。它们本质上都是把辅助容器和主应用容器放在同一个 Pod 中利用共享网络和存储的特性实现功能增强或代理。在正式开始之前有必要澄清 Sidecar 的一个术语歧义因为它在 K8s 生态中有双重含义Sidecar 模式设计模式泛指所有与主容器并行的辅助容器本篇与 Adapter、Ambassador 并列的就是这个广义概念。Sidecar 容器Kubernetes 特性v1.29 beta是initContainers中的一种特殊类型设置restartPolicy: Always后它会在整个 Pod 生命周期内持续运行并在普通容器启动前先行启动。本篇的实战部分将采用这个特性来部署日志采集 Sidecar。二、Sidecar 模式增强主容器能力2.1 什么是 Sidecar 模式Sidecar 模式是最常见的多容器 Pod 设计。核心思想是主容器只做自己的业务Sidecar 容器负责附加值——比如日志采集、文件同步、配置热加载等。它们共享同一个 Pod 的网络和存储卷通过localhost或共享文件进行协作。想象一下摩托车比赛的边车Sidecar——主驾驶员专注于操控方向边车里的助手可以观察路况、传递信息两者共享同一台车的速度和路线。这就是 Kubernetes 中 Sidecar 模式的形象比喻。2.2 实战为 Flask 应用添加日志采集 Sidecar我们贯穿案例的 Flask 应用会输出访问日志但日志只在容器内部。生产环境中需要把日志收集到外部系统如 Elasticsearch、Loki。直接修改 Flask 代码接入日志系统会增加业务代码的复杂度更好的做法是加一个 Sidecar 容器专门采集日志。以下 YAML 演示了一个典型的 Sidecar 部署——Flask 容器将日志写入共享 VolumeFilebeat Sidecar 读取并转发到 Elasticsearch此处简化为输出到 stdout 以便演示apiVersion: v1 kind: Pod metadata: name: flask-sidecar-demo labels: app: flask-sidecar spec: volumes: - name: shared-logs emptyDir:{}containers:# ---- 主容器Flask 应用 ----- name: flask-app image: flask-redis-counter:2.0 ports: - containerPort:5000env: - name: REDIS_HOST value: redis-service volumeMounts: - name: shared-logs mountPath: /app/logs# ---- Sidecar 容器Filebeat 日志采集 ----- name: log-collector image: docker.elastic.co/beats/filebeat:8.15.0 volumeMounts: - name: shared-logs mountPath: /var/log/flask readOnly:truecommand: - /bin/bash --c-|echo日志采集 Sidecar 已启动监听 /var/log/flasktail-f/var/log/flask/*.log2/dev/null||echo等待日志文件...解释一下数据流emptyDir卷在 Pod 创建时自动生成Pod 删除时随之销毁。Flask 向/app/logs写日志log-collector从/var/log/flask读日志——两个路径指向同一个 Volume。readOnly: true确保 Sidecar 只能读取不能修改日志文件。部署并验证kubectl apply-fflask-sidecar.yaml kubectl get pods# NAME READY STATUS RESTARTS AGE# flask-sidecar-demo 2/2 Running 0 30s# 模拟日志写入kubectlexecflask-sidecar-demo-cflask-app --sh-cecho test log /app/logs/access.log# 检查 Sidecar 是否读到了日志kubectl logs flask-sidecar-demo-clog-collector# 日志采集 Sidecar 已启动监听 /var/log/flask# test log业务容器只写了一行echoSidecar 容器就通过共享 Volume 实时读取到了日志内容。实际的 Filebeat 配置会更复杂包括定义输出目标为 Elasticsearch 或 Kafka但核心原理完全一致。Sidecar 容器的 K8s 原生特性从 v1.29 开始你可以在initContainers中设置restartPolicy: Always来声明一个 Sidecar 容器。这种 Sidecar 会在普通容器启动前就绪并在整个 Pod 生命周期内持续运行。上面的示例中我们仍使用普通容器模式两种方式功能等效但原生 Sidecar 特性提供了更好的生命周期保证。三、Adapter 模式统一监控数据格式Adapter 模式的核心思想是主应用输出的监控指标格式不符合 Prometheus 规范Adapter 容器负责转换格式对外暴露标准接口。它同样共享 Pod 网络但工作重点不是采集文件而是提供实时、可抓取的监控端点。3.1 场景你的 Flask 应用暴露了一个自定义的/metrics端点但输出的 JSON 格式 Prometheus 无法直接识别。Adapter 容器读取这个端点并转换为 Prometheus 格式。3.2 动手体验apiVersion: v1 kind: Pod metadata: name: flask-adapter-demo labels: app: flask-adapter spec: containers: - name: flask-app image: flask-redis-counter:2.0 ports: - containerPort:5000env: - name: REDIS_HOST value: redis-service - name: metrics-adapter image: alpine command: - /bin/sh --c-|whiletrue;do# 模拟从 Flask 的 /metrics 抓取 JSON 并转换为 Prometheus 格式echo# HELP flask_requests_total Total request countecho# TYPE flask_requests_total counterechoflask_requests_total$(curl-shttp://localhost:5000/health|grep-ostatus:ok|wc-l)sleep5doneAdapter 容器通过localhost:5000访问 Flask 主容器读取健康检查端点将其转换为 Prometheus 风格的指标输出到 stdout实际生产中会暴露一个 HTTP 端口供 Prometheus 抓取。这里curl连接localhost:5000能成功正是因为 Adapter 和主容器共享 Pod 的网络命名空间。四、Ambassador 模式代理外部服务Ambassador 模式的核心思想是主应用访问外部服务时不需要关心复杂的连接逻辑如 TLS 证书、连接池由 Ambassador 容器作为本地代理处理这些复杂性后转发给主容器。主应用只连接localhost上的代理端口。4.1 场景你的 Flask 应用需要连接外部的 Redis 集群而该集群要求 TLS 客户端证书认证。你的 Flask 镜像不想内置证书也不想修改连接逻辑。4.2 动手体验apiVersion: v1 kind: Pod metadata: name: flask-ambassador-demo labels: app: flask-ambassador spec: containers: - name: flask-app image: flask-redis-counter:2.0 ports: - containerPort:5000env: - name: REDIS_HOST value: localhost# 连接本地 Ambassador 代理- name: REDIS_PORT value:6379- name: redis-ambassador image: alpine/socat args: -TCP-LISTEN:6379,fork,reuseaddr-TCP:real-redis-cluster.example.com:6379Ambassador 容器使用socat在localhost:6379上建立一个 TCP 代理将流量转发到外部的real-redis-cluster.example.com:6379。Flask 容器通过REDIS_HOSTlocalhost连接这个本地代理完全不需要知道真实 Redis 的地址和证书细节。真实的生产场景中Ambassador 还可以集成 TLS 握手、认证令牌注入等逻辑——这些都封装在 Ambassador 容器中主应用完全无感知。五、三种模式总结与选择指南选择原则一个容器做好一件事多容器通过共享机制协作。如果辅助功能和主应用的生命周期紧密耦合必须一起调度、一起销毁就应该放在同一个 Pod 里。如果两个组件需要独立的扩缩容策略比如 Web 服务需要 5 个副本但日志采集只需要跟随节点部署则应该放在不同的 Pod 中。六、命令速查表七、本篇总结多容器 Pod 的设计哲学不是默认选择而是为了解决“功能增强”和“外部代理”的特定问题。Sidecar 模式增强主容器最常见——日志采集、文件同步。Adapter 模式适配器转换格式面向监控和可观测性。Ambassador 模式代理外部访问封装连接复杂性。核心机制三种模式都依赖 Pod 内的共享网络和共享存储这是与 Docker Compose 多容器协作最本质的区别。这三种模式为我们后续学习更高级的 K8s 能力做了重要铺垫。比如下一篇——第 24 篇健康检查探针机制详解我们将深入 liveness、readiness、startup 三种探针的配置和实战让 Pod 真正具备生产级的自愈和流量控制能力。想了解更多还可以去各个平台搜索「IT策士」一起升级 IT 思维
第 23篇 k8s之Pod:多容器 Pod 与设计模式(Sidecar 等)
发布时间:2026/5/31 2:14:40
IT策士 10余年一线大厂经验专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章助你少走弯路。在第 21 篇中我们学习了 Pod 的 YAML 结构和多容器共享网络第 22 篇深入了 Pod 的生命周期和重启策略。回顾第 21 篇我们部署过一个包含 Flask 和 Redis 两个容器的 Pod通过localhost共享网络。那篇文章的核心是“怎么用”今天我们要回答的是“为什么要这样设计”——把多个容器放进同一个 Pod到底能解决哪些实际问题这背后是 Kubernetes 社区经过大量生产实践总结出的三种经典设计模式Sidecar边车、Adapter适配器、Ambassador大使。这三种模式在 Compose 时代你几乎不会用到因为单机编排天然缺乏 Pod 这种“多个容器共享命运”的抽象。而到了 K8s 阶段合理地组织多容器 Pod 直接决定了你的应用架构是否优雅、可维护、可观测。一、为什么要在 Pod 里放多个容器先明确一点大部分 Pod 只需要一个容器。多容器 Pod 不是默认选择而是为了解决特定问题。哪些问题扩展或增强主容器功能但不修改主应用代码——比如自动采集日志、统一监控指标格式。在主容器和外部系统之间做代理或适配——比如连接外部数据库时需要客户端证书认证用一个边车容器专门处理 TLS。将辅助进程与主进程紧密绑定——它们必须共享同一个网络命名空间、同一个 IP、同一组存储卷。Kubernetes 官方文档总结了三种经典模式Sidecar边车、Adapter适配器、Ambassador大使。它们本质上都是把辅助容器和主应用容器放在同一个 Pod 中利用共享网络和存储的特性实现功能增强或代理。在正式开始之前有必要澄清 Sidecar 的一个术语歧义因为它在 K8s 生态中有双重含义Sidecar 模式设计模式泛指所有与主容器并行的辅助容器本篇与 Adapter、Ambassador 并列的就是这个广义概念。Sidecar 容器Kubernetes 特性v1.29 beta是initContainers中的一种特殊类型设置restartPolicy: Always后它会在整个 Pod 生命周期内持续运行并在普通容器启动前先行启动。本篇的实战部分将采用这个特性来部署日志采集 Sidecar。二、Sidecar 模式增强主容器能力2.1 什么是 Sidecar 模式Sidecar 模式是最常见的多容器 Pod 设计。核心思想是主容器只做自己的业务Sidecar 容器负责附加值——比如日志采集、文件同步、配置热加载等。它们共享同一个 Pod 的网络和存储卷通过localhost或共享文件进行协作。想象一下摩托车比赛的边车Sidecar——主驾驶员专注于操控方向边车里的助手可以观察路况、传递信息两者共享同一台车的速度和路线。这就是 Kubernetes 中 Sidecar 模式的形象比喻。2.2 实战为 Flask 应用添加日志采集 Sidecar我们贯穿案例的 Flask 应用会输出访问日志但日志只在容器内部。生产环境中需要把日志收集到外部系统如 Elasticsearch、Loki。直接修改 Flask 代码接入日志系统会增加业务代码的复杂度更好的做法是加一个 Sidecar 容器专门采集日志。以下 YAML 演示了一个典型的 Sidecar 部署——Flask 容器将日志写入共享 VolumeFilebeat Sidecar 读取并转发到 Elasticsearch此处简化为输出到 stdout 以便演示apiVersion: v1 kind: Pod metadata: name: flask-sidecar-demo labels: app: flask-sidecar spec: volumes: - name: shared-logs emptyDir:{}containers:# ---- 主容器Flask 应用 ----- name: flask-app image: flask-redis-counter:2.0 ports: - containerPort:5000env: - name: REDIS_HOST value: redis-service volumeMounts: - name: shared-logs mountPath: /app/logs# ---- Sidecar 容器Filebeat 日志采集 ----- name: log-collector image: docker.elastic.co/beats/filebeat:8.15.0 volumeMounts: - name: shared-logs mountPath: /var/log/flask readOnly:truecommand: - /bin/bash --c-|echo日志采集 Sidecar 已启动监听 /var/log/flasktail-f/var/log/flask/*.log2/dev/null||echo等待日志文件...解释一下数据流emptyDir卷在 Pod 创建时自动生成Pod 删除时随之销毁。Flask 向/app/logs写日志log-collector从/var/log/flask读日志——两个路径指向同一个 Volume。readOnly: true确保 Sidecar 只能读取不能修改日志文件。部署并验证kubectl apply-fflask-sidecar.yaml kubectl get pods# NAME READY STATUS RESTARTS AGE# flask-sidecar-demo 2/2 Running 0 30s# 模拟日志写入kubectlexecflask-sidecar-demo-cflask-app --sh-cecho test log /app/logs/access.log# 检查 Sidecar 是否读到了日志kubectl logs flask-sidecar-demo-clog-collector# 日志采集 Sidecar 已启动监听 /var/log/flask# test log业务容器只写了一行echoSidecar 容器就通过共享 Volume 实时读取到了日志内容。实际的 Filebeat 配置会更复杂包括定义输出目标为 Elasticsearch 或 Kafka但核心原理完全一致。Sidecar 容器的 K8s 原生特性从 v1.29 开始你可以在initContainers中设置restartPolicy: Always来声明一个 Sidecar 容器。这种 Sidecar 会在普通容器启动前就绪并在整个 Pod 生命周期内持续运行。上面的示例中我们仍使用普通容器模式两种方式功能等效但原生 Sidecar 特性提供了更好的生命周期保证。三、Adapter 模式统一监控数据格式Adapter 模式的核心思想是主应用输出的监控指标格式不符合 Prometheus 规范Adapter 容器负责转换格式对外暴露标准接口。它同样共享 Pod 网络但工作重点不是采集文件而是提供实时、可抓取的监控端点。3.1 场景你的 Flask 应用暴露了一个自定义的/metrics端点但输出的 JSON 格式 Prometheus 无法直接识别。Adapter 容器读取这个端点并转换为 Prometheus 格式。3.2 动手体验apiVersion: v1 kind: Pod metadata: name: flask-adapter-demo labels: app: flask-adapter spec: containers: - name: flask-app image: flask-redis-counter:2.0 ports: - containerPort:5000env: - name: REDIS_HOST value: redis-service - name: metrics-adapter image: alpine command: - /bin/sh --c-|whiletrue;do# 模拟从 Flask 的 /metrics 抓取 JSON 并转换为 Prometheus 格式echo# HELP flask_requests_total Total request countecho# TYPE flask_requests_total counterechoflask_requests_total$(curl-shttp://localhost:5000/health|grep-ostatus:ok|wc-l)sleep5doneAdapter 容器通过localhost:5000访问 Flask 主容器读取健康检查端点将其转换为 Prometheus 风格的指标输出到 stdout实际生产中会暴露一个 HTTP 端口供 Prometheus 抓取。这里curl连接localhost:5000能成功正是因为 Adapter 和主容器共享 Pod 的网络命名空间。四、Ambassador 模式代理外部服务Ambassador 模式的核心思想是主应用访问外部服务时不需要关心复杂的连接逻辑如 TLS 证书、连接池由 Ambassador 容器作为本地代理处理这些复杂性后转发给主容器。主应用只连接localhost上的代理端口。4.1 场景你的 Flask 应用需要连接外部的 Redis 集群而该集群要求 TLS 客户端证书认证。你的 Flask 镜像不想内置证书也不想修改连接逻辑。4.2 动手体验apiVersion: v1 kind: Pod metadata: name: flask-ambassador-demo labels: app: flask-ambassador spec: containers: - name: flask-app image: flask-redis-counter:2.0 ports: - containerPort:5000env: - name: REDIS_HOST value: localhost# 连接本地 Ambassador 代理- name: REDIS_PORT value:6379- name: redis-ambassador image: alpine/socat args: -TCP-LISTEN:6379,fork,reuseaddr-TCP:real-redis-cluster.example.com:6379Ambassador 容器使用socat在localhost:6379上建立一个 TCP 代理将流量转发到外部的real-redis-cluster.example.com:6379。Flask 容器通过REDIS_HOSTlocalhost连接这个本地代理完全不需要知道真实 Redis 的地址和证书细节。真实的生产场景中Ambassador 还可以集成 TLS 握手、认证令牌注入等逻辑——这些都封装在 Ambassador 容器中主应用完全无感知。五、三种模式总结与选择指南选择原则一个容器做好一件事多容器通过共享机制协作。如果辅助功能和主应用的生命周期紧密耦合必须一起调度、一起销毁就应该放在同一个 Pod 里。如果两个组件需要独立的扩缩容策略比如 Web 服务需要 5 个副本但日志采集只需要跟随节点部署则应该放在不同的 Pod 中。六、命令速查表七、本篇总结多容器 Pod 的设计哲学不是默认选择而是为了解决“功能增强”和“外部代理”的特定问题。Sidecar 模式增强主容器最常见——日志采集、文件同步。Adapter 模式适配器转换格式面向监控和可观测性。Ambassador 模式代理外部访问封装连接复杂性。核心机制三种模式都依赖 Pod 内的共享网络和共享存储这是与 Docker Compose 多容器协作最本质的区别。这三种模式为我们后续学习更高级的 K8s 能力做了重要铺垫。比如下一篇——第 24 篇健康检查探针机制详解我们将深入 liveness、readiness、startup 三种探针的配置和实战让 Pod 真正具备生产级的自愈和流量控制能力。想了解更多还可以去各个平台搜索「IT策士」一起升级 IT 思维