背景
ArgoCD职责主要是监听Git仓库中的应用编排的变化,并集群中应用真实运行状态进行对比,自动/手动去同步拉取应用编排的变更到部署集群中。Argo Rollouts提供了更强大的蓝绿、金丝雀部署能力。在实践中可以将两者结合来提供基于GitOps 的渐进式交付能力。
前提条件
-
创建Istio版本为1.12.4.50或更高版本的阿里云服务网格 (ASM) 企业版实例。
-
创建容器服务Kubernetes (ACK) 集群。
-
将ACK集群添加到阿里云服务网格ASM实例。
-
已安装Argo Rollouts(本文档以v1.2.1为例) 。
安装Argo Rollout
使用数据面集群的kubeconfig,执行如下命令,安装Argo Rollout服务端。更多详情可参考Arog Rollout官网。
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
执行如下命令安装Kubectl Argo Rollout插件,方便通过kubectl进行管理。
brew install argoproj/tap/kubectl-argo-rollouts
启用阿里云服务网格ASM的数据面KubeAPI访问能力
金丝雀发布
创建Rollout
将一下内容保存为rollout.yaml。
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: istio-rollout
spec:
revisionHistoryLimit: 2
selector:
matchLabels:
app: istio-rollout
template:
metadata:
annotations:
sidecar.istio.io/inject: "true"
labels:
app: istio-rollout
spec:
containers:
- name: istio-rollout
image: argoproj/rollouts-demo:blue
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m
strategy:
canary:
canaryService: istio-rollout-canary
stableService: istio-rollout-stable
trafficRouting:
istio:
virtualService:
name: istio-rollout-vsvc
routes:
- primary
steps:
- setWeight: 10
- pause: {} # 手工卡点
- setWeight: 20
- pause: {duration: 20s}
- setWeight: 30
- pause: {duration: 20s}
- setWeight: 40
- pause: {duration: 20s}
- setWeight: 50
- pause: {duration: 20s}
- setWeight: 60
- pause: {duration: 20s}
- setWeight: 70
- pause: {duration: 20s}
- setWeight: 80
- pause: {duration: 20s}
- setWeight: 90
- pause: {duration: 20s}
使用数据面集群的kubeconfig,执行如下命令:
kubectl apply -f rollout.yaml
创建Service
将一下内容保存为service.yaml
apiVersion: v1
kind: Service
metadata:
name: istio-rollout-canary
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: istio-rollout
---
apiVersion: v1
kind: Service
metadata:
name: istio-rollout-stable
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: istio-rollout
执行如下命令进行创建
kubectl apply -f service.yaml
创建Istio相关资源
1. 创建虚拟服务VirtualService
由于启用了ASM的数据面KubeAPI访问能力,可以通过数据面的kubeconfig访问ASM中的VirtualService和Gateway、DestinationRule等Istio资源。也可以通过ASM控制台或者ASM kubeconfig创建Istio资源。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: istio-rollout-vsvc
spec:
gateways:
- istio-rollout-gateway
hosts:
- '*'
http:
- match:
- uri:
prefix: /
name: primary
route:
- destination:
host: istio-rollout-stable
weight: 100
- destination:
host: istio-rollout-canary
2. 创建网关规则Gateway
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: istio-rollout-gateway
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*'
port:
name: http
number: 80
protocol: HTTP
创建阿里云服务网格ASM网关
选择阿里云服务网格的ASM网关作为我们测试访问的入口,端口设置为80。
查看创建状态
执行如下命令进行查看:
kubectl argo rollouts get rollout istio-rollout
kubectl argo rollouts get rollout istio-rollout
Name: istio-rollout
Namespace: default
Status: ✔ Healthy
Strategy: Canary
Step: 18/18
SetWeight: 100
ActualWeight: 100
Images: argoproj/rollouts-demo:blue (stable)
Replicas:
Desired: 1
Current: 1
Updated: 1
Ready: 1
Available: 1
NAME KIND STATUS AGE INFO
⟳ istio-rollout Rollout ✔ Healthy 52s
└──# revision:1
└──⧉ istio-rollout-7f96d86486 ReplicaSet ✔ Healthy 52s stable
└──□ istio-rollout-7f96d86486-vpqvb Pod ✔ Running 52s ready:2/2
测试初始状态
在阿里云服务网格 -> ASM网关处,可以获取到刚刚创建的ASM网关的IP地址,在浏览器中输入 http ://{ASM网关IP}/,即可访问。
访问效果如下所示,此界面会并发调用http ://{ASM网关IP}/color,将获取到颜色信息填充到方格中。因为在Rollout istio-rollout中,我们指定的颜色为blue,并且还未进行金丝雀发布,所以显示的只有蓝色。
滚动更新
1:更新镜像版本
我们接下来希望将格子中的颜色逐渐变为黄色。执行如下命令来设置镜像版本的:
kubectl argo rollouts set image istio-rollout "*=argoproj/istio-rollout:yellow"
此时,rollout中的image更新为了yellow版本。
yellow版本(金丝雀版本)的pod被创建出来,但blue版本(稳定版)依然保存。
2:查询效果
再次查看 http ://{ASM网关IP}/
可以看到有10%的方格被设置成了黄色。
3:原因解释
直接原因是因为在服务网格ASM中,之前配置的虚拟服务VirtualService的权重发生了变化,stable(蓝色)的权重从100被修改为了90。canary(黄色)为金丝雀版本,权重从0变为了10。
这个的变化是有Rollout控制的,我们开始创建的Rollout 的第一个step的setWeight中设置了金丝雀版本的权重为10,在开始滚动时,由Argo Rollout的控制器会修改Rollout中配置的VirtualService的权重。pause设置为空,表示需要人工卡点确认,才进到下一阶段。
4. 继续发布
执行如下命令继续发布,VirtualService中的权重会根据Rollout中的配置继续调整。由于后面的步骤中设置了时间,则会等待一段时间后自动调整。
kubectl argo rollouts promote istio-rollout
5. 更新完成
等待一段时间后所有的颜色块都变为了黄色。
查看Rollout状态,此时stabel的image更新为了yellow。
kubectl argo rollouts get rollout istio-rollout --watch
Name: istio-rollout
Namespace: default
Status: ✔ Healthy
Strategy: Canary
Step: 18/18
SetWeight: 100
ActualWeight: 100
Images: argoproj/rollouts-demo:yellow (stable)
Replicas:
Desired: 1
Current: 1
Updated: 1
Ready: 1
Available: 1
NAME KIND STATUS AGE INFO
⟳ istio-rollout Rollout ✔ Healthy 48m
├──# revision:4
│ └──⧉ istio-rollout-5fcf5864c4 ReplicaSet ✔ Healthy 27m stable
│ └──□ istio-rollout-5fcf5864c4-vw6kh Pod ✔ Running 26m ready:2/2
├──# revision:3
│ └──⧉ istio-rollout-897cb5b6d ReplicaSet • ScaledDown 27m
└──# revision:1
└──⧉ istio-rollout-7f96d86486 ReplicaSet • ScaledDown 48m
和Prometheus结合自动回滚
在金丝雀过程中可以手工执行如下命令进行回滚,会回退到stable版本。更优雅的方式是和Prometheus监控系统结合,当监控指标异常时,自动回滚到stable版本,并标记为降级。
kubectl argo rollouts abort istio-rollout
在阿里云服务网格ASM中启用Prometheus
参考文档:集成ARMS Prometheus实现网格监控或集成自建Prometheus实现网格监控。
配置Argo AnalysisTemplate
将阿里云服务网格ASM的prometheus地址配置在AnalysisTemplate的address处。
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: istio-success-rate
spec:
args:
- name: service
- name: namespace
metrics:
- name: success-rate
initialDelay: 60s
interval: 20s
successCondition: result[0] > 0.90
provider:
prometheus:
address: http://xxx.aliyuncs.com:9090/api/v1/prometheus/
query: >+
sum(irate(istio_requests_total{
reporter="source",
destination_service=~"{
{args.service}}.{
{args.namespace}}.svc.cluster.local",
response_code!~"5.*"}[40s])
)
/
sum(irate(istio_requests_total{
reporter="source",
destination_service=~"{
{args.service}}.{
{args.namespace}}.svc.cluster.local"}[40s])
)
为Rollout关联Analysis
在strategy中配置analysis,从第二步开启使用analysis进行监控,自动回滚。初始image为yellow(黄色),将一下内容保存为rollout.yaml。执行kubectl apply -f rollout.yaml对istio-rollout进行更新。
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: istio-rollout
spec:
revisionHistoryLimit: 2
selector:
matchLabels:
app: istio-rollout
template:
metadata:
annotations:
sidecar.istio.io/inject: "true"
labels:
app: istio-rollout
spec:
containers:
- name: istio-rollout
image: argoproj/rollouts-demo:yellow
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m
strategy:
canary:
canaryService: istio-rollout-canary
stableService: istio-rollout-stable
analysis:
startingStep: 1 # index of step list, of when to start this analysis
templates:
- templateName: istio-success-rate
args:
- name: service
value: canary
- name: namespace
valueFrom:
fieldRef:
fieldPath: metadata.namespace
trafficRouting:
istio:
virtualService:
name: istio-rollout-vsvc
routes:
- primary
steps:
- setWeight: 10
- pause: {} # 手工卡点
- setWeight: 20
- pause: {duration: 20s}
- setWeight: 30
- pause: {duration: 20s}
- setWeight: 40
- pause: {duration: 20s}
- setWeight: 50
- pause: {duration: 20s}
- setWeight: 60
- pause: {duration: 20s}
- setWeight: 70
- pause: {duration: 20s}
- setWeight: 80
- pause: {duration: 20s}
- setWeight: 90
- pause: {duration: 20s}
修改颜色为橙色
kubectl argo rollouts set image istio-rollout "*=argoproj/rollouts-demo:orange"
人工卡点确认
执行如下命令,进入到后续的自动金丝雀状态,并且从第二步开始,会结合Prometheus监控,如果金丝雀版本错误率高于90%,则触发回滚。
kubectl argo rollouts promote istio-rollout
人工卡点通过后,会自动后续的渐进式发布,通过如下命令可以查看:
kubectl argo rollouts get rollout istio-rollout --watch
设置Error
在后续渐进式发布中,我们可以手动设置Error。移动Error至100%后,所有的金丝雀版本(橙色)都有一个红框,表示错误。同时等待片刻后,将自动切换回只有黄色的(稳定版)。
(金丝雀中)
(自动回滚到稳定版)
总结
在阿里云服务网格ASM中,因为使用了Sidecar模式,更有助于统一服务中使用的指标,方便对金丝雀中的应用健康状态进行监控,及时自动发现问题进行回滚。