Kubernetes 应用最佳实践 - Sidecar 模式
2023-03-16 Kubernetes
Sidecar 模式
Sidecar (边车) 是一种安装在摩托车、踏板车或自行车侧面的单轮装置,使整个车辆成为三轮车辆。 – 维基百科
Sidecar 和 Kubernetes 之间并没有什么实质性联系,但是通过 Sidecar 的机械工业设计思路,可以提炼出一种代码或者模块间的工作模式,称之为 “Sidecar 模式”。
在前面的文章中提到过,Pod 是 Kubernetes 中应用运行的最小单位 (同时也是顶级资源),也称为容器组,既然每个 Pod 可以存在多个容器, 根据二八原则,可以将多个容器分为核心容器和非核心容器,将机械的 Sidecar (三轮摩托) 映射到 Pod 中的容器资源,就可以得到 “Sidecar 模式” 的通俗表达:
- 核心容器也称为 Main 容器,负责主要工作 (对应三轮摩托的驾驶位)
- 非核心容器也称为 Sidecar 容器,负责辅助工作和扩展性工作 (对应三轮摩托的侧面单轮装置)
组合优于继承
Sidecar 容器可以在不修改 Main 容器的情况下,进行功能扩展和增强,允许功能单一的容器通过运行时组合完成更多任务,同时分离每个容器的关注点。
大多数情况下,多个不同的容器由不同的团队开发,并且使用不同的技术栈,通过正交性保证单个容器在其他服务中可以被复用,既可以单个容器作为 Pod 独立运行,也可以多个容器协作运行。
示例
Pod 内部的容器可以通过卷 (Volume) 来共享文件数据,并且通过本地网络进行通信,我们可以利用 Pod 这两个特性来列举几个使用 Sidecar 模式的小例子。
1. 静态资源服务器
在这个示例中,主要分为两个容器:
- Main 容器: HTTP Server 容器仅仅提供静态资源文件的 HTTP 请求服务,不需要关注具体的文件来源
- Sidecar 容器: 将静态资源文件通过 Git 定时从远程服务器同步到本地 HTTP Server 指定的目录,不需要关注文件同步后的下一步操作
2. 配置热更新
在这个示例中,主要分为两个容器:
- Main 容器: 也就是应用容器
- Sidecar 容器: 将 ConfigMap 挂载为一个卷(Volume), 应用可以直接从卷中读取配置数据 (这里的 Sidecar 并不是容器形式,但是这也是 Sidecar 模式的一种体现)
当配置数据需要更新时,修改 ConfigMap, 然后 Kubernetes 会自动触发相关的事件,通知 Pod 更新其挂载的卷,Pod 接收到更新事件,重新加载卷中的配置文件,从而实现配置热更新。
3. 日志
在这个示例中,主要分为两个容器:
- Main 容器: 也就是应用容器
- Sidecar 容器: 也就是 FileBeat 日志收集组件
FileBeat 收集日志之后,发送到 ElasticSearch 集群, 最后通过 Kibana 展示。
适配器模式
Kubernetes 中的适配器模式是 Sidecar 模式的一个变种,作用和 “设计模式” 中的适配器模式类似,用于对异构的容器系统进行包装,最终对外输出自适应统一的接口。
容器允许我们以统一的方式打包和运行用不同库和语言编写的应用程序。如今,多个团队使用不同的技术并创建由异构组件组成的分布式系统是很常见的。
当其他系统必须以统一的方式处理所有组件时,这种异构性可能会造成困难。适配器模式通过隐藏系统的复杂性并提供对其的统一访问来提供解决方案。
示例
1. 监控系统
例如现在有一个监控系统希望监控所有服务,但是不同的服务是通过不同的技术栈完成的,并且接口输出的监控指标格式和协议也不相同,这时候就可以通过适配器模式, 在内部将不同的服务的指标转换成一种格式和协议,最后输出给监控系统 (例如 Prometheus)。
在这个示例中,主要分为两个容器:
- Main 容器: 也就是应用容器
- Sidecar 容器: 读取应用容器本地存储的指标,并转换为监控系统可以理解的格式和协议
例如,对于运行在 Pod 中的 Go 应用,Sidecar 容器知道如何获取和解析监控系统需要的数据,而对于运行在 Pod 中的 Java 应用,Sidecar 容器同样如此, 简单来说,Sidecar 容器就是那个 “最强辅助”。
大使模式
大使模式是 Sidecar 模式的另外一个变种,作用和 “设计模式” 中的代理模式类似,通过对外统一接口来隐藏内部的业务逻辑和实现。
示例
1. 缓存
在这个示例中,主要分为两个容器:
- Main 容器: 也就是应用容器
- Sidecar 容器: 读取缓存数据,这里将数据存储委托给 etcd
当然,也可以将 Sidecar 容器的存储委托方切换到 memcached: