部署
一个 Deployment 为 Pod 和 ReplicaSet 提供声明式更新。
您在 Deployment 中描述 期望状态,Deployment 控制器 以受控的速率将实际状态更改为期望状态。您可以定义 Deployment 来创建新的 ReplicaSet,或删除现有的 Deployment 并使用新的 Deployment 采用其所有资源。
注意
不要管理 Deployment 拥有的 ReplicaSet。如果您的用例未在下面涵盖,请考虑在 Kubernetes 主存储库中打开一个 issue。用例
以下是 Deployment 的典型用例
- 创建一个 Deployment 以推出 ReplicaSet。ReplicaSet 在后台创建 Pod。检查 rollout 的状态,以查看它是否成功。
- 通过更新 Deployment 的 PodTemplateSpec 来声明 Pod 的新状态。创建一个新的 ReplicaSet,并且 Deployment 管理以受控的速率将 Pod 从旧的 ReplicaSet 移动到新的 ReplicaSet。每个新的 ReplicaSet 都会更新 Deployment 的版本。
- 如果 Deployment 的当前状态不稳定,则回滚到较早的 Deployment 版本。每次回滚都会更新 Deployment 的版本。
- 扩大 Deployment 以方便更多的负载.
- 暂停 Deployment 的 rollout,以对其 PodTemplateSpec 应用多个修复,然后恢复它以启动新的 rollout。
- 使用 Deployment 的状态作为 rollout 已卡住的指标。
- 清理您不再需要的旧 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 规约。Deployment 创建一个 ReplicaSet,该 ReplicaSet 创建三个复制的 Pod,由
.spec.replicas
字段指示。.spec.selector
字段定义了创建的 ReplicaSet 如何查找要管理的 Pod。在这种情况下,您选择 Pod 模板中定义的标签(app: nginx
)。但是,只要 Pod 模板本身满足该规则,就可以使用更复杂的选择规则。注意
.spec.selector.matchLabels
字段是 {key,value} 对的映射。matchLabels
映射中的单个 {key,value} 等效于matchExpressions
的一个元素,该元素的key
字段为“key”,operator
为“In”,并且values
数组仅包含“value”。为了匹配,必须满足来自matchLabels
和matchExpressions
的所有要求。template
字段包含以下子字段- 使用
.metadata.labels
字段将 Pod 标记为app: nginx
。 - Pod 模板的规约,或
.template.spec
字段,指示 Pod 运行一个容器nginx
,该容器运行nginx
Docker Hub 镜像,版本为 1.14.2。 - 使用
.spec.template.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 rollout 状态,请运行
kubectl rollout status deployment/nginx-deployment
。输出类似于
Waiting for rollout to finish: 2 out of 3 new replicas have been updated... deployment "nginx-deployment" successfully rolled out
几秒钟后再次运行
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-template-hash 标签
警告
请勿更改此标签。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
或者,您可以
编辑
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
现在应该只显示新的 Podkubectl 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 被更新,则会缩小控制标签与 .spec.selector
匹配但模板与 .spec.template
不匹配的 Pod 的现有 ReplicaSet。最终,新的 ReplicaSet 会被扩展到 .spec.replicas
,并且所有旧的 ReplicaSet 都会被缩小到 0。
如果您在现有的滚动更新正在进行时更新 Deployment,Deployment 将根据更新创建一个新的 ReplicaSet 并开始扩大该 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。这取决于您指定的 rollingUpdate 参数(特别是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 控制器生成了一个用于回滚到修订 2 的
DeploymentRollback
事件。检查回滚是否成功并且 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
比例缩放
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 的新 rollout,但由于您上面提到的
maxUnavailable
要求而被阻止。查看 rollout 状态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。假设新的副本变为健康状态,rollout 过程最终应将所有副本移动到新的 ReplicaSet。要确认这一点,请运行
kubectl get deploy
输出类似于以下内容
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
rollout 状态确认了副本是如何添加到每个 ReplicaSet 的。
kubectl get rs
输出类似于以下内容
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
暂停和恢复 Deployment 的 rollout
当您更新 Deployment 时,或者计划更新时,您可以在触发一个或多个更新之前暂停该 Deployment 的 rollout。当您准备好应用这些更改时,您将恢复 Deployment 的 rollout。这种方法允许您在暂停和恢复之间应用多个修复程序,而无需触发不必要的 rollout。
例如,使用一个创建的 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
运行以下命令暂停
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
在暂停 Deployment 的 rollout 之前,Deployment 的初始状态将继续其功能,但是对 Deployment 的新更新在 Deployment rollout 暂停期间不会有任何影响。
最终,恢复 Deployment 的 rollout,并观察到一个新的 ReplicaSet 出现,其中包含所有新的更新
kubectl rollout resume deployment/nginx-deployment
输出类似于以下内容
deployment.apps/nginx-deployment resumed
监视 rollout 的状态,直到完成。
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
获取最新 rollout 的状态
kubectl get rs
输出类似于以下内容
NAME DESIRED CURRENT READY AGE nginx-2142116321 0 0 0 2m nginx-3926361531 3 3 3 28s
注意
在您恢复暂停的 Deployment 之前,您无法回滚该 Deployment。Deployment 状态
Deployment 在其生命周期中会进入各种状态。在 rollout 新的 ReplicaSet 时,它可以处于进行中状态,它可以处于完成状态,或者它可能无法进行。
进行中的 Deployment
当执行以下任务之一时,Kubernetes 会将 Deployment 标记为进行中
- Deployment 创建一个新的 ReplicaSet。
- Deployment 正在扩容其最新的 ReplicaSet。
- Deployment 正在缩减其较旧的 ReplicaSet。
- 新的 Pod 变为就绪或可用(至少准备好 MinReadySeconds 时间)。
当 rollout 变为“进行中”时,Deployment 控制器会向 Deployment 的 .status.conditions
添加一个具有以下属性的条件
类型:Progressing
状态:"True"
原因:NewReplicaSetCreated
|原因:FoundNewReplicaSet
|原因:ReplicaSetUpdated
您可以使用 kubectl rollout status
来监视 Deployment 的进度。
完成的 Deployment
当 Deployment 具有以下特征时,Kubernetes 会将其标记为完成
- 与 Deployment 关联的所有副本都已更新为您指定的最新版本,这意味着您请求的任何更新都已完成。
- 与 Deployment 关联的所有副本均可用。
- Deployment 的旧副本没有在运行。
当 rollout 变为“完成”时,Deployment 控制器会向 Deployment 的 .status.conditions
设置一个具有以下属性的条件
类型:Progressing
状态:"True"
原因: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 spec 中指定截止期限参数:(.spec.progressDeadlineSeconds
)。.spec.progressDeadlineSeconds
表示 Deployment 控制器在 Deployment 状态中指示 Deployment 进度已停滞之前等待的秒数。
以下 kubectl
命令使用 progressDeadlineSeconds
设置 spec,以使控制器在 10 分钟后报告 Deployment 的 rollout 缺少进度
kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
输出类似于以下内容
deployment.apps/nginx-deployment patched
一旦超过截止期限,Deployment 控制器就会向 Deployment 的 .status.conditions
添加一个具有以下属性的 DeploymentCondition
类型:Progressing
状态:"False"
原因:ProgressDeadlineExceeded
由于诸如 ReplicaSetCreateError
之类的原因,此条件也可能提前失败,然后设置为 "False"
的状态值。此外,一旦 Deployment rollout 完成,截止期限将不再考虑。
有关状态条件的更多信息,请参阅Kubernetes API 约定。
注意
Kubernetes 对停滞的 Deployment 不采取任何操作,只是报告一个具有reason: ProgressDeadlineExceeded
的状态条件。更高级别的编排器可以利用它并采取相应的操作,例如,将 Deployment 回滚到其先前版本。注意
如果您暂停 Deployment rollout,则 Kubernetes 不会根据您指定的截止期限检查进度。您可以安全地在 rollout 中途暂停 Deployment rollout,并在不触发超出截止期限的条件的情况下恢复。您的 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
类型:Available
和 状态:"True"
表示您的 Deployment 具有最小可用性。最小可用性由部署策略中指定的参数决定。类型:Progressing
和 状态:"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。
注意
将此字段显式设置为 0 将导致清除 Deployment 的所有历史记录,因此该 Deployment 将无法回滚。金丝雀部署
如果您想使用 Deployment 将版本发布到一部分用户或服务器,您可以创建多个 Deployment,每个版本一个,遵循管理资源中描述的金丝雀模式。
编写 Deployment Spec
与所有其他 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 然后创建 Pod。如果您升级 Deployment,旧修订版本的所有 Pod 将立即被终止。只有在成功移除旧版本 Pod 后,才会创建新修订版本的 Pod。如果您手动删除 Pod,则生命周期由 ReplicaSet 控制,并且会立即创建替换 Pod(即使旧 Pod 仍处于终止状态)。 如果您需要对 Pod 进行“至多”保证,则应考虑使用 StatefulSet。滚动更新 Deployment
当 .spec.strategy.type==RollingUpdate
时,Deployment 以滚动更新的方式更新 Pod。您可以指定 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 何时被视为就绪的更多信息,请参阅 容器探针。
修订历史限制
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。