K8S 1.18版本将内置支持Sidecar容器
一、前言
Kubernetes的目标不仅是使分布式应用程序的部署和运维变得简单可靠,还旨在能轻松地创建“云原生”应用程序,即易于创建在云环境中运行的分布式应用程序和服务,于是从1.18版本开始K8S将原生支持生命周期类型为Sidecar的容器。
在云原生时代,通过将应用的非业务功能提到Sidecar容器实现解耦,避免重复建设,给运维人员提供更为丰富而深入的控制同时,也大大减轻了开发人员的负担。
随着越来越多的应用程序开始实施这种模式,在K8S中出现了很多的问题。很快,Kubernetes意识到应该提供一种Sidecar模式的容器,并以不同的方式处理此类容器的生命周期。
二、痛点
Sidecar容器的所有问题都与容器生命周期相关性有关。由于Pod中的常规容器之间没有区别,因此无法控制哪个容器首先启动或最后终止,但是先正确运行Sidecar容器通常是应用程序容器正确运行的要求。
Pod启动
让我们看一个Istio服务网格示例。Envoy sidecar负责将所有传入和传出流量代理到应用程序容器。因此,在代理启动并运行之前,应用程序应该无法发送或接收流量。此时,如果应用程序尝试出站访问,则K8S的就绪性探针便形同虚设。如果应用容器先启动,您会在日志中看到很多莫名的错误消息,明明应用已启动了,为什么还报503呢?但如果代理容器正常启动,但业务容器遭遇CrashLoopBackoffs
时,应用容器根本启动失败,此时代理容器该何去何从?
其实这也不是一个非常棘手的问题,我们可以在应用程序容器的启动脚本中添加几秒钟的延迟,通过一个丑陋的解决方法间接地解决此问题,这也是Istio当下的做法。
三、解决方案
为了彻底解决上述痛点,从1.18版本开始,K8S内置的Sidecar功能将确保sidecar在正常业务流程开始之前就启动并运行,即通过更改pod的启动生命周期,在init容器完成后启动sidecar容器,在sidecar容器就绪后启动业务容器,从启动流程上保证顺序性。
四、新功能的影响
作业完成
如果Kubernetes作业具有Sidecar容器,则即使主容器完成后它仍将继续运行,并且作业本身永远不会达到完成状态。因为解决该问题的唯一方法是在业务过程完成时以某种方式发送信号给sidecar容器以退出。
这种解决方法存在一些问题:这意味着使用自定义逻辑扩展所有作业,并以某种方式在容器之间进行同步:通过共享的暂存卷或某些临时解决方案,例如Envoy的/quitquitquit
终结点。
故从Kubernetes 1.18开始,如果所有普通容器都已到达终端状态(Succeeded
for restartPolicy=OnFailure
或Succeeded/Failed
for restartPolicy=Never
),则将向所有sidecar容器发送 SIGTERM
信号。
Pod关闭
Pod关闭与Pod启动类似。如果Sidecar在业务过程之前终止,则在正常拆除业务应用程序期间可能会导致大量错误。在正常关闭期间,应用程序可以执行某种清除逻辑,例如关闭长期连接,回滚事务或将状态保存到外部存储(例如s3)。如果首先杀死了sidecar,则可能会导致清理逻辑无法正常运行。
一个很好的例子是argo项目中报告的一个问题。Argo尝试将容器日志存储在s3中,但是如果istio-proxy
先杀死则无法这样做,因为所有流量都应流经该容器。
此类问题的解决方案类似于启动问题。通过更改Pod终止生命周期,首先向所有应用容器发送一个SIGTERM
信号,等所有应用容器全部正常终止后,再向所有sidecar容器发送SIGTERM
信号。在正常的平滑期(TerminationGracePeriod
)内,如果所有的应用容器还未终止,像以前一样发送SIGKILL
信号强制终止,然后发送SIGTERM
信号给sidecar容器。
五、如何使用新功能?
通过更改Pod规范中的container.lifecycle.type
将容器标记为sidecar类型:Sidecar
,默认为Standard
,如下:
apiVersion: v1
kind: Pod
metadata:
name: bookings-v1-b54bc7c9c-v42f6
labels:
app: demoapp
spec:
containers:
- name: bookings
image: banzaicloud/allspark:0.1.1
...
- name: istio-proxy
image: docker.io/istio/proxyv2:1.4.3
lifecycle:
type: Sidecar
...
注意:在k8s 1.18版本,sidecar模式仅仅作为支撑功能,故需要通过Api Server显示启用。
六、总结
本篇先详细介绍了K8S即将推出的重磅功能,可以说此功能专为云原生而设计,这也是为什么K8S会越来越受欢迎的原因,然后进一步分析了当下K8S实施sidecar模式的痛点,以及引入新功能的一些影响,最后通过例子演示了如何应用sidecar模式到Pod中,可以看出此功能将从根本上解决目前很多使用sidecar模式存在的问题。
七、参考资料
https://banzaicloud.com/blog/k8s-sidecars
https://github.com/kubernetes/enhancements/issues/753
https://kubernetes.io/blog/2016/06/container-design-patterns
活动
获得 MOSN 核心开发团队指导,详见:https://github.com/mosn/mosn.io/issues/32
MOSN 是一款使用 Go 语言开发的网络代理软件,可以作为 Service Mesh 的数据平面,支持 Dubbo、Tars、SOFARPC、HTTP 1.1/2 等协议。由蚂蚁金服开源,并经过几十万容器的生产级验证。官方网站:https://mosn.io/zh