Kubernetes的Deployment控制器使用

Kubernetes的Deployment控制器使用

Deployment简述

Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代之前的ReplicationController 来方便的管理应用。典型的应用场景包括:html

  • 定义Deployment来建立Pod和ReplicaSet
  • 滚动升级和回滚应用
  • 扩容和缩容
  • 暂停和继续Deployment

好比一个简单的nginx应用能够定义为nginx

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

扩容:git

kubectl scale deployment nginx-deployment --replicas 10

若是集群支持 horizontal pod autoscaling 的话,还能够为Deployment设置自动扩展:github

kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80

更新镜像也比较简单:api

kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

回滚:安全

kubectl rollout undo deployment/nginx-deployment

Deployment 结构示意图

参考:https://kubernetes.io/docs/api-reference/v1.6/#deploymentspec-v1beta1-apps服务器

kubernetes deployment cheatsheet

图片 - kubernetes deployment cheatsheetapp

Deployment 概念详细解析

本文翻译自kubernetes官方文档:https://kubernetes.io/docs/concepts/workloads/controllers/deployment.mdless

根据2017年5月10日的Commit 8481c02 翻译。ide

Deployment 是什么?

Deployment为Pod和Replica Set(下一代Replication Controller)提供声明式更新。

您只须要在 Deployment 中描述您想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。您能够定义一个全新的 Deployment 来建立 ReplicaSet 或者删除已有的 Deployment 并建立一个新的来替换。

注意:您不应手动管理由 Deployment 建立的 ReplicaSet,不然您就篡越了 Deployment controller 的职责!下文罗列了 Deployment 对象中已经覆盖了全部的用例。若是未有覆盖您全部须要的用例,请直接在 Kubernetes 的代码库中提 issue。

典型的用例以下:

  • 使用Deployment来建立ReplicaSet。ReplicaSet在后台建立pod。检查启动状态,看它是成功仍是失败。
  • 而后,经过更新Deployment的PodTemplateSpec字段来声明Pod的新状态。这会建立一个新的ReplicaSet,Deployment会按照控制的速率将pod从旧的ReplicaSet移动到新的ReplicaSet中。
  • 若是当前状态不稳定,回滚到以前的Deployment revision。每次回滚都会更新Deployment的revision。
  • 扩容Deployment以知足更高的负载。
  • 暂停Deployment来应用PodTemplateSpec的多个修复,而后恢复上线。
  • 根据Deployment 的状态判断上线是否hang住了。
  • 清除旧的没必要要的 ReplicaSet。

建立 Deployment

下面是一个 Deployment 示例,它建立了一个 ReplicaSet 来启动3个 nginx pod。

下载示例文件并执行命令:

$ kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record
deployment "nginx-deployment" created

将kubectl的 --record 的 flag 设置为 true能够在 annotation 中记录当前命令建立或者升级了该资源。这在将来会颇有用,例如,查看在每一个 Deployment revision 中执行了哪些命令。

而后当即执行 get 将得到以下结果:

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         0         0            0           1s

输出结果代表咱们但愿的repalica数是3(根据deployment中的.spec.replicas配置)当前replica数( .status.replicas)是0, 最新的replica数(.status.updatedReplicas)是0,可用的replica数(.status.availableReplicas)是0。

过几秒后再执行get命令,将得到以下输出:

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           18s

咱们能够看到Deployment已经建立了3个 replica,全部的 replica 都已是最新的了(包含最新的pod template),可用的(根据Deployment中的.spec.minReadySeconds声明,处于已就绪状态的pod的最少个数)。执行kubectl get rskubectl get pods会显示Replica Set(RS)和Pod已建立。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-2035384211   3         3         0       18s

您可能会注意到 ReplicaSet 的名字老是<Deployment的名字>-<pod template的hash值>

$ kubectl get pods --show-labels
NAME                                READY     STATUS    RESTARTS   AGE       LABELS
nginx-deployment-2035384211-7ci7o   1/1       Running   0          18s       app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-kzszj   1/1       Running   0          18s       app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-qqcnn   1/1       Running   0          18s       app=nginx,pod-template-hash=2035384211

刚建立的Replica Set将保证老是有3个 nginx 的 pod 存在。

