部署

Deployment 管理着一组 Pod 来运行应用程序工作负载,通常是不维护状态的工作负载。

DeploymentPodReplicaSet 提供声明式更新。

您可以在 Deployment 中描述期望状态,Deployment 控制器 会以受控的速率将实际状态更改为期望状态。您可以定义 Deployment 来创建新的 ReplicaSet,或者删除现有的 Deployment 并使用新的 Deployment 采用其所有资源。

用例

以下是 Deployment 的典型用例

创建 Deployment

以下是一个 Deployment 的示例。它创建了一个 ReplicaSet 来启动三个 nginx Pod

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 字段指示。此名称将成为稍后创建的 ReplicaSet 和 Pod 的基础。有关更多详细信息,请参阅 编写 Deployment 规范

  • Deployment 创建了一个 ReplicaSet,该 ReplicaSet 创建了三个副本 Pod,由 .spec.replicas 字段指示。

  • .spec.selector 字段定义了创建的 ReplicaSet 如何查找要管理的 Pod。在这种情况下,您选择一个在 Pod 模板中定义的标签 (app: nginx)。但是,只要 Pod 模板本身满足规则,就可以使用更复杂的选择规则。

  • template 字段包含以下子字段

    • 使用 .metadata.labels 字段将 Pod 标记为 app: nginx
    • Pod 模板的规范,即 .template.spec 字段,指示 Pod 运行一个容器 nginx,该容器运行版本为 1.14.2 的 nginx Docker Hub 镜像。
    • 使用 .spec.template.spec.containers[0].name 字段创建一个名为 nginx 的容器。

在开始之前,请确保您的 Kubernetes 集群已启动并运行。按照以下步骤创建上述 Deployment

  1. 运行以下命令创建 Deployment

    kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
    
  2. 运行 kubectl get deployments 检查 Deployment 是否已创建。

    如果 Deployment 仍在创建中,则输出类似于以下内容

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   0/3     0            0           1s
    

    当您检查集群中的 Deployment 时,将显示以下字段

    • NAME 列出命名空间中 Deployment 的名称。
    • READY 显示应用程序中有多少个副本可供用户使用。它遵循 ready/desired 的模式。
    • UP-TO-DATE 显示已更新以达到期望状态的副本数量。
    • AVAILABLE 显示应用程序中有多少个副本可供用户使用。
    • AGE 显示应用程序已运行的时间。

    请注意,根据 .spec.replicas 字段,期望的副本数量为 3。

  3. 要查看 Deployment 发布状态,请运行 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
    
  4. 几秒钟后再次运行 kubectl get deployments。输出类似于以下内容

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           18s
    

    请注意,Deployment 已创建所有三个副本,并且所有副本都是最新的(它们包含最新的 Pod 模板)并且可用。

  5. 要查看 Deployment 创建的 ReplicaSet (rs),请运行 kubectl get rs。输出类似于以下内容

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-75675f5897   3         3         3       18s
    

    ReplicaSet 输出显示以下字段

    • NAME 列出命名空间中 ReplicaSet 的名称。
    • DESIRED 显示应用程序的副本的期望数量,您在创建 Deployment 时定义了该数量。这是期望状态
    • CURRENT 显示当前正在运行的副本数量。
    • READY 显示应用程序中有多少个副本可供用户使用。
    • AGE 显示应用程序已运行的时间。

    请注意,ReplicaSet 的名称始终格式为 [DEPLOYMENT-NAME]-[HASH]。此名称将成为创建的 Pod 的基础。

    HASH 字符串与 ReplicaSet 上的 pod-template-hash 标签相同。

  6. 要查看为每个 Pod 自动生成的标签,请运行 kubectl get pods --show-labels。输出类似于

    NAME                                READY     STATUS    RESTARTS   AGE       LABELS
    nginx-deployment-75675f5897-7ci7o   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
    nginx-deployment-75675f5897-kzszj   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
    nginx-deployment-75675f5897-qqcnn   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
    

    创建的 ReplicaSet 确保有三个 nginx Pod。

Pod-template-hash 标签

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

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

更新 Deployment

