Edit This Page

Deployments

一个 Deployment 控制器为 PodsReplicaSets提供描述性的更新方式。

描述 Deployment 中的 desired state,并且 Deployment 控制器以受控速率更改实际状态,以达到期望状态。可以定义 Deployments 以创建新的 ReplicaSets ,或删除现有 Deployments ,并通过新的 Deployments 使用其所有资源。

说明: 不要管理 Deployment 拥有的 ReplicaSets 。如果存在下面未介绍的用例,请考虑在主 Kubernetes 仓库中提出 issue。

You describe a desired state in a Deployment, and the Deployment controller changes the actual state to the desired state at a controlled rate. You can define Deployments to create new ReplicaSets, or to remove existing Deployments and adopt all their resources with new Deployments.

--> 描述 Deployment 中的 desired state,并且 Deployment 控制器以受控速率更改实际状态,以达到期望状态。可以定义 Deployments 以创建新的 ReplicaSets ,或删除现有 Deployments ,并通过新的 Deployments 使用其所有资源。

用例

以下是典型的 Deployments 用例:

  • 声明 Pod 的新状态 通过更新 Deployment 的 PodTemplateSpec。将创建新的 ReplicaSet ,并且 Deployment 管理器以受控速率将 Pod 从旧 ReplicaSet 移动到新 ReplicaSet 。每个新的 ReplicaSet 都会更新 Deployment 的修改历史。
  • 暂停 Deployment 对其 PodTemplateSpec 进行修改,然后恢复它以启动新的展开。

创建 Deployment

下面是 Deployment 示例。创建一个 ReplicaSet 展开三个 nginx Pods:

controllers/nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

在该例中:

  • 将创建名为 nginx-deployment 的 Deployment ,由 .metadata.name 字段指示。
  • Deployment 创建三个复制的 Pods,由 replicas 字段指示。
  • selector 字段定义 Deployment 如何查找要管理的 Pods。 在这种情况下,只需选择在 Pod 模板(app: nginx)中定义的标签。但是,更复杂的选择规则是可能的,只要 Pod 模板本身满足规则。
说明: `matchLabels` 字段是 {key,value} 的映射。单个 {key,value}在 `matchLabels` 映射中的值等效于 `matchExpressions` 的元素,其键字段是“key”,运算符为“In”,值数组仅包含“value”。所有要求,从 `matchLabels` 和 `matchExpressions`,必须满足才能匹配。
  • template 字段包含以下子字段:
  • Pod 标记为app: nginx,使用labels字段。
  • Pod 模板规范或 .template.spec 字段指示 Pods 运行一个容器, nginx,运行 nginx Docker Hub版本1.7.9的镜像 。
  • 创建一个容器并使用name字段将其命名为 nginx

按照以下步骤创建上述 Deployment :

开始之前,请确保的 Kubernetes 集群已启动并运行。

  1. 通过运行以下命令创建 Deployment :
说明: 可以指定 `--record` 标志来写入在资源注释`kubernetes.io/change-cause`中执行的命令。它对以后的检查是有用的。 例如,查看在每个 Deployment 修改中执行的命令。
```shell
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
```
  1. 运行 kubectl get deployments 以检查 Deployment 是否已创建。如果仍在创建 Deployment ,则输出以下内容:
```shell
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         0         0            0           1s
```
检查集群中的 Deployments 时,将显示以下字段:
  * `NAME` 列出了集群中 Deployments 的名称。
  * `DESIRED` 显示应用程序的所需 _副本_ 数,在创建 Deployment 时定义这些副本。这是 _期望状态_。
  * `CURRENT`显示当前正在运行的副本数。
  * `UP-TO-DATE`显示已更新以实现期望状态的副本数。
  * `AVAILABLE`显示应用程序可供用户使用的副本数。
  * `AGE` 显示应用程序运行的时间量。
请注意,根据`.spec.replicas`副本字段,所需副本的数量为 3。
  1. 要查看 Deployment 展开状态,运行 kubectl rollout status deployment.v1.apps/nginx-deployment。输出:
```shell
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment.apps/nginx-deployment successfully rolled out
```
  1. 几秒钟后再次运行 kubectl get deployments。输出:
```shell
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           18s
```
请注意, Deployment 已创建所有三个副本,并且所有副本都是最新的(它们包含最新的 Pod 模板)并且可用。
  1. 要查看 Deployment 创建的 ReplicaSet (rs),运行 kubectl get rs。输出:
