K8S系列深入解析控制器
Posted 颜淡慕潇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了K8S系列深入解析控制器相关的知识,希望对你有一定的参考价值。
目录
序言
在你想要放弃的时候,想想是什么让你当初坚持走到了这里。
Kubernetes (k8s) 是一个容器编排平台,允许在容器中运行应用程序和服务。今天学习一下k8s 控制器。
文章标记颜色说明:
- 黄色:重要标题
- 红色:用来标记结论
- 绿色:用来标记一级论点
- 蓝色:用来标记二级论点
1 基础介绍
1.1 前情提要
回忆一下,我和你详细介绍了 Pod 的用法,讲解了 Pod 这个 API 对象的各个字段。而接下来,我们就一起来看看“编排”这个 Kubernetes 项目最核心的功能吧。
实际上,你可能已经有所感悟:Pod 这个看似复杂的 API 对象,实际上就是对容器的进一步抽象和封装而已。
说得更形象些,“容器”镜像虽然好用,但是容器这样一个“沙盒”的概念,对于描述应用来说,还是太过简单了。
这就好比,集装箱固然好用,但是如果它四面都光秃秃的,吊车还怎么把这个集装箱吊起来并摆放好呢?
所以,Pod 对象,其实就是容器的升级版。它对容器进行了组合,添加了更多的属性和字段。这就好比给集装箱四面安装了吊环,使得 Kubernetes 这架“吊车”,可以更轻松地操作它。
Kubernetes 操作这些“集装箱”的逻辑,都由控制器(Controller)完成
1.2 Kube-controller-manager介绍
Kube-controller-manager是Kubernetes中的一个控制器,是Kubernetes系统中的一个组件,负责运行一些后台控制循环(controller loop),并监视系统中的各个资源的状态。
kube-controller-manager通常运行在Master节点上。kube-controller-manager包含了多个控制器,每个控制器都负责处理不同的资源。
1.3 控制器类型
以下是kube-controller-manager中的一些重要控制器:
Deployment控制器:用于确保Deployment对象所管理的Pod副本数量符合预期,并且进行滚动更新(Rolling Update)。
ReplicaSet控制器:用于确保ReplicaSet对象所管理的Pod副本数量符合预期。
DaemonSet 控制器:DaemonSet 控制器用于在集群中的每个节点上启动一个 Pod 副本,以便运行一些系统级别的守护进程,如日志收集器和监控代理。如果有新的节点加入集群,DaemonSet 控制器会自动在新节点上启动相应的 Pod 副本。
StatefulSet控制器:用于确保StatefulSet对象所管理的有状态应用程序的副本数量符合预期。
Node控制器:用于确保所有Node对象的状态都是最新的,并管理Node的状态。
Service控制器:用于确保Service对象的状态符合预期,并处理Service的创建、更新和删除等操作。
Namespace控制器:用于确保Namespace对象的状态符合预期,并处理Namespace的创建、更新和删除等操作。
Endpoint控制器:用于确保Endpoint对象的状态符合预期,并处理Endpoint的创建、更新和删除等操作。
Job控制器:用于确保Job对象所管理的任务成功完成,并对失败的任务进行重试。
CronJob控制器:用于确保CronJob对象所管理的定时任务按照预期执行。
在kube-controller-manager中,每个控制器都是一个独立的进程,它们之间相互独立,互不影响。同时,kube-controller-manager会自动监视资源对象的状态变化,并触发相应的控制器处理,以确保系统状态的一致性和稳定性。
2 使用介绍
2.1 控制循环
了解具体的使用之前,需要先看下“循环控制”这个概念
在 Kubernetes 中,控制循环(control loop)是一种通用的编排模式,用于监控和控制集群中的资源。
控制循环通过对比当前状态和期望状态之间的差异来确保集群的期望状态得以实现。
具体而言,控制循环包括以下几个步骤:
监控资源状态:控制循环会定期检查集群中的资源状态,例如 Pod、Service、Deployment 等。
计算期望状态:根据 Kubernetes 集群的配置文件和用户提交的操作,控制循环会计算出资源的期望状态。例如,用户可能会提交一个 Deployment 的 YAML 文件,其中指定了需要部署的 Pod 数量和镜像版本等信息,控制循环就会根据这些信息计算出 Deployment 的期望状态。
对比当前状态和期望状态:控制循环会将当前状态和期望状态进行对比,找出二者之间的差异。例如,如果一个 Deployment 的期望 Pod 数量为 3,但是当前只有 2 个 Pod 在运行,那么控制循环就会发现这个差异。
执行调整操作:控制循环会根据差异来执行调整操作,使得当前状态逐渐接近期望状态。例如,控制循环会自动创建新的 Pod,以便使得 Deployment 中的 Pod 数量达到期望值。
重复执行:控制循环会一直重复上述步骤,直到当前状态和期望状态完全一致。
注意,控制循环并不是一个线性的过程,而是由多个控制器(Controller)组成的复杂系统。每个控制器都会负责监控和管理一个或多个资源,例如 Deployment、StatefulSet、DaemonSet 等。不同的控制器之间还可以相互协作,以实现更复杂的功能。
2.2 Deployment控制器
我们曾经使用过 Deployment 这个最基本的控制器对象。现在,我们一起来回顾一下这个名叫 nginx-deployment 的例子:
apiVersion: apps/v1
kind: Deployment #资源类型
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
这个 Deployment 定义的编排动作非常简单,即:确保携带了 app=nginx 标签的 Pod 的个数,永远等于 spec.replicas 指定的个数,即 2 个。
这就意味着,如果在这个集群中,携带 app=nginx 标签的 Pod 的个数大于 2 的时候,就会有旧的 Pod 被删除;反之,就会有新的 Pod 被创建。
这时,你也许就会好奇:究竟是 Kubernetes 项目中的哪个组件,在执行这些操作呢?
没错,就是今天介绍 kube-controller-manager 的组件。
那他具体怎么控制的呢?我们以这个 Deployment 为例,分析一下:
实际上,这个组件,是一系列控制器的集合。可以查看一下 Kubernetes 项目pkg/controller 目录:
$ cd kubernetes/pkg/controller/
$ ls -d */
deployment/ job/ podautoscaler/
cloud/ disruption/ namespace/
replicaset/ serviceaccount/ volume/
cronjob/ garbagecollector/ nodelifecycle/ replication/ statefulset/ daemon/
...
这个目录下面的每一个控制器,都以独有的方式负责某种编排功能。而我们的 Deployment,正是这些控制器中的一种。
实际上,这些控制器之所以被统一放在 pkg/controller 目录下,就是因为它们都遵循 Kubernetes 项目中的一个通用编排模式,即:控制循环(control loop)。就是上面说的那个控制循环
比如,现在有一种待编排的对象 X,它有一个对应的控制器。那么,用一段 Go 语言风格的伪代码,描述这个控制循环:
for
实际状态 := 获取集群中对象 X 的实际状态(Actual State)
期望状态 := 获取集群中对象 X 的期望状态(Desired State)
if 实际状态 == 期望状态
什么都不做
else
执行编排动作,将实际状态调整为期望状态
实际状态:
在具体实现中,实际状态往往来自于 Kubernetes 集群本身。
比如,kubelet 通过心跳汇报的容器状态和节点状态,或者监控系统中保存的应用监控数据,或者控制器主动收集的它自己感兴趣的信息,这些都是常见的实际状态的来源。
期望状态:
而期望状态,一般来自于用户提交的 YAML 文件。
比如,Deployment 对象中 Replicas 字段的值。
很明显,这些信息往往都保存在 Etcd 中。接下来,以 Deployment 为例,简单描述一下它对控制器模型的实现:
Deployment 控制器从 Etcd 中获取到所有携带了“app: nginx”标签的 Pod,然后统计它们的数量,这就是实际状态;
Deployment 对象的 Replicas 字段的值就是期望状态;
Deployment 控制器将两个状态做比较,然后根据比较结果,确定是创建 Pod,还是删除已有的 Pod
PodTemplate:
其实,像 Deployment 这种控制器的设计原理,就是“用一种对象管理另一种对象”的“艺术”。
其中,这个控制器对象本身,负责定义被管理对象的期望状态。比如,Deployment 里的 replicas=2 这个字段。
而被控制对象的定义,则来自于一个“模板”。比如,Deployment 里的 template 字段。
可以看到,Deployment 这个 template 字段里的内容,跟一个标准的 Pod 对象的 API 定义,丝毫不差。而所有被这个 Deployment 管理的 Pod 实例,其实都是根据这个 template 字段的内容创建出来的。
像 Deployment 定义的 template 字段,在 Kubernetes 项目中有一个专有的名字,叫作 PodTemplate(Pod 模板)。
这个概念非常重要,因为后面讲解到的大多数控制器,都会使用 PodTemplate 来统一定义它所要管理的 Pod。更有意思的是,我们还会看到其他类型的对象模板,比如 Volume 的模板。
至此,对 Deployment 以及其他类似的控制器,做一个简单总结了:
如上图所示,类似 Deployment 这样的一个控制器,实际上都是由
- 上半部分的控制器定义(包括期望状态)
- 下半部分的被控制对象的模板组成的
3 总结
在这篇文章中,以 Deployment 为例,详细分享了 Kubernetes 项目如何通过一个称作“控制器模式”(controller pattern)的设计方法,来统一地实现对各种不同的对象或者资源进行的编排操作。
这个实现思路,正是 Kubernetes 项目进行容器编排的核心原理。
在此后讲解 Kubernetes 编排功能的文章中,我都会遵循这个逻辑展开,并且带你逐步领悟控制器模式在不同的容器化作业中的实现方式。
4 投票
K8S系列深入解析滚动升级
目录
专栏介绍
因为可能还有很多同学还不清楚上下文,所以简单介绍一下这个专栏要做的事:
主要是深入解析每个知识点,帮助大家完全掌握k8s,一下是已更新的章节
序号 | 文章 |
第一讲 | 深入解析 k8s:入门指南(一) |
第二讲 | 深入解析 k8s:入门指南(二) |
第三讲 | 深入解析Pod对象(一) |
第四讲 | 深入解析Pod对象(二) |
第五讲 | 深入解析无状态服务 |
第六讲 | 深入解析有状态服务 |
第七讲 | 深入解析控制器 |
第八讲 | 深入解析 ReplicaSet |
序言
那些看似不起波澜的日复一日,一定会在某一天让你看见坚持的意义。
文章标记颜色说明:
- 黄色:重要标题
- 红色:用来标记结论
- 绿色:用来标记一级论点
- 蓝色:用来标记二级论点
Kubernetes (k8s) 是一个容器编排平台,允许在容器中运行应用程序和服务。今天学习一下滚动升级。
希望这篇文章能让你不仅有一定的收获,而且可以愉快的学习,如果有什么建议,都可以留言和我交流
1 基础介绍
Kubernetes是一个流行的容器编排平台,其中的控制器是Kubernetes的核心组件之一,它可以控制Pod的部署和管理。
滚动升级是Kubernetes中的一种重要的控制器操作,可以让用户在不中断服务的情况下对应用程序进行升级。本文将深入解析Kubernetes控制器滚动升级的原理和实现方法。
1.1 什么是滚动升级
滚动升级是指在不中断服务的情况下,对应用程序进行升级的操作。
在Kubernetes中,滚动升级是通过控制器来实现的。控制器会根据用户的要求,逐步将旧版本的Pod逐步替换为新版本的Pod,直到所有的Pod都已经被更新为止。
这样做的优点是可以减少服务中断的时间,同时也可以保证应用程序的稳定性。
1.2 控制器滚动升级的原理
控制器滚动升级的原理:是将旧版本的Pod逐步替换为新版本的Pod。这个过程可以分为以下几个步骤:
创建新版本的Pod:首先需要创建新版本的Pod,并将其添加到控制器的ReplicaSet中。这个ReplicaSet会逐步替换旧版本的Pod。
逐步替换旧版本的Pod:控制器会逐步替换旧版本的Pod,直到所有的Pod都已经被更新为止。在这个过程中,控制器会根据用户定义的策略来控制更新的速度和数量,以确保服务的稳定性。
监控更新过程:在更新过程中,控制器会不断地监控新版本的Pod是否已经成功运行,并将运行失败的Pod进行重启或者回滚操作。这样可以保证应用程序的稳定性。
清理旧版本的Pod:当所有的Pod都已经更新完成后,控制器会自动清理旧版本的Pod,以释放资源。
1.3 控制器滚动升级的实现方法
控制器滚动升级的实现方法可以分为两种:
- 基于Deployment的滚动升级
- 基于StatefulSet的滚动升级
1 基于Deployment的滚动升级
基于Deployment的滚动升级是Kubernetes中最常用的滚动升级方法。
它通过定义一个Deployment对象来管理Pod的创建和更新。Deployment对象包含了Pod的副本数、更新策略、滚动升级速度等信息,可以通过kubectl命令或者Kubernetes API来进行管理。
在进行滚动升级时:
- 创建:需要先使用kubectl命令或者Kubernetes API创建一个新的Deployment对象,并将其更新到Kubernetes集群中。
- 更新:然后,使用kubectl命令或者Kubernetes API更新Deployment对象的镜像版本或者其他配置信息。
Kubernetes会自动根据新的配置信息来创建新版本的Pod,并将更新过程控制在用户定义的范围内。
2 基于StatefulSet的滚动升级
基于StatefulSet的滚动升级是一种相对较新的滚动升级方法。
它通过定义一个StatefulSet对象来管理Pod的创建和更新。与Deployment不同,StatefulSet对象可以保证Pod的唯一性和稳定性,可以在进行滚动升级时保持Pod的稳定性。
在进行滚动升级时,
- 创建StatefulSet对象:需要先使用kubectl命令或者Kubernetes API创建一个新的StatefulSet对象,并将其更新到Kubernetes集群中。
- 更新StatefulSet对象:然后,使用kubectl命令或者Kubernetes API更新StatefulSet对象的镜像版本或者其他配置信息。
Kubernetes会自动根据新的配置信息来创建
2 拓展
2.1 Deployment 的“滚动更新”示例
在 Kubernetes 中,可以使用 Deployment 对象来进行滚动更新。以下是一个 Deployment 滚动更新的详细代码使用介绍:
1 准备镜像
在进行滚动更新之前,需要准备一个新的镜像版本。这里我们以一个简单的 "Hello World" 应用程序为例,在 Docker Hub 上准备一个新版本的镜像。这里先用Nginx
2 创建 Deployment
在 Kubernetes 中,可以使用 YAML 文件或命令行工具来创建 Deployment。以下是一个示例 YAML 文件:
apiVersion: apps/v1
kind: Deployment #资源类型
metadata:
name: hello-world
spec:
replicas: 3
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: nginx:1.7.9 # <your-new-image>
ports:
- containerPort: 8080
在这个 YAML 文件中,定义了一个名为 "hello-world" 的 Deployment,它会启动 3 个 Pod,每个 Pod 都包含一个名为 "hello-world" 的容器。容器使用对应的版本镜像,并监听 8080 端口。
3 更新 Deployment
要更新 Deployment,可以使用
kubectl
命令行工具。以下是一个更新 Deployment 的示例命令:
kubectl set image deployment/hello-world hello-world=<your-new-image>
这个命令会将名为 "hello-world" 的 Deployment 的 "hello-world" 容器的镜像更新为你准备的新版本镜像。
4 监控更新状态
在更新 Deployment 后,可以使用
kubectl rollout status
命令来查看更新状态。以下是一个示例命令:
kubectl rollout status deployment/hello-world
这个命令会输出当前 Deployment 的更新状态,包括更新的版本和可用性等信息。
5 回滚更新
如果在更新过程中出现问题,可以使用
kubectl rollout undo
命令来回滚更新。以下是一个示例命令:
kubectl rollout undo deployment/hello-world
这个命令会将 Deployment 回滚到上一个版本,以恢复服务的可用性。
2.2 其他示例
除了上述提到的基本滚动更新过程,Kubernetes 还提供了一些高级功能和特性,以更好地管理应用程序和服务的更新和部署。以下是一些示例:
1 暂停和恢复更新
在滚动更新过程中,如果需要暂停更新以处理问题,可以使用
kubectl rollout pause
命令暂停更新。例如:
kubectl rollout pause deployment/hello-world
这个命令会暂停 "hello-world" Deployment 的更新。一旦问题解决,可以使用
kubectl rollout resume
命令恢复更新。例如:
kubectl rollout resume deployment/hello-world
这个命令会恢复 "hello-world" Deployment 的更新。
2 设置滚动更新策略
在创建 Deployment 时,可以设置滚动更新策略,以控制更新的速度和失败率。
例如,可以设置最大不可用 Pod 的数量和最大并行 Pod 的数量等参数。
以下是一个示例 YAML 文件:
apiVersion: apps/v1
kind: Deployment #资源类型
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx-deployment
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: nginx-deployment
spec:
containers:
- name: nginx-deployment
image: nginx:laste
ports:
- containerPort: 8080
在这个 YAML 文件中,设置了 RollingUpdate 策略,并指定了最大不可用 Pod 的数量和最大并行 Pod 的数量都为 1。
2.3 总结
我们来看一下在滚动升级中他们三者之间的关系是怎么样的
可以看到,
- 首先,当修改了 Deployment 里的 Pod 定义之后,Deployment Controller 会使用这个修改后的 Pod 模板,创建一个新的 ReplicaSet(v2),这个新的 ReplicaSet 的初始 Pod 副本数是:0。
- Deployment Controller 开始将这个新的 ReplicaSet-(v2)所控制的 Pod 副本数从 0 个变成 1 个,即:“水平扩展”出一个副本。
- Deployment Controller 又将旧的 ReplicaSet-(v1)所控制的旧 Pod 副本数减少一个,即:“水平收缩”成两个副本。
- 如此交替进行,新 ReplicaSet 管理的 Pod 副本数,从 0 个变成 1 个,再变成 2 个,最后变成 3 个。
- 而旧的 ReplicaSet 管理的 Pod 副本数则从 3 个变成 2 个,再变成 1 个,最后变成 0 个。
这样,就完成了这一组 Pod 的版本升级过程。
如上所示,Deployment 的控制器,实际上控制的是 ReplicaSet 的数目,以及每个 ReplicaSet 的属性。
而一个应用的版本,对应的正是一个 ReplicaSet;这个版本应用的 Pod 数量,则由 ReplicaSet 通过它自己的控制器(ReplicaSet Controller)来保证。
通过这样的多个 ReplicaSet 对象,Kubernetes 项目就实现了对多个“应用版本”的描述。
像这样,将一个集群中正在运行的多个 Pod 版本,交替地逐一升级的过程,就是“滚动更新”。
使用 Deployment 进行滚动更新是一种方便而可靠的方式,可以确保服务的连续性和可用性。在更新过程中,需要密切监控服务的性能和可用性,并及时采取措施来解决任何问题。
总的来说,Kubernetes 提供了一系列功能和特性,以帮助用户更好地管理应用程序和服务的更新和部署。这些功能可以根据用户的需求进行配置和使用。
3 投票
以上是关于K8S系列深入解析控制器的主要内容,如果未能解决你的问题,请参考以下文章