按照以下步骤更新您的 Deployment

  1. 让我们更新 nginx Pod 以使用 nginx:1.16.1 镜像而不是 nginx:1.14.2 镜像。

    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
    

    或使用以下命令

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

    其中 deployment/nginx-deployment 指示 Deployment,nginx 指示将要更新的容器,nginx:1.16.1 指示新镜像及其标签。

    输出类似于

    deployment.apps/nginx-deployment image updated
    

    或者,您可以 edit Deployment 并将 .spec.template.spec.containers[0].imagenginx:1.14.2 更改为 nginx:1.16.1

    kubectl edit deployment/nginx-deployment
    

    输出类似于

    deployment.apps/nginx-deployment edited
    
  2. 要查看发布状态,请运行

    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
    

获取有关已更新 Deployment 的更多详细信息

  • 滚动更新成功后,您可以通过运行 kubectl get deployments 查看部署情况。输出结果类似于:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           36s
    
  • 运行 kubectl get rs,可以看到 Deployment 通过创建一个新的 ReplicaSet 并将其扩展到 3 个副本,以及将旧的 ReplicaSet 缩减到 0 个副本,从而更新了 Pod。

    kubectl get rs
    

    输出类似于以下内容

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-1564180365   3         3         3       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 模板即可。

    Deployment 确保在更新 Pod 时,只有一定数量的 Pod 关闭。默认情况下,它确保至少 75% 的所需 Pod 数量处于运行状态(最多 25% 不可用)。

    Deployment 还确保创建的 Pod 数量不超过所需 Pod 数量的一定比例。默认情况下,它确保最多 125% 的所需 Pod 数量处于运行状态(最多 25% 的峰值)。

    例如,如果您仔细查看上面的 Deployment,您会发现它首先创建一个新的 Pod,然后删除一个旧的 Pod,然后再创建一个新的 Pod。在足够数量的新 Pod 出现之前,它不会终止旧 Pod,并且在足够数量的旧 Pod 被终止之前,它不会创建新的 Pod。它确保至少有 3 个 Pod 可用,并且总共最多有 4 个 Pod 可用。对于具有 4 个副本的 Deployment,Pod 的数量将在 3 到 5 个之间。

  • 获取 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.16.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 个副本,并将新的 ReplicaSet 扩展到 2 个副本,以便始终至少有 3 个 Pod 可用,并且最多创建 4 个 Pod。然后,它继续使用相同的滚动更新策略扩展和缩减新的和旧的 ReplicaSet。最后,您将在新的 ReplicaSet 中拥有 3 个可用的副本,并且旧的 ReplicaSet 将缩减为 0。

滚动更新(也称为多个更新同时进行)

每次 Deployment 控制器观察到新的 Deployment 时,都会创建一个 ReplicaSet 来启动所需的 Pod。如果 Deployment 更新,则控制其标签与 .spec.selector 匹配但其模板与 .spec.template 不匹配的 Pod 的现有 ReplicaSet 将被缩减。最终,新的 ReplicaSet 将被扩展到 .spec.replicas,所有旧的 ReplicaSet 将被缩减为 0。

如果您在现有滚动更新正在进行时更新 Deployment,则 Deployment 将根据更新创建一个新的 ReplicaSet 并开始对其进行扩展,并滚动更新之前正在扩展的 ReplicaSet——它会将其添加到旧 ReplicaSet 列表中并开始对其进行缩减。

例如,假设您创建了一个 Deployment 来创建 5 个 nginx:1.14.2 的副本,但随后将 Deployment 更新为创建 5 个 nginx:1.16.1 的副本,而此时只有 3 个 nginx:1.14.2 的副本已创建。在这种情况下,Deployment 会立即开始终止它创建的 3 个 nginx:1.14.2 Pod,并开始创建 nginx:1.16.1 Pod。它不会等到 5 个 nginx:1.14.2 的副本都创建完毕后再更改方向。

标签选择器更新

通常不建议进行标签选择器更新,建议您预先计划好您的选择器。无论如何,如果您需要执行标签选择器更新,请务必谨慎,并确保您已掌握所有影响。

  • 选择器添加要求 Deployment 规范中的 Pod 模板标签也使用新标签进行更新,否则将返回验证错误。此更改是非重叠的,这意味着新选择器不会选择使用旧选择器创建的 ReplicaSet 和 Pod,从而导致所有旧 ReplicaSet 成为孤立状态并创建一个新的 ReplicaSet。
  • 选择器更新会更改选择器键中的现有值——导致与添加相同的结果。
  • 选择器删除会从 Deployment 选择器中删除现有键——不需要对 Pod 模板标签进行任何更改。现有的 ReplicaSet 不会成为孤立状态,也不会创建新的 ReplicaSet,但请注意,删除的标签仍然存在于任何现有的 Pod 和 ReplicaSet 中。