```shell
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-75675f5897   3         3         3       18s
```
请注意, ReplicaSet 的名称始终被格式化为`[DEPLOYMENT-NAME]-[RANDOM-STRING]`。随机字符串是随机生成并使用 pod-template-hash 作为种子。
  1. 要查看每个 Pod 自动生成的标签,运行 kubectl get pods --show-labels。返回以下输出:
```shell
NAME                                READY     STATUS    RESTARTS   AGE       LABELS
nginx-deployment-75675f5897-7ci7o   1/1       Running   0          18s       app=nginx,pod-template-hash=3123191453
nginx-deployment-75675f5897-kzszj   1/1       Running   0          18s       app=nginx,pod-template-hash=3123191453
nginx-deployment-75675f5897-qqcnn   1/1       Running   0          18s       app=nginx,pod-template-hash=3123191453
```
创建的复制集可确保有三个 `nginx` Pods。
说明: 必须在 Deployment 中指定适当的选择器和 Pod 模板标签(在本例中为`app: nginx`)。不要与其他控制器(包括其他 Deployments 和状态设置)重叠标签或选择器。Kubernetes 不会阻止重叠,如果多个控制器具有重叠的选择器,这些控制器可能会冲突并运行意外。

Pod-template-hash 标签

说明: 不要更改此标签。

Deployment 控制器将 pod-template-hash 标签添加到 Deployment 创建或使用的每个 ReplicaSet 。

此标签可确保 Deployment 的子 ReplicaSets 不重叠。它通过对 ReplicaSet 的 PodTemplate 进行哈希处理,并使用生成的哈希值添加到 ReplicaSet 选择器、Pod 模板标签,并在 ReplicaSet 可能具有的任何现有 Pod 中。

更新 Deployment

说明: 仅当 Deployment Pod 模板(即 `.spec.template`)时,才会触发 Deployment 展开,例如,如果模板的标签或容器镜像已更新,其他更新(如扩展 Deployment )不会触发展开。

按照以下步骤更新 Deployment :

  1. 让我们更新 nginx Pods,以使用 nginx:1.9.1 镜像 ,而不是 nginx:1.7.9 镜像 。
```shell
kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
```
输出:

```shell
deployment.apps/nginx-deployment image updated
```
或者,可以 `edit`  Deployment 并将 `.spec.template.spec.containers[0].image` 从 `nginx:1.7.9` 更改至 `nginx:1.9.1`。

```shell
kubectl edit deployment.v1.apps/nginx-deployment
```
输出:

```shell
deployment.apps/nginx-deployment edited
```
  1. 要查看展开状态,运行:
```shell
kubectl rollout status deployment.v1.apps/nginx-deployment
```
输出:

```shell
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
```
或者

```shell
deployment.apps/nginx-deployment successfully rolled out
```

在更新后的 Deployment 上获取更多信息

  • 在展开成功后,可以通过运行 kubectl get deployments来查看 Deployment 。 输出:

    NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3         3         3            3           36s
    
  • 运行 kubectl get rs 以查看 Deployment 通过创建新的 ReplicaSet 并缩放它更新了 Pods 最多 3 个副本,以及将旧 ReplicaSet 缩放到 0 个副本。

    kubectl get rs
    
输出:

```shell
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-1564180365   3         3         3       6s
nginx-deployment-2035384211   0         0         0       36s
```
  • 运行 get pods 现在应仅显示新的 Pods:

    kubectl get pods
    

输出:

```shell
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
```
下次要更新这些 Pods 时,只需再次更新 Deployment  Pod 模板。
 Deployment 可确保在更新时仅关闭一定数量的 Pods。默认情况下,它确保至少 75%所需 Pods 运行(25%最大不可用)。
 Deployment 还确保仅创建一定数量的 Pods 高于期望的 Pods 数。默认情况下,它可确保最多增加 25% 期望 Pods 数(25%最大增量)。
例如,如果仔细查看上述 Deployment ,将看到它首先创建了一个新的 Pod,然后删除了一些旧的 Pods,并创建了新的 Pods。它不会杀死老 Pods,直到有足够的数量新的 Pods 已经出现,并没有创造新的 Pods,直到足够数量的旧 Pods 被杀死。它确保至少 2 个 Pods 可用,并且总共最多 4 个 Pods 可用。
  • 获取 Deployment 的更多信息
    kubectl describe deployments
    