注意: 您必须在 Deployment 中的 selector 指定正确的 pod template label(在该示例中是 app = nginx),不要跟其余的 controller 的 selector 中指定的 pod template label 搞混了(包括 Deployment、Replica Set、Replication Controller 等)。Kubernetes 自己并不会阻止您任意指定 pod template label,可是若是您真的这么作了,这些 controller 之间会相互打架,并可能致使不正确的行为。

Pod-template-hash label

注意:这个 label 不是用户指定的!

注意上面示例输出中的 pod label 里的 pod-template-hash label。当 Deployment 建立或者接管 ReplicaSet 时,Deployment controller 会自动为 Pod 添加 pod-template-hash label。这样作的目的是防止 Deployment 的子ReplicaSet 的 pod 名字重复。经过将 ReplicaSet 的 PodTemplate 进行哈希散列,使用生成的哈希值做为 label 的值,并添加到 ReplicaSet selector 里、 pod template label 和 ReplicaSet 管理中的 Pod 上。

更新Deployment

注意: Deployment 的 rollout 当且仅当 Deployment 的 pod template(例如.spec.template)中的label更新或者镜像更改时被触发。其余更新,例如扩容Deployment不会触发 rollout。

假如咱们如今想要让 nginx pod 使用nginx:1.9.1的镜像来代替原来的nginx:1.7.9的镜像。

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated

咱们可使用edit命令来编辑 Deployment,修改 .spec.template.spec.containers[0].image ,将nginx:1.7.9 改写成 nginx:1.9.1

$ kubectl edit deployment/nginx-deployment
deployment "nginx-deployment" edited

查看 rollout 的状态,只要执行:

$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out

Rollout 成功后,get Deployment:

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           36s

UP-TO-DATE 的 replica 的数目已经达到了配置中要求的数目。

CURRENT 的 replica 数表示 Deployment 管理的 replica 数量,AVAILABLE 的 replica 数是当前可用的replica数量。

咱们经过执行kubectl get rs能够看到 Deployment 更新了Pod,经过建立一个新的 ReplicaSet 并扩容了3个 replica,同时将原来的 ReplicaSet 缩容到了0个 replica。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-1564180365   3         3         0       6s
nginx-deployment-2035384211   0         0         0       36s

执行 get pods只会看到当前的新的 pod:

$ kubectl get pods
NAME                                READY     STATUS    RESTARTS   AGE
nginx-deployment-1564180365-khku8   1/1       Running   0          14s
nginx-deployment-1564180365-nacti   1/1       Running   0          14s
nginx-deployment-1564180365-z9gth   1/1       Running   0          14s

下次更新这些 pod 的时候,只须要更新 Deployment 中的 pod 的 template 便可。

Deployment 能够保证在升级时只有必定数量的 Pod 是 down 的。默认的,它会确保至少有比指望的Pod数量少一个是up状态(最多一个不可用)。

Deployment 同时也能够确保只建立出超过时望数量的必定数量的 Pod。默认的,它会确保最多比指望的Pod数量多一个的 Pod 是 up 的(最多1个 surge )。

在将来的 Kuberentes 版本中,将从1-1变成25%-25%。

例如,若是您本身看下上面的 Deployment,您会发现,开始建立一个新的 Pod,而后删除一些旧的 Pod 再建立一个新的。当新的Pod建立出来以前不会杀掉旧的Pod。这样可以确保可用的 Pod 数量至少有2个,Pod的总数最多4个。

$ kubectl describe deployments
Name:           nginx-deployment
Namespace:      default
CreationTimestamp:  Tue, 15 Mar 2016 12:01:06 -0700
Labels:         app=nginx
Selector:       app=nginx
Replicas:       3 updated | 3 total | 3 available | 0 unavailable
StrategyType:       RollingUpdate
MinReadySeconds:    0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
OldReplicaSets:     <none>
NewReplicaSet:      nginx-deployment-1564180365 (3/3 replicas created)
Events:
  FirstSeen LastSeen    Count   From                     SubobjectPath   Type        Reason              Message
  --------- --------    -----   ----                     -------------   --------    ------              -------
  36s       36s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-2035384211 to 3
  23s       23s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 1
  23s       23s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 2
  23s       23s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 2
  21s       21s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 0
  21s       21s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3

咱们能够看到当咱们刚开始建立这个 Deployment 的时候,建立了一个 ReplicaSet(nginx-deployment-2035384211),并直接扩容到了3个 replica。

