作者:王易可(楚岳)
背景
Helm 是云原生范畴被广泛选用的客户端运用打包和布置工具,其简洁的规划和易用的体会得到了用户的认可并形成了自己的生态,到现在已有近万个运用运用 Helm Chart 的办法打包。Helm 的规划理念足够简洁,甚至能够归纳为以下两条:
1. 对杂乱的 Kubernetes API 做打包和模板化,抽象并简化为少数参数。
2. 给出运用生命周期解决计划:制造、上传(保管)、版别化、分发(发现)、布置。
这两条规划原则确保了 Helm 足够灵敏,同时也足够简略,能够包括悉数的 Kubernetes API,很好的解决了云原生运用一次性交给的场景。可是关于具有必定规划的企业而言,运用 Helm 做软件的持续交给就出现了不小的应战。
Helm 持续交给的应战
Helm 规划之初就为了确保其简略易用,放弃了杂乱的组件编列。所以在运用布置时,Helm 是一股脑将一切的资源交给到 Kubernetes 集群中,期望经过 Kubernetes 面向终态的自愈才能,自动化的解决运用的依赖和编列问题。 这样的规划在初次布置时或许没有问题,可是关于具有必定规划的企业出产环境而言,就显得过于抱负化了。
一方面,在运用晋级时一股脑将资源悉数更新很简单因为部分服务短暂的不可用形满足体的服务中止;另一方面,假如软件存在 BUG,也无法及时回滚,很简单将影响规划扩大,难以控制。在某些更严峻的场景下,如存在出产环境部分配置被运维人工修正过,因为 Helm 一次性布置会将原有的修正悉数覆盖,而 Helm 之前的版别与出产环境或许并不一致,导致回滚也无法恢复,形成更大面积的故障。
由此可见,当具有必定规划今后,软件在出产环境的灰度和回滚的才能极其重要,而 Helm 自身并不能确保足够的安稳性。
如何针对 Helm 做金丝雀发布?
通常状况下,一个严谨的软件晋级进程会遵从相似如下流程:大致分红三个阶段,第一阶段晋级少数(如 20% )的实例,并切换少数流量到新版别,完结这个阶段后先暂停晋级。经过人工承认之后持续第二个阶段,晋级更大份额(如 90% )的实例和流量,再次暂停等待人工承认。最终阶段将全量晋级到新版别并验证结束,然后完结整个发布进程。假如晋级期间发现包括业务指标在内的任何反常,例如 CPU 或 memory 反常运用率升高或恳求 500 日志过多等状况,能够快速回滚。
上面便是一个典型的金丝雀发布的场景,那么针对 Helm Chart 运用,咱们该如何完结上面这个流程呢?业界的典型做法通常有如下两种:
-
修正 Helm Chart,将作业负载变成两份,并分别暴露出不同的 Helm 参数,在发布时不断修正两份作业负载的镜像、实例数和流量份额,然后完成灰度发布。
-
修正 Helm Chart,将原先的根底作业负载修正为具有同样功用可是具有灰度发布才能的自界说作业负载,并暴露出 Helm 参数,在发布是操作这些灰度发布的 CRD。
这两个计划都很杂乱,有不小的改形成本,尤其是当你的 Helm Chart 是第三方组件无法修正或自身不具有维护 Helm Chart 才能时,这些办法都是不可行的。 即便真的去改造了,比较于原先简略的作业负载模式,也存在不小的安稳性风险。究其原因,还是在于 Helm 本身的定位只是一个包办理工具,规划时并不考虑灰度发布、也不针对作业负载做办理。
事实上,当咱们跟社区的大量用户深入沟通今后,咱们发现大多数用户的运用并不杂乱,类别都是比如 Deployment、StatefulSet 这些经典的类型。所以,咱们经过 KubeVela 强壮的插件机制,联合OpenKruise 社区 [ 1] 做了一款针对这些限定类型的金丝雀发布插件。这款插件协助你不做任何迁移改造,轻松完结 Helm Chart 的灰度发布。 不仅如此,假如你的 Helm Chart 比较杂乱,你完全能够针对你的场景定制一个插件,获得同样的体会。
下面咱们经过一个实践的比如(以 Deployment 作业负载为例),手把手带你感受一下完好的流程。
运用 KubeVela 做金丝雀发布
预备环境
- 装置 KubeVela
curl -fsSl https://static.kubevela.net/script/install-velad.sh | bash
velad install
查看文末文档1 [ 2] 以了解更多装置细节。
- 启用相关的 addon
vela addon enable fluxcd
vela addon enable ingress-nginx
vela addon enable kruise-rollout
vela addon enable velaux
在这一步中,启动了以下几个插件:
-
fluxcd 插件协助咱们具有 helm 交给的才能;
-
ingress-nginx 插件用于供给金丝雀发布的流量办理才能;
-
kruise-rollout 供给金丝雀发布才能;
-
velaux 插件则供给界面操作和可视化。
- 将 nginx ingress-controller 的端口映射到本地
vela port-forward addon-ingress-nginx -n vela-system
初次布置
经过履行下面的指令,第一次发布 helm 运用。在这一步中,咱们经过 vela 的 CLI 工具布置,假如你熟悉 Kubernetes,也能够经过 kubectl apply 布置,作用完全相同。
cat <<EOF | vela up -f -
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: canary-demo
annotations:
app.oam.dev/publishVersion: v1
spec:
components:
- name: canary-demo
type: helm
properties:
repoType: "helm"
url: "https://wangyikewxgm.github.io/my-charts/"
chart: "canary-demo"
version: "1.0.0"
traits:
- type: kruise-rollout
properties:
canary:
# The first batch of Canary releases 20% Pods, and 20% traffic imported to the new version, require manual confirmation before subsequent releases are completed
steps:
- weight: 20
# The second batch of Canary releases 90% Pods, and 90% traffic imported to the new version.
- weight: 90
trafficRoutings:
- type: nginx
EOF
在上面的比如中,咱们声明晰一个名为 canary-demo 的运用,其中包括一个 helm 类型的组件(KubeVela 也支撑其他类型的组件布置),在组件的参数中包括 chart 的地址以及版别等信息。
别的,咱们还为这个组件声明晰 kruise-rollout 的运维特征,这个便是 kruise-rollout 这个插件装置后具有的才能。其中能够指定 helm 的晋级战略,第一个阶段先晋级 20% 的实例和流量,经过人工承认之后再晋级 90%,最终全量升到最新的版别。
需求留意的是,为了演示作用直观(体现版别改变),咱们专门预备了一个chart [ 3] 。该 helm chart 的主体包括一个 Deployment 和 Ingress 对象,这是 helm chart 制造时最通用的场景。假如你的 helm chart 同样具有上述的资源,也相同能够经过这个比如进行金丝雀的发布。
布置成功之后,咱们经过下面的指令拜访你集群内的网关地址,将会看到下面的作用:
$ curl -H "Host: canary-demo.com" http://localhost:8080/version
Demo: V1
别的,经过 VelaUX 的资源拓扑页面,咱们能够看到五个 V1 版别的实例已经悉数安排妥当。
晋级运用
运用下面的这个 yaml ,来晋级你的运用。
cat <<EOF | vela up -f -
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: canary-demo
annotations:
app.oam.dev/publishVersion: v2
spec:
components:
- name: canary-demo
type: helm
properties:
repoType: "helm"
url: "https://wangyikewxgm.github.io/my-charts/"
chart: "canary-demo"
# Upgade to version 2.0.0
version: "2.0.0"
traits:
- type: kruise-rollout
properties:
canary:
# The first batch of Canary releases 20% Pods, and 20% traffic imported to the new version, require manual confirmation before subsequent releases are completed
steps:
- weight: 20
# The second batch of Canary releases 90% Pods, and 90% traffic imported to the new version.
- weight: 90
trafficRoutings:
- type: nginx
EOF
咱们留意到新的 application 和初次布置的比较仅有两处改动:
-
把 app.oam.dev/publishVersion 的 annotation 从 v1 晋级到了 v2。这代表这次修正是一个新的版别。
-
把 helm chart 的版别晋级到了 2.0.0 ,该版别的 chart 中的 deployment 镜像的 tag 晋级到了 V2。
一段时间之后,咱们会发现晋级进程停在了咱们上面界说的第一个批次,也便是只晋级 20% 的实例和流量。这个时分屡次履行上面拜访网关的指令,你会发现 Demo: v1 和 Demo: v2交替出现,并且有差不多 20% 的概率得到 Demo: v2 的结果。
$ curl -H "Host: canary-demo.com" http://localhost:8080/version
Demo: V2
再次查看运用的资源的拓扑状况,会看到由 kruise-rollout trait 创立出来的 rolloutCR 为咱们创立了一个新版别的实例,而之前作业负载创立出来的 5 个旧版别的实例并没有发生改变。
接下来,咱们经过 vela 的 CLI 履行下面的指令,经过人工审阅恢复持续晋级:
vela workflow resume canary-demo
一段时间之后,经过资源拓扑图,咱们看到五个新版别的实例被创立出来了。这个时分咱们再次拜访网关,会发现出现 Demo:v2 的概率大幅增加,接近于 90%。
快速回滚
通常在一个真实场景中的发布中,常常会有经过人工审阅之后,发现新版别运用的状况反常,需求停止当前的晋级,快速将运用回退到晋级开始前的版别。
咱们就能够履行下面的指令,先暂停当前的发布作业流:
$ vela workflow suspend canary-demo
Rollout default/canary-demo in cluster suspended.
Successfully suspend workflow: canary-demo
紧接着回滚到发布之前的版别,也便是 V1 :
$ vela workflow rollback canary-demo
Application spec rollback successfully.
Application status rollback successfully.
Rollout default/canary-demo in cluster rollback.
Successfully rollback rolloutApplication outdated revision cleaned up.
这个时分,咱们再次拜访网关,会发现一切的恳求结果又回到了 V1 的状况。
$ curl -H "Host: canary-demo.com" http://localhost:8080/version
Demo: V1
这时分,经过资源拓扑图,咱们能够看到,金丝雀版别的实例也悉数被删除了,并且从始至终,v1 的五个实例,作为安稳版别的实例,一直没有发生任何改变。
假如你将上面的回滚操作改为恢复持续晋级,将会持续履行后续的晋级进程,完结全量发布。
上述 demo 的完好操作进程请参阅文末文档 2 [ 4] 。
假如你期望直接运用原生的 K8s 资源完成上面进程能够参阅文末文档3 [ 5] 。别的,除了 Deployment ,kruise-rollout 插件还支撑了 StatefulSet 和 OpenKruise 的 CloneSet ,假如你的 chart 中的作业负载类型是以上三种都能够经过上面的比如完成金丝雀发布。
相信你也看留意到,上面的比如咱们给出的是依据 nginx-Ingress-controller 的七层流量切分计划,别的咱们也支撑了KubernetesGateway 的API [ 6] 然后能够支撑更多的网关类型和四层的流量切分计划。
发布进程的安稳性是如何确保的?
初次布置完结后,kruise rollout 插件(以下简称 rollout)会监听 Helm Chart布置的资源,在咱们的比如中便是 deployment, servcie 和 ingress ,还支撑 StatefulSet 以及 OpenKruise Cloneset。rollout 会接收这个 deployment 后续的晋级动作。
在进行晋级时,新版别的 Helm 布置首要生效,会将 deployment 的镜像更新为 v2,可是这个时分 deployment 的晋级进程会被 rollout 从 controller-manager 手中接收,使得 deployment 下面的 Pod 不会被晋级。于此同时,rollout 会复制一个金丝雀版别的 deployemnt,镜像的 tag 为 v2,并创立一个 service 挑选到它下面的实例,和一个指向这个 service 的 ingress ,最终经过设置 ingress 相对应的 annotation,让这个 ingress 接受金丝雀版别的流量(具体能够参阅文末文档 4 [ 7] ),然后完成流量切分。
在经过一切的人工承认过程之后,完结全量发布时,rollout 会把安稳版别的 deployment 晋级控制权交还给 controller-manager ,到时安稳版别的实例会连续晋级到新版别,当安稳版别的实例悉数安排妥当之后,才会连续毁掉金丝雀版别的 deployment,service 和 ingress,然后确保了整个进程中恳求流量不会因为打到没有安排妥当的实例上,导致恳求反常,做到无损的金丝雀发布。
之后咱们还将在以下方面持续迭代,支撑更多的场景并带来愈加安稳可靠的晋级体会:
-
晋级进程对接 KubeVela 的 workflow 系统,然后引进愈加丰厚的中间过程扩展系统,支撑晋级进程中经过 workflow 履行通知发送等功用。甚至在各个过程的暂停阶段,对接外部的可观测性系统,经过查看日志或许监控等指标,自动决策是否持续发布或回滚,然后完成无人值守的发布战略。
-
集成 istio 等 更多的 addon,支撑 ServiceMesh 的流量切分计划。
-
除了支撑依据百分比流量切分办法,支撑依据 header 或 cookie 的流量切分规则,以及支撑比如蓝绿发布等特性。
总结
前文已经说到,KubeVela 支撑 Helm 做金丝雀发布的流程完全是经过插件(Addon)系统完成的,fluxcd addon 助咱们经过布置和办理 helm chart 的生命周期。kruise-rollout addon 协助咱们完成 workload 的实例晋级以及在晋级进程中流量的切换。经过组合两个 addon 的办法,完成了关于 Helm 运用的全生命周期的办理和金丝雀晋级,不需求对你的 Helm Chart 做任何改动。你也能够针对你的场景编写插件 [ 8] ,完结更特殊的场景或流程。
依据 KubeVela 强壮的可扩展才能,你不仅能够灵敏的组合这些 addon,你还能够保持上层运用不做任何变化的状况下,依据不同的渠道或环境动态替换底层的才能完成。 例如,假如你更期望选用 argocd 不是 fluxcd 完成关于 Helm 运用的布置,你就能够经过启用 argocd 的 addon 完成相同的功用,上层的 Helm 运用不需求做任何改变或迁移。
现在 KubeVela 社区已经供给了数十个 addon ,能够能够协助渠道扩展 可观测性,gitops,finops ,rollout 等各方面的才能。
假如你对 addon 感兴趣的话,也十分欢迎为Addon 的库房 [ 9] 提交你的自界说插件,为社区贡献新的生态才能!
参阅链接:
[1] OpenKruise 社区:
openkruise.io/
[2] 文档 1:
kubevela.net/docs/instal…
[3] chart:
github.com/wangyikewxg…
[4] 文档 2:
kubevela.net/docs/tutori…
[5] 文档 3:
*kubevela.net/docs/tutori…
[6] API :
gateway-api.sigs.k8s.io/
[7] 文档 4:
kubernetes.github.io/ingress-ngi…
[8] 编写插件:
kubevela.net/docs/platfo…
[9] Addon 的库房地址:
github.com/kubevela/ca…
您能够经过如下资料了解更多关于 KubeVela 以及 OAM 项目的细节:
-
项目代码库:github.com/oam-dev/kubevela 欢迎 Star/Watch/Fork!
-
项目官方主页与文档:kubevela.io ,从 1.1 版别开始,已供给中文、英文文档,更多言语文档欢迎开发者进行翻译。
-
项目钉钉群:23310022;Slack:CNCF #kubevela Channel
-
加入微信群:请先添加以下 maintainer 微信号,标明进入 KubeVela 用户群:
戳此处:查看 KubeVela 项目官网!!