输出:

Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Thu, 30 Nov 2017 10:56:25 +0000
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision=2
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
   Containers:
    nginx:
      Image:        nginx:1.9.1
      Port:         80/TCP
      Environment:  <none>
      Mounts:       <none>
    Volumes:        <none>
  Conditions:
    Type           Status  Reason
    ----           ------  ------
    Available      True    MinimumReplicasAvailable
    Progressing    True    NewReplicaSetAvailable
  OldReplicaSets:  <none>
  NewReplicaSet:   nginx-deployment-1564180365 (3/3 replicas created)
  Events:
    Type    Reason             Age   From                   Message
    ----    ------             ----  ----                   -------
    Normal  ScalingReplicaSet  2m    deployment-controller  Scaled up replica set nginx-deployment-2035384211 to 3
    Normal  ScalingReplicaSet  24s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 1
    Normal  ScalingReplicaSet  22s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 2
    Normal  ScalingReplicaSet  22s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 2
    Normal  ScalingReplicaSet  19s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 1
    Normal  ScalingReplicaSet  19s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 3
    Normal  ScalingReplicaSet  14s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 0
可以看到,当第一次创建 Deployment 时,它创建了一个 ReplicaSet  (nginx-deployment-2035384211)并将其直接扩展至 3 个副本。更新 Deployment 时,它创建了一个新的 ReplicaSet (nginx-deployment-1564180365),并将其扩展为 1,然后将旧 ReplicaSet 缩小到 2,以便至少有 2 个 Pod 可用,并且最多创建 4 个 Pod。然后,它继续向上和向下扩展新的和旧的 ReplicaSet ,具有相同的滚动更新策略。最后,将有 3 个可用的副本在新的 ReplicaSet 中,旧 ReplicaSet 将缩小到 0。

翻转(多 Deployment 动态更新)

每次 Deployment 控制器观察新 Deployment 时,都会创建一个 ReplicaSet 以启动所需的 Pods。如果更新了 Deployment ,则控制其标签的 Pods 的现有 ReplicaSet 匹配 .spec.selector,但其模板不匹配 .spec.template 被缩小。最终,新的 ReplicaSet 缩放为 .spec.replicas,所有旧 ReplicaSets 缩放为 0。

当 Deployment 正在展开时进行更新, Deployment 会为每个更新创建一个新的 ReplicaSet 并开始向上扩展,之前的 ReplicaSet 会被添加到旧 ReplicaSets 队列并开始向下扩展。

例如,假设创建一个 Deployment 以创建 nginx:1.7.9 的 5 个副本,然后更新 Deployment 以创建 5 个 nginx:1.9.1 的副本,而此时只有 3 个nginx:1.7.9 的副本已创建。在这种情况下, Deployment 会立即开始杀死3个 nginx:1.7.9 Pods,并开始创建 nginx:1.9.1 Pods。它不等待 nginx:1.7.9 的 5 个副本在改变任务之前完成创建。

使用标签选择器进行更新

通常不鼓励更新标签选择器,建议提前规划选择器。在任何情况下,如果需要执行标签选择器更新,请格外小心,并确保已掌握所有的含义。

说明: 在 API 版本 `apps/v1` 中, Deployment 标签选择器在创建后是不可变的。
  • 选择器添加还需要使用新标签更新 Deployment 规范中的 Pod 模板标签,否则将返回验证错误。此更改是非重叠的,这意味着新的选择器不选择使用旧选择器创建的 ReplicaSets 和 Pod,从而导致弃用所有旧 ReplicaSets 和创建新的 ReplicaSet 。
  • 选择器更新更改选择器键中的现有值 -- 导致发生与添加相同的行为。
  • 选择器删除从 Deployment 选择器中删除现有密钥 -- 不需要在Pod 模板标签做任意更改。现有 ReplicaSets 不会孤立,并且不会创建新的 ReplicaSet ,但请注意,已删除的标签仍然存在于任何现有的 Pods 和 ReplicaSets 中。

回滚 Deployment

有时,可能需要回滚 Deployment ;例如,当 Deployment 不稳定时,例如循环崩溃。默认情况下,所有 Deployment 历史记录都保留在系统中,以便可以随时回滚(可以通过修改修改历史记录限制来更改该限制)。

说明: 触发 Deployment 展开时,将创建 Deployment 修改版。这意味着仅当 Deployment Pod 模板 (`.spec.template`) 发生更改时,才会创建新修改版本,例如,如果更新模板的标签或容器镜像 。其他更新,如扩展 Deployment 、不要创建 Deployment 修改版,以便方便同时手动或自动缩放。这意味着,当回滚到较早的修改版时,只有 Deployment Pod 模板部分回滚。
  • 假设在更新 Deployment 时犯了一个拼写错误,将镜像名称命名为 nginx:1.91 而不是 nginx:1.9.1
    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
    
