k8s-蓝绿发布与金丝雀发布
一、蓝绿发布
在Kubernetes中,蓝绿发布(Blue-Green Deployment) 是一种部署策略,通过同时维护两个完全独立的生产环境(“蓝”和“绿”),在验证新版本(绿)后,一次性将流量从旧版本(蓝)切换到新版本,若发现问题则立即回退。其核心特点是零停机时间和快速回滚。
---
蓝绿发布的核心原理
双环境共存:
蓝环境(Blue):当前生产环境,处理所有用户流量。
绿环境(Green):新版本环境,部署完成后处于待命状态。
流量切换:
通过更新负载均衡规则或Service选择器,将所有流量从蓝环境切换到绿环境。
快速回滚:
若绿环境异常,只需将流量重新指向蓝环境即可恢复。
---
蓝绿发布的实现方法及步骤
---
1. 通过Service切换标签(Label Selector)
原理:利用Kubernetes Service的标签选择器,将流量从旧版本Pod(蓝)切换到新版本Pod(绿)。
步骤:
部署蓝环境(旧版本):
# deployment-blue.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue # 标签标识蓝环境
template:
metadata:
labels:
app: myapp
version: blue
spec:
containers:
- name: myapp
image: janakiramm/myapp:v1
imagePullPolicy: IfNotPresent
---
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: NodePort
selector:
app: myapp
version: blue # 初始指向蓝环境
ports:
- protocol: TCP
port: 80
targetPort: 8080
部署绿环境(新版本):
# deployment-green.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-green
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: green # 标签标识绿环境
template:
metadata:
labels:
app: myapp
version: green
spec:
containers:
- name: myapp
image: janakiramm/myapp:v2
imagePullPolicy: IfNotPresent
切换Service流量到绿环境:
kubectl patch service myapp-service -p '{"spec":{"selector":{"version":"green"}}}'
验证与回滚:
若绿环境运行正常,删除蓝环境的Deployment。
若异常,重新切换Service选择器回version: blue。
优缺点:
优点:简单直接,依赖Kubernetes原生功能。
缺点:需手动切换,无流量逐步验证过程。
---
2. 通过Ingress控制器(如Nginx)切换后端服务
原理:通过更新Ingress规则,将流量从蓝环境Service切换到绿环境Service。
步骤:
部署蓝环境和绿环境:
分别为蓝、绿环境创建Deployment和Service(如myapp-blue-svc和myapp-green-svc)。
配置初始Ingress指向蓝环境:
# ingress-blue.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-blue-svc # 初始指向蓝环境
port:
number: 80
更新Ingress指向绿环境:
# ingress-green.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-green-svc # 切换至绿环境
port:
number: 80
应用新Ingress配置:
kubectl apply -f ingress-green.yaml
优缺点:
优点:适用于HTTP流量,支持复杂路由规则。
缺点:需手动操作,依赖Ingress控制器的更新速度。
---
3. 通过Istio服务网格切换流量
原理:使用Istio的VirtualService动态路由流量,支持蓝绿切换和流量镜像等高级功能。
步骤:
部署蓝绿环境:
创建两个Deployment(蓝和绿)及对应的Service(如myapp-blue和myapp-green)。
配置DestinationRule定义子集:
# destination-rule.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
subsets:
- name: blue
labels:
version: blue
- name: green
labels:
version: green
配置VirtualService初始指向蓝环境:
# virtual-service-blue.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- route:
- destination:
host: myapp
subset: blue # 100%流量到蓝环境
切换流量到绿环境:
# virtual-service-green.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- route:
- destination:
host: myapp
subset: green # 100%流量到绿环境
应用新路由规则:
kubectl apply -f virtual-service-green.yaml
优缺点:
优点:支持流量镜像(Shadowing)、按需切换。
缺点:需引入Istio,配置复杂度高。
---
4. 通过Argo Rollouts自动化蓝绿发布
原理:使用Argo Rollouts控制器自动化蓝绿发布流程,包括自动创建绿环境、切换流量和清理旧版本。
步骤:
安装Argo Rollouts:
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
定义Rollout资源:
# rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: myapp
spec:
strategy:
blueGreen:
activeService: myapp-active # 指向当前生产环境(蓝)
previewService: myapp-preview # 指向绿环境(预发布)
autoPromotionEnabled: false # 手动触发切换
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1
部署初始版本(蓝环境):
kubectl apply -f rollout.yaml
更新镜像触发绿环境部署:
kubectl argo rollouts set image myapp myapp=myapp:v2
手动验证并切换流量:
kubectl argo rollouts promote myapp # 将流量从蓝切换到绿
优缺点:
优点:全自动化,集成预发布验证和清理。
缺点:需额外安装Argo Rollouts组件。
---
总结
方法 适用场景 核心优势 局限性
Service标签切换 简单场景,快速切换 无需额外工具 手动操作,无流量验证
Ingress控制器 HTTP服务,需精细路由控制 灵活配置路由规则 依赖Ingress更新速度
Istio服务网格 复杂环境,需流量镜像或高级路由 支持流量镜像和动态路由 需引入Istio,复杂度高
Argo Rollouts 自动化全流程,需预发布验证 自动化创建、验证和清理环境 需额外组件支持
最佳实践
数据库兼容性:确保新版本与旧版本数据库模式兼容,或使用双写策略。
会话保持:若应用有状态(如用户登录),需确保流量切换后会话不丢失。
监控与告警:在切换前后监控关键指标(错误率、延迟、资源使用率)。
自动化测试:在切换前对绿环境进行自动化API测试和冒烟测试。
根据团队的技术栈和运维能力,选择最合适的蓝绿发布方案。对于需要全自动化和预发布验证的场景,推荐使用Argo Rollouts;对于已使用服务网格的团队,Istio是更优选择。
二、金丝雀发布
在Kubernetes中,金丝雀发布(Canary Release) 是一种渐进式部署策略,目的是将新版本应用逐步暴露给一小部分用户或流量,通过持续监控确保其稳定性后,再逐步扩大范围直至完全替换旧版本。这种策略的名称来源于“矿井中的金丝雀”——早期矿工用金丝雀来检测有毒气体,如果金丝雀存活,说明环境安全。
---
金丝雀发布的核心原理
小范围验证:
先部署新版本(金丝雀版本)到生产环境,但仅允许少量用户或流量访问它(例如5%的请求)。
大部分流量仍由旧版本处理,确保用户整体体验不受影响。
监控与观察:
监控新版本的性能指标(如错误率、延迟、CPU/内存使用率等)。
如果新版本表现稳定,逐步增加其流量比例;如果发现问题,立即回滚。
逐步替换:
最终将100%流量切换到新版本,完成平滑升级。
---
为什么在Kubernetes中使用金丝雀发布?
降低风险:
避免一次性全量发布导致全局故障,尤其适用于关键业务场景。
快速反馈:
通过真实流量验证新版本,比测试环境更可靠。
无缝回滚:
发现问题时,只需将流量切回旧版本,无需重新部署。
---
金丝雀发布的典型实现方式
---
1. 基于Deployment副本数的金丝雀发布
原理
通过调整新旧版本Pod的副本数比例,利用Kubernetes Service的负载均衡能力,按比例分配流量到新旧版本。
步骤
部署旧版本:
# deployment-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 9 # 初始副本数为9
selector:
matchLabels:
app: myapp
version: v1
template:
metadata:
labels:
app: myapp
version: v1
spec:
containers:
- name: myapp
image: janakiramm/myapp:v1
---
apiVersion: v1
kind: Service
metadata:
name: myapp-service1
spec:
selector:
app: myapp # 同时选择v1和v2的Pod
ports:
- protocol: TCP
port: 80
targetPort: 80
部署金丝雀版本:
# deployment-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v2
spec:
replicas: 1 # 初始副本数为1(占10%流量)
selector:
matchLabels:
app: myapp
version: v2
template:
metadata:
labels:
app: myapp
version: v2
spec:
containers:
- name: myapp
image: janakiramm/myapp:v2
逐步调整副本比例:
若v2运行正常,逐步增加其副本数,同时减少v1的副本数:
kubectl scale deployment myapp-v2 --replicas=3 # 占25%流量(3/(9+3)=25%)
kubectl scale deployment myapp-v1 --replicas=9 # 保持旧版本可用
最终将v1副本数降为0,完成全量切换。
优缺点
优点:无需额外工具,完全依赖Kubernetes原生资源。
缺点:流量分配不够精确(依赖负载均衡策略),需手动调整副本数。
---
2. 基于Nginx Ingress控制器的金丝雀发布
原理
通过Ingress的注解(Annotation)按权重分流流量,将特定比例的请求定向到新版本。
步骤
部署主版本和金丝雀版本:
# deployment-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 3
template:
metadata:
labels:
app: myapp
version: v1
# ...其他配置
# service-v1.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-v1
spec:
selector:
app: myapp
version: v1
ports:
- port: 80
targetPort: 8080
# deployment-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v2
spec:
replicas: 1
template:
metadata:
labels:
app: myapp
version: v2
# ...其他配置
# service-v2.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-v2
spec:
selector:
app: myapp
version: v2
ports:
- port: 80
targetPort: 8080
配置主ingres规则和金丝雀Canary Ingress:
[root@k8s-master ingress]# cat master-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress # 创建一个类型为Ingress的资源
metadata:
name: nginx-ingress # 这个资源的名字为 nginx-ingress
spec:
ingressClassName: nginx # 使用nginx
rules:
- host: all.jx.com # 访问此内容的域名
http:
paths:
- backend:
service:
name: all-version # 对应nginx的服务名字,该规则的namespace必须与service的一致
port:
number: 80 # 访问的端口
path: / # 匹配规则
pathType: Prefix # 匹配类型,这里为前缀匹配
############################
[root@k8s-master ingress]# cat ingress-canary.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10" # 10%流量到v2
spec:
ingressClassName: nginx # 使用nginx
rules:
- host: all.jx.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service1
port:
number: 80
调整流量权重:
修改canary-weight注解值,逐步增加新版本流量:
kubectl annotate ingress/myapp-canary \
nginx.ingress.kubernetes.io/canary-weight="50" # 50%流量到v2
最终删除旧版本Ingress,完成发布。
优缺点
优点:流量控制精确,无需Service Mesh。
缺点:依赖Nginx Ingress控制器功能。
---
3. 基于Istio服务网格的金丝雀发布
原理
通过VirtualService和DestinationRule定义流量路由规则,按权重分配请求到不同版本。
步骤
部署新旧版本:
# deployment-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
template:
metadata:
labels:
app: myapp
version: v1
# ...其他配置
# deployment-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v2
spec:
template:
metadata:
labels:
app: myapp
version: v2
# ...其他配置
创建DestinationRule:
# destination-rule.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
配置VirtualService流量分割:
# virtual-service.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- route:
- destination:
host: myapp
subset: v1
weight: 90
- destination:
host: myapp
subset: v2
weight: 10
逐步调整权重:
修改weight值,逐步将流量切换到v2:
weight: 50 # 50%流量到v2
最终将v1权重设为0,完成全量切换。
优缺点
优点:支持基于请求头、Cookie等高级路由规则,流量控制精准。
缺点:需引入Istio服务网格,架构复杂度高。
---
4. 基于Flagger的自动化金丝雀发布
原理
集成Prometheus监控,自动化渐进式发布:根据预设指标(如错误率、延迟)自动调整流量或回滚。
步骤
安装Flagger和Prometheus:
kubectl apply -k github.com/fluxcd/flagger/kustomize/istio
定义Canary资源:
# canary.yaml
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp-v1 # 旧版本Deployment
service:
port: 80
analysis:
interval: 1m # 检查间隔
threshold: 5 # 最大失败次数
metrics:
- name: request-success-rate
thresholdRange:
min: 99 # 成功率≥99%
interval: 1m
触发金丝雀发布:
更新Deployment镜像版本:
kubectl set image deployment/myapp-v1 myapp=myapp:v2
Flagger自动完成以下流程:
创建金丝雀Deployment(myapp-v2)。
2 逐步将流量从0%提升到5%、25%、50%、100%。
若指标正常,最终替换旧版本;若异常,自动回滚。
优缺点
优点:全自动化,集成监控和回滚。
缺点:依赖Prometheus和Flagger组件,配置复杂。
---
总结
方法 适用场景 核心优势 局限性
Deployment副本数 简单场景,无需精确流量控制 无需额外工具 流量分配不精确,需手动调整
Nginx Ingress 需要按权重分流的HTTP服务 精确流量控制,配置简单 依赖Ingress控制器功能
Istio服务网格 复杂路由需求(如基于请求头) 高级流量控制,精准灵活 需引入Istio,复杂度高
Flagger自动化工具 需要全自动化监控和回滚的关键业务 自动化渐进发布,安全可靠 依赖Prometheus和Flagger组件
---
金丝雀发布 vs 蓝绿部署
金丝雀发布:逐步替换,新旧版本共存,适合需要持续验证的场景。
蓝绿部署:同时运行两个完整环境(蓝/绿),一次性切换流量,适合快速回滚,但资源消耗更大。
---
最佳实践
关键指标监控:
错误率、请求延迟、资源利用率(CPU/内存)。
业务自定义指标(如订单成功率)。
设置回滚阈值:
例如:若错误率超过1%,自动回滚到旧版本。
结合A/B测试:
根据用户特征(如地理位置、设备类型)定向分发流量。
---
总结
金丝雀发布是Kubernetes中降低发布风险的核心策略,通过逐步验证新版本的稳定性,确保业务连续性。选择实现方式时需权衡团队技术栈、流量控制精度和运维复杂度。对于关键业务,建议结合自动化工具(如Flagger)和监控告警,实现安全可控的渐进式发布。
三、蓝绿发布 vs 金丝雀发布区别
特性 蓝绿发布 金丝雀发布
环境数量 同时维护两个完整环境 新旧版本共存于同一环境
流量切换 一次性全量切换 逐步迁移流量
资源消耗 较高(需双倍资源) 较低(仅需部分副本)
回滚速度 极快(秒级切换) 较快(需调整流量比例)
适用场景 关键业务的全量验证 渐进式验证和风险控制
更多推荐
所有评论(0)