回滚 Deployment

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

  • 假设您在更新 Deployment 时输入错误,将镜像名称写成 nginx:1.161 而不是 nginx:1.16.1

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

    输出类似于以下内容

    deployment.apps/nginx-deployment image updated
    
  • 滚动更新卡住了。您可以通过检查滚动更新状态来验证它。

    kubectl rollout status deployment/nginx-deployment
    

    输出类似于以下内容

    Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
    
  • 按 Ctrl-C 停止上述滚动更新状态监视。有关卡住的滚动更新的更多信息,请在此处阅读更多内容

  • 您会看到旧副本的数量(将 nginx-deployment-1564180365nginx-deployment-2035384211 的副本计数相加)为 3,而新副本的数量(来自 nginx-deployment-3066724191)为 1。

    kubectl get rs
    

    输出类似于以下内容

    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
    

    输出类似于以下内容

    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 的描述

    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 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.161
        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 的修订版本

    kubectl rollout history deployment/nginx-deployment
    

    输出类似于以下内容

    deployments "nginx-deployment"
    REVISION    CHANGE-CAUSE
    1           kubectl apply --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml
    2           kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
    3           kubectl set image deployment/nginx-deployment nginx=nginx:1.161
    

    CHANGE-CAUSE 在创建时从 Deployment 注释 kubernetes.io/change-cause 复制到其修订版本。您可以通过以下方式指定 CHANGE-CAUSE 消息:

    • 使用 kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1" 对 Deployment 进行注释。
    • 手动编辑资源的清单。
  2. 要查看每个修订版本的详细信息,请运行

    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.16.1
      Containers:
       nginx:
        Image:      nginx:1.16.1
        Port:       80/TCP
         QoS Tier:
            cpu:      BestEffort
            memory:   BestEffort
        Environment Variables:      <none>
      No volumes.
    

回滚到先前修订版本

请按照以下步骤将 Deployment 从当前版本回滚到先前版本(版本 2)。

  1. 现在,您已决定撤消当前滚动更新并回滚到先前修订版本。

    kubectl rollout undo deployment/nginx-deployment
    

    输出类似于以下内容

    deployment.apps/nginx-deployment rolled back
    

    或者,您可以使用 --to-revision 指定要回滚到的特定修订版本。

    kubectl rollout undo deployment/nginx-deployment --to-revision=2
    

    输出类似于以下内容

    deployment.apps/nginx-deployment rolled back
    

    有关滚动更新相关命令的更多详细信息,请阅读 kubectl rollout

    Deployment 现在已回滚到先前稳定的修订版本。如您所见,Deployment 控制器生成了一个 DeploymentRollback 事件,用于回滚到修订版本 2。

  2. 要检查回滚是否成功以及 Deployment 是否按预期运行,请运行

    kubectl get deployment nginx-deployment
    

    输出类似于以下内容

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           30m
    
  3. 获取 Deployment 的描述

    kubectl describe deployment nginx-deployment
    

    输出类似于以下内容

    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/nginx-deployment nginx=nginx:1.16.1
    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.16.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/nginx-deployment --replicas=10

输出类似于以下内容

deployment.apps/nginx-deployment scaled

假设您的集群中启用了水平 Pod 自动扩展,则可以为您的 Deployment 设置一个自动扩展器,并根据现有 Pod 的 CPU 利用率选择要运行的最小和最大 Pod 数量。

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

输出类似于以下内容

deployment.apps/nginx-deployment scaled

比例缩放

RollingUpdate Deployment 支持同时运行应用程序的多个版本。当您或自动扩展器扩展正在滚动更新(正在进行或已暂停)的 RollingUpdate Deployment 时,Deployment 控制器会在现有的活动 ReplicaSet(具有 Pod 的 ReplicaSet)中平衡额外的副本,以降低风险。这称为*比例缩放*。