当咱们更新这个 Deployment 的时候,它会建立一个新的 ReplicaSet(nginx-deployment-1564180365),将它扩容到1个replica,而后缩容原先的 ReplicaSet 到2个 replica,此时知足至少2个 Pod 是可用状态,同一时刻最多有4个 Pod 处于建立的状态。

接着继续使用相同的 rolling update 策略扩容新的 ReplicaSet 和缩容旧的 ReplicaSet。最终,将会在新的 ReplicaSet 中有3个可用的 replica,旧的 ReplicaSet 的 replica 数目变成0。

Rollover(多个rollout并行)

每当 Deployment controller 观测到有新的 deployment 被建立时,若是没有已存在的 ReplicaSet 来建立指望个数的 Pod 的话,就会建立出一个新的 ReplicaSet 来作这件事。已存在的 ReplicaSet 控制 label 与.spec.selector匹配可是 template 跟.spec.template不匹配的 Pod 缩容。最终,新的 ReplicaSet 将会扩容出.spec.replicas指定数目的 Pod,旧的 ReplicaSet 会缩容到0。

若是您更新了一个的已存在并正在进行中的 Deployment,每次更新 Deployment都会建立一个新的 ReplicaSet并扩容它,同时回滚以前扩容的 ReplicaSet ——将它添加到旧的 ReplicaSet 列表中,开始缩容。

例如,假如您建立了一个有5个niginx:1.7.9 replica的 Deployment,可是当还只有3个nginx:1.7.9的 replica 建立出来的时候您就开始更新含有5个nginx:1.9.1 replica 的 Deployment。在这种状况下,Deployment 会当即杀掉已建立的3个nginx:1.7.9的 Pod,并开始建立nginx:1.9.1的 Pod。它不会等到全部的5个nginx:1.7.9的 Pod 都建立完成后才开始改变航道。

Label selector 更新

咱们一般不鼓励更新 label selector,咱们建议事先规划好您的 selector。

任何状况下,只要您想要执行 label selector 的更新,请必定要谨慎并确认您已经预料到全部可能所以致使的后果。

  • 增添 selector 须要同时在 Deployment 的 spec 中更新新的 label,不然将返回校验错误。此更改是不可覆盖的,这意味着新的 selector 不会选择使用旧 selector 建立的 ReplicaSet 和 Pod,从而致使全部旧版本的 ReplicaSet 都被丢弃,并建立新的 ReplicaSet。
  • 更新 selector,即更改 selector key 的当前值,将致使跟增添 selector 一样的后果。
  • 删除 selector,即删除 Deployment selector 中的已有的 key,不须要对 Pod template label 作任何更改,现有的 ReplicaSet 也不会成为孤儿,可是请注意,删除的 label 仍然存在于现有的 Pod 和 ReplicaSet 中。

回退Deployment

有时候您可能想回退一个 Deployment,例如,当 Deployment 不稳定时,好比一直 crash looping。

默认状况下,kubernetes 会在系统中保存前两次的 Deployment 的 rollout 历史记录,以便您能够随时回退(您能够修改revision history limit来更改保存的revision数)。

注意: 只要 Deployment 的 rollout 被触发就会建立一个 revision。也就是说当且仅当 Deployment 的 Pod template(如.spec.template)被更改,例如更新template 中的 label 和容器镜像时,就会建立出一个新的 revision。

其余的更新,好比扩容 Deployment 不会建立 revision——所以咱们能够很方便的手动或者自动扩容。这意味着当您回退到历史 revision 时,只有 Deployment 中的 Pod template 部分才会回退。

假设咱们在更新 Deployment 的时候犯了一个拼写错误,将镜像的名字写成了nginx:1.91,而正确的名字应该是nginx:1.9.1

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.91
deployment "nginx-deployment" image updated

Rollout 将会卡住。

$ kubectl rollout status deployments nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...

按住 Ctrl-C 中止上面的 rollout 状态监控。

您会看到旧的 replica(nginx-deployment-1564180365 和 nginx-deployment-2035384211)和新的 replica (nginx-deployment-3066724191)数目都是2个。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-1564180365   2         2         0       25s
nginx-deployment-2035384211   0         0         0       36s
nginx-deployment-3066724191   2         2         2       6s