输出:

```shell
deployment.apps/nginx-deployment image updated
```
  • 展开遇到问题。可以通过检查展开状态来验证它:

    kubectl rollout status deployment.v1.apps/nginx-deployment
    
输出:

```shell
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
```
  • 按 Ctrl-C 停止上述展开状态表。有关卡住展开的详细信息,参考这里
  • 查看旧 ReplicaSets :
    kubectl get rs
    
输出:

```shell
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-1564180365   3         3         3       25s
nginx-deployment-2035384211   0         0         0       36s
nginx-deployment-3066724191   1         1         0       6s
```
  • 查看创建的 Pod,看到由新 ReplicaSet 创建的 1 个 Pod 卡在镜像拉取循环中。

    kubectl get pods
    
输出:

```shell
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-1564180365-hysrc   1/1       Running            0          25s
nginx-deployment-3066724191-08mng   0/1       ImagePullBackOff   0          6s
```
说明: Deployment 控制器自动停止不良展开,并停止向上扩展新的 ReplicaSet 。这取决于指定的滚动更新参数(具体为 `maxUnavailable`)。默认情况下,Kubernetes 将值设置为 25%。
  • 获取 Deployment 描述信息:
    kubectl describe deployment
    
输出:

```shell
Name:           nginx-deployment
Namespace:      default
CreationTimestamp:  Tue, 15 Mar 2016 14:48:04 -0700
Labels:         app=nginx
Selector:       app=nginx
Replicas:       3 desired | 1 updated | 4 total | 3 available | 1 unavailable
StrategyType:       RollingUpdate
MinReadySeconds:    0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx:1.91
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    ReplicaSetUpdated
OldReplicaSets:     nginx-deployment-1564180365 (3/3 replicas created)
NewReplicaSet:      nginx-deployment-3066724191 (1/1 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 1
  21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3
  13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 0
  13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 1
```

要解决此问题,需要回滚到以前稳定的 Deployment 版本。

检查 Deployment 展开历史

按照如下步骤检查回滚历史:

  1. 首先,检查 Deployment 修改历史:
```shell
kubectl rollout history deployment.v1.apps/nginx-deployment
```
输出:

```shell
deployments "nginx-deployment"
REVISION    CHANGE-CAUSE
1           kubectl apply --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml --record=true
2           kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record=true
3           kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
```
`CHANGE-CAUSE` 从 Deployment 注释 `kubernetes.io/change-cause` 创建时复制到其修改版。可以通过以下条件指定 `CHANGE-CAUSE` 消息:
* 使用 `kubectl annotate deployment.v1.apps/nginx-deployment kubernetes.io/change-cause="image updated to 1.9.1"`  Deployment 对 Deployment 进行分号。
* 追加 `--record` 以保存正在更改资源的 `kubectl` 命令。
* 手动编辑资源的清单。
  1. 查看修改历史的详细信息,运行:
```shell
kubectl rollout history deployment.v1.apps/nginx-deployment --revision=2
```
输出:

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

回滚到上一次修改

按照下面给出的步骤将 Deployment 从当前版本回滚到以前的版本(即版本 2)。

  1. 现在已决定撤消当前展开并回滚到以前的版本:
```shell
kubectl rollout undo deployment.v1.apps/nginx-deployment
```
输出:

```shell
deployment.apps/nginx-deployment
```
或者,可以通过使用 `--to-revision` 来回滚到特定修改版本:

```shell
kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
```
输出:

