目录
1、关于Pod控制器
1.1Pod控制器概述
1.2 控制器与Pod对象
1.3 ReplicaSet控制器
1.3.1 ReplicaSet概述
1.3.2 创建ReplicaSet
1.3.3 ReplicaSet管控下的Pod对象
1.3.4 更新ReplicaSet控制器
1.3.5 删除ReplicaSet控制器资源
1、关于Pod控制器
我们可以把API Server类比成一个存储对象的数据库系统,它向客户端提供了API,并负责存储由用户创建的各种资源对象,至于各对象的当前状态如何才能符合用户期望的状态,则需要交由另一类称为控制器的组件来负责完成。Kubernetes提供了众多的控制器来管理各种类型的资源,如Node Lifecycle Controller、Namespace Controller、Service Controller和Deployment Controller等,它们的功用几乎可以做到见名知义。创建完成后,每一个控制器对象都可以通过内部的和解循环 (reconciliation loop),不间断地监控着由其负责的所有资源并确保其处于或不断地逼近用户定义的目标状态。
尽管能够由kubelet为其提供自愈能力,但在节点宕机时,自主式Pod对象的重建式自愈机制则需要由Pod控制器对象负责提供,并且由它来负责实现生命周期中的各类自动管理行为,如创建及删除等。
1.1Pod控制器概述
Master的各组件中,API Server仅负责将资源存储于etcd中,并将其变动通知给各相关的客户端程序,如kubelet、kube-scheduler、kube-proxy和kube-controller-manager等,kube-scheduler监控到处于未绑定状态的Pod对象出现时遂启动调度器为其挑选适配的工作节点,然而, Kubernetes的核心功能之一还在于要确保各资源对象的当前状态 (status)以匹配用户期望的状态(spec),使当前状态不断地向期望状态“和解”(reconciliation)来完成容器应用管理,而这些则是kube-controller-manager的任务。kube-controller-manager是一个独立的单体守护进程,然而它包含了众多功能不同的控制器类型分别用于各类和解任务,如图5-1所示。
提示
Kubernetes
可用的控制器有
attachdetach
、bootstrapsigner
、
clusterrole-aggregation
、
cronjob
、
csrapproving
、
csrcleaner
、
csrsigning
、
daemonset
、
deployment
、
disruption
、
endpoint
、
garbagecollector
、
horizontalpodautoscaling
、
job
、
namespace
、
node
、
persistentvolume-binder
、
persistentvolume-expander
、
podgc
、
pvc-
protection
、
replicaset
、
replication- controller
、
resourcequota
、
route
、
service
、
serviceaccount
、
serviceaccount-token
、
statefulset
、
tokencleaner
和
ttl
等数十种。
创建为具体的控制器对象之后,每个控制器均通过API Server提供的接口持续监控相关资源对象的当前状态,并在因故障、更新或其他原因导致系统状态发生变化时,尝试让资源的当前状态向期望状态迁移和逼近。简单来说,每个控制器对象运行一个和解循环负责状态和解,并将目标资源对象的当前状态写入到其status字段中。控制器的“和解”循环如图5-2所示。
List-Watch是Kubernetes实现的核心机制之一,在资源对象的状态发生变动时,由API Server负责写入etcd并通过水平触发(level-triggered)机制主动通知给相关的客户端程序以确保其不会错过任何一个事件。控制器通过API Server的watch接口实时监控目标资源对象的变动并执行和解操作,但并不会与其他控制器进行任何交互,甚至彼此之间根本就意识不到对方的存在。
工作负载(workload)一类的控制器资源类型包括ReplicationController、ReplicaSet、Deployment、DaemonSet、 StatefulSet、Job和CronJob等,它们分别代表了一种类型的Pod控制器资源,后面的篇幅主要介绍各控制器的特性及其应用,不过StatefulSet控制器依赖于存储卷资源,因此它将单独在存储卷之后的章节中给予介绍。
1.2 控制器与Pod对象
Pod
控制器资源通过持续性地监控集群中运行着的
Pod
资源对象来确保受其管控的资源严格符合用户期望的状态,例如资源副本的数量要精
确符合期望等。通常,一个
Pod
控制器资源至少应该包含三个基本的组
成部分。
-
标签选择器:匹配并关联Pod资源对象,并据此完成受其管控的Pod资源计数。
-
期望的副本数:期望在集群中精确运行着的Pod资源的对象数量。
-
Pod模板:用于新建Pod资源对象的Pod模板资源。
注意:DaemonSet用于确保集群中的每个工作节点或符合条件的每个节点上都运行着一个Pod副本,而不是某个精确的数量值,因此不具有上面组成部分中的第二项。
例如,一个如图
5-3
所示的
Deployment
控制器资源使用的标签选择器为
“role=be-eshop”
,它期望相关的
Pod
资源副本数量精确为
3
个,少于
此数量的缺失部分将由控制器通过
Pod
模板予以创建,而多出的副本也
将由控制器负责终止及删除。
1.3 ReplicaSet控制器
1.3.1 ReplicaSet概述
ReplicaSet(简称RS)是Pod控制器类型的一种实现,用于确保由其管控的Pod对象副本数在任一时刻都能精确满足期望的数量。如图5-4所示,ReplicaSet控制器资源启动后会查找集群中匹配其标签选择器的Pod资源对象,当前活动对象的数量与期望的数量不吻合时,多则删除,少则通过Pod模板创建以补足,等Pod资源副本数量符合期望值后即进入下一轮和解循环。
ReplicaSet的副本数量、标签选择器甚至是Pod模板都可以随时按需进行修改,不过仅改动期望的副本数量会对现存的Pod副本产生直接影响。修改标签选择器可能会使得现有的Pod副本的标签变得不再匹配,此时ReplicaSet控制器要做的不过是不再计入它们而已。另外,在创建完成后,ReplicaSet也不会再关注Pod对象中的实际内容,因此Pod模板的改动也只会对后来新建的Pod副本产生影响。
相比较于手动创建和管理
Pod
资源来说,
ReplicaSet
能够实现以下功能。
-
确保Pod资源对象的数量精确反映期望值:ReplicaSet需要确保由其控制运行的Pod副本数量精确吻合配置中定义的期望值,否则就会自动补足所缺或终止所余。
-
确保Pod健康运行:探测到由其管控的Pod对象因其所在的工作节点故障而不可用时,自动请求由调度器于其他工作节点创建缺失的Pod副本
-
弹性伸缩:业务规模因各种原因时常存在明显波动,在波峰或波谷期间,可以通过ReplicaSet控制器动态调整相关Pod资源对象的数量。 此外,在必要时还可以通过HPA(HroizontalPodAutoscaler)控制器实现Pod资源规模的自动伸缩。
1.3.2 创建ReplicaSet
类似于Pod资源,创建ReplicaSet控制器对象同样可以使用YAML或JSON格式的清单文件定义其配置,而后使用相关的创建命令来完成资源创建。它也由kind、apiVersion、metadata、spec和status这5个一级字段组成,其中status为只读字段,因此需要在清单文件中配置的仅为前4个字段。它的spec字段一般嵌套使用以下几个属性字段。
- replicas<integer>:期望的
-
selector<Object>:当前控制器匹配Pod对象副本的标签选择器,支持matchLabels和matchExpressions两种匹配机制。
-
template<Object>:用于补足Pod副本数量时使用的Pod模板资源。
-
minReadySecond<integer>s:新建的Pod对象,在启动后的多长时间内如果其容器未发生崩溃等异常情况即被视为“就绪”;默认为0秒,表示一旦就绪性探测成功,即被视作可用。
[root@master ~]# vim replicaSet.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-example
spec:
replicas: 2
selector:
matchLabels:
app: rs-demo
template:
metadata:
labels:
app: rs-demo
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
[root@master ~]# kubectl apply -f replicaSet.yaml
replicaset.apps/rs-example created
集群中当前没有标签为
“app
:
rs-demo”
的
Pod
资源存在,因此
rs-example
需要按照
replicas
字段的定义创建它们,名称以其所属的控制器
名称为前缀。这两个
Pod
资源一开始都处于
ContainerCreating
状态,即处于
容器创建过程中,待创建过程完成后,其状态即转为
Running
,
Pod
也将
转变为
“READY”
:
[root@master ~]# kubectl get pods -l app=rs-demo
NAME READY STATUS RESTARTS AGE
rs-example-ms4ps 1/1 Running 0 113s
rs-example-t6w67 1/1 Running 0 113s
接下来可以使用
“kubectl get replicaset”
命令查看
ReplicaSet
控制器资源的相关状态。下面的命令结果显示出它已经根据清单中配置的
Pod
模
板创建了
2
个
Pod
资源,这时它们已创建完成
:
[root@master ~]# kubectl get replicaset rs-example -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
rs-example 2 2 2 4m59s myapp ikubernetes/myapp:v1 app=rs-demo
- DESIRED:期望有几个pod
- CURRENT:当前一共有几个pod
- READY:有几个pod已经就绪了
- AGE:什么时间创建的
经由控制器创建与用户自主创建的
Pod
对象的功能并无二致,但其自动和解的功能在很大程度上能为用户省去不少的管理精力,这也是使
得
Kubernetes
系统之上的应用程序变得拥有自愈能力的主要保障。
1.3.3 ReplicaSet管控下的Pod对象
上面创建的rc-example通过标签选择器将拥有“app=rs-demo”标签的Pod资源收归于麾下,并确保其数量精确符合所期望的数目,使用标签选择器显示出的Pod资源列表也能验证这一点。然而,实际中存着不少可能导致Pod对象数目与期望值不符合的可能性,如Pod对象的意外删除、Pod对象标签的变动(已有的Pod资源变得不匹配控制器的标签选择器,或者外部的Pod资源标签变得匹配到了控制器的标签选择器)、控制器的标签选择器变动,甚至是工作节点故障等。ReplicaSet 控制器的和解循环过程能够实时监控到这类异常,并及时启动和解操作。
1.缺少Pod副本
任何原因导致的相关
Pod
对象丢失,都会由
ReplicaSet
控制器自动补足。例如,手动删除上面列出的一个
Pod
对象,命令如下:
[root@master ~]# kubectl delete pods rs-example-ms4ps
pod "rs-example-ms4ps" deleted
再次列出相关
Pod对象的信息,可以看到被删除的rs-example-t6w67
进入了终止过程,而新的
Pod对象rs-example-zcjmj
正在被rs-example创建
器创建:
[root@master ~]# kubectl get pods -l app=rs-demo -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rs-example-cwxgh 1/1 Running 0 3s 10.244.1.11 node1 <none> <none>
rs-example-t6w67 0/1 Terminating 0 14m 10.244.1.10 node1 <none> <none>
rs-example-zcjmj 1/1 Running 0 3m 10.244.2.11 node2 <none> <none>
另外,强行修改隶属于控制器rs-example的某Pod资源(匹配于标签控制器)的标签,会导致它不再被控制器作为副本计数,这也将触发控制器的Pod对象副本缺失补足机制。例如,将rs-example-p66nv的标签app的值置空:
[root@master ~]# kubectl label pods rs-example-cwxgh app= --overwrite
pod/rs-example-cwxgh labeled
列出
rs-example
相关
Pod对象的信息,发现rs-example-cwxgh
已经消失不见,并且正在创建新的对象副本
[root@master ~]# kubectl get pods -l app=rs-demo
NAME READY STATUS RESTARTS AGE
rs-example-q494g 1/1 Running 0 38s
rs-example-zcjmj 1/1 Running 0 7m16s
由此可见,修改
Pod
资源的标签即可将其从控制器的管控之下移出,当然,修改后的标签如果又能被其他控制器资源的标签选择器所命
中,则此时它又成了隶属于另一控制器的副本。如果修改其标签后的
Pod
对象不再隶属于任何控制器,那么它就将成为自主式
Pod
,与此前手
动直接创建的
Pod
对象的特性相同,即误删除或所在的工作节点故障都
会造成其永久性的消失。
2.多出Pod副本
一旦被标签选择器匹配到的
Pod资源数量因任何原因超出期望值,多余的部分都将被控制器自动删除。例如,为mypod
手动为其添 加“app
:
rs-demo”
标签:
[root@master ~]# kubectl label pods mypod app=rs-demo
pod/mypod labeled
列出
rs-example
相关Pod对象的信息,发现rs-example-q494g
已经消失不见,已创建新的对象副本mypod
[root@master ~]# kubectl get pods -l app=rs-demo
NAME READY STATUS RESTARTS AGE
mypod 1/1 Running 0 6d23h
rs-example-zcjmj 1/1 Running 0 16m
这就意味着,任何自主式的或本隶属于其他控制器的
Pod
资源其标签变动的结果一旦匹配到了其他的副本数足额的控制器,就会导致这类
Pod
资源被删除。
3.查看Pod资源变动的相关事件
“kubectl describe replicasets”
命令可打印出
ReplicaSet
控制器的详细状态,从下面命令结果中
Events
一段也可以看出,
rs-example
执行了
Pod
资源的创建和删除操作,为的就是确保其数量的精确性。
[root@master ~]# kubectl describe replicasets/rs-example
Name: rs-example
Namespace: default
Selector: app=rs-demo
Labels: <none>
Annotations: <none>
Replicas: 2 current / 2 desired
Pods Status: 2 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=rs-demo
Containers:
myapp:
Image: ikubernetes/myapp:v1
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 32m replicaset-controller Created pod: rs-example-ms4ps
Normal SuccessfulCreate 32m replicaset-controller Created pod: rs-example-t6w67
Normal SuccessfulCreate 20m replicaset-controller Created pod: rs-example-zcjmj
Normal SuccessfulCreate 17m replicaset-controller Created pod: rs-example-cwxgh
Normal SuccessfulCreate 14m replicaset-controller Created pod: rs-example-q494g
Normal SuccessfulDelete 4m48s replicaset-controller Deleted pod: rs-example-q494g
事实上,
ReplicaSet
控制器能对
Pod
对象数目的异常及时做出响应,是因为它向
API Server
注册监听(
watch
)了相关资源及其列表的变动信
息,于是
API Server会在变动发生时立即通知给相关的监听客户端。
而因节点自身故障而导致的
Pod
对象丢失,
ReplicaSet
控制器一样会
使用补足资源的方式进行处理。
1.3.4 更新ReplicaSet控制器
ReplicaSet
控制器的核心组成部分是标签选择器、副本数量及
Pod
模板,但更新操作一般是围绕
replicas
和
template
两个字段值进行的,毕竟
改变标签选择器的需求几乎不存在。改动
Pod
模板的定义对已经创建完
成的活动对象无效,但在用户逐个手动关闭其旧版本的
Pod
资源后就能
以新代旧,实现控制器下应用版本的滚动升级。另外,修改副本的数量
也就意味着应用规模的扩展(提升期望的副本数量)或收缩(降低期望
的副本数量)。这两种操作也是系统运维人员日常维护工作的重要组成
部分。
ReplicaSet
控制器的
Pod
模板可随时按需修改,但它仅影响这之后由其新建的
Pod
对象,对已有的副本不会产生作用。大多数情况下,用户
需要改变的通常是模板中的容器镜像文件及其相关的配置以实现应用的
版本升级。下面的示例清单文件片断(replicaSet-v2.yaml
)中的内容与 之前版本(replicaSet.yaml
)的唯一不同之处也仅在于镜像文件的改
动:
[root@master ~]# vim replicaSet-v2.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-example
spec:
replicas: 2
selector:
matchLabels:
app: rs-demo
template:
metadata:
labels:
app: rs-demo
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80
对新版本的清单文件执行
“kubectl apply”
或
“kubectl replace”
命令即可完成
rs-example
控制器资源的修改操作:
[root@master ~]# kubectl apply -f replicaSet-v2.yaml
replicaset.apps/rs-example configured
不过,控制器
rs-example
管控的现存
Pod
对象使用的仍然是原来版本中定义的镜像:
[root@master ~]# kubectl get pods -l app=rs-demo -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
Name Image
mypod ikubernetes/myapp:v1
rs-example-zcjmj ikubernetes/myapp:v1
此时,手动删除控制器现有的
Pod
对象(或修改与其匹配的控制器标签选择器的标签),并由控制器基于新的
Pod
模板自动创建出足额的
Pod
副本,即可完成一次应用的升级。新旧更替的过程支持如下两类操
作方式。
-
一次性删除控制器相关的所有Pod副本或更改相关的标签:剧烈更替,可能会导致Pod中的应用短时间不可访问(如图所示);生产实践中,此种做法不可取。
-
分批次删除旧有的Pod副本或更改其标签(待控制器补足后再删除另一批):滚动更替,更替期间新旧版本共存(如图所示)。
例如,这里采用第一种方式进行操作,一次性删除
rs-example
相关的所有
Pod
副本:
[root@master ~]# kubectl delete pods -l app=rs-demo
pod "mypod" deleted
pod "rs-example-zcjmj" deleted
再次列出
rc-example
控制器相关的
Pod
及其容器镜像版本时可以发现,使用新版本镜像的
Pod
已经创建完成:
[root@master ~]# kubectl get pods -l app=rs-demo -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
Name Image
rs-example-jdp8k ikubernetes/myapp:v2
rs-example-zrm66 ikubernetes/myapp:v2
必要时,用户还可以将
Pod
模板改回旧的版本进行应用的
“
降级
”
或
“
回滚
”
,它的操作过程与上述过程基本类似。事实上,修改
Pod
模
板时,不仅仅能替换镜像文件的版本,甚至还可以将其替换成其他正在
运行着的、完全不同应用的镜像,只不过此类需求并不多见。若同时改
动的还有
Pod
模板中的其他字段,那么在新旧更替的过程中,它们也将
随之被应用。
以上操作只为说明应用部署的方式,实际使用时还需要更为完善的机制。即便是仅执行了一到多次删除操作,手动执行更替操作也并非一
项轻松的任务,幸运的是,更高级别的
Pod
控制器
Deployment
能够自动
实现更完善的滚动更新和回滚,并为用户提供自定义更新策略的接口。
而且,经过精心组织的更新操作还可以实现诸如蓝绿部署(
Blue/Green
Deployment
)、金丝雀部署(
Canary Deployment
)和灰度部署等,这些
内容将在后面章节中详细展开说明。
2.扩容和缩容
改动
ReplicaSet
控制器对象配置中期望的
Pod
副本数量(
replicas
字段)会由控制器实时做出响应,从而实现应用规模的水平伸缩。
replicas
的修改及应用方式同
Pod
模板,不过,
kubectl
还提供了一个专用的子命
令
scale
用于实现应用规模的伸缩,它支持从资源清单文件中获取新的目
标副本数量,也可以直接在命令行通过
“--replicas”
选项进行读取,例如
将
rs-example
控制器的
Pod
副本数量提升至
5
个:
[root@master ~]# kubectl scale replicasets rs-example --replicas=5
replicaset.apps/rs-example scaled
由下面显示的
rs-example
资源的状态可以看出,将其
Pod
资源副本数量扩展至
5
个的操作已经成功完成:
[root@master ~]# kubectl get replicasets rs-example
NAME DESIRED CURRENT READY AGE
rs-example 5 5 5 88m
收缩规模的方式与扩展相同,只需要明确指定目标副本数量即可。
例如:
[root@master ~]# kubectl scale replicasets rs-example --replicas=3
replicaset.apps/rs-example scaled
另外,
kubectl scale
命令还支持在现有
Pod
副本数量符合指定的值时才执行扩展操作,这仅需要为命令使用
“--current-replicas”
选项即可。例
如,下面的命令表示如果
rs-example
目前的
Pod
副本数量为
2
,就将其扩
展至
4
个:
[root@master ~]# kubectl scale replicasets rs-example --current-replicas=2 --replicas=4
error: Expected replicas to be 2, was 3
但由于
rs-example
控制器现存的副本数量是
3
个,因此上面的扩展操作未执行并返回了错误提示。
注意
如果
ReplicaSet
控制器管控的是有状态的应用,例如主
从架构的
Redis
集群,那么上述这些升级、降级、扩展和收缩的操作都
需要精心编排和参与才能进行,不过,这也在一定程度上降低了
Kubernetes
容器编排的价值和意义。好在,它提供了
StatefulSet
资源来应
对这种需求,因此
ReplicaSet
通常仅用于管理无状态的应用,如
HTTP
服务程序等。
1.3.5 删除ReplicaSet控制器资源
使用
kubectl delete
命令删除
ReplicaSet
对象时默认会一并删除其管控的各
Pod
对象。有时,考虑到这些
Pod
资源未必由其创建,或者即便由其
创建却也并非其自身的组成部分,故而可以为命令使用
“--
cascade=false”
选项,取消级联,删除相关的
Pod
对象,这在
Pod
资源后续
可能会再次用到时尤有用。例如,删除
rs
控制器
rs-example
:
[root@master ~]# kubectl delete replicasets rs-example --cascade=false
replicaset.apps "rs-example" deleted
删除操作完成后,此前由
rs-example
控制器管控的各
Pod
对象仍处于活动状态,但它们变成了自主式
Pod
资源,用户需要自行组织和维护好
它们。
尽管
ReplicaSet
控制器功能强大,但在实践中,它却并非是用户直接使用的控制器,而是要由比其更高一级抽象的
Deployment
控制器对象
来调用