一、什么是蓝绿发布?
蓝绿发布 = 两套完整环境(Blue/Green)同时存在,通过 Service 一次性切换流量。
Blue 代表当前线上版本;Green代表新版本;切换点是 Service selector
二、蓝绿发布示例
-
有两套环境同时在线,Service 一刀切流量
-
K8s资源结构
sql
Deployment(blue) ---> Pod (v1)
Deployment(green) ---> Pod (v2)
Service ---> selector 决定流量去向
- 当前线上v1(Blue版)
bash
# 部署(Deployment) - 用于管理应用程序的Pod副本
apiVersion: apps/v1 # Kubernetes应用部署的API版本
kind: Deployment # 资源类型:Deployment用于管理无状态应用的部署
metadata: # 元数据部分
name: golang-per-day-65 # 部署名称
namespace: codee-jun # Kubernetes命名空间
spec: # 部署规格
# 副本数量:期望运行的Pod数量
replicas: 3 # 运行3个Pod副本,提供高可用性
strategy: # 策略:滚动更新策略
type: RollingUpdate # 策略类型:滚动更新
rollingUpdate: # 滚动更新配置
maxSurge: 1 # 最大激增数:允许同时运行的最大Pod数量超过期望副本数
maxUnavailable: 1 # 最大不可用数:允许同时运行的最大Pod数量低于期望副本数
# 选择器:用于选择管理哪些Pod
selector:
matchLabels: # 匹配标签:选择具有特定标签的Pod
app: golang-per-day-65 # 标签名称,用于标识应用
version: v1 # 版本标签,用于标识应用的不同版本
- 新版本V2(Green版)
bash
selector:
matchLabels: # 匹配标签:选择具有特定标签的Pod
app: golang-per-day-65 # 标签名称,用于标识应用
version: v2 # 版本标签,用于标识应用的不同版本
- Service 切换成v2
makefile
# 服务(Service) - 用于暴露应用程序并提供负载均衡
apiVersion: v1 # Kubernetes API版本
kind: Service # 资源类型:Service用于暴露应用程序
metadata:
name: golang-per-day-65 # 服务名称
namespace: codee-jun # Kubernetes命名空间
spec: # 服务规格
ports: # 端口配置列表
- protocol: TCP # 协议类型:TCP
port: 8080 # 服务端口(集群内部访问端口)
targetPort: 8080 # 目标端口(Pod内部端口)
sessionAffinity: ClientIP # 会话亲和性:ClientIP表示同一客户端的请求会转发到同一Pod,为了保持session一致性
selector: # Pod选择器
app: golang-per-day-65 # 匹配具有app=golang-per-day-65标签的Pod
# version: v1 # 匹配具有version=v1标签的Pod
version: v2 # 匹配具有version=v2标签的Pod
- 发布/回滚
6.1 发布新版本
apache
kubectl patch svc golang-per-day-65 \
-p '{"spec":{"selector":{"version":"v2","app":"golang-per-day-65"}}}'
6.2 秒级回滚
apache
kubectl patch svc golang-per-day-65 \
-p '{"spec":{"selector":{"version":"v1","app":"golang-per-day-65"}}}'
三、什么是金丝雀发布?
简单来说,金丝雀发布(Canary Deployment)就是一种"先找一小拨人试用,没问题再全量推广"的策略。
它之所以叫这个名字,是因为以前矿工下井前会先放一只金丝雀进去,如果金丝雀出了意外,说明井下有毒气,矿工就不会进去。在软件世界里,新版本就是那只金丝雀。
四、金丝雀发布示例
-
少量流量先给新版本,逐步放量
-
K8s资源结构
sql
service.yaml ---> v1
service.v2.yaml ---> v2
ingress.yaml ---> stable
ingress.canary.yaml ---> canary
- service.yaml
makefile
# 服务(Service) - 用于暴露应用程序并提供负载均衡
apiVersion: v1 # Kubernetes API版本
kind: Service # 资源类型:Service用于暴露应用程序
metadata:
name: golang-per-day-65 # 服务名称
namespace: codee-jun # Kubernetes命名空间
spec: # 服务规格
ports: # 端口配置列表
- protocol: TCP # 协议类型:TCP
port: 8080 # 服务端口(集群内部访问端口)
targetPort: 8080 # 目标端口(Pod内部端口)
sessionAffinity: ClientIP # 会话亲和性:ClientIP表示同一客户端的请求会转发到同一Pod,为了保持session一致性
selector: # Pod选择器
app: golang-per-day-65 # 匹配具有app=golang-per-day-65标签的Pod
version: v1 # 匹配具有version=v1标签的Pod
- service.v2.yaml
bash
spec: # 服务规格
ports: # 端口配置列表
- protocol: TCP # 协议类型:TCP
port: 8080 # 服务端口(集群内部访问端口)
targetPort: 8080 # 目标端口(Pod内部端口)
sessionAffinity: ClientIP # 会话亲和性:ClientIP表示同一客户端的请求会转发到同一Pod,为了保持session一致性
selector: # Pod选择器
app: golang-per-day-65 # 匹配具有app=golang-per-day-65标签的Pod
version: v2 # 匹配具有version=v2标签的Pod
- ingress.yaml
bash
# golang_per_day_65 项目的 Ingress 配置
# 用于管理外部访问集群内服务的路由规则
apiVersion: networking.k8s.io/v1
kind: Ingress
# Ingress 元数据配置
metadata:
name: golang_per_day_65-ingress # Ingress 资源名称
namespace: codee_jun # 所属命名空间
annotations: # Nginx Ingress 控制器特定配置
# CORS 配置
nginx.ingress.kubernetes.io/enable-cors: "true" # 启用跨域资源共享
nginx.ingress.kubernetes.io/cors-allow-origin: "https://golang_per_day_65.com" # 允许的源
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS" # 允许的HTTP方法
nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" # 允许的请求头
nginx.ingress.kubernetes.io/cors-allow-credentials: "true" # 如果需要凭证
# 代理配置
nginx.ingress.kubernetes.io/proxy-body-size: "1024m" # 允许的请求体大小
# 会话亲和性配置
nginx.ingress.kubernetes.io/affinity: "cookie" # 启用基于cookie的会话亲和性
nginx.ingress.kubernetes.io/session-cookie-name: "golang_per_day_65-session" # 会话cookie名称
nginx.ingress.kubernetes.io/session-cookie-expires: "172800" # cookie过期时间(秒)
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" # cookie最大生存时间(秒)
# Ingress 规格配置
spec:
ingressClassName: nginx # 使用的Ingress控制器类名
# TLS 配置(HTTPS)
tls:
- hosts:
- golang_per_day_65.com # 域名
secretName: codee-jun-tls-secret # tls证书
# 路由规则
rules:
- host: golang_per_day_65.com # 域名
http: # 协议
paths: # 路径
- path: / # 路径
pathType: Prefix # 路径类型
backend: # 后端
service: # 服务
name: golang-per-day-65 # 服务名称
port: # 服务端口
number: 8080 # 服务端口号
- ingress.canary.yaml
bash
annotations: # Nginx Ingress 控制器特定配置
nginx.ingress.kubernetes.io/canary: "true" # 启用金丝雀发布
nginx.ingress.kubernetes.io/canary-weight: "10" # 金丝雀发布权重
...
rules:
- host: golang_per_day_65.com # 域名
http: # 协议
paths: # 路径
- path: / # 路径
pathType: Prefix # 路径类型
backend: # 后端
service: # 服务
name: golang-per-day-65-v2 # 服务名称
port: # 服务端口
number: 8080 # 服务端口号
- 按百分比发布
bash
annotations:
nginx.ingress.kubernetes.io/canary: "true" # 启用金丝雀发布
nginx.ingress.kubernetes.io/canary-weight: "10" #10%到新版本 # 金丝雀发布权重
- 按 Header
bash
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "true"
javascript
// 请求示例
curl -H "X-Canary: true" http://golang-per-day.com/version/v2
- 按 Cookie
bash
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "canary"
javascript
// 请求示例
curl --cookie "canary=true" http://golang-per-day.com/version/v2
- 回滚
javascript
kubectl delete -f ingress.canary.yaml
五、蓝绿和金丝雀有什么区别?
蓝绿发布:是"瞬间大切换":就像换衣服,脱掉旧的直接穿上新的。速度快,但万一新衣服不合身,那一刻所有人都看到了。
金丝雀发布:是"渐进式切换":就像试菜,先给一两个人尝尝,大家觉得好,再给全餐厅的人上菜。
总结起来,金丝雀发布是用最小的代价,在真实的战场上验证武器。

友情链接:加班费计算器(vx小程序搜索"加班计")
*源码地址*
留言给
如果您喜欢这篇文章,请您(点赞、分享、亮爱心),万分感谢!