```shell
deployment.apps/nginx-deployment
```
更多有关回滚相关指令,请参考 [`kubectl rollout`](/docs/reference/generated/kubectl/kubectl-commands#rollout).
现在, Deployment 将回滚到以前的稳定版本。如所见, Deployment 回滚事件回滚到修改版 2 是从 Deployment 控制器生成的。
  1. 检查回滚是否成功、 Deployment 是否正在运行,运行:
```shell
kubectl get deployment nginx-deployment
```
输出:

```shell
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           30m
```
  1. 获取 Deployment 描述信息:
```shell
kubectl describe deployment nginx-deployment
```
输出:

```shell
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Sun, 02 Sep 2018 18:17:55 -0500
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision=4
                        kubernetes.io/change-cause=kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record=true
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx:1.9.1
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-deployment-c4747d96c (3/3 replicas created)
Events:
  Type    Reason              Age   From                   Message
  ----    ------              ----  ----                   -------
  Normal  ScalingReplicaSet   12m   deployment-controller  Scaled up replica set nginx-deployment-75675f5897 to 3
  Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 1
  Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 2
  Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 2
  Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 1
  Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 3
  Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 0
  Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-595696685f to 1
  Normal  DeploymentRollback  15s   deployment-controller  Rolled back deployment "nginx-deployment" to revision 2
  Normal  ScalingReplicaSet   15s   deployment-controller  Scaled down replica set nginx-deployment-595696685f to 0
```

缩放 Deployment

可以使用如下指令缩放 Deployment :

kubectl scale deployment.v1.apps/nginx-deployment --replicas=10

输出:

deployment.apps/nginx-deployment scaled

假设启用水平自动缩放 Pod在集群中,可以为 Deployment 设置自动缩放器,并选择最小和最大 要基于现有 Pods 的 CPU 利用率运行的 Pods。

kubectl autoscale deployment.v1.apps/nginx-deployment --min=10 --max=15 --cpu-percent=80

输出:

deployment.apps/nginx-deployment scaled

比例缩放

滚动更新 Deployments 支持同时运行应用程序的多个版本。当自动缩放器缩放处于展开中间的滚动更新 Deployment (仍在进行中或暂停)时, Deployment 控制器平衡现有活动中的其他 ReplicaSets (带 Pods 的 ReplicaSets ),以降低风险。这称为比例缩放。

例如,运行一个10个副本的 Deployment ,最大增加=3, 最大不可用=2.

  • 确保这10个副本都在运行。
    kubectl get deploy
    

输出:

NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment     10        10        10           10          50s
  • 更新到新镜像,该镜像恰好无法从集群内部解析。
    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:sometag
    
输出:

```shell
deployment.apps/nginx-deployment image updated
```
  • 镜像更新使用 ReplicaSet nginx-deployment-1989198191 启动新的展开,但由于上面提到的最大不可用要求。检查展开状态:
    kubectl get rs
    
  输出:

```shell
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-1989198191   5         5         0         9s
nginx-deployment-618515232    8         8         8         1m
```
  • 然后,出现了新的 Deployment 扩展请求。自动缩放器增加 Deployment 副本到15。 Deployment 控制器需要决定在何处添加这些新 5 个副本。如果未使用比例缩放,所有 5 个都将添加到新的 ReplicaSet 中。使用比例缩放,可以将其他副本分布到所有 ReplicaSets 。更大的比例转到 ReplicaSets 与大多数副本和较低的比例都转到副本较少的 ReplicaSets 。任何剩余部分都添加到具有最多副本的 ReplicaSet 。具有零副本的 ReplicaSets 不会放大。

在上面的示例中,3 个副本添加到旧 ReplicaSet 中,2 个副本添加到新 ReplicaSet 。展开过程最终应将所有副本移动到新的 ReplicaSet ,假定新的副本变得正常。要确认这一点,请运行:

kubectl get deploy

输出:

NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment     15        18        7            8           7m

展开状态确认副本如何添加到每个 ReplicaSet 。

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 。

  • 例如,对于一个刚刚创建的 Deployment : 获取 Deployment 信息:

    kubectl get deploy
    

输出:

NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     3         3         3            3           1m

获取 Deployment 状态:

kubectl get rs

输出:

NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   3         3         3         1m

使用如下指令中断运行:

```shell
kubectl rollout pause deployment.v1.apps/nginx-deployment
```
输出:

```shell
deployment.apps/nginx-deployment paused
```
  • 然后更新 Deployment 镜像:

    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
    
输出:

```shell
deployment.apps/nginx-deployment image updated
```
  • 注意没有新的展开:

    kubectl rollout history deployment.v1.apps/nginx-deployment
    
输出:

```shell
deployments "nginx"
REVISION  CHANGE-CAUSE
1   <none>
```
  • 获取展开状态确保 Deployment 更新已经成功:

    kubectl get rs
    
输出:

```shell
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   3         3         3         2m
```
  • 更新是很容易的,例如,可以这样更新使用到的资源:

    kubectl set resources deployment.v1.apps/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
    
输出:

```shell
deployment.apps/nginx-deployment resource requirements updated
```
暂停 Deployment 之前的初始状态将继续其功能,但新的更新只要暂停 Deployment , Deployment 就不会产生任何效果。
  • 最后,恢复 Deployment 并观察新的 ReplicaSet ,并更新所有新的更新:

    kubectl rollout resume deployment.v1.apps/nginx-deployment
    
输出:

```shell
deployment.apps/nginx-deployment resumed
```
  • 观察展开的状态,直到完成。

    kubectl get rs -w
    
输出:

```shell
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
```
  • 获取最近展开的状态:

    kubectl get rs
    
输出:

```shell
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   0         0         0         2m
nginx-3926361531   3         3         3         28s
```

可以在触发一个或多个更新之前暂停 Deployment ,然后继续它。这允许在暂停和恢复之间应用多个修补程序,而不会触发不必要的 Deployment 。

  • 例如,对于一个刚刚创建的 Deployment : 获取 Deployment 信息:
    kubectl get deploy
    

输出:

NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     3         3         3            3           1m

获取 Deployment 状态:

kubectl get rs

输出:

NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   3         3         3         1m

使用如下指令中断运行: shell kubectl rollout pause deployment.v1.apps/nginx-deployment

输出:
```
deployment.apps/nginx-deployment paused
```
  • 然后更新 Deployment 镜像:
    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
    
输出:
```
deployment.apps/nginx-deployment image updated
```
  • 注意没有新的展开:
    kubectl rollout history deployment.v1.apps/nginx-deployment
    
输出:
```
deployments "nginx"
REVISION  CHANGE-CAUSE
1   <none>
```
  • 获取展开状态确保 Deployment 更新已经成功:
    kubectl get rs
    
输出:
```
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   3         3         3         2m
```
  • 更新是很容易的,例如,可以这样更新使用到的资源:
    kubectl set resources deployment.v1.apps/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
    
输出:
```
deployment.apps/nginx-deployment resource requirements updated
```
暂停 Deployment 之前的初始状态将继续其功能,但新的更新只要暂停 Deployment , Deployment 就不会产生任何效果。
  • 最后,恢复 Deployment 并观察新的 ReplicaSet ,并更新所有新的更新:
    kubectl rollout resume deployment.v1.apps/nginx-deployment
    
输出:
```
deployment.apps/nginx-deployment 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
```
  • 获取最近展开的状态:
    kubectl get rs
    
输出:
```
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   0         0         0         2m
nginx-3926361531   3         3         3         28s
```
说明: 暂停的 Deployment 不可以回滚,除非恢复它以后。

Deployment 状态

一个 Deployment 的生命周期中会有许多状态。当正在生产新的 ReplicaSet 时可能是正在运行,可能是已完成,也可能是 Deployment 失败

正在 Deployment

Kubernetes 使用 运行中 来标记一个 Deployment ,当下面的任务被执行时:

  • 创建新的 ReplicaSet 。
  • 正在向上扩展最新的 ReplicaSet 。
  • Deployment 向下扩展旧的 ReplicaSet(s) 。
  • 新的 Pods 已经就绪或者可用(在最小就绪时间内就绪)。

可以使用 kubectl rollout status 监视 Deployment 的进度。

完成 Deployment

Kubernetes 将 Deployment 标记为 完成,当它具有以下特征时:

  • 与 Deployment 关联的所有副本都已更新到指定的最新版本,这意味着请求的任何更新都已完成。
  • 与 Deployment 关联的所有副本都可用。
  • 未运行 Deployment 的旧副本。

可以使用 kubectl rollout status 检查 Deployment 是否已完成。如果展开成功完成,kubectl rollout status 返回退出代码 0。

kubectl rollout status deployment.v1.apps/nginx-deployment

输出:

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

Deployment 失败

你的 Deployment 可能会在未完成的情况下尝试 Deployment 其最新的 ReplicaSet 时遇到问题。可能发生此情况由于以下一些因素:

  • 配额不足
  • 就绪探测失败
  • 镜像拉取错误
  • 权限不足
  • 限制范围
  • 应用程序运行时配置错误

检测此条件的一种方法是在 Deployment 规范中指定截止时间参数:([.spec.progressDeadlineSeconds](#progress-deadline-seconds))。.spec.progressDeadlineSeconds 进度截止时间秒表示 Deployment 控制器在指示(处于 Deployment 状态)之前等待的秒数 Deployment 进度已停止。

以下 kubectl 命令设置具有进度的规范,使控制器报告 10 分钟后 Deployment 进度不足:

kubectl patch deployment.v1.apps/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'

输出:

deployment.apps/nginx-deployment patched

超过截止时间后, Deployment 控制器将添加具有以下属性到 Deployment 的 .status.conditions

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

参考 Kubernetes API 约定 获取更多状态条件相关信息。

说明: Kubernetes 对已停止的 Deployment 不执行任何操作,只需使用`Reason=ProgressDeadlineExceeded`。更高级别的编排器可以利用它并相应地采取行动,例如,将 Deployment 回滚到其以前的版本。
说明: 如果暂停 Deployment ,Kubernetes 不会根据指定的截止时间检查进度。可以在展开栏中间安全地暂停 Deployment ,并在不触发超过最后期限时恢复。

Deployments 可能会出现短暂的错误,既不是因为设置的超时时间过短,也不是因为任何真正的暂时性错误。例如配额不足。如果描述 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, Deployment 状态输出:

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 进度截止时间,Kubernetes 将更新状态和进度状态:

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

可以通过缩减 Deployment 来解决配额不足的问题,或者直接在命名空间中增加配额。如果配额条件满足, Deployment 控制器完成了 Deployment 展开, Deployment 状态会更新为成功(Status=True and Reason=NewReplicaSetAvailable)。

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

Type=AvailableStatus=True 表示 Deployment 具有最低可用性。最低可用性由 Deployment 策略中的参数指定。Type=ProgressingStatus=True 表示 Deployment 处于展开中间,并且正在运行,或者已成功完成进度,最小所需新的副本处于可用(请参阅此种状态原因的相关细节,在我们的案例中Reason=NewReplicaSetAvailable 表示 Deployment 已完成)。

可以使用 kubectl rollout status 检查 Deployment 是否未能取得进展。kubectl rollout status如果 Deployment 已超过进度截止时间,则返回非零退出代码。

kubectl rollout status deployment.v1.apps/nginx-deployment

输出:

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 模板中应用多个调整,甚至将其暂停。

清理策略

可以在 Deployment 中设置 .spec.revisionHistoryLimit ,以指定保留多少此 Deployment 的 ReplicaSets。其余的将在后台进行垃圾回收。默认情况下,是10。

说明: 显式将此字段设置为 0 将导致清理 Deployment 的所有历史记录,因此 Deployment 将无法回滚。

金丝雀 Deployment

如果要使用 Deployment 向用户或服务器子集展开版本,则可以创建多个 Deployments ,每个版本一个,遵循资源管理

编写 Deployment 脚本

同其他 Kubernetes 配置, Deployment 需要 apiVersionkind, 和 metadata 字段。有关配置文件的其他信息,参考 应用 Deployment ,配置容器,和 使用 kubectl 管理资源 相关文档。

Deployment 还需要 .spec 部分

Pod 示例

.spec仅需要 .spec.template.spec.selector

.spec.template 是一个 Pod 示例。它和 Pod的约束完全相同,除了它是嵌套的,而且没有 apiVersionkind

除了 Pod 的必填字段外, Deployment 中的 Pod 模板必须指定适当的标签和适当的重新启动策略。对于标签,请确保不要与其他控制器重叠。请参考选择器)。

只有 .spec.template.spec.restartPolicy 等于 Always 被允许,这是在没有指定时的默认设置。

副本

.spec.replicas 是指定所需 Pod 的可选字段。它的默认值是1。

选择器

.spec.selector 是指定本次 Deployment Pods 标签选择器的必要字段。

.spec.selector 必须匹配 .spec.template.metadata.labels,否则请求会被 API 拒绝。

在 API apps/v1版本中,.spec.selector.metadata.labels 不会被默认设置为 .spec.template.metadata.labels,如果没有设置的话。所以需要明确进行设置。同时在 apps/v1版本中, Deployment 创建后 .spec.selector 是可变的。

当 Pods 的标签和选择器匹配时,此类 Pods 的模板和 .spec.template 不同,或者此类 Pods 的总数超过 .spec.replicas, Deployment 会终结这些 Pods。如果 Pods 总数达不到期望值,会用 .spec.template 创建新的 Pods。

说明: 不应创建其标签与此选择器匹配的 Pods,或者直接创建另一个 Deployment ,或通过创建其他控制器(如 ReplicaSet 或复制控制器)。如果这样做,第一个 Deployment 认为它创建了这些其他 Pods。Kubernetes 不会阻止你这么做。

如果有多个具有重叠选择器的控制器,则控制器之间会因冲突而故障。

策略

.spec.strategy 策略指定用于用新 Pods 替换旧 Pods 的策略。.spec.strategy.type 可以是“Recreate”或“RollingUpdate”。“RollingUpdate”是默认值。

重新创建 Deployment

.spec.strategy.type==Recreate,所有现有的 Pods 在创建新 Pods 之前被杀死。

滚动更新 Deployment

Deployment 会在 .spec.strategy.type==RollingUpdate时,采取 滚动更新的方式更新Pods。可以指定 maxUnavailablemaxSurge 来控制滚动更新操作。

最大不可用

.spec.strategy.rollingUpdate.maxUnavailable 是指定最大数量的可选字段,表示在更新过程中不可用的 Pods。该值可以是绝对数字(例如,5)或所需 Pods 的百分比(例如,10%)。绝对数按百分比计算,四舍五入下来。如果 .spec.strategy.rollingUpdate.maxSurge 为 0,则该值不能为 0。默认值为 25%。

例如,当此值设置为 30% 时,滚动更新开始时会立即将旧 ReplicaSet 向下扩展到期望 Pods 的70%。新 Pods 准备就绪后,可以缩放旧 ReplicaSet 进一步向下,然后向上扩展新的 ReplicaSet ,确保可用的 Pods 总数在更新期间,任何时候都至少为 70% 所需的 Pods。

最大增量

.spec.strategy.rollingUpdate.maxSurge 是指定最大 Pods 数的可选字段可在所需的 Pods 数上创建。该值可以是绝对数(例如,5)或所需 Pods 的百分比(例如,10%)。如果 MaxUnavailable 0,则值不能为 0。绝对数通过舍入从百分比计算。默认值为 25%。

例如,当此值设置为 30% 时,启动滚动更新后,会立即展开新的 ReplicaSet ,以便新旧 Pod 的总数不超过所需的 130%。一旦旧 Pods 被杀死,新的 ReplicaSet 可以进一步扩展,确保更新期间任何时间运行的 Pods 总数最多为所需 Pods 总数的130%。

Deployment 失败等待时间

.spec.progressDeadlineSeconds 是一个可选字段,用于指定等待的秒数而后在系统报告中返回 Deployment 失败,同时在资源状态中 Type=ProgressingStatus=FalseReason=ProgressDeadlineExceeded 。 Deployment 控制器将保留正在重试 Deployment 。将来,一旦实现自动回滚, Deployment 控制器将回滚 Deployment ,只要它探测到这样的条件。

如果指定,则此字段需要大于 .spec.minReadySeconds

最小就绪时间

.spec.minReadySeconds 是一个可选字段,用于指定新创建的 Pod 在没有任意容器崩溃情况下的最小就绪时间,以便将其视为可用。默认值为 0(Pod 在准备就绪后立即将被视为可用)。了解有关何时Pod 被视为已准备就绪,参考容器探针

回滚

.spec.rollbackTo 字段已经在 API 版本 extensions/v1beta1apps/v1beta1中废弃了,并且从 apps/v1beta2版本开始不在支持。相应的,会开始使用已经引入回滚到上一个版本中的 kubectl rollout undo

修改历史限制

Deployment 修改历史记录存储在它所控制的 ReplicaSets 中。

.spec.revisionHistoryLimit 修改历史记录限制是一个可选字段,用于指定要保留的旧 ReplicaSets 的数量以允许回滚。这些旧 ReplicaSets 消耗 etcd 中的资源,并占用 kubectl get rs 的输出。每个 Deployment 修改版的配置都存储在其 ReplicaSets 中;因此,一旦删除了旧的 ReplicaSet ,将失去回滚到 Deployment 版本的能力。默认情况下,将保留 10 个旧 ReplicaSets ,但其理想值取决于新 Deployment 的频率和稳定性。

更具体地说,将此字段设置为 0 意味着将清理所有具有 0 个副本的旧 ReplicaSets 。在这种情况下,无法撤消新的 Deployment 展开,因为它的修改历史被清除了。

暂停

.spec.paused 是用于暂停和恢复 Deployment 的可选布尔字段。暂停的 Deployment 和未暂停的 Deployment 唯一的区别,只要暂停 Deployment 处于暂停状态, PodTemplateSpec 的任意修改都不会触发新的展开。默认 Deployment 在创建时是不会被暂停的。

Deployments 的替代方案

kubectl滚动更新

kubectl rolling update更新 Pods 和副本控制器的方式类似。但是,建议采取 Deployments 的方式来更新,因为它们是声明性的,在服务器端,并且具有其他功能,例如,即使在滚动更新完成后,也会回滚到以前的任何修改版本。