目录
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所示。
创建为具体的控制器对象之后,每个控制器均通过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模板资源。
注意:DaemonSet用于确保集群中的每个工作节点或符合条件的每个节点上都运行着一个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副本数量精确吻合配置中定义的期望值,否则就会自动补足所缺或终止所余。
- 确保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
[root@master ~]# kubectl get pods -l app=rs-demoNAME READY STATUS RESTARTS AGE
rs-example-ms4ps 1/1 Running 0 113s
rs-example-t6w67 1/1 Running 0 113s
[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:什么时间创建的
1.3.3 ReplicaSet管控下的Pod对象
上面创建的rc-example通过标签选择器将拥有“app=rs-demo”标签的Pod资源收归于麾下,并确保其数量精确符合所期望的数目,使用标签选择器显示出的Pod资源列表也能验证这一点。然而,实际中存着不少可能导致Pod对象数目与期望值不符合的可能性,如Pod对象的意外删除、Pod对象标签的变动(已有的Pod资源变得不匹配控制器的标签选择器,或者外部的Pod资源标签变得匹配到了控制器的标签选择器)、控制器的标签选择器变动,甚至是工作节点故障等。ReplicaSet 控制器的和解循环过程能够实时监控到这类异常,并及时启动和解操作。
1.缺少Pod副本
[root@master ~]# kubectl delete pods rs-example-ms4ps
pod "rs-example-ms4ps" deleted
[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
[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
2.多出Pod副本
[root@master ~]# kubectl label pods mypod app=rs-demo
pod/mypod labeled
[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
3.查看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
1.3.4 更新ReplicaSet控制器
1.更改Pod模板:升级应用
[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
[root@master ~]# kubectl apply -f replicaSet-v2.yaml
replicaset.apps/rs-example configured
[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副本或更改其标签(待控制器补足后再删除另一批):滚动更替,更替期间新旧版本共存(如图所示)。
[root@master ~]# kubectl delete pods -l app=rs-demo
pod "mypod" deleted
pod "rs-example-zcjmj" deleted
[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
2.扩容和缩容
[root@master ~]# kubectl scale replicasets rs-example --replicas=5
replicaset.apps/rs-example scaled
[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
[root@master ~]# kubectl scale replicasets rs-example --current-replicas=2 --replicas=4
error: Expected replicas to be 2, was 3
1.3.5 删除ReplicaSet控制器资源
[root@master ~]# kubectl delete replicasets rs-example --cascade=false
replicaset.apps "rs-example" deleted