看下建立 Pod,您会看到有两个新的 ReplicaSet 建立的 Pod 处于 ImagePullBackOff 状态,循环拉取镜像。

$ kubectl get pods
NAME                                READY     STATUS             RESTARTS   AGE
nginx-deployment-1564180365-70iae   1/1       Running            0          25s
nginx-deployment-1564180365-jbqqo   1/1       Running            0          25s
nginx-deployment-3066724191-08mng   0/1       ImagePullBackOff   0          6s
nginx-deployment-3066724191-eocby   0/1       ImagePullBackOff   0          6s

注意,Deployment controller会自动中止坏的 rollout,并中止扩容新的 ReplicaSet。

$ kubectl describe deployment
Name:           nginx-deployment
Namespace:      default
CreationTimestamp:  Tue, 15 Mar 2016 14:48:04 -0700
Labels:         app=nginx
Selector:       app=nginx
Replicas:       2 updated | 3 total | 2 available | 2 unavailable
StrategyType:       RollingUpdate
MinReadySeconds:    0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
OldReplicaSets:     nginx-deployment-1564180365 (2/2 replicas created)
NewReplicaSet:      nginx-deployment-3066724191 (2/2 replicas created)
Events:
  FirstSeen LastSeen    Count   From                    SubobjectPath   Type        Reason              Message
  --------- --------    -----   ----                    -------------   --------    ------              -------
  1m        1m          1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-2035384211 to 3
  22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 1
  22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 2
  22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 2
  21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 0
  21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3
  13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 1
  13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-1564180365 to 2
  13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 2

为了修复这个问题,咱们须要回退到稳定的 Deployment revision。

检查 Deployment 升级的历史记录

首先,检查下 Deployment 的 revision:

$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment":
REVISION    CHANGE-CAUSE
1           kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml--record
2           kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3           kubectl set image deployment/nginx-deployment nginx=nginx:1.91

由于咱们建立 Deployment 的时候使用了--record参数能够记录命令,咱们能够很方便的查看每次 revision 的变化。

查看单个revision 的详细信息:

$ kubectl rollout history deployment/nginx-deployment --revision=2
deployments "nginx-deployment" revision 2
  Labels:       app=nginx
          pod-template-hash=1159050644
  Annotations:  kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
  Containers:
   nginx:
    Image:      nginx:1.9.1
    Port:       80/TCP
     QoS Tier:
        cpu:      BestEffort
        memory:   BestEffort
    Environment Variables:      <none>
  No volumes.

回退到历史版本

如今,咱们能够决定回退当前的 rollout 到以前的版本:

$ kubectl rollout undo deployment/nginx-deployment
deployment "nginx-deployment" rolled back

也可使用 --revision参数指定某个历史版本:

$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment "nginx-deployment" rolled back

与 rollout 相关的命令详细文档见kubectl rollout

该 Deployment 如今已经回退到了先前的稳定版本。如您所见,Deployment controller产生了一个回退到revison 2的DeploymentRollback的 event。

$ kubectl get deployment
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           30m

$ kubectl describe deployment
Name:           nginx-deployment
Namespace:      default
CreationTimestamp:  Tue, 15 Mar 2016 14:48:04 -0700
Labels:         app=nginx
Selector:       app=nginx
Replicas:       3 updated | 3 total | 3 available | 0 unavailable
StrategyType:       RollingUpdate
MinReadySeconds:    0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
OldReplicaSets:     <none>
NewReplicaSet:      nginx-deployment-1564180365 (3/3 replicas created)
Events:
  FirstSeen LastSeen    Count   From                    SubobjectPath   Type        Reason              Message
  --------- --------    -----   ----                    -------------   --------    ------              -------
  30m       30m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-2035384211 to 3
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 1
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 2
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 2
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 0
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 2
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 1
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-1564180365 to 2
  2m        2m          1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-3066724191 to 0
  2m        2m          1       {deployment-controller }                Normal      DeploymentRollback  Rolled back deployment "nginx-deployment" to revision 2
  29m       2m          2       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3

清理 Policy

您能够经过设置.spec.revisonHistoryLimit项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留全部的 revision;若是将该项设置为0,Deployment就不容许回退了。

Deployment 扩容

您可使用如下命令扩容 Deployment:

$ kubectl scale deployment nginx-deployment --replicas 10
deployment "nginx-deployment" scaled

