15. Pod 自动管理——Deployment
本章讲解知识点
- 前言
- ReplicaSet 和 Deployment
- Deployment 的升级
- Deployment 的回滚
<br>
1. 前言
通过前面对 Pod 的由浅入深的了解后,我们知道了 Kubernetes 中最小的部署单元就是 Pod,Pod 确实也很方便,配置一些参数就能够有很多强大的功能,如探针检查、preStop 等。
Pod 这个看似复杂的 API 对象,实际上就是对容器的进一步抽象和封装而已。说得更形象些,“容器”镜像虽然好用,但是容器这样一个“沙盒”的概念,对于描述应用来说,还是太过简单了。这就好比,集装箱固然好用,但是如果它四面都光秃秃的,吊车还怎么把这个集装箱吊起来并摆放好呢?所以,Pod 对象,其实就是容器的升级版。它对容器进行了组合,添加了更多的属性和字段。这就好比给集装箱四面安装了吊环,使得 Kubernetes 这架“吊车”,可以更轻松地操作它。
但是我们感觉好像还是哪里不得劲,那 Pod 扩缩容如何搞,要一个一个手动创建新 Pod?升级又如何弄,要一个一个修改 Pod 镜像?
那样可就太麻烦了。所以本章就是要回答这个疑问。
我们之前说过,Kubernetes 的优势就在于 Pod 自动扩缩容、滚动更新、灰度升级,当然要借助一定的工具,那就是 ReplicaSet 和 Deployment。
<br>
2. ReplicaSet 和 Deployment
2.1. 概念与区别
ReplicaSet 和 Deployment 是 Kubernetes 中两种不同的资源对象,它们都用于管理 Pod 的副本数,在实现方式和功能上有所不同。
ReplicaSet 是一个低级别的控制器,它用于确保运行中的 Pod 副本数与用户指定的副本数相匹配。在 ReplicaSet 中,用户需要定义一个标签选择器和所需的 Pod 副本数,ReplicaSet会使用标签选择器来查找和管理与该标签匹配的 Pod 副本数。如果用户对 ReplicaSet 做出更改,例如调整所需的副本数, ReplicaSet 将更新现有 Pod 的副本数或创建/删除 Pod 以确保所需的副本数得到满足。
Deployment 是一个高级别的控制器,它使用 ReplicaSet 作为底层实现来提供更高级别的部署功能,例如滚动升级和版本回滚。Deployment 可以管理多个 ReplicaSet,并根据用户指定的策略来逐步更新 Pod 副本。在 Deployment 中,用户需要定义一个标签选择器(Deployment 控制器从 Etcd 中获取到所有携带了“app: nginx”标签的 Pod,然后统计它们的数量)、所需的 Pod 副本数和一个 Pod 模板(Deployment 这个 template 字段里的内容,跟一个标准的 Pod 对象的 API 定义,丝毫不差。而所有被这个 Deployment 管理的 Pod 实例,其实都是根据这个 template 字段的内容创建出来的),Deployment 会使用标签选择器和 Pod 模板来创建一个新的 ReplicaSet,并逐步更新现有的 Pod 副本,以确保 Pod 副本数的更新过程是平滑和可靠的。
另一个区别是,在更新 Pod 副本数时,Deployment 和 ReplicaSet 的行为也有所不同。在 Deployment 中,如果更新了 Pod 模板,Deployment 会自动创建一个新的 ReplicaSet 来逐步替换旧的 ReplicaSet 中的 Pod 副本,直到所有新的 Pod 副本都处于运行状态。如果在升级过程中出现故障,Deployment 会自动回滚到之前的版本,以确保应用的可靠性。而在 ReplicaSet 中,如果用户手动更改 Pod 副本数,ReplicaSet 将更新现有 Pod 的副本数或创建/删除 Pod 以满足所需的副本数,但不提供任何回滚或升级策略。
总的来说,Deployment 是一个更高级别的控制器,可以提供更多的功能,例如滚动升级和版本回滚,对于应用的部署和管理来说更加适合。而 ReplicaSet 则更加简单,只关注于管理 Pod 副本的状态和数量。使用哪种控制器应该根据实际情况和需求来选择。
因此我们主要使用 Deployment 来管理副本的数量。
通过上面的叙述,大家应该清楚了,为了更好的管理 Pod,我们将使用 ReplicaSet 和 Deployment。
2.2. 小实验
下面是我们学习 Pod 时创建的第一个 Pod 定义文件
apiVersion: v1 kind: Pod metadata: name: my-first-pod spec: containers: - name: my-first-container image: nginx:latest ports: - containerPort: 80
接下来我们把它改造成 Deployment 定义文件,命名为 my-first-deploy.yaml。并指定标签选择器、Pod模板和所需的副本数:
apiVersion: apps/v1 kind: Deployment metadata: name: my-first-deploy spec: replicas: 1 selector: matchLabels: app: my-first-deploy template: metadata: labels: app: my-first-deploy spec: containers: - name: my-first-container image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80
应用 Deployment 对象:
[root@master mtuser]# kubectl create -f my-first-deploy.yaml deployment.apps/my-first-deploy created [root@master mtuser]# [root@master mtuser]# kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE my-first-deploy 1/1 1 1 25s [root@master mtuser]# [root@master mtuser]# kubectl get rs NAME DESIRED CURRENT READY AGE my-first-deploy-997ddff99 1 1 1 34s
分别查看 Deployment 和 ReplicaSet,这个时候已经创建好了一个副本,并且所有副本都是最新可用的。当然实例数可以更改为任意数量,不过需要有节点能够调度。它们各自最终运行在哪个节点上,完全由 Master 的 Scheduler 经过一系列算法计算得出,用户无法干预调度过程和结果。
接下来我们来感受一下使用 Deployment 对于自动扩缩容、自动升级的方便之处。
比如我们增加副本数为 3:
[root@master mtuser]# kubectl scale deployment/my-first-deploy --replicas=3 deployment.extensions/my-first-deploy scaled [root@master mtuser]# kubectl get pod NAME READY STATUS RESTARTS AGE my-first-deploy-997ddff99-b54r6 1/1 Running 0 54s my-first-deploy-997ddff99-b9hbx 1/1 Running 0 54s my-first-deploy-997ddff99-zvf4k 1/1 Running 0 4m8s
我们发现,只需要一条命令,就实现了自动扩容,而不是手动去增加副本
升级同样如此,只需要一条命令就可以实现所有的 Pod 镜像替换:
[root@master mtuser]# kubectl set image deploy/my-first-deploy my-first-container=nginx:1.2.1 deployment.extensions/my-first-deploy image updated
由此,我们成功通过 Deployment 实现了 Pod 的自动管理工作。
2.3 Deployment 应用场景
无状态 Deployment 适合部署无状态应用程序,这些应用程序的所有实例都可以执行相同的任务,并使用相同的配置和数据。例如,Web 服务器、应用程序服务器、负载均衡器、缓存等。
相对应的,有状态 StatefulSet 则适合部署有状态应用程序,这些应用程序需要持久化存储、唯一的网络标识符和有序的部署/扩展。例如,数据库服务器、消息队列、分布式存储系统等。我们将在下一章节详解 StatefulSet。
在无状态 Deployment 中,所有 Pod 都可以被视为互相替换的副本。因此,当需要扩展应用程序时,可以通过在 Deployment 中增加副本数来增加容量。另外,因为无状态应用程序通常不需要持久化存储或其他状态信息,所以可以随意删除或重新启动 Pod。
相反,在有状态 StatefulSet 中,每个 Pod 都有一个唯一的标识符和一个持久化存储卷。这使得 StatefulSet 可以更好地管理有状态应用程序的生命周期和数据持久化。例如,在扩展 StatefulSet 时,可以逐步地添加新的 Pod 并在运行中保留现有的 Pod,这样可以确保数据的完整性和可靠性。
总的来说,无状态 Deployment 适合处理无状态应用程序,可以通过水平扩展来增加容量。而有状态 StatefulSet 更适合部署有状态应用程序,可以更好地管理应用程序的生命周期和数据持久化。
<br>
3. Deployment 的升级
接下来我们来深入了解一下 Deployment 升级的工作原理。
当需要升级集群中的某个服务时,停止与该服务相关的所有 Pod,然后下载新版本镜像并创建新的 Pod,这是一个挑战,尤其是对于大规模的集群来说,采用全部停止再逐步升级的方式会导致服务不可用的时间较长,这对于生产环境来说是无法承受的。而 Kubernetes 的滚动升级功能可以解决这个问题。
Deployment 提供了方便的升级和回滚机制。可以通过更新 Deployment 的镜像版本或其他配置来进行升级,并且可以轻松回滚到之前的版本。
升级 Deployment 的步骤如下:
- 修改 Deployment 的 YAML 文件,例如修改镜像版本号或其他配置信息。
- 使用
kubectl apply
命令将修改的 YAML 文件应用到 Kubernetes 集群中。
这将触发 Deployment 的升级过程。升级过程中,Deployment 会逐步停止旧版本的 Pod,并启动新版本的 Pod,直到所有 Pod 都被更新为新版本。可以使用 kubectl get pods
命令查看升级过程中 Pod 的状态。
3.1. Rolling Update
Kubernetes 滚动升级(Rolling Update)是一种在不中断服务的情况下,逐步升级 Kubernetes Deployment 中的 Pod 的方法。滚动升级允许将新版本的应用程序部署到 Kubernetes 集群中,并同时逐步将旧版本的应用程序停止。
Kubernetes 滚动升级采用逐步替换 Pod 的方式来实现升级。首先,新版本的 Pod 会被逐步添加到 Kubernetes 集群中,并且会被自动纳入负载均衡器的服务端点列表。同时,旧版本的 Pod 也会逐步从服务端点列表中剔除。在逐步添加新版本 Pod 和逐步删除旧版本 Pod 的过程中,服务仍然可以对外提供服务,不会出现服务中断的情况。
3.2. 小实验
我们先创建 Deployment 定义文件。
[root@master mtuser]# kubectl create -f my-first-deploy.yaml deployment.apps/my-first-deploy created [root@master mtuser]# [root@master mtuser]# kubectl get pod NAME READY STATUS RESTARTS AGE my-first-deploy-997ddff99-r6f2k 1/1 Running 0 22s [root@master mtuser]# [root@master mtuser]# kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE my-first-deploy 1/1 1 1 31s
可以看到已运行的副本数有一个pod,我们通过命令将其扩容至3个副本数
在 Kubernetes 中,可以通过 kubectl scale
命令来扩容 Pod。下面的命令将 Pod 扩容至3个副本数
kubectl scale deployment/my-first-deploy --replicas=3
现在我们将 Pod 镜像更新为 nginx:1.2.1,我们可以通过 kubectl set image
命令为 Deployment 设置新的镜像名称:
[root@master mtuser]# kubectl set image deploy/my-first-deploy my-first-container=nginx:1.2.1 deployment.extensions/my-first-deploy image updated
镜像名(或 Pod 定义)一旦发生了修改,则将触发系统完成 Deployment 所有运行 Pod 的滚动升级操作。可以使用 kubectl rollout status
命令查看 Deployment 的更新过程:
[root@master mtuser]# kubectl set image deploy/my-first-deploy my-first-container=nginx:1.2.1 deployment.extensions/my-first-deploy image updated [root@master mtuser]# kubectl rollout status deploy/my-first-deploy Waiting for deployment "my-first-deploy" rollout to finish: 1 out of 3 new replicas have been updated... Waiting for deployment "my-first-deploy" rollout to finish: 1 out of 3 new replicas have been updated... Waiting for deployment "my-first-deploy" rollout to finish: 1 out of 3 new replicas have been updated... Waiting for deployment "my-first-deploy" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "my-first-deploy" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "my-first-deploy" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "my-first-deploy" rollout to finish: 1 old replicas are pending termination... Waiting for deploy
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专刊适合于立志转行云计算的小白,有一定的编程、操作系统、计算机网络、数据结构、算法基础。 本专刊同时也适合于面向云计算(Docker + Kubernetes)求职的从业者。 本专刊囊括了云计算、VMWare、Docker、Kubernetes、Containerd等一系列知识点的讲解,并且最后总