Deployment Controller详解(上)

上一篇在《Kubectl 部署无状态应用》中介绍了如何使用 Deployment 部署五个 hello world 实例时,我们并没有详细探讨 Deployment Controller 的各项功能。因此,本文将深入介绍 Deployment Controller 的作用以及它能够完成的任务。

本文来自官方文档梳理:https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

1. 什么是 Deployment?

Deployment 为 Pod 和 Replica Set(下一代 Replication Controller)提供声明式更新。

只需要在 Deployment 中描述您想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和 ReplicaSet 的实际状态改变到您的目标状态。您可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。

  • 定义 Deployment 来创建 Pod 和 ReplicaSet
  • 滚动升级和回滚应用
  • 扩容和缩容
  • 暂停和继续 Deployment

写到这,想起当年在某节打工时的一个场景:研发上线时,可以选择是否对当前服务进行扩缩容、按照比例对服务进行灰度、回滚服务等等。

是的,这一系列的功能,背后就是Deployment Controller在起作用。

创建Deployment

上一篇中使用了官方提供的node example例子。在本文中,此次将使用nginx镜像进行演示。

以下是部署的示例。它创建一个 ReplicaSet 来启动三个nginxPod:

vim nginx-deployment.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
  1. 执行:
kubectl apply -f nginx-deployment.yaml
  1. 查看Deployment 是否已创建:
kubectl get deployments
------
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment      3/3     3            3           2m2s
  1. 要查看Deployment 创建的ReplicaSet,可以运行:
kubectl get rs
------
NAME                            DESIRED   CURRENT   READY   AGE
nginx-deployment-86dcfdf4c6     3         3         3       4m10s
  1. 要查看为每个 Pod 自动生成的标签,可以运行:
kubectl get pods --show-labels
------
NAME                                  READY   STATUS    RESTARTS   AGE     LABELS
nginx-deployment-86dcfdf4c6-2tdlj     1/1     Running   0          6m19s   app=nginx,pod-template-hash=86dcfdf4c6
nginx-deployment-86dcfdf4c6-jqs52     1/1     Running   0          6m19s   app=nginx,pod-template-hash=86dcfdf4c6
nginx-deployment-86dcfdf4c6-vhpsv     1/1     Running   0          6m19s   app=nginx,pod-template-hash=86dcfdf4c6

2. 更新部署

注意:当且仅当 Deployment 的 Pod 模板(即.spec.template)发生更改(例如,模板的标签或容器映像更新)时,才会触发 Deployment 的推出。其他更新(例如扩展部署)不会触发部署。

  1. 将nginx Pod 从nginx:1.14.2更新成nginx:1.16.1
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1

或者使用kubectl edit deployment/nginx-deployment来对文件手动进行更改。

  1. 查看部署状态

运行kubectl get rs可以看到 Deployment 通过创建新的 ReplicaSet 并将其扩展到 3 个副本,以及将旧的 ReplicaSet 缩减到 0 个副本来更新 Pod。

输出类似于:

NAME                            DESIRED   CURRENT   READY   AGE
nginx-deployment-848dd6cfb5     3         3         3       3m10s
nginx-deployment-86dcfdf4c6     0         0         0       12m
  • 下次想要更新这些Pod时,只需再次更新Deployment的Pod模板即可。
  • 部署可确保更新时只有一定数量的 Pod 处于关闭状态。默认情况下,它确保至少有 75% 的所需 Pod 数量处于运行状态(最多 25% 不可用)。
  • 部署还确保仅创建高于所需 Pod 数量的一定数量的 Pod。默认情况下,它确保最多 125% 的所需 Pod 数量处于启动状态(最大激增 25%)。
  • 例如,如果你仔细观察上面的 Deployment,你会发现它首先创建了一个新的 Pod,然后删除了一个旧的 Pod,并创建了另一个新的 Pod。在出现足够数量的新 Pod 之前,它不会杀死旧 Pod;并且在杀死足够数量的旧 Pod 之前,它不会创建新 Pod。它确保至少有 3 个 Pod 可用,并且总共最多有 4 个 Pod 可用。如果部署有 4 个副本,Pod 的数量将在 3 到 5 之间。
  1. 查看部署详细信息

kubectl describe deployments

Deployment Controller详解(上)_第1张图片
这里可以看到,当第一次创建Deployment时,它创建了一个ReplicaSet(nginx-deployment-86dcfdf4c6),并直接将其扩展到3个副本。当更新 Deployment 时,它创建了一个新的 ReplicaSet (nginx-deployment-848dd6cfb5) 并将其扩展到 1 并等待它出现。然后将旧的 ReplicaSet 缩小到 2 个,将新的 ReplicaSet 扩大到 2 个,这样每次都至少有 3 个 Pod 可用,最多创建 4 个 Pod。然后,它使用相同的滚动更新策略继续扩展和缩小新旧 ReplicaSet。最后,新的 ReplicaSet 中将有 3 个可用副本,而旧的 ReplicaSet 会缩小到 0。

3. 回滚部署

假设在更新部署时犯了拼写错误,将nginx:1.16.1写成了nginx:1.161

kubectl set image deployment/nginx-deployment nginx=nginx:1.161

执行kubectl rollout status deployment/nginx-deployment来验证执行过程。

此时,可以 Ctrl-C 停止掉,执行kubectl get rs
Deployment Controller详解(上)_第2张图片
查看创建的 Pod,您会发现新 ReplicaSet 创建的 1 个 Pod 陷入了镜像拉取循环。

kubectl get pods

Deployment Controller详解(上)_第3张图片

注意:部署控制器会自动停止错误的部署,并停止扩展新的副本集。这取决于maxUnavailable指定的rollingUpdate 参数。Kubernetes 默认将该值设置为 25%。

要解决此问题,您需要回滚到之前稳定的 Deployment 版本。

1. 首先,检查此 Deployment 的历史修订
kubectl rollout history deployment/nginx-deployment

Deployment Controller详解(上)_第4张图片
CHANGE-CAUSE在创建时,从部署注释复制kubernetes.io/change-cause到其修订版本。此处,本文并没有进行注释,因此CHANGE-CAUSE显示none。

CHANGE-CAUSE可以通过使用注释部署方式指定消息:

kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1"
2. 查看每个修订的详细信息
kubectl rollout history deployment/nginx-deployment --revision=2
3. 回滚到以前的修订

撤消当前的修改并回滚到以前的修订版

kubectl rollout undo deployment/nginx-deployment

或者

kubectl rollout undo deployment/nginx-deployment --to-revision=2

再次执行kubectl get deployment nginx-deployment查看是否回滚。

你可能感兴趣的:(kubernetes,kubernetes,云原生)