假设您的集群中启用了horizontal pod autoscaling,您能够给 Deployment 设置一个 autoscaler,基于当前 Pod的 CPU 利用率选择最少和最多的 Pod 数。

$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
deployment "nginx-deployment" autoscaled

比例扩容

RollingUpdate Deployment 支持同时运行一个应用的多个版本。或者 autoscaler 扩 容 RollingUpdate Deployment 的时候,正在中途的 rollout(进行中或者已经暂停的),为了下降风险,Deployment controller 将会平衡已存在的活动中的 ReplicaSet(有 Pod 的 ReplicaSet)和新加入的 replica。这被称为比例扩容。

例如,您正在运行中含有10个 replica 的 Deployment。maxSurge=3,maxUnavailable=2。

$ kubectl get deploy
NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment     10        10        10           10          50s

您更新了一个镜像,而在集群内部没法解析。

$ kubectl set image deploy/nginx-deployment nginx=nginx:sometag
deployment "nginx-deployment" image updated

镜像更新启动了一个包含ReplicaSet nginx-deployment-1989198191的新的rollout,可是它被阻塞了,由于咱们上面提到的maxUnavailable。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-1989198191   5         5         0         9s
nginx-deployment-618515232    8         8         8         1m

而后发起了一个新的Deployment扩容请求。autoscaler将Deployment的repllica数目增长到了15个。Deployment controller须要判断在哪里增长这5个新的replica。若是咱们没有谁用比例扩容,全部的5个replica都会加到一个新的ReplicaSet中。若是使用比例扩容,新添加的replica将传播到全部的ReplicaSet中。大的部分加入replica数最多的ReplicaSet中,小的部分加入到replica数少的ReplciaSet中。0个replica的ReplicaSet不会被扩容。

在咱们上面的例子中,3个replica将添加到旧的ReplicaSet中,2个replica将添加到新的ReplicaSet中。rollout进程最终会将全部的replica移动到新的ReplicaSet中,假设新的replica成为健康状态。

$ kubectl get deploy
NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment     15        18        7            8           7m
$ kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-1989198191   7         7         0         7m
nginx-deployment-618515232    11        11        11        7m

暂停和恢复Deployment

您能够在发出一次或屡次更新前暂停一个 Deployment,而后再恢复它。这样您就能屡次暂停和恢复 Deployment,在此期间进行一些修复工做,而不会发出没必要要的 rollout。

例如使用刚刚建立 Deployment:

$ kubectl get deploy
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     3         3         3            3           1m
[mkargaki@dhcp129-211 kubernetes]$ kubectl get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   3         3         3         1m

使用如下命令暂停 Deployment:

$ kubectl rollout pause deployment/nginx-deployment
deployment "nginx-deployment" paused

而后更新 Deplyment中的镜像:

$ kubectl set image deploy/nginx nginx=nginx:1.9.1
deployment "nginx-deployment" image updated

注意新的 rollout 启动了:

$ kubectl rollout history deploy/nginx
deployments "nginx"
REVISION  CHANGE-CAUSE
1   <none>

$ kubectl get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   3         3         3         2m

您能够进行任意屡次更新,例如更新使用的资源:

$ kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi
deployment "nginx" resource requirements updated

Deployment 暂停前的初始状态将继续它的功能,而不会对 Deployment 的更新产生任何影响,只要 Deployment是暂停的。

最后,恢复这个 Deployment,观察完成更新的 ReplicaSet 已经建立出来了:

$ kubectl rollout resume deploy nginx
deployment "nginx" resumed
$ KUBECTL get rs -w
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   2         2         2         2m
nginx-3926361531   2         2         0         6s
nginx-3926361531   2         2         1         18s
nginx-2142116321   1         2         2         2m
nginx-2142116321   1         2         2         2m
nginx-3926361531   3         2         1         18s
nginx-3926361531   3         2         1         18s
nginx-2142116321   1         1         1         2m
nginx-3926361531   3         3         1         18s
nginx-3926361531   3         3         2         19s
nginx-2142116321   0         1         1         2m
nginx-2142116321   0         1         1         2m
nginx-2142116321   0         0         0         2m
nginx-3926361531   3         3         3         20s
^C
$ KUBECTL get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   0         0         0         2m
nginx-3926361531   3         3         3         28s

