找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4480

积分

0

好友

616

主题
发表于 2 小时前 | 查看: 3| 回复: 0

讲句实话,我刚开始用 Kubernetes 的时候,对“发布”这件事是没有太强烈概念的。不就是代码改完,打包,推镜像,kubectl apply 一下么,然后看 Pod 都起来了,心里基本就觉得差不多了。

那时候甚至以为:Kubernetes 已经帮我把发布这件事解决了。

直到有一次线上出问题。

一个小改动,上去之后 CPU 开始飙高,接口时好时坏,最烦的不是全挂,而是那种“有的正常、有的 500”。群里一堆人问你,压力你,你这边还在一行行翻日志找问题,真的压力山大。那一刻才明白一件事:Kubernetes 只是帮你“发上去”,但怎么发、发得稳不稳,是另一回事。

后来踩坑多了,才慢慢把这几种发布方式搞清楚。今天就不讲那些太虚太大的概念,咱们直接从运维视角,把常见几种发布方式一次性讲明白。

滚动发布

先从最基础的说起。其实大部分人平时用的 Deployment,默认就是滚动发布,只不过很多时候大家没认真看过配置,一直忽略了它的存在。

下面是一个最常用的模板:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
    spec:
      containers:
      - name: demo-app
        image: nginx:1.27
        ports:
        - containerPort: 80

这里面最关键的其实就两个参数:

maxSurge 表示发布过程中,最多可以比原来多出来多少个 Pod。

maxUnavailable 表示发布过程中,最多允许多少个 Pod 不可用。

比如你现在有 4 个 Pod,配置成:

maxSurge: 1
maxUnavailable: 1

意思就是:更新的时候,最多先多起 1 个新 Pod,同时最多允许 1 个旧 Pod 不可用。

这个配置的好处是比较稳,不会一下子把服务搞空。但问题也很明显,如果新版本本身有问题,它还是会一点点替换进去,所以它适合日常更新,不适合那种你心里都没底的大版本上线。

蓝绿发布

蓝绿发布别看名字高大上,本质上真没多复杂。 说白了就是:一套旧版本在跑、一套新版本提前准备好、最后靠 Service 切 selector。

先来两个 Deployment。

旧版本 Blue

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app-blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo-app
      version: blue
  template:
    metadata:
      labels:
        app: demo-app
        version: blue
    spec:
      containers:
      - name: demo-app
        image: nginx:1.26
        ports:
        - containerPort: 80

新版本 Green

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo-app
      version: green
  template:
    metadata:
      labels:
        app: demo-app
        version: green
    spec:
      containers:
      - name: demo-app
        image: nginx:1.27
        ports:
        - containerPort: 80

然后 Service 先指向 blue

apiVersion: v1
kind: Service
metadata:
  name: demo-app-svc
spec:
  selector:
    app: demo-app
    version: blue
  ports:
  - port: 80
    targetPort: 80

等你确认 green 没问题了,再把 selector 改成 green

spec:
  selector:
    app: demo-app
    version: green

这就是蓝绿发布最核心的动作。这个方案最大的优点就是:简单、直接、回滚快。

回滚怎么办?再把 selector 切回 blue 就完了。

但他也有他的痛点:得准备两套资源。

如果你的服务本来就吃资源,那蓝绿发布在很多公司里就不是“技术问题”,而是“老板批不批机器”的问题。

金丝雀发布

金丝雀发布和蓝绿发布最大的区别,不在于是不是两个版本同时存在,而在于:它不是一刀切,而是一点点放量。

如果你用的是 Nginx Ingress,可以这么搞。

先准备一个稳定版 Service 和一个金丝雀版 Service。 Ingress 主规则走稳定版

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-app
spec:
  ingressClassName: nginx
  rules:
  - host: demo.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-app-stable
            port:
              number: 80

然后再单独配一个 canary Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-app-canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
  - host: demo.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-app-canary
            port:
              number: 80

这里最关键的是这两个 annotation

nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"

