每日一Go-66、K8s 蓝绿发布 & 金丝雀发布实战:Service 切流量 + Ingress 灰度一次讲透

一、什么是蓝绿发布?

蓝绿发布 = 两套完整环境(Blue/Green)同时存在,通过 Service 一次性切换流量。

Blue 代表当前线上版本;Green代表新版本;切换点是 Service selector

二、蓝绿发布示例

  1. 有两套环境同时在线,Service 一刀切流量

  2. K8s资源结构

sql 复制代码
Deployment(blue) ---> Pod (v1)
Deployment(green) ---> Pod (v2)
Service ---> selector 决定流量去向
  1. 当前线上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 # 版本标签,用于标识应用的不同版本
  1. 新版本V2(Green版)
bash 复制代码
  selector:
    matchLabels: # 匹配标签:选择具有特定标签的Pod
      app: golang-per-day-65 # 标签名称,用于标识应用
      version: v2 # 版本标签,用于标识应用的不同版本
  1. 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
  1. 发布/回滚

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)就是一种"先找一小拨人试用,没问题再全量推广"的策略。

它之所以叫这个名字,是因为以前矿工下井前会先放一只金丝雀进去,如果金丝雀出了意外,说明井下有毒气,矿工就不会进去。在软件世界里,新版本就是那只金丝雀。

四、金丝雀发布示例

  1. 少量流量先给新版本,逐步放量

  2. K8s资源结构

sql 复制代码
service.yaml     ---> v1
service.v2.yaml ---> v2
ingress.yaml      ---> stable
ingress.canary.yaml ---> canary
  1. 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
  1. 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
  1. 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 # 服务端口号
  1. 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 # 服务端口号
  1. 按百分比发布
bash 复制代码
annotations:
  nginx.ingress.kubernetes.io/canary: "true"                         # 启用金丝雀发布
  nginx.ingress.kubernetes.io/canary-weight: "10"   #10%到新版本                 # 金丝雀发布权重
  1. 按 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
  1. 按 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
  1. 回滚
javascript 复制代码
kubectl delete -f ingress.canary.yaml

五、蓝绿和金丝雀有什么区别?

蓝绿发布:是"瞬间大切换":就像换衣服,脱掉旧的直接穿上新的。速度快,但万一新衣服不合身,那一刻所有人都看到了。

金丝雀发布:是"渐进式切换":就像试菜,先给一两个人尝尝,大家觉得好,再给全餐厅的人上菜。

总结起来,金丝雀发布是用最小的代价,在真实的战场上验证武器。



友情链接:加班费计算器(vx小程序搜索"加班计")


*源码地址*

留言给


如果您喜欢这篇文章,请您(点赞、分享、亮爱心),万分感谢!

相关推荐
不是万能的豆学长7 小时前
filetidy 文件整理助手:一键归类 + 规范重命名(Python 零依赖单文件工具)
大数据·开发语言·python·技术美术
懂点Tech11 小时前
ctfshow MISC入门图片篇(信息附加):misc41解题思路
开发语言·python
catchadmin12 小时前
PHP 8.7 协程新提案 让跨协程代码共享请求身份
开发语言·php
念何架构之路13 小时前
go-grpc设计思想
开发语言·后端·golang
酷炫码神14 小时前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
microrain14 小时前
SagooIoT 的缓存换后端只改一行配置,文件后端连 Redis 都不需要
物联网·缓存·golang·sagooiot
Elastic 中国社区官方博客14 小时前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn18815 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn15 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
喵了几个咪16 小时前
GoWind ShortPlay 深度拆解:三服务 BFF + Core,一条请求的完整工程链路
golang·gowind