部署
部署为Pod和ReplicaSets提供声明式更新。
您在部署中描述一个期望状态,然后部署控制器以受控速率将实际状态更改为期望状态。您可以定义部署来创建新的 ReplicaSets,或者删除现有部署并使用新的部署采用其所有资源。
注意
不要管理由部署拥有的 ReplicaSets。如果您使用案例不在下面列出,请考虑在主 Kubernetes 存储库中打开一个问题。用例
以下是部署的典型用例
- 创建部署以推出 ReplicaSet。ReplicaSet 在后台创建 Pod。检查推出状态以查看其是否成功。
- 声明 Pod 的新状态,方法是更新部署的 PodTemplateSpec。将创建一个新的 ReplicaSet,并且部署将以受控速率管理将 Pod 从旧 ReplicaSet 移动到新 ReplicaSet。每个新的 ReplicaSet 都会更新部署的版本。
- 回滚到更早的部署版本,如果部署的当前状态不稳定。每次回滚都会更新部署的版本。
- 扩展部署以容纳更多负载.
- 暂停部署的推出以将多个修复应用于其 PodTemplateSpec,然后恢复它以开始新的推出。
- 使用部署的状态作为推出卡住的指标。
- 清理不再需要的旧 ReplicaSets。
创建部署
以下是一个部署的示例。它创建了一个 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
的部署,由.metadata.name
字段指示。此名称将成为稍后创建的 ReplicaSets 和 Pods 的基础。有关更多详细信息,请参阅编写部署规范。部署创建了一个 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
字段包含以下子字段- Pod 使用
.metadata.labels
字段标记为app: nginx
。 - Pod 模板的规范或
.template.spec
字段表明 Pod 运行一个容器nginx
,它运行nginx
Docker Hub 镜像版本 1.14.2。 - 使用
.spec.template.spec.containers[0].name
字段创建一个容器并将其命名为nginx
。
- Pod 使用
在开始之前,请确保您的 Kubernetes 集群已启动并正在运行。按照以下步骤创建上述部署
通过运行以下命令创建部署
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
运行
kubectl get deployments
以检查是否已创建部署。如果部署仍在创建中,则输出类似于以下内容
NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 0/3 0 0 1s
当您检查集群中的部署时,将显示以下字段
NAME
列出命名空间中的部署名称。READY
显示应用程序有多少个副本可供用户使用。它遵循以下模式:ready/desired。UP-TO-DATE
显示已更新以实现期望状态的副本数量。AVAILABLE
显示应用程序有多少个副本可供用户使用。AGE
显示应用程序运行的时间量。
请注意,根据
.spec.replicas
字段,期望的副本数为 3。要查看部署推出状态,请运行
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
请注意,部署已创建所有三个副本,并且所有副本均为最新(它们包含最新的 Pod 模板)且可用。
要查看部署创建的 ReplicaSet(
rs
),请运行kubectl get rs
。输出类似于以下内容NAME DESIRED CURRENT READY AGE nginx-deployment-75675f5897 3 3 3 18s
ReplicaSet 输出显示以下字段
NAME
列出命名空间中的 ReplicaSet 名称。DESIRED
显示应用程序的期望副本数,您在创建部署时定义了该数字。这是期望状态。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。
注意
您必须在部署中指定适当的选择器和 Pod 模板标签(在本例中为app: nginx
)。
不要将标签或选择器与其他控制器(包括其他部署和 StatefulSets)重叠。Kubernetes 不会阻止您重叠,如果多个控制器具有重叠的选择器,则这些控制器可能会发生冲突并产生意外的行为。
pod-template-hash 标签
注意
不要更改此标签。pod-template-hash
标签由部署控制器添加到部署创建或采用的每个 ReplicaSet。
此标签可确保部署的子 ReplicaSet 不重叠。它是通过对 ReplicaSet 的PodTemplate
进行哈希处理并使用生成的哈希值作为添加到 ReplicaSet 选择器、Pod 模板标签以及 ReplicaSet 可能拥有的任何现有 Pod 中的标签值来生成的。
更新部署
注意
只有当部署的 Pod 模板(即.spec.template
)发生更改时,例如更新模板的标签或容器镜像时,才会触发部署的推出。其他更新(例如扩展部署)不会触发推出。按照以下步骤更新您的部署
让我们将 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
表示部署,nginx
表示将进行更新的容器,而nginx:1.16.1
表示新镜像及其标签。输出类似于
deployment.apps/nginx-deployment image updated
或者,您可以
edit
部署并将.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
获取有关更新的部署的更多详细信息
推出成功后,您可以通过运行
kubectl get deployments
来查看部署。输出类似于以下内容NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 36s
运行
kubectl get rs
以查看部署通过创建新的 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 时,您只需要再次更新部署的 Pod 模板。
部署确保在更新 Pod 时,只有特定数量的 Pod 处于停机状态。默认情况下,它确保至少有 75% 的期望 Pod 数处于启动状态(最多 25% 不可用)。
部署还确保创建的 Pod 数不超过期望的 Pod 数的特定数量。默认情况下,它确保最多有 125% 的期望 Pod 数处于启动状态(最多 25% 飙升)。
例如,如果您仔细查看上面的部署,您会看到它首先创建一个新的 Pod,然后删除一个旧的 Pod,然后创建另一个新的 Pod。它不会在足够数量的新 Pod 启动之前杀死旧的 Pod,也不会在足够数量的旧 Pod 被杀死之前创建新的 Pod。它确保至少有 3 个 Pod 可用,并且最多有 4 个 Pod 可用。对于具有 4 个副本的部署,Pod 的数量将在 3 到 5 之间。
获取有关部署的详细信息
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
您会看到,当您首次创建部署时,它会直接创建一个副本集(nginx-deployment-2035384211)并将其扩展到 3 个副本。当您更新部署时,它会创建一个新的副本集(nginx-deployment-1564180365)并将其扩展到 1 个副本,并等待它启动。然后,它将旧的副本集缩减到 2 个副本,并将新的副本集扩展到 2 个副本,以便始终至少有 3 个 Pod 可用,并且最多创建 4 个 Pod。然后,它继续使用相同的滚动更新策略,对新的和旧的副本集进行扩展和缩减。最后,新的副本集中将有 3 个可用副本,旧的副本集将缩减到 0 个副本。
注意
Kubernetes 在计算availableReplicas
的数量时不计算正在终止的 Pod,该数量必须介于 replicas - maxUnavailable
和 replicas + maxSurge
之间。因此,您可能会注意到在部署过程中 Pod 的数量超出了预期,并且部署所消耗的总资源超过了 replicas + maxSurge
,直到正在终止的 Pod 的 terminationGracePeriodSeconds
过期。回滚(也称为多个更新正在进行中)
每次部署控制器观察到新的部署时,都会创建一个副本集来启动所需的 Pod。如果部署被更新,则控制与 .spec.selector
匹配的标签但模板不匹配 .spec.template
的 Pod 的现有副本集将被缩减。最终,新的副本集将扩展到 .spec.replicas
,所有旧的副本集都将缩减到 0。
如果您在现有的部署正在进行时更新部署,则部署会根据更新创建一个新的副本集,并开始将其扩展,然后将之前正在扩展的副本集回滚 - 它会将该副本集添加到其旧副本集列表中,并开始将其缩减。
例如,假设您创建了一个部署来创建 5 个 nginx:1.14.2
的副本,但随后更新了部署来创建 5 个 nginx:1.16.1
的副本,而当时只创建了 3 个 nginx:1.14.2
的副本。在这种情况下,部署会立即开始终止它已创建的 3 个 nginx:1.14.2
Pod,并开始创建 nginx:1.16.1
Pod。它不会等到 5 个 nginx:1.14.2
的副本创建完毕才改变方向。
标签选择器更新
通常不建议进行标签选择器更新,建议您提前规划您的选择器。无论如何,如果您需要执行标签选择器更新,请格外小心,并确保您已了解所有影响。
注意
在 API 版本apps/v1
中,部署的标签选择器在创建后将不可变。- 选择器添加需要更新部署规范中的 Pod 模板标签,其中包含新标签,否则会返回验证错误。此更改是非重叠更改,这意味着新的选择器不会选择使用旧选择器创建的副本集和 Pod,这会导致所有旧的副本集成为孤儿,并创建一个新的副本集。
- 选择器更新会更改选择器键中的现有值 - 导致与添加相同的行为。
- 选择器删除会从部署选择器中删除现有键 - 不需要对 Pod 模板标签进行任何更改。现有的副本集不会成为孤儿,并且不会创建新的副本集,但请注意,删除的标签仍然存在于任何现有的 Pod 和副本集中。
回滚部署
有时,您可能希望回滚部署;例如,当部署不稳定时,例如循环崩溃。默认情况下,所有部署的回滚历史记录都保存在系统中,以便您可以随时回滚(您可以通过修改修订历史记录限制来更改此设置)。
注意
当部署的回滚被触发时,会创建部署的修订版。这意味着只有在部署的 Pod 模板(.spec.template
)发生更改时才会创建新的修订版,例如,如果您更新了模板的标签或容器映像。其他更新(例如扩展部署)不会创建部署修订版,以便您可以同时进行手动或自动扩展。这意味着,当您回滚到早期修订版时,只有部署的 Pod 模板部分会被回滚。假设您在更新部署时输入了错误,将映像名称设置为
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,您会看到由新的副本集创建的 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
注意
部署控制器会自动停止错误的回滚,并停止扩展新的副本集。这取决于您指定的滚动更新参数(具体而言是maxUnavailable
)。Kubernetes 默认情况下将该值设置为 25%。获取部署的描述
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
要解决此问题,您需要回滚到部署的先前稳定修订版。
检查部署的回滚历史记录
按照以下步骤检查回滚历史记录
首先,检查此部署的修订版
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
从部署注释kubernetes.io/change-cause
复制到其创建时的修订版。您可以通过以下方式指定CHANGE-CAUSE
消息- 使用
kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1"
为部署添加注释 - 手动编辑资源的清单。
- 使用
要查看每个修订版的详细信息,请运行
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.
回滚到先前修订版
按照以下步骤将部署从当前版本回滚到先前版本,即版本 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
。部署现在已回滚到先前的稳定修订版。如您所见,从部署控制器生成了一个
DeploymentRollback
事件,用于回滚到修订版 2。检查回滚是否成功,并且部署按预期运行,请运行
kubectl get deployment nginx-deployment
输出类似于以下内容
NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 30m
获取部署的描述
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
扩展部署
您可以使用以下命令扩展部署
kubectl scale deployment/nginx-deployment --replicas=10
输出类似于以下内容
deployment.apps/nginx-deployment scaled
假设 水平 Pod 自动扩展 在您的集群中启用,您可以为您的部署设置自动扩展器,并根据现有 Pod 的 CPU 使用率选择要运行的 Pod 的最小和最大数量。
kubectl autoscale deployment/nginx-deployment --min=10 --max=15 --cpu-percent=80
输出类似于以下内容
deployment.apps/nginx-deployment scaled
比例扩展
滚动更新部署支持同时运行应用程序的多个版本。当您或自动扩展器扩展正在进行回滚(正在进行中或已暂停)的滚动更新部署时,部署控制器会在现有活动副本集(具有 Pod 的副本集)中平衡额外的副本,以降低风险。这称为“比例扩展”。
例如,您正在运行一个具有 10 个副本的部署,maxSurge=3,maxUnavailable=2。
确保部署中的 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
映像更新使用副本集 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
然后,部署的新的扩展请求出现了。自动扩展器将部署的副本增加到 15 个。部署控制器需要决定在何处添加这 5 个新副本。如果您没有使用比例扩展,则所有 5 个副本都将被添加到新的副本集中。使用比例扩展,您会在所有副本集中分布额外的副本。更大的比例分配给具有最多副本的副本集,更小的比例分配给具有较少副本的副本集。任何剩余部分都会被添加到具有最多副本的副本集。具有零个副本的副本集不会被扩展。
在上面的示例中,3 个副本被添加到旧的副本集中,2 个副本被添加到新的副本集中。回滚过程最终应该将所有副本移动到新的副本集中,假设新副本变得健康。要确认这一点,请运行
kubectl get deploy
输出类似于以下内容
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
回滚状态确认了如何将副本添加到每个副本集中。
kubectl get rs
输出类似于以下内容
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
暂停和恢复部署的回滚
当您更新部署或计划更新部署时,您可以在触发一个或多个更新之前暂停该部署的回滚。当您准备好应用这些更改时,您可以恢复该部署的回滚。此方法允许您在暂停和恢复之间应用多个修复程序,而不会触发不必要的回滚。
例如,对于使用以下命令创建的部署
获取部署详细信息
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
然后更新部署的映像
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>
获取回滚状态以验证现有的副本集是否未更改
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
在暂停其回滚之前,部署的初始状态将继续其功能,但只要部署回滚处于暂停状态,对部署的新更新将不会有任何影响。
最终,恢复部署回滚,并观察具有所有新更新的新副本集出现
kubectl rollout resume deployment/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
注意
在恢复暂停的部署之前,您无法回滚它。部署状态
部署在其生命周期中会进入各种状态。它可以 正在进行 回滚新的副本集,它可以 完成,或者它可以 无法进行。
正在进行的部署
当执行以下任一任务时,Kubernetes 会将部署标记为“正在进行”
- 部署创建新的副本集。
- 部署正在扩展其最新的副本集。
- 部署正在缩减其旧的副本集。
- 新的 Pod 变得就绪或可用(至少就绪 MinReadySeconds)。
当回滚变为“正在进行”时,部署控制器会向部署的 .status.conditions
中添加一个具有以下属性的条件
type: Progressing
status: "True"
reason: NewReplicaSetCreated
|reason: FoundNewReplicaSet
|reason: ReplicaSetUpdated
您可以使用 kubectl rollout status
监控部署的进度。
完成的部署
当部署具有以下特征时,Kubernetes 会将部署标记为“完成”
- 与部署相关的所有副本都已更新到您指定的最新版本,这意味着您请求的任何更新都已完成。
- 与部署相关的所有副本都可用。
- 部署的任何旧副本都不在运行。
当回滚变为“完成”时,部署控制器会向部署的 .status.conditions
中设置一个具有以下属性的条件
type: Progressing
status: "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 spec 中指定截止日期参数来检测此条件:(.spec.progressDeadlineSeconds
)。.spec.progressDeadlineSeconds
表示 Deployment 控制器在指示 (在 Deployment 状态中) Deployment 进度已停滞之前等待的秒数。
以下 kubectl
命令将使用 progressDeadlineSeconds
设置 spec,以便控制器在 Deployment 的 rollout 10 分钟后报告缺乏进度。
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 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
type: Available
与 status: "True"
表示您的 Deployment 具有最低可用性。最低可用性由部署策略中指定的参数决定。type: Progressing
与 status: "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 模板还必须指定适当的标签和适当的重启策略。对于标签,请确保不要与其他控制器重叠。请参阅 selector。
仅允许 .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
是不可变的。
如果 Deployment 的模板与 .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 仍处于 Terminating 状态)。如果您需要对 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 的总数不会超过所需 Pod 的 130%。一旦旧的 Pod 被杀死,新的 ReplicaSet 可以进一步扩展,确保在更新期间任何时候运行的 Pod 的总数最多为所需 Pod 的 130%。
以下是一些使用 maxUnavailable
和 maxSurge
的滚动更新部署示例
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 处于暂停状态,对暂停的 Deployment 的 PodTemplateSpec 的任何更改都不会触发新的推出。Deployment 在创建时默认不处于暂停状态。
下一步
- 了解有关 Pod 的更多信息。
- 使用 Deployment 运行无状态应用程序.
- 阅读 Deployment 以了解 Deployment API。
- 阅读有关 Pod 中断预算 的信息,以及如何使用它在中断期间管理应用程序可用性。
- 使用 kubectl 创建 Deployment。