Deployments
一个 Deployment 控制器为 Pods和 ReplicaSets提供描述性的更新方式。
描述 Deployment 中的 _desired state_,并且 Deployment 控制器以受控速率更改实际状态,以达到期望状态。可以定义 Deployments 以创建新的 ReplicaSets ,或删除现有 Deployments ,并通过新的 Deployments 使用其所有资源。
注意:不要管理 Deployment 拥有的 ReplicaSets 。如果存在下面未介绍的用例,请考虑在主 Kubernetes 仓库中提出 issue。
- 用例
- 创建 Deployment
- 更新 Deployment
- 回滚 Deployment
- 缩放 Deployment
- 暂停、恢复 Deployment
- Deployment 状态
- 清理策略
- 金丝雀 Deployment
- 编写 Deployment 脚本
- Deployments 的替代方案
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 用例:
- 创建 Deployment 以展开 ReplicaSet 。 ReplicaSet 在后台创建 Pods。检查 ReplicaSet 展开的状态,查看其是否成功。
- 声明 Pod 的新状态 通过更新 Deployment 的 PodTemplateSpec。将创建新的 ReplicaSet ,并且 Deployment 管理器以受控速率将 Pod 从旧 ReplicaSet 移动到新 ReplicaSet 。每个新的 ReplicaSet 都会更新 Deployment 的修改历史。
- 回滚到较早的 Deployment 版本,如果 Deployment 的当前状态不稳定。每次回滚都会更新 Deployment 的修改。
- 暂停 Deployment 对其 PodTemplateSpec 进行修改,然后恢复它以启动新的展开。
- 使用 Deployment 状态 作为卡住展开的指示器。
- 清理较旧的 ReplicaSets ,那些不在需要的。
创建 Deployment
下面是 Deployment 示例。创建一个 ReplicaSet 展开三个 nginx
Pods:
controllers/nginx-deployment.yaml
|
---|
|
在该例中:
- 将创建名为
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 集群已启动并运行。
- 通过运行以下命令创建 Deployment :
注意:可以指定 `--record` 标志来写入在资源注释`kubernetes.io/change-cause`中执行的命令。它对以后的检查是有用的。
例如,查看在每个 Deployment 修改中执行的命令。
```shell
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
```
运行
kubectl get deployments
以检查 Deployment 是否已创建。如果仍在创建 Deployment ,则输出以下内容: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。
要查看 Deployment 展开状态,运行
kubectl rollout status deployment.v1.apps/nginx-deployment
。输出:Waiting for rollout to finish: 2 out of 3 new replicas have been updated... deployment.apps/nginx-deployment successfully rolled out
几秒钟后再次运行
kubectl get deployments
。输出:NAME DESIRED CURRENT 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 的名称始终被格式化为`[DEPLOYMENT-NAME]-[RANDOM-STRING]`。随机字符串是随机生成并使用 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=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 :
让我们更新 nginx Pods,以使用
nginx:1.9.1
镜像 ,而不是nginx:1.7.9
镜像 。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
```
要查看展开状态,运行:
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 展开历史
按照如下步骤检查回滚历史:
首先,检查 Deployment 修改历史:
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` 命令。
* 手动编辑资源的清单。
查看修改历史的详细信息,运行:
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)。
现在已决定撤消当前展开并回滚到以前的版本:
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 控制器生成的。
检查回滚是否成功、 Deployment 是否正在运行,运行:
kubectl get deployment nginx-deployment
输出:
```shell
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 30m
```
获取 Deployment 描述信息:
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
输出:
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=Available
和 Status=True
表示 Deployment 具有最低可用性。最低可用性由 Deployment 策略中的参数指定。Type=Progressing
和 Status=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 需要 apiVersion
, kind
, 和 metadata
字段。有关配置文件的其他信息,参考 应用 Deployment ,配置容器,和 使用 kubectl 管理资源 相关文档。
Deployment 还需要 .spec
部分。
Pod 示例
.spec
仅需要 .spec.template
和 .spec.selector
。
.spec.template
是一个 Pod 示例。它和 Pod的约束完全相同,除了它是嵌套的,而且没有 apiVersion
或 kind
。
除了 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。可以指定 maxUnavailable
和 maxSurge
来控制滚动更新操作。
最大不可用
.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=Progressing
、 Status=False
、 Reason=ProgressDeadlineExceeded
。 Deployment 控制器将保留正在重试 Deployment 。将来,一旦实现自动回滚, Deployment 控制器将回滚 Deployment ,只要它探测到这样的条件。
如果指定,则此字段需要大于 .spec.minReadySeconds
。
最小就绪时间
.spec.minReadySeconds
是一个可选字段,用于指定新创建的 Pod 在没有任意容器崩溃情况下的最小就绪时间,以便将其视为可用。默认值为 0(Pod 在准备就绪后立即将被视为可用)。了解有关何时Pod 被视为已准备就绪,参考容器探针。
回滚
.spec.rollbackTo
字段已经在 API 版本 extensions/v1beta1
和 apps/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 的方式来更新,因为它们是声明性的,在服务器端,并且具有其他功能,例如,即使在滚动更新完成后,也会回滚到以前的任何修改版本。
反馈
此页是否对您有帮助?
感谢反馈。如果您有一个关于如何使用 Kubernetes 的特定的、需要答案的问题,可以访问 Stack Overflow. 在 GitHub 仓库上登记新的问题 报告问题 或者 提出改进建议.