例如,您正在运行一个具有 10 个副本的 Deployment,maxSurge=3,maxUnavailable=2。

  • 确保 Deployment 中的 10 个副本正在运行。

    kubectl get deploy
    

    输出类似于以下内容

    NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment     10        10        10           10          50s
    
  • 您更新到一个新的镜像,该镜像恰好无法从集群内部解析。

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

    输出类似于以下内容

    deployment.apps/nginx-deployment image updated
    
  • 镜像更新使用 ReplicaSet nginx-deployment-1989198191 启动新的滚动更新,但由于您上面提到的 maxUnavailable 要求,它被阻止了。查看滚动更新状态

    kubectl get rs
    

    输出类似于以下内容

    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 中。使用比例缩放,您可以将额外的副本分散到所有 ReplicaSet 中。副本数较多的 ReplicaSet 获得的比例较大,副本数较少的 ReplicaSet 获得的比例较低。任何剩余的副本都将添加到副本数最多的 ReplicaSet 中。副本数为零的 ReplicaSet 不会被扩展。

在我们上面的示例中,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 的滚动更新。这种方法允许您在暂停和恢复之间应用多个修复程序,而不会触发不必要的滚动更新。

  • 例如,使用已创建的 Deployment

    获取 Deployment 详细信息

    kubectl get deploy
    

    输出类似于以下内容

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

    获取 rollout 状态

    kubectl get rs
    

    输出类似于以下内容

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   3         3         3         1m
    
  • 运行以下命令暂停 rollout

    kubectl rollout pause deployment/nginx-deployment
    

    输出类似于以下内容

    deployment.apps/nginx-deployment paused
    
  • 然后更新 Deployment 的镜像

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

    输出类似于以下内容

    deployment.apps/nginx-deployment image updated
    
  • 注意,没有新的 rollout 启动

    kubectl rollout history deployment/nginx-deployment
    

    输出类似于以下内容

    deployments "nginx"
    REVISION  CHANGE-CAUSE
    1   <none>
    
  • 获取 rollout 状态以验证现有的 ReplicaSet 没有更改

    kubectl get rs
    

    输出类似于以下内容

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   3         3         3         2m
    
  • 您可以根据需要进行任意数量的更新,例如,更新将使用的资源

    kubectl set resources deployment/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
    

    输出类似于以下内容

    deployment.apps/nginx-deployment resource requirements updated
    

    在暂停 rollout 之前,Deployment 的初始状态将继续其功能,但对 Deployment 的新更新在 Deployment rollout 暂停时不会生效。

  • 最终,恢复 Deployment rollout 并观察一个新的 ReplicaSet 出现,其中包含所有新的更新

    kubectl rollout resume deployment/nginx-deployment
    

    输出类似于以下内容

    deployment.apps/nginx-deployment resumed
    
  • 观察 rollout 的状态,直到它完成。

    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
    
  • 获取最新 rollout 的状态

    kubectl get rs
    

    输出类似于以下内容

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

Deployment 状态

Deployment 在其生命周期中会进入各种状态。它可以在推出新的 ReplicaSet 时进行中,它可以完成,或者它可以无法进行

进行中的 Deployment

当执行以下任务之一时,Kubernetes 会将 Deployment 标记为进行中

  • Deployment 创建一个新的 ReplicaSet。
  • Deployment 正在扩展其最新的 ReplicaSet。
  • Deployment 正在缩减其较旧的 ReplicaSet。
  • 新的 Pod 变为就绪或可用(至少已就绪 MinReadySeconds)。

当 rollout 变为“进行中”时,Deployment 控制器会将具有以下属性的条件添加到 Deployment 的 .status.conditions

  • 类型:Progressing
  • 状态:“True”
  • reason: NewReplicaSetCreated | reason: FoundNewReplicaSet | reason: ReplicaSetUpdated

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

已完成的 Deployment

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

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

当 rollout 变为“完成”时,Deployment 控制器会将具有以下属性的条件设置为 Deployment 的 .status.conditions

  • 类型:Progressing
  • 状态:“True”
  • reason: NewReplicaSetAvailable

Progressing 条件将保留状态值 "True",直到启动新的 rollout。即使副本的可用性发生变化(这反而会影响 Available 条件),该条件也会保持。

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

kubectl rollout status deployment/nginx-deployment

输出类似于以下内容

Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out

并且 kubectl rollout 的退出状态为 0(成功)

echo $?
0