第一个表示这是一个金丝雀规则。
第二个表示把 10% 流量 导给 canary 版本。

这个方式的好处就是非常直观。你可以先给 10%,看监控、看日志、看告警,觉得稳了再往上调成 30%、50%,最后再全量切换。

但这里有个很容易被忽略的点:金丝雀发布不是配完就完了,它依赖监控。

你没有这些东西,其实很难做得稳:

  • 错误率
  • 接口耗时
  • CPU / 内存
  • 业务核心指标

不然你只是“把流量分过去了”,但到底有没有出问题,你心里根本没数。

灰度发布

金丝雀是按流量切,灰度是按规则切。

比如你想让公司内部测试同学先访问新版本,或者只让带特定 Header 的请求走新版本,那就可以用灰度规则。

还是以 Nginx Ingress 为例,最常见的是按 Header 灰度。

主 Ingress 还是走稳定版,这里就不重复了。新版本单独搞一个带 Header 判断的 canary Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-app-gray
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "X-Gray"
    nginx.ingress.kubernetes.io/canary-by-header-value: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: demo.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-app-v2
            port:
              number: 80

这个配置是什么意思?

意思就是:当请求头里带上

X-Gray: true

这个请求才会打到 demo-app-v2。否则还是走旧版本。

这种方式特别适合做几类事情:内部测试先试、指定用户先试、某个终端先试、某个区域先试。

这个玩法比金丝雀更精细,因为你不是随机给 10% 流量,而是明确规定“谁能进新版本”。

但你也得知道: 灰度发布不是纯运维配置,它很容易和业务耦合起来。

因为你得跟前端、后端、网关约定好:

  • Header 叫什么
  • 谁来加
  • 哪类用户带这个 Header
  • 怎么撤掉

所以灰度发布做得好,看起来很高级;做不好,就会变成一坨谁也说不清的流量规则。

A/B 测试

如果从配置层面看,A/B 测试跟灰度真的很像。都是把不同请求导向不同版本。

比如你完全可以用 Header 或 Cookie 来做

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-app-ab
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-cookie: "ab-test"
spec:
  ingressClassName: nginx
  rules:
  - host: demo.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-app-b
            port:
              number: 80

比如当用户带上 ab-test 这个 Cookie,就让它走 B 版本。

但 A/B 测试和灰度发布最大的区别,是目的不一样。

灰度发布更关心的是:新版本稳不稳。

A/B 测试更关心的是:哪个版本效果更好。

比如:哪个按钮点击率更高、哪个页面停留时间更长、哪个推荐策略转化更高。

所以这一块你可以在文章里顺手点一句:A/B 测试看起来是发布,实际上更偏产品实验。

总结与建议

很多人一看到这些发布方式,就想一步到位:金丝雀、灰度、Service Mesh...

但我干了这么几年下来,反而越来越觉得:

大部分团队,其实不需要那么复杂。

如果你现在:

  • 发布还靠手点
  • 出问题不会回滚
  • 监控都没打全

那你就算上 Istio,也一样会炸,技术这东西,真不是越复杂越牛。把这些基础发布策略的原理、配置和适用场景搞清楚,结合自己团队的实际情况去选择,往往比盲目追求新技术更有用。

能稳住业务的,才是好方案。 本文提到的几种策略各有优缺点,滚动发布适用于常规迭代,蓝绿发布适合简单粗暴的切换,金丝雀和灰度发布则通过精细化流量控制来保障上线安全,而 A/B 测试则超越了发布本身,服务于产品和业务实验。在实际的云原生运维实践中,不妨从滚动发布开始,逐步根据需求引入更高级的策略,稳扎稳打地构建起自己的发布体系。如果你想了解更多相关的技术实践和社区讨论,也可以访问 云栈社区 来获取更多资源。




上一篇:Go开发求职游族网络:高频面试题与个人复盘解析
下一篇:代数环的本质与处理:从Simulink的Unit Delay到Modelica的DAE求解与AI融合
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-1 07:39 , Processed in 0.546338 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表