注意: 在恢复 Deployment 以前您没法回退一个已经暂停的 Deployment。

Deployment 状态

Deployment 在生命周期中有多种状态。在建立一个新的 ReplicaSet 的时候它能够是 progressing 状态, complete 状态,或者 fail to progress 状态。

进行中的 Deployment

Kubernetes 将执行过下列任务之一的 Deployment 标记为 progressing 状态:

  • Deployment 正在建立新的ReplicaSet过程当中。
  • Deployment 正在扩容一个已有的 ReplicaSet。
  • Deployment 正在缩容一个已有的 ReplicaSet。
  • 有新的可用的 pod 出现。

您可使用kubectl rollout status命令监控 Deployment 的进度。

完成的 Deployment

Kubernetes 将包括如下特性的 Deployment 标记为 complete 状态:

  • Deployment 最小可用。最小可用意味着 Deployment 的可用 replica 个数等于或者超过 Deployment 策略中的指望个数。
  • 全部与该 Deployment 相关的replica都被更新到了您指定版本,也就说更新完成。
  • 该 Deployment 中没有旧的 Pod 存在。

您能够用kubectl rollout status命令查看 Deployment 是否完成。若是 rollout 成功完成,kubectl rollout status将返回一个0值的 Exit Code。

$ kubectl rollout status deploy/nginx
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx" successfully rolled out
$ echo $?
0

失败的 Deployment

您的 Deployment 在尝试部署新的 ReplicaSet 的时候可能卡住,永远也不会完成。这多是由于如下几个因素引发的:

  • 无效的引用
  • 不可读的 probe failure
  • 镜像拉取错误
  • 权限不够
  • 范围限制
  • 程序运行时配置错误

探测这种状况的一种方式是,在您的 Deployment spec 中指定spec.progressDeadlineSecondsspec.progressDeadlineSeconds 表示 Deployment controller 等待多少秒才能肯定(经过 Deployment status)Deployment进程是卡住的。

下面的kubectl命令设置progressDeadlineSeconds 使 controller 在 Deployment 在进度卡住10分钟后报告:

$ kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
"nginx-deployment" patched

当超过截止时间后,Deployment controller 会在 Deployment 的 status.conditions中增长一条DeploymentCondition,它包括以下属性:

  • Type=Progressing
  • Status=False
  • Reason=ProgressDeadlineExceeded

浏览 Kubernetes API conventions 查看关于status conditions的更多信息。

注意: kubernetes除了报告Reason=ProgressDeadlineExceeded状态信息外不会对卡住的 Deployment 作任何操做。更高层次的协调器能够利用它并采起相应行动,例如,回滚 Deployment 到以前的版本。

注意: 若是您暂停了一个 Deployment,在暂停的这段时间内kubernetnes不会检查您指定的 deadline。您能够在 Deployment 的 rollout 途中安全的暂停它,而后再恢复它,这不会触发超过deadline的状态。

您可能在使用 Deployment 的时候遇到一些短暂的错误,这些多是因为您设置了过短的 timeout,也有多是由于各类其余错误致使的短暂错误。例如,假设您使用了无效的引用。当您 Describe Deployment 的时候可能会注意到以下信息:

$ kubectl describe deployment nginx-deployment
<...>
Conditions:
  Type            Status  Reason
  ----            ------  ------
  Available       True    MinimumReplicasAvailable
  Progressing     True    ReplicaSetUpdated
  ReplicaFailure  True    FailedCreate
<...>

执行 kubectl get deployment nginx-deployment -o yaml,Deployement 的状态可能看起来像这个样子:

status:
  availableReplicas: 2
  conditions:
  - lastTransitionTime: 2016-10-04T12:25:39Z
    lastUpdateTime: 2016-10-04T12:25:39Z
    message: Replica set "nginx-deployment-4262182780" is progressing.
    reason: ReplicaSetUpdated
    status: "True"
    type: Progressing
  - lastTransitionTime: 2016-10-04T12:25:42Z
    lastUpdateTime: 2016-10-04T12:25:42Z
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: 2016-10-04T12:25:39Z
    lastUpdateTime: 2016-10-04T12:25:39Z
    message: 'Error creating: pods "nginx-deployment-4262182780-" is forbidden: exceeded quota:
      object-counts, requested: pods=1, used: pods=3, limited: pods=2'
    reason: FailedCreate
    status: "True"
    type: ReplicaFailure
  observedGeneration: 3
  replicas: 2
  unavailableReplicas: 2