失败的 Deployment

您的 Deployment 可能会卡在尝试部署其最新的 ReplicaSet 而从未完成。这可能是由于以下一些因素造成的

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

您可以检测到这种情况的一种方法是在 Deployment 规范中指定 deadline 参数:(.spec.progressDeadlineSeconds)。.spec.progressDeadlineSeconds 表示 Deployment 控制器在指示(在 Deployment 状态中)Deployment 进度已停滞之前等待的秒数。

以下 kubectl 命令将使用 progressDeadlineSeconds 设置规范,以使控制器在 10 分钟后报告 Deployment 的 rollout 缺乏进展

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

输出类似于以下内容

deployment.apps/nginx-deployment patched

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

  • 类型:Progressing
  • 状态:“False”
  • reason: ProgressDeadlineExceeded

此条件也可能提前失败,然后由于 ReplicaSetCreateError 等原因将其设置为状态值 "False"。此外,一旦 Deployment rollout 完成,将不再考虑截止时间。

有关状态条件的更多信息,请参阅Kubernetes API 约定

您可能会遇到 Deployment 的瞬态错误,这可能是由于您设置的超时时间过短,也可能是由于可以视为瞬态的任何其他类型的错误。例如,假设您的配额不足。如果您描述 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 将更新 Progressing 条件的状态和原因

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

您可以通过缩减 Deployment、缩减您可能正在运行的其他控制器或增加命名空间中的配额来解决配额不足的问题。如果您满足配额条件并且 Deployment 控制器随后完成了 Deployment rollout,您将看到 Deployment 的状态更新为成功条件(status: "True"reason: NewReplicaSetAvailable)。

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

type: Availablestatus: "True" 表示您的 Deployment 具有最低可用性。最低可用性由部署策略中指定的参数决定。type: Progressingstatus: "True" 表示您的 Deployment 正在 rollout 过程中并且正在进行中,或者它已成功完成其进度并且所需的最低限度的新副本可用(有关详细信息,请参阅条件的原因 - 在我们的例子中,reason: NewReplicaSetAvailable 表示 Deployment 已完成)。

您可以使用 kubectl rollout status 检查 Deployment 是否无法进行。如果 Deployment 已超过进度截止时间,kubectl rollout status 将返回非零退出代码。

kubectl rollout status deployment/nginx-deployment

输出类似于以下内容

Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline

并且 kubectl rollout 的退出状态为 1(表示错误)

echo $?
1

对失败的 Deployment 进行操作

适用于完整 Deployment 的所有操作也适用于失败的 Deployment。您可以对其进行放大/缩小,回滚到以前的版本,甚至可以在需要在 Deployment Pod 模板中应用多个调整时暂停它。

清理策略

您可以在 Deployment 中设置 .spec.revisionHistoryLimit 字段,以指定要为此 Deployment 保留多少个旧 ReplicaSet。其余的将在后台被垃圾回收。默认情况下,它是 10。

金丝雀部署

如果您想使用 Deployment 将发布 rollout 到一部分用户或服务器,您可以为每个发布创建多个 Deployment,遵循管理资源中描述的金丝雀模式。

编写 Deployment 规范

与所有其他 Kubernetes 配置一样,Deployment 需要 .apiVersion.kind.metadata 字段。有关使用配置文件的一般信息,请参阅部署应用程序、配置容器和使用 kubectl 管理资源文档。

当控制平面为 Deployment 创建新的 Pod 时,Deployment 的 .metadata.name 是命名这些 Pod 的基础的一部分。Deployment 的名称必须是有效的DNS 子域名值,但这可能会对 Pod 主机名产生意外结果。为了获得最佳兼容性,该名称应遵循更严格的DNS 标签规则。

Deployment 还需要一个.spec 部分

Pod 模板

.spec.template.spec.selector.spec 的唯一必需字段。

.spec.template 是一个Pod 模板。它与Pod的架构完全相同,只是它是嵌套的并且没有 apiVersionkind

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

只允许.spec.template.spec.restartPolicy 等于 Always,如果未指定,则默认为此值。

副本

.spec.replicas 是一个可选字段,用于指定所需的 Pod 数量。默认为 1。

如果您手动扩展 Deployment,例如通过 kubectl scale deployment deployment --replicas=X,然后根据清单更新该 Deployment(例如:通过运行 kubectl apply -f deployment.yaml),则应用该清单会覆盖您之前所做的手动扩展。

