Deployment控制器

Deployment是构建于ReplicaSet之上的一种控制器。相较于ReplicaSet有以下特性:

  • 事件和状态查看:在需要的时候可以查看Deployment对象升级的详细进度和状态。
  • 回滚:升级完成之后,一旦发现问题,可以使用回滚机制,将应用返回到前一个或用户指定的历史记录中的版本。
  • 版本记录:记录每一次的变更操作,以便于后续回滚操作
  • 暂停和启动:对每一次升级都能够随时启动和暂停。
  • 多种自动更新方案:支持重建更新机制和滚动更新机制。

创建Deployment

Deployment是构建于ReplicaSet之上的,故其spec字段包含了ReplicaSet支持的replicas、selector、template和minReadySeconds。并基于此创建ReplicaSet,下面是一个示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
          containerPort: 80
          - name: http

使用相关命令创建对象之后,使用kubectl get replicasets -l app=myapp可以查看由Deployment创建的ReplicaSet控制器。

更新策略

Deployment控制器详细信息中包了其更新策略的相关配信息,可以通过kubectl describe deployments myapp-deploy命令中输出的StrategyType、RollingUpdateStrategy字段查看控制器的更新策略。默认是RollingUpdate。

重新创建

首先删除现有的Pod对象,然后控制器基于新模板重新创建出新版本资源对象。通常用于新旧版本不兼容时才会使用,此种更新方式会造成短暂的不可用。

滚动升级

在删除旧版本的同时创建新版本,这是默认的更新策略。其优点在于服务不会中断,但不同的客户端可能得到不同版本的响应。
更新时Deployment控制器会创建一个新的ReplicaSet控制器,新的控制器创建新版本的Pod对象,旧的控制器逐渐减少Pod对象,直到达到用户定义的值。在使用滚动升级的时候有两个重要属性spec.strategy.rollingUpdate.maxSurge和spec.strategy.rollingUpdate.maxUnavailable

  • maxSurge:升级过程中总的Pod对象数量最多可以超过多少个。
  • maxUnavailable:升级过程中可以接受多少个Pod对象不可用(可用对象包括新旧版本)

注意两者不可以同时为零。

spec.minReadySeconds:使用此字段可以用来控制应用升级的速度。默认更新过程中新的Pod对象一旦就绪,则立即开始下一轮替换操作。此选项用来定义新对象创建后至少多久才将其视作就绪,就绪之前更新过程会被阻塞。精心设置的等待时长和就绪性探测能规避一部分Bug而导致的升级故障。
spec.revisionHistoryLimit:该字段指定控制器可以保存的历史版本的数量。

要保存版本升级历史,需要在创建Deployment对象时使用--record选项

升级Deployment

对于Deployment控制器的修改,可以使用applypatch命令进行修改。如需修改镜像,使用set image是比较方便的。如下面的示例:
kubectl patch deployments myapp-deploy -p '{"spec": {"minReadySeconds": 5}}'

注意上述命令中对minReadySeconds的修改不会对现有Pod产生影响。原因在于该字段为控制器级别。如需改动现有Pod资源的属性,需要对其内嵌的template模板进行修改。

下面是一个修改Pod内镜像的示例:
kubectl set image deployments myapp-deploy myapp=ikubernetes/myapp:v2
一些辅助命令

  • kubectl rollout status输出滚动更新过程中的状态信息,如kubectl rollout deployments myapp-deploy
  • kubectl get deployments myapp-deploy --watch监控更新过程中Pod的变化

更新过程中Deployment会新建一个ReplicaSet用以管理新版本Pod对象,在新的的ReplicaSet创建Pod时,旧的ReplicaSet下的Pod会逐步删除。

金丝雀发布

服务器上同时存在两个版本的应用,通常是人工选定少数用户路由至新版本,验证没有问题之后则将剩余旧版全部更新,这种更新方式便是金丝雀发布。
Deployment控制器可以控制更新节奏配合maxSurge和maxUnavailable可以精巧控制更新过程。为了降低对系统的影响,通常建议“先添加,再删除,且可用Pod不低于期望值”下面是一个演示,用以说明其工作方式:

kubectl patch deployments myapp-deploy -p '{"spec": {"strategy": {"rollingUpdate": {"maxSurge": 1, "maxUnavailable": 0}}}}'

然后启动更新过程,然后立即暂停。这个操作时间和max ReadySeconds属性相关。可以使用“&&”连接两个命令:

kubectl set image deployments myapp-deploy myapp=ikubernetes/myapp:v3 && kubectl rollout pause deployments myapp-deploy

此时通过Service或ingress通过路由设定将选定用户接入新版,在验证一段时间没有问题之后即可将更新过程恢复kubectl rollout resume deployments myapp-deploy

回滚

如果因为某些原因导致更新无法正常进行,或者更新之后出现问题,则应该将应用回滚到之前的版本或者指定的历史记录中的版本。
命令kubectl rollout undo deployments myapp-deploy可以将控制器控制的应用回滚到上一个版本。如果需要指定版本号,使用--to-revision选项。如kubectl rollout undo deployments myapp-deploy --to-revision=2。查看Deployment历史版本的命令为kubectl rollout history deployments myapp-deploy
回滚操作中,回滚操作会被当做一次更新追加到历史记录中。如果此前的更新过程处于暂停状态,回滚操作需要先将Pod模版中的版本改回之前的版本,然后继续,否则将一直处于暂停状态,无法回滚。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!