Deployment 为 Pod 和 ReplicaSet 提供了一个声明式的方法来管理应用。以下是典型的应用场景:
定义 Deployment 来创建 Pod 和 ReplicaSet
:通过 Deployment 对象可以定义 Pod 的模板和所需的副本数量。Kubernetes 会根据这些配置创建相应数量的 Pod,并通过 ReplicaSet 进行管理,确保指定数量的副本在运行。`
滚动升级和回滚应用
:Deployment 支持滚动升级和回滚应用的功能。你可以通过更新 Deployment 的配置来实现应用程序的升级,Kubernetes 会逐步创建新的 Pod 副本并逐步停止旧的副本,从而实现无缝的应用程序升级。如果升级出现问题,你也可以轻松地回滚到之前的版本。`
扩容和缩容
:通过更新 Deployment 的副本数量,可以实现扩容和缩容。Kubernetes 会根据你指定的副本数量自动启动或停止相应数量的 Pod。`
暂停和继续 Deployment:
Deployment 还支持暂停和继续操作。你可以暂停 Deployment,暂停后,Kubernetes 将停止创建新的 Pod 副本。当你需要进行维护或者排查问题时,这是非常有用的。暂停后,你也可以随时继续 Deployment,Kubernetes 会根据之前的配置继续创建新的 Pod 副本。`
比如一个简单的 nginx 应用可以定义为:
yaml
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
- 扩容:
css
kubectl scale deployment nginx-deployment --replicas 10
- 如果集群支持 horizontal pod autoscaling 的话,还可以为 Deployment 设置自动扩展:
css
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
- 更新镜像也比较简单:
arduino
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
- 回滚:
bash
kubectl rollout undo deployment/nginx-deployment
创建 Deployment
首先,我们需要下载一个示例文件并执行一些命令。你只需要在终端输入这个命令:
ruby
$ kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
执行完之后,你会看到一个提示,告诉你 Deployment "nginx-deployment" 已经创建成功了。
嗯,现在让我们执行一条 get 命令,看看有什么结果呢?
arduino
$ kubectl get deployments
我们希望有 3 个 replica(也就是 Pod 的副本),但是当前还没有创建任何副本。所以它显示的 Desired 是 3,而 Current、Up-to-date 和 Available 都是 0。
但是再过几秒钟,我们再执行 get 命令看看会发生什么:
arduino
$ kubectl get deployments
现在的结果Deployment 已经创建了 3 个 replica,Desired、Current、Up-to-date 和 Available 都变成了 3。这意味着我们成功地创建了 3 个最新版本的 Pod。
ReplicaSet 输出中包含以下字段:
NAME
列出名字空间中 ReplicaSet 的名称;DESIRED
显示应用的期望副本个数,即在创建 Deployment 时所定义的值。 此为期望状态;CURRENT
显示当前运行状态中的副本个数;READY
显示应用中有多少副本可以为用户提供服务;AGE
显示应用已经运行的时间长度。
注意 ReplicaSet 的名称格式始终为 [Deployment 名称]-[哈希]
。 该名称将成为所创建的 Pod 的命名基础。 其中的哈希
字符串与 ReplicaSet 上的 pod-template-hash
标签一致。
如果你还想了解更多信息,可以使用 kubectl get rs 命令查看 ReplicaSet 的情况,或者使用 kubectl get pods 命令查看 Pod 的情况。这样你就能看到 Replica Set 和 Pod 都已经成功创建!
要查看每个 Pod 自动生成的标签,运行 kubectl get pods --show-labels
。 输出类似于:
更新 Deployment
说明:
仅当 Deployment Pod 模板(即
.spec.template
)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。
可以通过以下两种方式之一来完成。
- 方法一:使用
kubectl set image
命令直接更新Deployment的容器镜像。
arduino
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
或者可以使用下面的命令:
arduino
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的容器镜像。
- 方法二:使用
kubectl edit
命令编辑Deployment的配置文件执行更新操作。
bash
kubectl edit deployment/nginx-deployment
执行上述命令后,将打开一个文本编辑器,允许您手动修改Deployment的配置。在编辑器中,将.spec.template.spec.containers[0].image
从nginx:1.14.2
更改为nginx:1.16.1
,然后保存并退出编辑器。
获取关于已更新的 Deployment 的更多信息: 在上线成功后,可以通过运行 kubectl get deployments
来查看 Deployment: 输出类似于:
vbnet
➜ ~ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 18m
➜ ~
- 运行
kubectl get rs
以查看 Deployment 通过创建新的 ReplicaSet 并将其扩容到 3 个副本并将旧 ReplicaSet 缩容到 0 个副本完成了 Pod 的更新操作:
arduino
kubectl get rs
sql
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 3 6s
nginx-deployment-2035384211 0 0 0 36s
- 现在运行
get pods
应仅显示新的 Pod:
arduino
kubectl get pods
输出类似于:
sql
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 的更多信息
vbnet
kubectl describe deployments
➜ ~ kubectl describe deployments
Name: nginx-deployment
Namespace: default
CreationTimestamp: Wed, 18 Oct 2023 22:22:07 +0800
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
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: nginx-deployment-cbdccf466 (0/0 replicas created)
NewReplicaSet: nginx-deployment-74b6b979f (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 20m deployment-controller Scaled up replica set nginx-deployment-cbdccf466 to 3
Normal ScalingReplicaSet 9m20s deployment-controller Scaled up replica set nginx-deployment-74b6b979f to 1
Normal ScalingReplicaSet 9m4s deployment-controller Scaled down replica set nginx-deployment-cbdccf466 to 2 from 3
Normal ScalingReplicaSet 9m4s deployment-controller Scaled up replica set nginx-deployment-74b6b979f to 2 from 1
Normal ScalingReplicaSet 8m55s deployment-controller Scaled down replica set nginx-deployment-cbdccf466 to 1 from 2
Normal ScalingReplicaSet 8m55s deployment-controller Scaled up replica set nginx-deployment-74b6b979f to 3 from 2
Normal ScalingReplicaSet 8m41s deployment-controller Scaled down replica set nginx-deployment-cbdccf466 to 0 from 1
回滚 Deployment
通过回滚 Deployment 来还原到先前的状态。默认情况下,系统会保留 Deployment 的所有上线记录,以便可以随时回滚到先前的版本。
可以使用以下命令来回滚 Deployment:
bash
kubectl rollout undo deployment/nginx-deployment
上述命令将会将 Deployment 回滚到先前的版本,即回到上一个修订版本。这将触发新的滚动过程,将 Deployment 恢复到先前的状态。执行命令后,会输出类似于 "deployment.apps/nginx-deployment rolled back" 的消息,表示回滚成功。
可以使用以下命令来查看 Deployment 的滚动历史记录:
bash
kubectl rollout history deployment/nginx-deployment
输出类似于:
bash
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 添加注解。
- 手动编辑资源的清单。
上述命令将显示 Deployment 的所有修订版本以及其相关信息,包括修订版本号、回滚到该版本的命令、修订的部署时间等。最新的修订版本显示在列表的顶部。
如果您想要回滚到特定的修订版本,可以使用以下命令:
ini
kubectl rollout undo deployment/nginx-deployment --to-revision=<revision>
Deployment 状态
将 <revision>
替换为您想要回滚到的修订版本号。执行命令后,将触发新的滚动过程,将 Deployment 恢复到指定版本。
进行中的 Deployment
在Deployment的生命周期中,它可能会经历多种状态。当你上线一个新的ReplicaSet时,Deployment可能处于"进行中"(Progressing)状态,也可能是"已完成"(Complete)状态,甚至可能是"失败"(Failed)状态,无法继续进行下去。
首先,让我们来看看"进行中"(Progressing)状态。
当Deployment创建一个新的ReplicaSet、正在扩容最新的ReplicaSet,或者正在减少旧有的ReplicaSet时,Kubernetes会将Deployment标记为"进行中"状态。当新的Pod已经准备就绪或可用(至少经过了MinReadySeconds秒)时,进程将被标记为进行中。当部署进入"进行中"状态时,Deployment控制器会在Deployment的.status.conditions中添加一个包含以下属性的条件条目:
yaml
type: Progressing
status: "True"
reason: NewReplicaSetCreated | reason: FoundNewReplicaSet | reason: ReplicaSetUpdated
如果你想监视Deployment的进度,可以使用kubectl rollout status命令。
完成的 Deployment
接下来是"已完成"(Complete)状态。当Deployment满足以下条件时,Kubernetes将其标记为"已完成"状态:
与Deployment关联的所有副本已更新到指定的最新版本,这意味着之前请求的所有更新都已完成。
与Deployment关联的所有副本都可用。
旧的副本已被删除,不再运行。
当部署进入"已完成"状态时,Deployment控制器会在Deployment的.status.conditions中添加一个包含以下属性的条件条目:
vbnet
type: Progressing
status: "True"
reason: NewReplicaSetAvailable
Progressing条件的状态值将持续为"True",直到触发新的上线操作。即使副本的可用状态发生变化(从而影响到Available条件),Progressing条件的值也不会改变。
失败的 Deployment
你的 Deployment 可能会在尝试部署其最新的 ReplicaSet 受挫,一直处于未完成状态。 造成此情况一些可能因素如下:
- 配额(Quota)不足
- 就绪探测(Readiness Probe)失败
- 镜像拉取错误
- 权限不足
- 限制范围(Limit Ranges)问题
- 应用程序运行时的配置错误
为了及时检测并解决这种情况,我们可以在部署规约中设置一个截止时间参数,告诉控制器,在指定的时间之后如果还没有进展,就需要报告部署失败了。比如可以使用以下命令设置截止时间为10分钟:
css
kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
当截止时间到达后,控制器会在部署的状态中添加一个属性,告诉我们部署进展是否停滞了:
vbnet
type: Progressing
status: "False"
reason: ProgressDeadlineExceeded