如果HorizontalPodAutoscaler(或任何类似的水平扩展 API)正在管理 Deployment 的扩展,请不要设置 .spec.replicas

而是允许 Kubernetes 控制平面自动管理 .spec.replicas 字段。

选择器

.spec.selector 是一个必需字段,用于指定此 Deployment 所针对的 Pod 的标签选择器

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

在 API 版本 apps/v1 中,如果未设置 .spec.selector.metadata.labels,则它们不会默认为 .spec.template.metadata.labels。因此,必须显式设置它们。另请注意,在 apps/v1 中创建 Deployment 后,.spec.selector 是不可变的。

如果 Pod 的标签与选择器匹配,但其模板与 .spec.template 不同,或者此类 Pod 的总数超过 .spec.replicas,则 Deployment 可能会终止这些 Pod。如果 Pod 数量少于所需数量,它会使用 .spec.template 启动新的 Pod。

如果您有多个控制器具有重叠的选择器,则这些控制器将相互冲突,并且无法正常运行。

策略

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

重新创建 Deployment

.spec.strategy.type==Recreate 时,在创建新 Pod 之前,所有现有 Pod 都会被终止。

滚动更新 Deployment

.spec.strategy.type==RollingUpdate 时,Deployment 会以滚动更新的方式更新 Pod。您可以指定 maxUnavailablemaxSurge 来控制滚动更新过程。

最大不可用数量

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

例如,当此值设置为 30% 时,在滚动更新开始时,可以立即将旧 ReplicaSet 缩减到所需 Pod 的 70%。在新 Pod 准备就绪后,可以进一步缩减旧 ReplicaSet,然后扩展新 ReplicaSet,确保更新期间始终可用的 Pod 总数至少为所需 Pod 的 70%。

最大激增数量

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

例如,当此值设置为 30% 时,可以在滚动更新开始时立即扩展新 ReplicaSet,以便旧 Pod 和新 Pod 的总数不超过所需 Pod 的 130%。在终止旧 Pod 后,可以进一步扩展新 ReplicaSet,确保更新期间任何时候运行的 Pod 总数最多为所需 Pod 的 130%。

以下是一些使用 maxUnavailablemaxSurge 的滚动更新 Deployment 示例

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
 strategy:
   type: RollingUpdate
   rollingUpdate:
     maxUnavailable: 1

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
 strategy:
   type: RollingUpdate
   rollingUpdate:
     maxSurge: 1

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
 strategy:
   type: RollingUpdate
   rollingUpdate:
     maxSurge: 1
     maxUnavailable: 1

进度截止时间(秒)

.spec.progressDeadlineSeconds 是一个可选字段,用于指定在系统报告 Deployment 进度失败 之前您希望等待 Deployment 进展的秒数 - 在资源状态中显示为条件,其中 type: Progressingstatus: "False"reason: ProgressDeadlineExceeded。Deployment 控制器将继续重试 Deployment。默认为 600。将来,一旦实现了自动回滚,Deployment 控制器将在观察到此类条件后立即回滚 Deployment。

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

最小就绪时间(秒)

.spec.minReadySeconds 是一个可选字段,用于指定新创建的 Pod 在其任何容器未崩溃的情况下应保持就绪状态的最短秒数,以便将其视为可用。默认为 0(Pod 在就绪后立即被视为可用)。要详细了解何时将 Pod 视为就绪,请参阅 容器探针

修订历史记录限制

Deployment 的修订历史记录存储在其控制的 ReplicaSet 中。

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

更具体地说,将此字段设置为零意味着将清除所有具有 0 个副本的旧 ReplicaSet。在这种情况下,无法撤销新的 Deployment 部署,因为其修订历史记录已被清除。

已暂停

.spec.paused 是一个可选的布尔字段,用于暂停和恢复 Deployment。已暂停的 Deployment 与未暂停的 Deployment 之间的唯一区别是,只要已暂停的 Deployment 中的 PodTemplateSpec 发生任何更改,就不会触发新的部署。默认情况下,Deployment 在创建时不会暂停。

下一步

上次修改时间:2024 年 3 月 14 日下午 2:28 PST:添加元数据以使用 API 参考链接机制 (c889d9b251)