最终,一旦超过 Deployment 进程的 deadline,kuberentes 会更新状态和致使 Progressing 状态的缘由:

Conditions:
  Type            Status  Reason
  ----            ------  ------
  Available       True    MinimumReplicasAvailable
  Progressing     False   ProgressDeadlineExceeded
  ReplicaFailure  True    FailedCreate

您能够经过缩容 Deployment的方式解决配额不足的问题,或者增长您的 namespace 的配额。若是您知足了配额条件后,Deployment controller 就会完成您的 Deployment rollout,您将看到 Deployment 的状态更新为成功状态(Status=True而且Reason=NewReplicaSetAvailable)。

Conditions:
  Type          Status  Reason
  ----          ------  ------
  Available     True    MinimumReplicasAvailable
  Progressing   True    NewReplicaSetAvailable

Type=Available、 Status=True 觉得这您的Deployment有最小可用性。 最小可用性是在Deployment策略中指定的参数。Type=Progressing 、 Status=True意味着您的Deployment 或者在部署过程当中,或者已经成功部署,达到了指望的最少的可用replica数量(查看特定状态的Reason——在咱们的例子中Reason=NewReplicaSetAvailable 意味着Deployment已经完成)。

您可使用kubectl rollout status命令查看Deployment进程是否失败。当Deployment过程超过了deadline,kubectl rollout status将返回非0的exit code。

$ kubectl rollout status deploy/nginx
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline
$ echo $?
1

操做失败的 Deployment

全部对完成的 Deployment 的操做都适用于失败的 Deployment。您能够对它扩/缩容,回退到历史版本,您甚至能够屡次暂停它来应用 Deployment pod template。

清理Policy

您能够设置 Deployment 中的 .spec.revisionHistoryLimit 项来指定保留多少旧的 ReplicaSet。 余下的将在后台被看成垃圾收集。默认的,全部的 revision 历史就都会被保留。在将来的版本中,将会更改成2。

注意: 将该值设置为0,将致使全部的 Deployment 历史记录都会被清除,该 Deployment 就没法再回退了。

用例

金丝雀 Deployment

若是您想要使用 Deployment 对部分用户或服务器发布 release,您能够建立多个 Deployment,每一个 Deployment 对应一个 release,参照 managing resources 中对金丝雀模式的描述。

编写 Deployment Spec

在全部的 Kubernetes 配置中,Deployment 也须要apiVersionkindmetadata这些配置项。配置文件的通用使用说明查看 部署应用,配置容器,和 使用 kubectl 管理资源 文档。

Deployment也须要 .spec section.

Pod Template

.spec.template 是 .spec中惟一要求的字段。

.spec.template 是 pod template. 它跟 Pod有如出一辙的schema,除了它是嵌套的而且不须要apiVersion 和 kind字段。

另外为了划分Pod的范围,Deployment中的pod template必须指定适当的label(不要跟其余controller重复了,参考selector)和适当的重启策略。

.spec.template.spec.restartPolicy 能够设置为 Always , 若是不指定的话这就是默认配置。

Replicas

.spec.replicas 是能够选字段,指按期望的pod数量,默认是1。

Selector

.spec.selector是可选字段,用来指定 label selector ,圈定Deployment管理的pod范围。

若是被指定, .spec.selector 必须匹配 .spec.template.metadata.labels,不然它将被API拒绝。若是 .spec.selector 没有被指定, .spec.selector.matchLabels 默认是 .spec.template.metadata.labels

在Pod的template跟.spec.template不一样或者数量超过了.spec.replicas规定的数量的状况下,Deployment会杀掉label跟selector不一样的Pod。

注意: 您不该该再建立其余label跟这个selector匹配的pod,或者经过其余Deployment,或者经过其余Controller,例如ReplicaSet和ReplicationController。不然该Deployment会被把它们当成都是本身建立的。Kubernetes不会阻止您这么作。

若是您有多个controller使用了重复的selector,controller们就会互相打架并致使不正确的行为。

策略

.spec.strategy 指定新的Pod替换旧的Pod的策略。 .spec.strategy.type 能够是"Recreate"或者是 "RollingUpdate"。"RollingUpdate"是默认值。

