Kubernetes早起的版本中仅有ReplicationCOntroller一种控制器的Pod控制器,后来的版本中陆续引入了更多控制器的实现,这其中就包括用来取代ReplicationController的新一代实现ReplicaSet。事实上,除了额外支持基于集合(set-based)的标签选择器,以及它的滚动更新(Rolling-Update)机制要基于更高级的控制Deployment实现之外,目前的ReplicaSet的其余功能基本上与ReplicationController相同。考虑到Kubernetes强烈推荐使用ReplicaSet控制器,且表示ReplicationController不久后即将废弃,这里就重点介绍ReplicaSet控制器。
ReplicaSet控制器概述
ReplicaSet(简称RS)是Pod控制器类型的一种实现,用于确保由其管控的Pod对象副本数在任一时刻都能精确满足期望的数量,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资源规模的自动伸缩。
创建ReplicaSet控制器
类似于Pod资源,创建ReplicaSet控制器对象同样可以使用YAML或者JSON格式的清单文件定义其配置,而后使用相关的创建命令来完成资源创建,如下面清单中,它由apiVersion、kind、metadata、spec和status这五个字段组成,其中status为只读字段,因此在清单中定义前四个字段就可以,它的spec字段一般嵌套以下几种属性的字段。
- replicas:期望的Pod对象副本数量。
- selector:当前控制器匹配Pod对象副本的标签选择器,支持matchLabels和matchExpressions两种匹配机制。
- template:用于补足Pod副本数量时使用的Pod模版资源。
- minReadySeconds:新建的Pod对象,在启动后多长时间内如果其容器未发生崩溃等异常情况即被视为 "就绪";默认为0秒,表示容器启动成功后,会先进行就绪性探测,如果探测成功,即被视作为可用。
1.RelicaSet控制器资源配置清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
cat nginx-rs.yaml apiVersion: apps/v1 kind: ReplicaSet metadata: name: nginx-rs-controller namespace: default labels: app: nginx-rs spec: replicas: 3 #Pod副本期望数量,默认值为1 selector: matchLabels: #控制器标签选择器,要与Pod的标签相匹配才能管控Pod app: nginx-pod template: #Pod模版 metadata: labels: app: nginx-pod #Pod标签 spec: containers: - name: nginx-containers image: nginx:latest ports: - name: http containerPort: 80 |
2.创建Pod对象
1 2 3 4 5 |
kubectl apply -f nginx-rs.yaml kubectl get pods -o wide | grep nginx-rs nginx-rs-controller-j72dz 1/1 Running 0 102s 10.244.3.113 k8s-node01 <none> <none> nginx-rs-controller-r9kh2 1/1 Running 0 102s 10.244.5.108 k8s-node03 <none> <none> nginx-rs-controller-tf9bx 1/1 Running 0 102s 10.244.3.112 k8s-node01 <none> <none> |
3.查看控制器状态
1 2 3 |
kubectl get replicaset nginx-rs-controller -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR nginx-rs-controller 3 3 3 49m nginx-containers nginx:latest app=nginx-pod |
4.查看Pod的创建过程
kubectl describe pods nginx-rs-controller-r9kh2
ReplicaSet管控Pod对象
在实际中存在着不少可能导致Pod对象数量与期望值不符合的可能性,如Pod对象的意外删除、Pod对象标签的变动(已有Pod资源变得不匹配控制器的标签选择器,或者外部的Pod资源标签变得匹配到了控制器的标签选择器)、控制器的标签选择器变动,甚至是工作节点操作故障等。RelicaSet控制器的和解循环过程能够实时监控到这类异常,并及时启动和解操作。
1.缺少副本
任何原因导致的相关Pod对象丢失,都会由ReplicaSet控制器自动补足。例如手动删除一个Pod对象,命令如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#查看当前Pod状态 kubectl get pods -o wide | grep nginx-rs-con nginx-rs-controller-j72dz 1/1 Running 0 59m 10.244.3.113 k8s-node01 <none> <none> nginx-rs-controller-r9kh2 1/1 Running 0 59m 10.244.5.108 k8s-node03 <none> <none> nginx-rs-controller-tf9bx 1/1 Running 0 59m 10.244.3.112 k8s-node01 <none> <none> #删除一个Pod kubectl delete pods nginx-rs-controller-j72dz pod "nginx-rs-controller-j72dz" deleted #再次列出相关Pod对象信息,可以看到nginx-rs-controller-j72dz Pod已经被删除,然后由RelicaSet控制器再次创建了一个nginx-rs-controller-7r5g7 Pod kubectl get pods -o wide | grep nginx-rs-con nginx-rs-controller-7r5g7 0/1 ContainerCreating 0 5s <none> k8s-node03 <none> <none> nginx-rs-controller-r9kh2 1/1 Running 0 60m 10.244.5.108 k8s-node03 <none> <none> nginx-rs-controller-tf9bx 1/1 Running 0 60m 10.244.3.112 k8s-node01 <none> <none> |
2.修改ReplicaSet控制器所管控Pod的标签
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#查看当前Pod标签 kubectl get pods --show-labels | grep nginx-rs nginx-rs-controller-7r5g7 1/1 Running 0 5m49s app=nginx-pod nginx-rs-controller-r9kh2 1/1 Running 0 65m app=nginx-pod nginx-rs-controller-tf9bx 1/1 Running 0 65m app=nginx-pod #修改一个Pod标签value为空 kubectl label pods nginx-rs-controller-r9kh2 app= --overwrite #查看Pod状态,如下可以看到由ReplicaSet重新创建了nginx-rs-controller-d76fx Pod,标签app=这台Pod已经不归属与RelicaSet控制器管理 kubectl get pods --show-labels | grep nginx-rs nginx-rs-controller-7r5g7 1/1 Running 0 6m36s app=nginx-pod nginx-rs-controller-d76fx 0/1 ContainerCreating 0 2s app=nginx-pod nginx-rs-controller-r9kh2 1/1 Running 0 66m app= nginx-rs-controller-tf9bx 1/1 Running 0 66m app=nginx-pod |
由此可见,修改Pod资源的标签可将其从控制器的管控之下移出,当然修改后的标签如果又能被其他控制器资源的标签所命中,则此时它又隶属于另一个控制器的副本。
3.多出Pod副本
一旦被标签选择器匹配到的Pod资源数量超出期望值,多余的部分都会被控制器自动删除,例如我们将上面那个Pod标签重新定义为由ReplicaSet控制器所管理的标签:
1 2 3 4 5 6 7 |
kubectl label pods nginx-rs-controller-r9kh2 app=nginx-pod --overwrite #查看Pod状态,如下可以看到Pod nginx-rs-controller-d76fx 正在被控制器移除,我们刚加进去的nginx-rs-controller-r9kh2成了ReplicaSet控制器所管控的一份子 kubectl get pods --show-labels -l app=nginx-pod | grep nginx-rs nginx-rs-controller-7r5g7 1/1 Running 0 13m app=nginx-pod nginx-rs-controller-d76fx 0/1 Terminating 0 6m53s app=nginx-pod nginx-rs-controller-r9kh2 1/1 Running 0 73m app=nginx-pod nginx-rs-controller-tf9bx 1/1 Running 0 73m app=nginx-pod |
如上就意味着,任何自主式或者隶属于其他控制器的Pod资源标签变动的结果一旦匹配到了其他的副本书足额的控制器,就会导致控制器中的Pod资源被删除。
4.查看Pod资源变动的相关事件
kubectl describe replicaset
命令可以打印出replicaset控制器的详细信息,从下面命令Events段可以看出Pod资源的变动。
kubectl describe replicaset nginx-rs-controller
ReplicaSet控制器能对Pod对象树木的异常及时做出响应,是因为它向API Server注册监听(watch)了相关资源及其列表的变动信息,于是API Server会在变动发生时立即通知给相关的监听客户端。
更新ReplicaSet控制器
ReplicaSet控制器的核心组成部分是标签选择器、副本数量以及Pod模版,但更新一般是围绕replicaSet和template两个字段值进行的,毕竟改变标签选择器的需求几乎不存在,改动Pod模版的定义对已经创建完成的活动对象无效,但在用户依次手动关闭其旧Pod资源后就能以新代旧,实现控制器下应用版本的滚动升级,另外如果修改副本的数量就意味着应用规模的扩展或者收缩,这两个也是系统运维人员日常维护工作的重要重要组成部分。
1.更改Pod模版:升级应用
ReplicaSet控制器的Pod模版可随时按需修改,但它仅影响这之后由其新建的Pod对象,对已有的Pod对象不会产生作用,大多数情况下,用户需要改变的通常是模版中的容器镜像文件及其相关的配置以实现应用的版本升级,下面就演示一个升级容器镜像文件的清单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
cat nginx-rs.yaml apiVersion: apps/v1 kind: ReplicaSet metadata: name: nginx-rs-controller namespace: default labels: app: nginx-rs spec: replicas: 3 selector: matchLabels: app: nginx-pod template: metadata: labels: app: nginx-pod spec: containers: - name: nginx-containers #image: nginx:latest image: nginx:1.18.0 #将nginx最新镜像替换为1.18.0 ports: - name: http containerPort: 80 |
对新版本的清单文件执行kubectl apply
或kubectl replace
命令即可完成nginx-rs-controller控制器资源的修改操作:
kubectl replace -f nginx-rs.yaml
不过控制器nginx-rs-controller管控的现存Pod对象使用的依然是原来版本中定义的nginx镜像
1 2 3 4 5 |
kubectl get pods -l app=nginx-pod -o custom-columns=Name:metadata.name,Image:spec.containers[0].image Name Image nginx-rs-controller-7r5g7 nginx:latest nginx-rs-controller-r9kh2 nginx:latest nginx-rs-controller-tf9bx nginx:latest |
此时,手动删除控制器现有的Pod对象(或修改与其匹配的控制器标签选择器的标签),并由控制器基于新的Pod模版自动创建出足额的Pod副本,即可完成一次应用升级。新旧更替的过程支持如下两类操作方式。
- 一次性删除控制器相关的所有Pod副本或更改相关标签:剧烈更替,可能会导致Pod中的应用短时间不可访问,生产实践中,此中方法不可取。
- 分批次删除旧的Pod副本或更改其标签(待控制器补足后再删除另外一批);滚动更替,更新期间新旧版本共存
例如,这里采用第一种方式进行操作,一次性删除nginx-rs-controller相关的所有Pod副本
1 2 3 4 5 6 7 8 9 10 |
kubectl delete pods -l app=nginx-pod pod "nginx-rs-controller-7r5g7" deleted pod "nginx-rs-controller-r9kh2" deleted pod "nginx-rs-controller-tf9bx" deleted #再次列出nginx-rs-controller相关的Pod及其容器镜像版本时可以发现,使用新的镜像Pod已经创建完成 kubectl get pods -l app=nginx-pod -o custom-columns=Name:metadata.name,Image:spec.containers[0].image Name Image nginx-rs-controller-6zpc9 nginx:1.18.0 nginx-rs-controller-vvgjb nginx:1.18.0 nginx-rs-controller-z9qh6 nginx:1.18.0 |
以上操作只说明了应用部署的方式,实际使用时还需要更加完善的机制,即便是进执行了一到多次删除操作,手动执行更替操作也并发一项轻松的任务,幸运的是,更高级的Pod控制器Deployment能够自动实现更完善的滚动更新和回滚,并为用户提供自定义更新策略的接口,而且,经过精心组织的更新操作还可以实现诸如蓝绿部署(Blue/Green Deployment)、金丝雀部署(Canary Deployment)和灰度部署等。
尽管REplicaSet控制器功能强大,但在实践中,它并非是我们直接使用的控制器,而是要由比其更高一级抽象的 Deployment 控制器对象来调用。