Vis/skjul meny Yingchi Blog

Kubernetes Rolling Update 滚动升级

用户希望应用程序始终可用,而开发人员则需要每天多次部署它们的新版本。在 Kubernetes 中,这些是通过滚动更新(Rolling Updates)完成的。 滚动更新 允许通过使用新的实例逐步更新 Pod 实例,零停机进行 Deployment 更新。

Kubernetes Rolling Update 基本概念

概念

当集群中的某个服务需要升级时,传统的做法是,先将要更新的服务下线,业务停止后再更新版本和配置,然后重新启动并提供服务。这种方式很明显的一个问题就是:会导致服务较长时间不可用,并且在大规模服务场景下会产生极大的工作量。

滚动更新就是针对多实例服务的一种不中断服务的更新升级方式。一般情况下,对于多实例服务,滚动更新采用对各个实例逐个进行单独更新而非同一时刻对所有实例进行全部更新的方式。

对于 kubernetes 集群部署的 service 来说,rolling update 就是指一次仅更新一个pod,并逐个进行更新,而不是在同一时刻将该 service 下面的所有 pod 全部停止,然后更新为新版本后再全部上线,rolling update 方式可以避免业务中断。

特点

优点:

  • 业务不中断,用户体验影响较小,较平滑
  • 相对于蓝绿部署,更加节约资源——它不需要运行两个集群、两倍的实例数

滚动更新也并不是银弹,有很多问题需要考虑到,比如:因为是逐步更新,那么我们在上线代码的时候,就会短暂出现新老版本不一致的情况,如果对上线要求较高的场景,那么就需要考虑如何做好兼容的问题

K8S 基于 Deployment 的 Rolling Update

kubernetes 的 Deployment 是一个相比较早前 Replication Controller 以及现在的 Replica Set 更高级别的抽象。Deployment会创建一个Replica Set,用来保证Deployment中的Pod的副本数。要 rolling-update deployment 中的 Pod,只需要修改 Deployment 自己的yml 文件并应用即可。这个修改会创建一个新的 Replica Set,在增加这个新 RS 的 pod 数的同时,减少旧RS的pod,直至完全升级。而这一切都发生在 Server 端,并不需要 kubectl 参与。

创建一个Deployment yml文件nginx-demo-dm.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-deploy
  minReadySeconds: 10
  template:
    metadata:
      labels:
        app: nginx-deploy
        version: v1
    spec:
      containers:
        - name: nginx-deploy
          image: nginx:1.10.1
          ports:
            - containerPort: 80
              protocol: TCP

创建该deployment:

kubect create -f nginx-demo-dm.yml --record

直接修改该 deployment 的 YAML 文件,修改到目标版本配置,如下 :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-deploy
  minReadySeconds: 10
  template:
    metadata:
      labels:
        app: nginx-deploy
        version: v2
    spec:
      containers:
        - name: nginx-deploy
          image: nginx:1.11.9
          ports:
            - containerPort: 80
              protocol: TCP

修改了其中一个 label,修改了 image 的 tag,然后执行:

kubectl apply -f nginx-demo-dm.yml --record

没错,不需要像 kubectl rolling-update [SVC] -f [TARGET-RC]这种 Replication Controller 时代的滚动更新形式,只需要像平常一样 apply -f即可,唯一不同的是需要加一个 --record ,目的很明显,方便回滚。

此时可以查看 Deployment 具体的滚动更新过程:

kubectl describe deployment nginx-demo

由于通过 --record 记录了更新历史,可以通过 kubectl rollout history 命令查看

kubectl rollout history deployment nginx-demo

回滚

如果需要回滚到之前一个版本:

kubectl rollout undo deployment nginx-demo

回滚到指定版本:

kubectl rollout undo deployment xxx-deployment --to-version=2

参考