部署
Deployment 为 Pod 和 ReplicaSet 提供声明式更新。
你在 Deployment 中描述一个**期望状态**,Deployment 控制器 以受控速率将实际状态更改为期望状态。你可以定义 Deployment 以创建新的 ReplicaSet,或移除现有 Deployment 并使用新的 Deployment 采用所有其资源。
注意
不要管理由 Deployment 所拥有的 ReplicaSet。如果你的用例未在下面涵盖,请考虑在 Kubernetes 主存储库中提出问题。用例
以下是 Deployment 的典型用例:
- 创建 Deployment 以推出 ReplicaSet。ReplicaSet 在后台创建 Pod。检查推出的状态以查看其是否成功。
- 通过更新 Deployment 的 PodTemplateSpec 来声明 Pod 的新状态。一个新的 ReplicaSet 将被创建,Deployment 会逐步将其扩容,同时缩减旧的 ReplicaSet,确保 Pod 以受控速率替换。每个新的 ReplicaSet 都会更新 Deployment 的修订版本。
- 如果 Deployment 的当前状态不稳定,回滚到先前的 Deployment 修订版本。每次回滚都会更新 Deployment 的修订版本。
- 扩容 Deployment 以处理更多负载。.
- 暂停 Deployment 的推出,以对其 PodTemplateSpec 应用多个修复,然后恢复它以开始新的推出。
- 使用 Deployment 的状态 作为推出停滞的指标。
- 清理不再需要的旧 ReplicaSet。
创建 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 Spec。
Deployment 创建了一个 ReplicaSet,该 ReplicaSet 创建三个复制的 Pod,由 `.spec.replicas` 字段指示。
`.spec.selector` 字段定义了创建的 ReplicaSet 如何找到要管理的 Pod。在本例中,你选择 Pod 模板(`app: nginx`)中定义的标签。但是,只要 Pod 模板本身满足规则,就可以使用更复杂的选择规则。
注意
`.spec.selector.matchLabels` 字段是一个 {键,值} 对的映射。`matchLabels` 映射中的单个 {键,值} 等效于 `matchExpressions` 的一个元素,其 `key` 字段是“键”,`operator` 是“In”,并且 `values` 数组仅包含“值”。为了匹配,必须满足 `matchLabels` 和 `matchExpressions` 的所有要求。`.spec.template` 字段包含以下子字段:
- 使用 `.metadata.labels` 字段将 Pod 标记为 `app: nginx`。
- Pod 模板的规约,即 `.spec` 字段,指示 Pod 运行一个容器,名为 `nginx`,它运行 1.14.2 版本的 `nginx` Docker Hub 镜像。
- 使用 `.spec.containers[0].name` 字段创建并命名一个容器为 `nginx`。
在开始之前,请确保你的 Kubernetes 集群已启动并正在运行。按照以下步骤创建上述 Deployment:
通过运行以下命令创建 Deployment:
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
运行 `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。
要查看 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
几秒钟后再次运行 `kubectl get deployments`。输出类似于:
NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 18s
请注意,Deployment 已创建所有三个副本,并且所有副本都是最新的(它们包含最新的 Pod 模板)并且可用。
要查看 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` 标签相同。
要查看为每个 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。
注意
你必须在 Deployment 中指定适当的选择器和 Pod 模板标签(在本例中为 `app: nginx`)。
不要让标签或选择器与其他控制器(包括其他 Deployment 和 StatefulSet)重叠。Kubernetes 不会阻止你重叠,如果多个控制器有重叠的选择器,这些控制器可能会冲突并表现出意外行为。
Pod 模板哈希标签
注意
不要更改此标签。`pod-template-hash` 标签由 Deployment 控制器添加到 Deployment 创建或采用的每个 ReplicaSet 中。
此标签确保 Deployment 的子 ReplicaSet 不会重叠。它是通过对 ReplicaSet 的 `PodTemplate` 进行哈希计算,并将生成的哈希用作添加到 ReplicaSet 选择器、Pod 模板标签以及 ReplicaSet 可能具有的任何现有 Pod 中的标签值来生成的。
更新 Deployment
注意
仅当 Deployment 的 Pod 模板(即 `.spec.template`)发生更改时,例如模板的标签或容器镜像已更新时,才会触发 Deployment 的推出。其他更新,例如缩放 Deployment,不会触发推出。按照以下步骤更新你的 Deployment:
让我们将 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].image` 从 `nginx:1.14.2` 更改为 `nginx:1.16.1`。
kubectl edit deployment/nginx-deployment
输出类似于:
deployment.apps/nginx-deployment edited
要查看推出状态,请运行:
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` 查看 Deployment。输出类似于:
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 下线。默认情况下,它确保至少 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。
注意
Kubernetes 在计算 `availableReplicas` 数量时不计算正在终止的 Pod,该数量必须介于 `replicas - maxUnavailable` 和 `replicas + maxSurge` 之间。因此,你可能会注意到,在推出期间 Pod 数量可能超出预期,并且 Deployment 消耗的总资源可能超出 `replicas + maxSurge`,直到正在终止的 Pod 的 `terminationGracePeriodSeconds` 过期。滚动(即飞行中的多次更新)
每当 Deployment 控制器观察到新的 Deployment 时,就会创建一个 ReplicaSet 来启动所需的 Pod。如果 Deployment 被更新,则控制 Pod 的现有 ReplicaSet(其标签与 `.spec.selector` 匹配但其模板与 `.spec.template` 不匹配)将缩减。最终,新的 ReplicaSet 将扩容到 `.spec.replicas`,所有旧的 ReplicaSet 将缩减到 0。
如果你在现有推出正在进行时更新 Deployment,Deployment 会根据更新创建一个新的 ReplicaSet 并开始扩容,然后将之前正在扩容的 ReplicaSet 滚动更新——它会将其添加到旧 ReplicaSet 列表中并开始缩减。
例如,假设你创建了一个 Deployment 以创建 5 个 `nginx:1.14.2` 副本,但在只创建了 3 个 `nginx:1.14.2` 副本时更新了 Deployment 以创建 5 个 `nginx:1.16.1` 副本。在这种情况下,Deployment 立即开始杀死它已创建的 3 个 `nginx:1.14.2` Pod,并开始创建 `nginx:1.16.1` Pod。它不会等待 5 个 `nginx:1.14.2` 副本创建完毕再改变方向。
标签选择器更新
通常不鼓励进行标签选择器更新,建议你预先规划好选择器。在任何情况下,如果你需要执行标签选择器更新,请务必谨慎并确保你已完全理解所有影响。
注意
在 API 版本 `apps/v1` 中,Deployment 的标签选择器在创建后是不可变的。- 选择器添加需要 Deployment 规约中的 Pod 模板标签也更新新标签,否则将返回验证错误。此更改是非重叠的,这意味着新选择器不选择使用旧选择器创建的 ReplicaSet 和 Pod,导致所有旧 ReplicaSet 孤立并创建新的 ReplicaSet。
- 选择器更新更改选择器键中的现有值——导致与添加相同的行为。
- 选择器删除会从 Deployment 选择器中移除现有键——不需要对 Pod 模板标签进行任何更改。现有的 ReplicaSet 不会被孤立,也不会创建新的 ReplicaSet,但请注意,已移除的标签仍然存在于任何现有 Pod 和 ReplicaSet 中。
回滚 Deployment
有时,你可能希望回滚 Deployment;例如,当 Deployment 不稳定(例如,崩溃循环)时。默认情况下,Deployment 的所有推出历史记录都保留在系统中,因此你可以随时回滚(你可以通过修改修订历史限制来更改此设置)。
注意
当 Deployment 的推出被触发时,会创建一个 Deployment 修订版本。这意味着只有当 Deployment 的 Pod 模板(`.spec.template`)发生更改时,才会创建新的修订版本,例如,如果你更新模板的标签或容器镜像。其他更新,例如缩放 Deployment,不会创建 Deployment 修订版本,以便你可以促进同时的手动或自动缩放。这意味着当你回滚到较早的修订版本时,只有 Deployment 的 Pod 模板部分会被回滚。假设你在更新 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-1564180365` 和 `nginx-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 控制器会自动停止错误的推出,并停止扩容新的 ReplicaSet。这取决于你指定的滚动更新参数(特别是 `maxUnavailable`)。Kubernetes 默认将其值设置为 25%。获取 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 的推出历史
按照以下步骤检查推出历史:
首先,检查此 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 添加注解。
- 手动编辑资源的清单。
要查看每个修订版本的详细信息,请运行:
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。
现在你已决定撤销当前的推出并回滚到上一个修订版本。
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。
检查回滚是否成功以及 Deployment 是否按预期运行,运行:
kubectl get deployment nginx-deployment
输出类似于:
NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 30m
获取 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
按比例扩缩
滚动更新型 Deployment 支持同时运行应用程序的多个版本。当你或自动扩缩器扩缩一个处于推出中(正在进行或已暂停)的滚动更新型 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 详细信息。
kubectl get deploy
输出类似于:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 3 3 3 3 1m
获取推出状态。
kubectl get rs
输出类似于:
NAME DESIRED CURRENT READY AGE nginx-2142116321 3 3 3 1m
通过运行以下命令暂停:
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
请注意,没有新的推出启动。
kubectl rollout history deployment/nginx-deployment
输出类似于:
deployments "nginx" REVISION CHANGE-CAUSE 1 <none>
获取推出状态以验证现有 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
Deployment 在暂停推出之前的初始状态将继续其功能,但只要 Deployment 推出处于暂停状态,对 Deployment 的新更新将不会产生任何影响。
最终,恢复 Deployment 推出并观察到新的 ReplicaSet 出现,其中包含所有新更新。
kubectl rollout resume deployment/nginx-deployment
输出类似于:
deployment.apps/nginx-deployment resumed
监视推出状态,直到完成。
kubectl get rs --watch
输出类似于:
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
当执行以下任务之一时,Kubernetes 将 Deployment 标记为**进行中**:
- Deployment 创建了一个新的 ReplicaSet。
- Deployment 正在扩容其最新的 ReplicaSet。
- Deployment 正在缩减其旧的 ReplicaSet。
- 新的 Pod 变得就绪或可用(至少在 MinReadySeconds 期间就绪)。
当推出变为“进行中”时,Deployment 控制器会在 Deployment 的 `.status.conditions` 中添加一个具有以下属性的条件:
type: Progressing
status: "True"
- `reason: NewReplicaSetCreated` | `reason: FoundNewReplicaSet` | `reason: ReplicaSetUpdated`
你可以使用 `kubectl rollout status` 监视 Deployment 的进度。
完成的 Deployment
当 Deployment 具有以下特征时,Kubernetes 会将其标记为**完成**:
- 与 Deployment 相关联的所有副本都已更新到你指定的最新版本,这意味着你请求的任何更新都已完成。
- 与 Deployment 相关联的所有副本都可用。
- 没有 Deployment 的旧副本正在运行。
当推出变为“完成”时,Deployment 控制器会在 Deployment 的 `.status.conditions` 中设置一个具有以下属性的条件:
type: Progressing
status: "True"
reason: NewReplicaSetAvailable
此 `Progressing` 条件将保持 `“True”` 状态值,直到启动新的推出。即使副本的可用性发生变化(这会影响 `Available` 条件),该条件也保持不变。
你可以使用 `kubectl rollout status` 检查 Deployment 是否已完成。如果推出成功完成,`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 规约中指定一个截止日期参数:(`.spec.progressDeadlineSeconds`)。`.spec.progressDeadlineSeconds` 表示 Deployment 控制器在指示(在 Deployment 状态中)Deployment 进度已停滞之前等待的秒数。
以下 `kubectl` 命令将 spec 中的 `progressDeadlineSeconds` 设置为 10 分钟,以便控制器在 10 分钟后报告 Deployment 推出没有进展:
kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
输出类似于:
deployment.apps/nginx-deployment patched
一旦超过截止日期,Deployment 控制器将在 Deployment 的 `.status.conditions` 中添加一个具有以下属性的 DeploymentCondition:
type: Progressing
status: "False"
reason: ProgressDeadlineExceeded
此条件也可能提前失败,然后由于 `ReplicaSetCreateError` 等原因而设置为 `“False”`。此外,一旦 Deployment 推出完成,截止日期将不再考虑。
有关状态条件的更多信息,请参阅 Kubernetes API 约定。
注意
Kubernetes 对停滞的 Deployment 不采取任何行动,只是报告一个状态条件,其 `reason: ProgressDeadlineExceeded`。高级编排器可以利用它并采取相应的行动,例如,将 Deployment 回滚到其以前的版本。注意
如果你暂停了 Deployment 推出,Kubernetes 不会根据你指定的截止日期检查进度。你可以在推出中途安全地暂停 Deployment 推出,然后恢复而不会触发超出截止日期的条件。你的 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 推出,你将看到 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 正在推出过程中并正在取得进展,或者它已成功完成其进展并且所需的新副本已可用(有关详细信息,请参阅条件的原因——在我们的示例中,`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。
注意
明确将此字段设置为 0 将导致清理你的 Deployment 的所有历史记录,因此该 Deployment 将无法回滚。清理仅在 Deployment 达到完成状态后才开始。如果你将 `.spec.revisionHistoryLimit` 设置为 0,任何推出仍然会在 Kubernetes 删除旧的 ReplicaSet 之前触发新的 ReplicaSet 的创建。
即使修订历史限制不为零,你也可以拥有比你配置的限制更多的 ReplicaSet。例如,如果 Pod 崩溃循环,并且随着时间的推移触发了多个滚动更新事件,你最终可能会拥有比 `.spec.revisionHistoryLimit` 更多的 ReplicaSet,因为 Deployment 从未达到完整状态。
金丝雀部署
如果你希望使用 Deployment 向一部分用户或服务器推出版本,可以创建多个 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 的模式完全相同,只是它是嵌套的,没有 `apiVersion` 或 `kind`。
除了 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。
注意
你不应创建标签与此选择器匹配的其他 Pod,无论是直接创建、通过创建另一个 Deployment 还是通过创建另一个控制器(例如 ReplicaSet 或 ReplicationController)。如果你这样做,第一个 Deployment 会认为它创建了这些其他 Pod。Kubernetes 不会阻止你这样做。如果多个控制器具有重叠的选择器,它们将相互冲突,并且无法正常工作。
策略
`.spec.strategy` 指定用于替换旧 Pod 的新 Pod 的策略。`.spec.strategy.type` 可以是 "Recreate" 或 "RollingUpdate"。 "RollingUpdate" 是默认值。
重新创建 Deployment
当 `.`spec.strategy.type==Recreate` 时,所有现有 Pod 在创建新 Pod 之前都会被杀死。
注意
这只会在升级时保证在创建之前终止 Pod。如果你升级 Deployment,旧版本的所有 Pod 将立即终止。在创建新版本的任何 Pod 之前,等待成功移除。如果你手动删除 Pod,生命周期由 ReplicaSet 控制,并且替换将立即创建(即使旧 Pod 仍处于终止状态)。如果你需要对 Pod 的“最多”保证,你应该考虑使用StatefulSet。滚动更新 Deployment
当 `.`spec.strategy.type==RollingUpdate` 时,Deployment 会以滚动更新的方式更新 Pod(逐步缩减旧 ReplicaSet 并扩容新的 ReplicaSet)。你可以指定 `maxUnavailable` 和 `maxSurge` 来控制滚动更新过程。
最大不可用数
`.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 的 130%。一旦旧 Pod 被杀死,新的 ReplicaSet 可以进一步扩容,确保在更新期间任何时候运行的 Pod 总数最多为所需 Pod 的 130%。
以下是一些使用 `maxUnavailable` 和 `maxSurge` 的滚动更新 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: Progressing`、`status: "False"` 和 `reason: ProgressDeadlineExceeded` 的条件。Deployment 控制器将继续重试 Deployment。默认值为 600。将来,一旦实现了自动回滚,Deployment 控制器将在观察到此类条件后立即回滚 Deployment。
如果指定,此字段必须大于 `.spec.minReadySeconds`。
最小就绪秒数
`.spec.minReadySeconds` 是一个可选字段,它指定新创建的 Pod 在其任何容器未崩溃的情况下应保持就绪的最短秒数,以便将其视为可用。默认值为 0(Pod 一旦就绪即被视为可用)。要了解有关 Pod 何时被视为就绪的更多信息,请参阅容器探针。
终止 Pods
你可以通过在API 服务器和kube-controller-manager 上设置 `DeploymentReplicaSetTerminatingReplicas` 特性门控来启用此特性。
由于删除或缩减而进入终止状态的 Pod 可能需要很长时间才能终止,并且在此期间可能会消耗额外的资源。因此,所有 Pod 的总数可能会暂时超过 `.spec.replicas`。可以使用 Deployment 的 `.status.terminatingReplicas` 字段跟踪正在终止的 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 在创建时默认不暂停。
下一步
- 了解更多关于Pod的信息。
- 使用 Deployment 运行无状态应用程序。.
- 阅读 Deployment 以了解 Deployment API。
- 了解 PodDisruptionBudget 以及如何使用它来管理中断期间的应用程序可用性。
- 使用 kubectl 创建 Deployment。