Kube-controller-manager(Deployment)

基于1.25

Deployment控制器主要控制Deployment资源。

  • Deploymen控制器依旧更新策略调整RS资源

控制器初始化

Deployment控制器初始化的时候,会创建工作队列存储Deployment资源对象的Key

  • Deployment资源对象:监听Add、Update、Delete事件,把监听到的RS资源对象的Key加入到工作队列中,等待Worker协程消费处理
  • RS资源对象
  • Pod资源对象

主要执行逻辑

  1. dc.Listener.Deployments

    获取Deployment资源对象。通过Deployment Informer的Lister接口Get获取完整的Deployment资源对象

  2. dc.getReconcileSetsForDeployment

    获取管理的RS对象

  3. d.DeletionTimestamp !=nil

    判断是否执行Reconcile

  4. d.Spec.Paused

    判断是否暂停版本更新。当处于Paused状态时,Deployment Controller仅仅通过RS将Pod数量调谐到Deployment对象的规定数量,但不处理Pod模版的更新

    pod数量的调谐sync func完成

  1. getRollbackTo(d)!=nil

    判断是否会滚版本

    • 如果Deployment资源对象存在“deprecated.deployment.rollback.to” Annotation,则认为是Pod模版需要会滚到Annotation指定版本去,调用rollback func寻找目标的RS并将Deployment资源对象的Pod模版修改为该RS的配置

    • Ref:https://github.com/kubernetes/kubernetes/blob/88e994f6bf8fc88114c5b733e09afea339bea66d/pkg/controller/deployment/deployment_controller.go#L645

      // rollback is not re-entrant in case the underlying replica sets are updated with a new
      // revision so we should ensure that we won't proceed to update replica sets until we
      // make sure that the deployment has cleaned up its rollback spec in subsequent enqueues.
      if getRollbackTo(d) != nil {
      return dc.rollback(ctx, d, rsList)
      }
  2. dc.isScalingEvent

    根据期望副本数量的变化执行Pod的拓展/缩容的操作。

    如果Deployment被认为发生了扩容/缩容操作,就需要调用sync执行Pod数量的调谐

    负责检查Deployment是否扩容/缩容的是isScalingEvent func:检查Deployment关联的各个活跃的RS的”deployment.kubernetes.io/desired-replicas” Annotation记录的Deployment的期望副本数量,如果不一致,则说明Deployment发生了扩容/缩容

    • Ref:https://github.com/kubernetes/kubernetes/blob/88e994f6bf8fc88114c5b733e09afea339bea66d/pkg/controller/deployment/sync.go#L529

      // isScalingEvent checks whether the provided deployment has been updated with a scaling event
      // by looking at the desired-replicas annotation in the active replica sets of the deployment.
      //
      // rsList should come from getReplicaSetsForDeployment(d).
      func (dc *DeploymentController) isScalingEvent(ctx context.Context, d *apps.Deployment, rsList []*apps.ReplicaSet) (bool, error) {
      newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(ctx, d, rsList, false)
      if err != nil {
      return false, err
      }
      allRSs := append(oldRSs, newRS)
      for _, rs := range controller.FilterActiveReplicaSets(allRSs) {
      desired, ok := deploymentutil.GetDesiredReplicasAnnotation(rs)
      if !ok {
      continue
      }
      if desired != *(d.Spec.Replicas) {
      return true, nil
      }
      }
      return false, nil
      }

    PodTempldate的更新操作不会影响Spec.Replicas字段。所以只更新PodTempldate不会,进入到此处的Pod扩缩容操作

  3. switch d.Spec.Strategy.Type

    按更新策略更新Pod。

    当更新策略为Recreate时,调用dc.rolloutRecreate func执行Pod更新

    当更新策略为RollingUpdate,调用dc.rolloutRolling func 执行Pod更新

调谐Pod的数量

当Deployment处于Suspend状态,或期望副本数量发生变化时,Deployment控制器调用sync func,借助RS调谐Pod数量

Deployment控制首先获取Deployment关联的所有RS,根据实际情况执行以下逻辑:

  • 如果仅有一个或者完全没有活跃的RS:找出创建时间最近的RS,将其副本数量调整到Deployment对象一致
  • 如果最新的RS存在,并且副本数和Deployment一致,就把其他的RSPod期望数降为0,删除这些旧的Pod
  • 如果有多个活跃的RS,更新策略为RollingUpdate,通过多次迭代,逐渐把旧RS的Pod删除,并且调整最新的RS的Pod数
  • 第三种情况,说明Pod版本更新和Pod副本数量同时执行,K8s不推荐,应该把更新副本数和版本更新分开

更新策略

Deployment 支持更新策略为 Recrate和 RollingUpdate 俩种

Recrate

如果Deployment资源对象的更新策略为Recreate,Deployment关联的所有RS

  1. 所有非最新的RS的Pod副本数量将为0,来删除旧的Pod
  2. 在删除所有旧Pod之前,Deployment Controller只会更新Deployment的状态,不会创建新的Pod
  3. 删除所有旧的Pod之后,Deployment Controller创建使用新Pod模版的RS,实现创建新的Pod

RollingUpdate

Deployment会多次执行同步操作,每次同步操作通过调节新、旧RS的Spec.Replicas字段的方式,创建和删除一些Pod,分次逐步完成Pod的更新

  • Spec.MaxSurge:指定超出期望Pod的数量
  • Spec.MaxUnavailable:更新过程中不可用的Pod数量
  1. Deployment Controller获取Deployment关联的所有RS
  • 如果所有RS都和DeploymentPod模版不同,就会创建一个新的RS(Recreate不一样,它选择只有删除所有的Pod,才会创建新的RS)
  1. Deployment Controller会尝试扩容最新的RS,使得总可用的Pod数量不超过MaxSurge的上限
  • Deployment Controller会修改新的RS的Spec.Replicas,扩容一部分Pod,并且结束同步
  • 如果新的RS已经成功扩容了新的Pod,DeploymentController就会删除一些旧的Pod
  1. Deployment Controller会执行旧Pod的缩容,使得总不可用数量不超过Max Unavailable的下限
  • Deployment Controller会修改新的RS的Spec.Replicas,缩容一部分Pod,并且结束同步
  1. Deployment Controller 会检查Deployment状态,如果可用Pod已经达到Spec.Replicas一致,更新完成,清理冗余的RS

版本回滚

Deployment Controller创建的RS都有一条注解记录(deployment.kubernetes.io/version)其版本号

版本回滚主要是3步骤:

  1. 获取回滚的版本号

    Deployment Controller 调用getRollbackTo func获取回滚版本号,回滚版本号记录在Deployment中的Annotation(deprecated.deployment.rollback.io)中

  2. 根据回滚版本号,找到对应的RS

    如果回滚版本号是0,则Deployment Controller 回滚到次新版本。Deployment Controller根据回滚版本号,找到对应的RS对象

  3. 更新Deployment的Pod模版

    Deployment Controlller更新Deployment资源对象的Pod模版,将其更换为回滚的目标RS中的Pod模版,并且清空回滚Annottaion

    需要注意回滚过程只更新Pod模版回滚,Pod模版之外的配置无法回滚