SideCar
北京土话叫三蹦子,通俗叫就是带棚子的三轮摩托车。今天我们要聊的 K8S 中三蹦子也称为边三轮车:边三轮车是在摩托车边上挂靠一个拖斗,云原生中的叫法是主容器和边车容器。本系列文章将展示 SideCar
模式的用法,以及如何通过 KCL 等面向配置的编程语言来简化 YAML 的编写。
首先以最简方式在 Kubernetes
环境启动一个 Web 服务。在下面 pod.yaml
文件中定义一个 Pod
,其中只有一个 Nginx
服务,在 80 端口启动一个 web
服务。
apiVersion: v1
kind: Pod
metadata:
name: web-app
spec:
containers:
- image: nginx
name: main-container
ports:
- containerPort: 80
Pod
是云原生中的一个基础原语。Pod
将多个容器包装为一个逻辑单元,Kubernetes
运行时确保 Pod
中的容器运行在一个机器上。因此 Pod
中的所有容器都共享生命周期、共享磁盘卷、共享网络环境等。SideCar
模式就是在 Pod
中增加其他容器来扩展和增强主容器的能力。
然后通过 kubectl create
命令行工具创建 Pod
,然后通过 kubectl get po
查看 Pod
执行状态:
$ kubectl create -f pod.yaml
$ kubectl get po
NAME READY STATUS RESTARTS AGE
web-app 1/1 Running 0 45m
可以看到一个名为 web-app
的 Pod
已经正常启动并运行,其中包含 Nginx
服务。为了便于外部访问配置端口转发,将宿主的 3999 端口对应到主容器的 80 端口:
$ kubectl port-forward web-app 3999:80
Forwarding from 127.0.0.1:3999 ->80
Forwarding from [::1]:3999 -> 80
端口转发是一个阻塞程序,保持命令行窗口打开。然后在浏览器打开测试页面:
现在我们尝试在不修改原始 Nginx
容器镜像的前提下,通过 SideCar
模式为 Nginx
服务增加定制 Web
页面的能力。在开始前先删除之前启动的 Pod
:
$ kubectl delete po web-app
pod "web-app" deleted
然后在 Pod
中增加第二个 Busybox SideCar
容器,完整的 pod.yaml
文件如下:
apiVersion: v1
kind: Pod
metadata:
name: web-app
spec:
containers:
- image: nginx
name: main-container
ports:
- containerPort: 80
# --- 以下是新添加的内容 ---
# 和 SideCar 通过 磁盘卷共享要发布的文件目录
volumeMounts:
- name: var-logs
mountPath: /usr/share/nginx/html
# SideCar 容器
- image: busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(date -u) 'Hi I am from Sidecar container' > /var/log/index.html; sleep 5;done"]
name: sidecar-container
volumeMounts: var-logs
mountPath: /var/log
# Pod 中全部容器共享磁盘卷
volumes:
- name: var-logs
emptyDir: {}
Busybox SideCar
容器执行的命令对应以下 Shell
脚本:
while true; do
echo $(date -u) 'Hi I am from Sidecar container' > /var/log/index.html;
sleep 5;
done
SideCar
容器只有一个功能:每隔 5 秒钟覆盖一次 /var/log/index.html
文件,这个文件刚好对应 Nginx
的服务的首页页面文件。
然后重新启动 Pod
,并重新映射本地宿主机端口到容器端口:
$ kubectl create -f pod.yaml
pod/web-app created
$ kubectl port-forward web-app 3999:80
Forwarding from 127.0.0.1:3999 -> 80
Forwarding from [::1]:3999 -> 80
重新打开浏览器后将看到以下页面:
简单来说,Busybox
是 SideCar
容器角色,负责生产首页数据;而 Nginx
是主容器,负责消费 Busybox
生产的主页数据;两个容器通过 var-logs
磁盘卷共享空间。如果以 Go 语言的术语类比,Nginx
是主 Goroutine
,Busybox
是后台干脏活的 Goroutine
,而共享的磁盘卷类似 Channel
的作用。
在这个例子中 Nginx
依然是主容器,SideCar
容器是 BusyBox
。我们还可以挂更多 SideCar
容器,比如网络、监控、日志等等。
这样就通过 SideCar
模式,在不修改 Nginx
主容器的前提下,扩展出了网络、监控、日志等能力。
现在容器已经成为一种流行的打包技术,各种不同角色的同学可以通过容器以统一的方式构建、发布和运行程序,甚至管理各种资源。因此容器更像一个功能明确的产品,它有自己的运行时、发布周期、文档和 API 等。好的容器/产品只负责解决一个问题,保持了 KISS 原则可以让容器本身具有极高的重用性和可被替代性。正是因为可重用才使得现代化的构建程序的流程更加敏捷和高效。但是可复用的容器一般都功能单一,我们常常需要通过各种手段扩展容器的功能,以及需要更多的容器之间的协同。
三蹦子 SideCar
可以在不改造主摩托车的前提下增加 N 个拖车功能,相应地云原生 SideCar
模式可以在无需修改主容器的前提下扩展并增强已有主容器功能。如果将云原生的玩法和面向对象编程联系起来,容器镜像就是 Java
中的 class
,而执行中的容器就是 class
的实例。而面向对象的 class
继承就是基于已有的容器镜像做扩展,SideCar
则是通过类似组合的模式扩展 class
的能力。
面向对象编程中有一个“组合优于继承,多用组合少用继承”的规则,因此 SideCar 也是推荐使用的模式。正是因为三蹦子模式的优点,最近在云原生场景也被大量使用:比如在边车上架一些类似机关枪的网络服务、监控、跟踪等功能。
这一篇文章我们简要介绍并在 Kubernetes
环境展示了 SideCar
模式,同时结合传统的面向对象编程思想对比了 SideCar
和组合编程模式的关系。SideCar
模式的优势不仅仅体现在无害增强主容器,更灵活的是可以在 apply
时动态调整 SideCar
能力。
在后面的文章中,我们将尝试结合 KCL
等现代化的云原生配置语言来简化 SideCar
配置的编写。通过尝试探索通过 KCL
动态注入和修改 SideCar
来扩展基于已有配置的能力。
1
jieyanji 2023-06-30 10:41:30 +08:00
考 k8s 认证中,就有一提,要求读取 nginx 容器里面的日志文件,然后打印到 console
|
2
xinmans 2023-07-02 13:48:47 +08:00
不就是共享云盘的逻辑吗,搞得很神秘
|