Recreate Deployment

.spec.strategy.type==Recreate时,在建立出新的Pod以前会先杀掉全部已存在的Pod。

Rolling Update Deployment

.spec.strategy.type==RollingUpdate时,Deployment使用rolling update 的方式更新Pod 。您能够指定maxUnavailable 和 maxSurge 来控制 rolling update 进程。

Max Unavailable

.spec.strategy.rollingUpdate.maxUnavailable 是可选配置项,用来指定在升级过程当中不可用Pod的最大数量。该值能够是一个绝对值(例如5),也能够是指望Pod数量的百分比(例如10%)。经过计算百分比的绝对值向下取整。若是.spec.strategy.rollingUpdate.maxSurge 为0时,这个值不能够为0。默认值是1。

例如,该值设置成30%,启动rolling update后旧的ReplicatSet将会当即缩容到指望的Pod数量的70%。新的Pod ready后,随着新的ReplicaSet的扩容,旧的ReplicaSet会进一步缩容,确保在升级的全部时刻能够用的Pod数量至少是指望Pod数量的70%。

Max Surge

.spec.strategy.rollingUpdate.maxSurge 是可选配置项,用来指定能够超过时望的Pod数量的最大个数。该值能够是一个绝对值(例如5)或者是指望的Pod数量的百分比(例如10%)。当MaxUnavailable为0时该值不能够为0。经过百分比计算的绝对值向上取整。默认值是1。

例如,该值设置成30%,启动rolling update后新的ReplicatSet将会当即扩容,新老Pod的总数不能超过时望的Pod数量的130%。旧的Pod被杀掉后,新的ReplicaSet将继续扩容,旧的ReplicaSet会进一步缩容,确保在升级的全部时刻全部的Pod数量和不会超过时望Pod数量的130%。

Progress Deadline Seconds

.spec.progressDeadlineSeconds 是可选配置项,用来指定在系统报告Deployment的failed progressing——表现为resource的状态中type=ProgressingStatus=False、 Reason=ProgressDeadlineExceeded前能够等待的Deployment进行的秒数。Deployment controller会继续重试该Deployment。将来,在实现了自动回滚后, deployment controller在观察到这种状态时就会自动回滚。

若是设置该参数,该值必须大于 .spec.minReadySeconds

Min Ready Seconds

.spec.minReadySeconds是一个可选配置项,用来指定没有任何容器crash的Pod并被认为是可用状态的最小秒数。默认是0(Pod在ready后就会被认为是可用状态)。进一步了解什么什么后Pod会被认为是ready状态,参阅 Container Probes

Rollback To

.spec.rollbackTo 是一个能够选配置项,用来配置Deployment回退的配置。设置该参数将触发回退操做,每次回退完成后,该值就会被清除。

Revision

.spec.rollbackTo.revision是一个可选配置项,用来指定回退到的revision。默认是0,意味着回退到上一个revision。

Revision History Limit

Deployment revision history存储在它控制的ReplicaSets中。

.spec.revisionHistoryLimit 是一个可选配置项,用来指定能够保留的旧的ReplicaSet数量。该理想值取决于心Deployment的频率和稳定性。若是该值没有设置的话,默认全部旧的Replicaset或会被保留,将资源存储在etcd中,是用kubectl get rs查看输出。每一个Deployment的该配置都保存在ReplicaSet中,然而,一旦您删除的旧的RepelicaSet,您的Deployment就没法再回退到那个revison了。

若是您将该值设置为0,全部具备0个replica的ReplicaSet都会被删除。在这种状况下,新的Deployment rollout没法撤销,由于revision history都被清理掉了。

Paused

.spec.paused是能够可选配置项,boolean值。用来指定暂停和恢复Deployment。Paused和没有paused的Deployment之间的惟一区别就是,全部对paused deployment中的PodTemplateSpec的修改都不会触发新的rollout。Deployment被建立以后默认是非paused。

Deployment 的替代选择

kubectl rolling update

Kubectl rolling update 虽然使用相似的方式更新Pod和ReplicationController。可是咱们推荐使用Deployment,由于它是声明式的,客户端侧,具备附加特性,例如即便滚动升级结束后也能够回滚到任何历史版本。

相关文章
相关标签/搜索