三、 基于Kaniko的设计实现
目前支持在容器内部进行镜像构建的开源技术有很多:Kaniko,BuildKit,Img等,其中Kaniko作为Google官方开源的容器化构建解决方案,目前收获了最高的star数量,社区活跃度也最高。排名其后的BuildKit和Img也通过其自身的技术优点吸引了一大批粉丝。
从架构上看,BuildKit和Img都是通过内置一个非Root权限的嵌套容器去执行构建。而Kaniko没有拉起嵌套容器去做构建,而是直接实现了Docker daemon中create job的功能,更加的轻量、高效、安全。因此,SREWorks基于Kaniko去做云原生下的镜像构建。
在引入Kaniko之后,SREWorks的中心管控appmanager服务按照如下架构来对接ApiServer拉起和管控执行构建任务的pod。
AppManager关键模块讲解:
• Provider模块:AppManager内置了一系列的Provider负责处理Client客户端的请求。
• 构建任务状态管理器(ComponentPackageTaskStateActionManager):负责监听各类构建任务状态更新事件,进而调用不同构建阶段的子处理器。
• RunningState,FailureState,SuccessState等模块:具体负责处理不同构建阶段的事务。
• ComponentPackageBuilderService模块:负责具体的镜像构建、构建Pod管控等工作。
这里主要讲一下镜像构建的主要工作流程:
a) 将应用Component包(每个应用可包含多个Component,每个Component又可包含多个Container)拆解为多个Container构建任务。
b) 启动构建Pod Informer监听。
c) 下载每个Container构建源代码,并渲染Dockerfile文件。
d) 渲染并下发构建Pod yaml并监听构建pod状态。
e) 当构建pod到达终态时,进行Component交付包生成、资源清理等工作。
四、 设计反思
通过以上基于Kaniko架构设计和实现,SREWorks提出了持续交付云原生化的设计要求,并为此设计并实现了自己的解决方案。在此罗列一些目前的架构Feature供大家深入发掘一下:
• 内置了Dockerfile参数动态渲染功能,这为运维人员提供了可操作空间。
• 由于目前云底座K8S等,都已支持所有实现了Container Runtime Interface(CRI)的容器运行时(例如Docker、containerd、CRI-O),所以本文所提DinD,在目前云原生形态下称其为DinC(Container)更为准确。
• SREWorks的持续交付物的核心是镜像,在某些特殊场景下,交付物即使转变为机器时代的Jar包或者比镜像更高级的形态,但是本文的弹性架构设计依然适用。
• 共享PV下发构建tar包:可以去除MinIO的依赖,执行构建任务的pod直接从共享PVC内读取构建tar包。但是由于在某些云底座上,无内置“ReadWriteMany”访问模式的PV,所以暂时关闭了这项功能。
• 构建Pod替换成Job:使用Pod进行构建的初衷是足够轻量化,且AppManager具有绝对的管控权限。目前还没有足够的替换理由。
五、 云原生建设感悟浅谈
广义地来看,可以说现在的几乎所有云产品都是云原生的,因为他们都或多或少满足了云原生所标榜的微服务、容器、持续交付、DevOps。但是,狭义地来看,在某些场景下,其往往又不能完全满足云原生的某些特性:例如可复用、免运维、资源池化等。
正如CNCF对云原生的定义:“云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API”。在作者看来,其内在含义代表着一种以产品能力为导向的最佳上云实践。
脱离“产品”这个导向,云原生化往往是没有意义的;“最佳实践”代表云原生化是不断迭代的;以本文镜像构建的演进为例,也是在产品能力的指导下,不断迭代和完善的,这就是云原生化的意义。