在 Kubernetes 中,Deployment 是一种控制器(Controller),用于管理一组 Pod 的创建和扩展。它提供了一种声明性的方式来描述应用的期望状态,并确保这些状态被维护。Deployment 控制器会监视你的应用副本数量、健康状态等,并根据需要调整 Pod 的数量。
一个 Deployment 为 Pod 和 ReplicaSet 提供声明式的更新能力。
一、Deployment 对象详解
一个 Deployment 对象包含以下主要字段:
-
apiVersion : 指定 API 的版本,通常是
apps/v1。 -
kind : 指定 Kubernetes 对象的类型,这里是
Deployment。 -
metadata: 包含对象的元数据,如名称、命名空间等。
-
spec: 描述 Deployment 的期望状态,包括:
- replicas: 期望的 Pod 副本数量。
- selector: 用于选择 Pod 的标签选择器。
- template: 定义 Pod 的模板,包括容器定义、卷、环境变量等。
- strategy : 定义更新策略,如滚动更新(
RollingUpdate)或重新创建(Recreate)。 - minReadySeconds: Pod 准备就绪前的秒数。
- revisionHistoryLimit: 保留的历史版本数。
示例
下面是一个简单的 Deployment 示例,它创建了一个运行 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.17.8
ports:
- containerPort: 80
主要操作命令
-
创建 Deployment:
kubectl apply -f deployment.yaml -
查看 Deployment 状态:
kubectl get deployments -
查看 Deployment 的详细信息:
kubectl describe deployment <deployment-name> -
更新 Deployment (例如,更改镜像版本):
kubectl set image deployment/<deployment-name> nginx=nginx:1.18.0或者使用
kubectl edit deployment <deployment-name>直接编辑文件。 -
缩放 Deployment (例如,增加副本数):
kubectl scale deployment <deployment-name> --replicas=5 -
删除 Deployment:
kubectl delete deployment <deployment-name>
进阶使用和最佳实践
- 使用 ConfigMap 和 Secrets: 可以将配置信息和敏感信息从 Deployment 中分离出来,使用 ConfigMap 和 Secrets 管理。
- 滚动更新和回滚: 使用 Deployment 可以轻松地实现应用的零停机更新,并通过回滚到旧版本快速恢复服务。
- 健康检查: 在 Pod 模板中配置 readinessProbe 和 livenessProbe,确保只有健康的 Pod 被服务流量访问。
- 资源限制: 通过设置容器的资源请求(requests)和限制(limits),确保应用不会消耗过多资源,影响集群稳定性。
- 标签和选择器: 合理使用标签和选择器可以更灵活地管理资源和服务。
二、更新 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 执行
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
获取关于已更新的 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。默认情况下,它确保至少所需 Pod 的 75% 处于运行状态(最大不可用比例为 25%)。
Deployment 还确保仅所创建 Pod 数量只可能比期望 Pod 数高一点点。 默认情况下,它可确保启动的 Pod 个数比期望个数最多多出 125%(最大峰值 25%)。
例如,如果仔细查看上述 Deployment ,将看到它首先创建了一个新的 Pod,然后删除旧的 Pod, 并创建了新的 Pod。它不会杀死旧 Pod,直到有足够数量的新 Pod 已经出现。 在足够数量的旧 Pod 被杀死前并没有创建新 Pod。它确保至少 3 个 Pod 可用, 同时最多总共 4 个 Pod 可用。 当 Deployment 设置为 4 个副本时,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 中,旧 ReplicaSet 将缩容到 0。
说明:
Kubernetes 在计算 availableReplicas 数值时不考虑终止过程中的 Pod, availableReplicas 的值一定介于 replicas - maxUnavailable 和 replicas + maxSurge 之间。 因此,你可能在上线期间看到 Pod 个数比预期的多,Deployment 所消耗的总的资源也大于 replicas + maxSurge 个 Pod 所用的资源,直到被终止的 Pod 所设置的 terminationGracePeriodSeconds 到期为止。
翻转(多 Deployment 动态更新)
Deployment 控制器每次注意到新的 Deployment 时,都会创建一个 ReplicaSet 以启动所需的 Pod。 如果更新了 Deployment,则控制标签匹配 .spec.selector 但模板不匹配 .spec.template 的 Pod 的现有 ReplicaSet 被缩容。 最终,新的 ReplicaSet 缩放为 .spec.replicas 个副本, 所有旧 ReplicaSet 缩放为 0 个副本。
当 Deployment 正在上线时被更新,Deployment 会针对更新创建一个新的 ReplicaSet 并开始对其扩容,之前正在被扩容的 ReplicaSet 会被翻转,添加到旧 ReplicaSet 列表并开始缩容。
例如,假定你在创建一个 Deployment 以生成 nginx:1.14.2 的 5 个副本,但接下来更新 Deployment 以创建 5 个 nginx:1.16.1 的副本,而此时只有 3 个 nginx:1.14.2 副本已创建。在这种情况下,Deployment 会立即开始杀死 3 个 nginx:1.14.2 Pod, 并开始创建 nginx:1.16.1 Pod。它不会等待 nginx:1.14.2 的 5 个副本都创建完成后才开始执行变更动作。
更改标签选择算符
Deployment 的标签选择算符在创建后不可更改 ; 它无法通过 kubectl patch、kubectl edit、kubectl apply 或 helm upgrade 等工具进行更新。
如果必须更改选择算符,则必须删除 Deployment 并重新创建。 你务必要谨慎操作,并确保自己理解以下潜在影响:
- 新增内容: 当你使用条件更苛刻的选择算符创建新的 Deployment 时,新 Deployment 必须 拥有合适的 Pod 模板。 如果你已有清单文件,并对其进行编辑以缩小选择算符的范围,则需要编辑该 Deployment 中 Pod 模板的元数据,添加新的标签以与之匹配,否则 API 服务器将返回验证错误。 将被执行的变更是一个非覆盖性质 的变更:新的 Deployment 将无法"看到"旧的 Pod(缺少新标签),导致旧的 ReplicaSet 被孤立,与此同时一个全新的 ReplicaSet 会被创建。
- 值更新: 更改选择算符中某些键的现有值(例如,从
v1到v2)会导致与添加相同的行为(孤立加上重新创建)。 - 移除操作: 从 Deployment 选择算符中移除已有的键时不需要更改 Pod 模板标签。 这类变更是覆盖性质的:新的、范围更广的选择算符将匹配旧的 Pod。 现有的 ReplicaSet 不会被孤立,也不会创建新的 ReplicaSet, 但请注意,已移除的标签仍然存在于任何现有的 Pod 和 ReplicaSet 中。 你可以通过触发 Deployment 的滚动更新来清理这些标签。