Back
Featured image of post 部署策略及容器化实现

部署策略及容器化实现

部署策略

不同的应用有不同的部署场景,有的应用必须是滚动更新的,不可以有服务停止的时间。而有些应用由于某些原因,比如不支持新旧版本共存,必须是版本一键切换的。

常见的部署策略包括蓝绿发布,金丝雀发布(灰度发布),A/B Test发布等。

基础发布

基础发布是最为原始也是最为简单的一种发布策略,即替换式更新。把线上所有服务一次性替换为更新版本。缺点是回滚慢,风险较高,服务有中断时间。

多服务发布

服务有多版本共存的情况下,可以采取跟基础发布类似的策略,同时一次性更新。但由于多版本共存,因此风险比基础发布更低一些,但仍然存在某个版本出问题的可能性。缺点是回滚慢,多版本带来的管理复杂,测试复杂等。

滚动发布

滚动发布是滚动式更新服务的每一个节点。好处是回滚相对简单,滚动的方式更容易发现问题,因此风险较低。不过,服务必须支持新旧版本共存的情况。

蓝绿发布

蓝绿发布是环境镜像替换。绿环境是线上运行环境,蓝环境是需要发布版本的另一个环境,把流量从绿环境切换到蓝环境完成版本更新。
蓝环境一般会进行深度测试,因此风险较低。此外,流量切换很快捷,回滚是瞬间完成的。缺点是成本较高,在一些复杂的微服务场景下也很难做到覆盖所有的回归测试,从而可能造成服务中断或其他问题。

金丝雀发布

金丝雀发布(国内一般称之为灰度发布)类似于滚动发布,以增量的方式进行版本迭代。不同的是金丝雀发布更倾向于百分比的推进,并可以指定发布的节点,从而可以在增量迭代的过程中进行数据监控及比对,从而提早发现问题。

好处是风险低,成本比蓝绿发布低,回滚方便。缺点也是显而易见的,比对和测试需要更长的时间周期和更复杂的运维操作。不停迭代的新版本数量也需要监控的更新。

A/B测试发布

A/B Test需要多个版本在线上同时运行进行指标测量和比较。可以通过路由规则,A/B测试工具等实现流量分流及测量。最后根据比较结果选择最好的版本进行全量发布。

A/B测试倾向于实验和探索测试。优点是成本低,工具齐全。缺点是存在风险,测试复杂,自动化实现更困难。

部署策略的选择

一般来说,蓝绿发布和金丝雀发布是比较常用的发布策略。如果应用支持新旧版本共存的话,首选是金丝雀发布,如果不支持的话,首选是蓝绿发布。
对于一些故障容忍度较高的服务,可以采用最为简单的基础发布策略。

基于风险和成本简单归纳一下

低风险,低成本: 金丝雀发布
高风险,低成本: 基础发布
低风险,高成本: 蓝绿发布


部署策略的容器化实现

基础发布

更新Deployment的.spec.strategy.type==Recreate
则默认部署策略会变成重新创建,也就是基础发布的策略方式:杀死所有Pod,然后重新创建新版本的Pod

滚动发布

kubernetes的Deployment默认部署策略就是滚动发布,好处是通过探针可以实时检测服务的健康状况,在新Pod就绪健康之前会一直等待,从而避免更大规模的故障风险。

控制发布速度

  • minReadySeconds
    这个属性指定新创建的Pod在运行多少秒后才能将其视为可用。对于一些需要加载数据到内存的应用来说尤为有用。
  • maxSurge
    这个属性决定了Deployment中除了配置的期待副本数量外,最多允许超出的pod实例数量。也决定了升级的速度,数量越大,升级更新越快。
  • maxUnavailable
    设置在滚动发布期间,Deployment最大允许多少个pod处于不可用状态。谨慎设置,尤其是在流量高峰期。一般我们设置为0,副本数量会一直保持在期待状态中。

配置示例

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 10
  minReadySeconds: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
        readinessProbe:
          failureThreshold: 10
          httpGet:
            path: /ready
            port: 80
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 5
          successThreshold: 1
          timeoutSeconds: 3
status: {}

金丝雀发布

尽管可以通过kubectl rollout pause暂停滚动更新方式实现手动粗粒度灰度,但由于无法精准控制比例,官方文档建议是建立多个Deployment实现。

具体思路

  1. 建立多个Deployments,通过标签识别是否是灰度版本,比如release: canaryrelease: stable
  2. 前端忽略上述标签,统一流量入口。
  3. 通过不断调整canary Deployment和线上版本的副本数,来达到递增更新的目的。

配置示例

     name: frontend
     replicas: 3
     ...
     labels:
        app: guestbook
        tier: frontend
        track: stable
     ...
     image: gb-frontend:v3

---
     name: frontend-canary
     replicas: 1
     ...
     labels:
        app: guestbook
        tier: frontend
        track: canary
     ...
     image: gb-frontend:v4
---
 selector:
     app: guestbook
     tier: frontend

自动调整副本数

难点是需要手动调整两个Deployment的副本数,如果使用HPA的话只需要调整一个Deployment就好了,另外一个Deployment会根据压力自动伸缩。

一个比较讨巧的办法是创建多个Deployment,比如10%流量比例的,30%流量比例的,60%流量比例的,然后串行发布即可。

自动化实现副本数的调整比较复杂,好在有开源案例可以实现,比如Flagger。

原理就是定期分析canary的请求成功率和延迟,逐渐增大canary的流量权重,直至全量更新。

除了金丝雀发布外,Flagger还支持A/B Test发布策略。

蓝绿发布

蓝绿发布的实现较为简单,只需要创建一个green Deployment,然后通过标签选择器,把前端SVC由blue Deployment指向green Deployment即可。

配置示例

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    release: blue
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

---
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    release: green
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

---
apiVersion: v1
kind: Service
metadata: 
  name: nginx
  labels: 
    name: nginx
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector: 
    release: green
  type: LoadBalancer

参考文档

  1. https://harness.io/blog/continuous-verification/blue-green-canary-deployment-strategies/
  2. https://medium.com/tech-at-wildlife-studios/canary-deployment-in-kubernetes-how-to-use-the-pattern-b2e9c40d085d
  3. https://kubernetes.io/zh/docs/concepts/cluster-administration/manage-deployment/
  4. https://www.ianlewis.org/en/bluegreen-deployments-kubernetes
  5. https://docs.flagger.app/tutorials/nginx-progressive-delivery
Built with Hugo
Theme Stack designed by Jimmy