灰度发布是一种渐进式发布策略,通过逐步将新版本应用引入到少部分用户或流量中。此增量式的发布方式使团队能够监控系统行为、收集指标并确保稳定性,然后再进行全面部署。该方法显著降低了风险,尤其是在生产环境中。
Argo Rollouts 支持灰度发布策略来滚动更新 Deployment,并通过 Gateway API 插件控制流量。在 ACP 中,可以使用 ALB 作为 Gateway API Provider 来实现 Argo Rollouts 的流量控制。
创建 Deployment
首先定义应用的“稳定”版本,即当前用户访问的版本。创建一个 Kubernetes Deployment,设置合适的副本数、容器镜像版本(例如 hello:1.23.1
)及标签,如 app=web
。
使用以下 YAML:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: hello:1.23.1
ports:
- containerPort: 80
YAML 字段说明:
apiVersion
:用于创建资源的 Kubernetes API 版本。
kind
:资源类型,这里是 Deployment。
metadata.name
:Deployment 的名称。
spec.replicas
:期望的 Pod 副本数。
spec.selector.matchLabels
:Deployment 用于选择管理的 Pod 标签。
template.metadata.labels
:Pod 的标签,Service 用于选择 Pod。
spec.containers
:Pod 中运行的容器列表。
containers.name
:容器名称。
containers.image
:容器镜像。
containers.ports.containerPort
:容器暴露的端口。
使用 kubectl
应用配置:
kubectl apply -f deployment.yaml
这将搭建生产环境。
也可以使用 Helm Chart 创建 Deployment 和 Service。
创建稳定服务
创建一个 Kubernetes Service
,用于暴露稳定版本的 Deployment。该服务根据标签选择 Pod,初始选择器为 app=web
。
apiVersion: v1
kind: Service
metadata:
name: web-stable
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
YAML 字段说明:
apiVersion
:用于创建 Service 的 Kubernetes API 版本。
kind
:资源类型,这里是 Service。
metadata.name
:Service 名称。
spec.selector
:根据标签选择 Pod。
ports.protocol
:使用的协议(TCP)。
ports.port
:Service 暴露的端口。
ports.targetPort
:容器接收流量的端口。
使用命令应用:
kubectl apply -f web-stable-service.yaml
该服务允许外部访问稳定版本。
创建灰度服务
创建一个 Kubernetes Service
,用于暴露灰度版本的 Deployment。该服务根据标签选择 Pod,初始选择器为 app=web
。
apiVersion: v1
kind: Service
metadata:
name: web-canary
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
YAML 字段说明:
apiVersion
:用于创建 Service 的 Kubernetes API 版本。
kind
:资源类型,这里是 Service。
metadata.name
:Service 名称。
spec.selector
:根据标签选择 Pod。
ports.protocol
:使用的协议(TCP)。
ports.port
:Service 暴露的端口。
ports.targetPort
:容器接收流量的端口。
使用命令应用:
kubectl apply -f web-canary-service.yaml
该服务允许外部访问灰度版本。
创建 Gateway
使用 example.com
作为访问域名,创建 Gateway 以该域名暴露服务:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: default
spec:
gatewayClassName: exclusive-gateway
listeners:
- allowedRoutes:
namespaces:
from: All
name: gateway-metric
port: 11782
protocol: TCP
- allowedRoutes:
namespaces:
from: All
hostname: example.com
name: web
port: 80
protocol: HTTP
使用命令:
kubectl apply -f gateway.yaml
Gateway 会分配一个外部 IP 地址,可通过 Gateway 资源的 status.addresses
中类型为 IPAddress
的字段获取该 IP。
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: default
...
status:
addresses:
- type: IPAddress
value: 192.168.134.30
DNS 配置
在 DNS 服务器中配置域名,将域名解析到 Gateway 的 IP 地址。使用命令验证 DNS 解析:
nslookup example.com
Server: 192.168.16.19
Address: 192.168.16.19#53
Non-authoritative answer:
Name: example.com
Address: 192.168.134.30
应返回 Gateway 的地址。
创建 HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web
spec:
hostnames:
- example.com
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: default
namespace: default
sectionName: web
rules:
- backendRefs:
- group: ""
kind: Service
name: web-canary
namespace: default
port: 80
weight: 0
- group: ""
kind: Service
name: web-stable
namespace: default
port: 80
weight: 100
matches:
- path:
type: PathPrefix
value: /
使用命令:
kubectl apply -f httproute.yaml
访问稳定服务
集群外部通过域名访问服务:
或者在浏览器中访问 http://example.com
。
创建 Rollout
接下来,使用 Argo Rollouts 创建采用 Canary
策略的 Rollout
资源。
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollout-canary
spec:
minReadySeconds: 30
replicas: 2
revisionHistoryLimit: 3
selector:
matchLabels:
app: web
strategy:
canary:
canaryService: web-canary
maxSurge: 25%
maxUnavailable: 0
stableService: web-stable
steps:
- setWeight: 50
- pause: {}
- setWeight: 100
trafficRouting:
plugins:
argoproj-labs/gatewayAPI:
httpRoute: web
namespace: default
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: web
scaleDown: onsuccess
YAML 字段说明:
spec.selector
:Pod 标签选择器。现有 ReplicaSet 中被选择的 Pod 会受此 Rollout 影响,必须与 Pod 模板标签匹配。
workloadRef
:指定工作负载引用及缩容策略。
scaleDown
:指定迁移到 Rollout 后是否缩减工作负载(Deployment)。可选值:
- "never":不缩减 Deployment。
- "onsuccess":Rollout 健康后缩减 Deployment。
- "progressively":Rollout 扩容时逐步缩减 Deployment,失败时恢复 Deployment。
strategy
:部署策略,支持 BlueGreen
和 Canary
。
canary
:灰度策略定义。
canaryService
:控制器更新以选择灰度 Pod 的服务,流量路由必需。
stableService
:控制器更新以选择稳定 Pod 的服务,流量路由必需。
steps
:定义灰度更新的步骤序列,首次部署时跳过。
setWeight
:设置灰度 ReplicaSet 的流量比例。
pause
:暂停发布,支持单位 s、m、h,{}
表示无限期暂停。
plugin
:执行配置的插件,此处配置了 gatewayAPI
插件。
使用命令应用:
kubectl apply -f rollout.yaml
这将为部署设置灰度发布策略。初始设置权重为 50,等待推广。50% 流量转发至灰度服务。推广后权重设为 100,100% 流量转发至灰度服务,最终灰度服务成为稳定服务。
验证 Rollout
创建 Rollout
后,Argo Rollouts 会创建一个与 Deployment 模板相同的新 ReplicaSet。当新 ReplicaSet 的 Pod 健康时,Deployment 会缩容至 0。
使用以下命令确认 Pod 正常运行:
kubectl argo rollouts get rollout rollout-canary
Name: rollout-canary
Namespace: default
Status: ✔ Healthy
Strategy: Canary
Step: 9/9
SetWeight: 100
ActualWeight: 100
Images: hello:1.23.1 (stable)
Replicas:
Desired: 2
Current: 2
Updated: 2
Ready: 2
Available: 2
NAME KIND STATUS AGE INFO
⟳ rollout-canary Rollout ✔ Healthy 32s
└──# revision:1
└──⧉ rollout-canary-5c9d79697b ReplicaSet ✔ Healthy 32s stable
├──□ rollout-canary-5c9d79697b-fh78d Pod ✔ Running 32s ready:1/1
└──□ rollout-canary-5c9d79697b-rrbtj Pod ✔ Running 32s ready:1/1
准备灰度部署
接下来,准备新版本应用作为绿色部署。更新 Deployment web
的镜像版本(例如 hello:1.23.2
)。使用命令:
kubectl patch deployment web -p '{"spec":{"template":{"spec":{"containers":[{"name":"web","image":"hello:1.23.2"}]}}}}'
这将为测试设置新版本应用。
Rollout 会创建新的 ReplicaSet 管理灰度 Pod,50% 流量转发至灰度 Pod。使用以下命令验证:
kubectl argo rollouts get rollout rollout-canary
Name: rollout-canary
Namespace: default
Status: ॥ Paused
Message: CanaryPauseStep
Strategy: Canary
Step: 1/3
SetWeight: 50
ActualWeight: 50
Images: hello:1.23.1 (stable)
hello:1.23.2 (canary)
Replicas:
Desired: 2
Current: 3
Updated: 1
Ready: 3
Available: 3
NAME KIND STATUS AGE INFO
⟳ rollout-canary Rollout ॥ Paused 95s
├──# revision:2
│ └──⧉ rollout-canary-5898765588 ReplicaSet ✔ Healthy 46s canary
│ └──□ rollout-canary-5898765588-ls5jk Pod ✔ Running 45s ready:1/1
└──# revision:1
└──⧉ rollout-canary-5c9d79697b ReplicaSet ✔ Healthy 95s stable
├──□ rollout-canary-5c9d79697b-fk269 Pod ✔ Running 94s ready:1/1
└──□ rollout-canary-5c9d79697b-wkmcn Pod ✔ Running 94s ready:1/1
当前运行 3 个 Pod,包含稳定和灰度版本。权重为 50,50% 流量转发至灰度服务。发布流程暂停,等待推广。
如果使用 Helm Chart 部署应用,可用 Helm 工具升级到灰度版本。
访问 http://example.com
,50% 流量将转发至灰度服务,响应应有所不同。
推广 Rollout
当灰度版本测试通过后,可推广 Rollout,将所有流量切换至灰度 Pod。使用命令:
kubectl argo rollouts promote rollout-canary
验证 Rollout 是否完成:
kubectl argo rollouts get rollout rollout-canary
Name: rollout-canary
Namespace: default
Status: ✔ Healthy
Strategy: Canary
Step: 3/3
SetWeight: 100
ActualWeight: 100
Images: hello:1.23.2 (stable)
Replicas:
Desired: 2
Current: 2
Updated: 2
Ready: 2
Available: 2
NAME KIND STATUS AGE INFO
⟳ rollout-canary Rollout ✔ Healthy 8m42s
├──# revision:2
│ └──⧉ rollout-canary-5898765588 ReplicaSet ✔ Healthy 7m53s stable
│ ├──□ rollout-canary-5898765588-ls5jk Pod ✔ Running 7m52s ready:1/1
│ └──□ rollout-canary-5898765588-dkfwg Pod ✔ Running 68s ready:1/1
└──# revision:1
└──⧉ rollout-canary-5c9d79697b ReplicaSet • ScaledDown 8m42s
├──□ rollout-canary-5c9d79697b-fk269 Pod ◌ Terminating 8m41s ready:1/1
└──□ rollout-canary-5c9d79697b-wkmcn Pod ◌ Terminating 8m41s ready:1/1
若稳定版本镜像更新为 hello:1.23.2
,且 revision 1 的 ReplicaSet 缩容为 0,表示发布完成。
访问 http://example.com
,100% 流量将转发至灰度服务。
中止 Rollout(可选)
若在发布过程中发现灰度版本存在问题,可中止发布,将所有流量切回稳定服务。使用命令:
kubectl argo rollouts abort rollout-canary
验证结果:
kubectl argo rollouts get rollout rollout-canary
Name: rollout-demo
Namespace: default
Status: ✖ Degraded
Message: RolloutAborted: Rollout aborted update to revision 3
Strategy: Canary
Step: 0/3
SetWeight: 0
ActualWeight: 0
Images: hello:1.23.1 (stable)
Replicas:
Desired: 2
Current: 2
Updated: 0
Ready: 2
Available: 2
NAME KIND STATUS AGE INFO
⟳ rollout-canary Rollout ✖ Degraded 18m
├──# revision:3
│ └──⧉ rollout-canary-5c9d79697b ReplicaSet • ScaledDown 18m canary,delay:passed
└──# revision:2
└──⧉ rollout-canary-5898765588 ReplicaSet ✔ Healthy 17m stable
├──□ rollout-canary-5898765588-ls5jk Pod ✔ Running 17m ready:1/1
└──□ rollout-canary-5898765588-dkfwg Pod ✔ Running 10m ready:1/1
访问 http://example.com
,100% 流量将转发至稳定服务。