Kubernetes控制器之ReplicaSet
ReplicaSet用來(lái)維護(hù)一組在任何時(shí)候都處于運(yùn)行狀態(tài)的Pod保持穩(wěn)定的副本數(shù)。因此,它通常用來(lái)保證給定數(shù)量的完全相同的Pod的可用性。現(xiàn)在ReplicaSet基本取代了ReplicationController,ReplicaSet支持集合式的selector,而ReplicationController僅支持等式。不過(guò)現(xiàn)在建議使用Deployment來(lái)自動(dòng)管理ReplicaSet,這樣無(wú)需擔(dān)心跟其他機(jī)制的不兼容問(wèn)題,并且還支持版本記錄、回滾、暫停升級(jí)等高級(jí)特性。
本文主要對(duì)Kubernetes的ReplicaSet控制器進(jìn)行簡(jiǎn)單總結(jié)。
一、環(huán)境信息
本文所使用的環(huán)境如下:
- 操作系統(tǒng):CentOS Linux release 8.2.2004
- Docker:19.03.12
- kubernetes:v1.18.5
二、ReplicaSet簡(jiǎn)介
ReplicaSet的目的是維護(hù)一組在任何時(shí)候都處于運(yùn)行狀態(tài)的Pod保持穩(wěn)定的副本數(shù)。因此,它通常用來(lái)保證給定數(shù)量的完全相同的Pod的可用性。
至于RepicaSet的工作原理,首先RepicaSet是通過(guò)一組字段定義的,包括一個(gè)用來(lái)識(shí)別可獲得的Pod的selector,一個(gè)用來(lái)表明應(yīng)該維護(hù)的Pod副本數(shù)(replica),一個(gè)用來(lái)指定應(yīng)該創(chuàng)建新Pod以滿足副本數(shù)條件時(shí)要使用的Pod模板(template)等。每個(gè) ReplicaSet都將根據(jù)需要?jiǎng)?chuàng)建和刪除Pod以達(dá)到期望的Pod副本數(shù)。當(dāng)ReplicaSet需要?jiǎng)?chuàng)建新的Pod時(shí),會(huì)使用所提供的Pod模板。ReplicaSet通過(guò)Pod上的metadata.ownerReferences字段連接到所屬Pod,該字段指定當(dāng)前對(duì)象屬于哪個(gè)資源。ReplicaSet所獲得的Pod都在其ownerReferences字段中包含了屬主ReplicaSet的標(biāo)識(shí)信息。正是通過(guò)這一連接,ReplicaSet獲知了它所維護(hù)的Pod集合的狀態(tài)并據(jù)此計(jì)劃其操作行為。ReplicaSet使用其selector來(lái)識(shí)別要獲取的Pod。如果某個(gè)Pod沒(méi)有OwnerReference或者其OwnerReference不是一個(gè)控制器,并且其匹配到某ReplicaSet的selector,則該P(yáng)od立即被此ReplicaSet獲得。
雖然ReplicaSet可以確保任何時(shí)間都有指定數(shù)量的Pod副本運(yùn)行并可以獨(dú)立使用,但現(xiàn)在它主要是用作協(xié)調(diào)Deploymen創(chuàng)建、刪除和更新Pod的一種機(jī)制。使用Deployment時(shí),我們不必?fù)?dān)心它們創(chuàng)建的ReplicaSet如何管理,Deployment會(huì)擁有并管理它們,并向Pod提供聲明式的更新以及許多其他有用的功能,例如滾動(dòng)更新,Deployment支持而ReplicaSet不支持。所以推薦使用Deployment而不是直接使用ReplicaSet,除非需要自定義更新業(yè)務(wù)流程或根本不需要更新。
三、創(chuàng)建ReplicaSet
1.ReplicaSet清單
可以通過(guò)以下命令查看ReplicaSet資源清單規(guī)則:
kubectl explain rs kubectl explain rs.spec kubectl explain rs.spec.template也可以通過(guò)官方Kubernetes API手冊(cè)進(jìn)行查找。這里主要總結(jié)一下資源清單中重要的字段:
| apiVersion | string | api版本定義 |
| kind | string | 資源類型定義 |
| metadata | object | 元數(shù)據(jù)定義 |
| spec | object | ReplicaSet的Spec定義 |
| spec.replicas | integer | Pod副本的期望數(shù)目,默認(rèn)值為1 |
| spec.selector | object | 標(biāo)簽選擇器,定義匹配Pod的標(biāo)簽。ReplicaSet管理所有標(biāo)簽與標(biāo)簽選擇器匹配的Pod |
| spec.selector.matchLabels | object | {key,value}對(duì)的映射 |
| spec.template | object | Pod模板定義,除了它是嵌套的并且沒(méi)有apiVersion和kind之外,與Pod資源清單的語(yǔ)法幾乎完全一致。它是spec唯一需要的字段 |
| spec.template.metadata | object | Pod的元數(shù)據(jù)定義 |
| spec.template.metadata.name | string | 定義Pod的名稱 |
| spec.template.metadata.labels | object | 定義Pod的標(biāo)簽,必須與spec.selector匹配(可以多出其他標(biāo)簽),否則它將被API拒絕 |
| spec.template.spec | object | Pod的Spec定義 |
注意:
- 對(duì)于2個(gè)指定相同spec.selector但不同spec.template.metadata.labels和spec.template.spec字段的ReplicaSet,每個(gè)ReplicaSet將忽略另一個(gè)ReplicaSet創(chuàng)建的Pod。
- 通常情況下不應(yīng)該創(chuàng)建標(biāo)簽與此ReplicaSet標(biāo)簽選擇器匹配的任何Pod,或者直接與另一個(gè)ReplicaSet或另一個(gè)控制器(如 Deployment)匹配的任何Pod,否則ReplicaSet會(huì)認(rèn)為是它創(chuàng)建了這些Pod。
2.ReplicaSet示例
ReplicaSet通過(guò)其selector來(lái)識(shí)別要獲取的Pod,管理所有標(biāo)簽與標(biāo)簽選擇器匹配的Pod,一個(gè)簡(jiǎn)單的示意圖如下:
首先準(zhǔn)備一個(gè)鏡像,創(chuàng)建一個(gè)名為mynginx1的Dockerfile文件:
構(gòu)建mynginx:v1鏡像:
docker build -t mynginx:v1 -f mynginx1 .創(chuàng)建ReplicaSet資源清單文件mynginx-rs.yaml:
apiVersion: apps/v1 kind: ReplicaSet metadata:name: mynginx-rslabels:app: mynginxenv: test spec:replicas: 3selector:matchLabels:app: mynginxenv: testtemplate:metadata:labels:app: mynginxenv: testcreator: rtxtitanvspec:containers:- name: nginximage: mynginx:v1imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80執(zhí)行以下命令創(chuàng)建ReplicaSet:
kubectl apply -f mynginx-rs.yaml查看ReplicaSet和Pod信息:
kubectl get rs -o wide kubectl describe rs mynginx-rs kubectl get pod -o wide --show-labels
驗(yàn)證這些Pod的所有者引用是否為mynginx-rs,查看其中一個(gè)Pod的Yaml:
查看結(jié)果如下,這里只列出了其中一部分:
apiVersion: v1 kind: Pod metadata:creationTimestamp: "2020-08-24T02:06:33Z"generateName: mynginx-rs-labels:app: mynginxcreator: rtxtitanvenv: test ...name: mynginx-rs-jrv2tnamespace: defaultownerReferences:- apiVersion: apps/v1blockOwnerDeletion: truecontroller: truekind: ReplicaSetname: mynginx-rsuid: 066e381d-e74e-48ab-bfaa-732e308f2d0aresourceVersion: "543754"selfLink: /api/v1/namespaces/default/pods/mynginx-rs-jrv2tuid: aaf22e96-38f5-4604-a4cb-119f26e67117 ...可見(jiàn)在元數(shù)據(jù)的ownerReferences字段中設(shè)置了mynginx-rs的信息。下面刪除其中一個(gè)Pod再次查看Pod,發(fā)現(xiàn)又創(chuàng)建了一個(gè)新的Pod以維持Pod副本數(shù):
3.獲取非模板創(chuàng)建的Pod
在創(chuàng)建沒(méi)有控制器管理的Pod時(shí)最好確保Pod的標(biāo)簽不要與ReplicaSet的標(biāo)簽選擇器匹配,因?yàn)镽eplicaSet不限于擁有其Pod模板所指定的Pod,它可以獲取其他的Pod。獲取非模板創(chuàng)建的Pod有兩種情況,如果先創(chuàng)建了ReplicaSet再創(chuàng)建標(biāo)簽與ReplicaSet的標(biāo)簽選擇器匹配的Pod,ReplicaSet也會(huì)獲取這些標(biāo)簽與ReplicaSet的標(biāo)簽選擇器匹配的Pod,但是由于ReplicaSet會(huì)維護(hù)Pod副本數(shù)穩(wěn)定處于期望副本數(shù),獲取了這些非模板創(chuàng)建的Pod后ReplicaSet所管理的Pod超出了期望副本數(shù),這時(shí)這些非模板創(chuàng)建的Pod會(huì)被ReplicaSet終止。如下圖所示,灰色的兩個(gè)Pod表示在ReplicaSet之后創(chuàng)建的標(biāo)簽與ReplicaSet標(biāo)簽選擇器匹配的Pod,被ReplicaSet獲取之后由于超出了期望副本數(shù)3而被終止:
下面就創(chuàng)建兩個(gè)與ReplicaSet的標(biāo)簽選擇器匹配的Pod,先創(chuàng)建資源清單文件mynginx-pods.yaml:
創(chuàng)建與ReplicaSet的標(biāo)簽選擇器匹配的Pod并查看,發(fā)現(xiàn)新創(chuàng)建的Pod已終止或正在終止:
如果先創(chuàng)建標(biāo)簽與ReplicaSet的標(biāo)簽選擇器匹配的Pod再創(chuàng)建ReplicaSet,ReplicaSet會(huì)先獲取這些Pod,如果沒(méi)有達(dá)到期望的副本數(shù),ReplicaSet會(huì)根據(jù)其Spec創(chuàng)建了新的Pod直到Pod副本數(shù)達(dá)到期望數(shù)目為止,不管怎樣,ReplicaSet會(huì)維護(hù)Pod副本數(shù)保持在期望副本數(shù)。如下圖所示,先創(chuàng)建了圖中左邊的兩個(gè)Pod,然后創(chuàng)建ReplicaSet,先創(chuàng)建的兩個(gè)Pod標(biāo)簽匹配ReplicaSet標(biāo)簽選擇器,被ReplicaSet獲取,此時(shí)Pod副本數(shù)小于期望副本數(shù)3(如果等于期望副本數(shù),則不會(huì)再創(chuàng)建Pod,如果多于期望副本數(shù),會(huì)刪除多余的Pod以維持期望副本數(shù)),ReplicaSet會(huì)根據(jù)其Pod模板再創(chuàng)建一個(gè)Pod:
刪除ReplicaSet,然后先創(chuàng)建上面這兩個(gè)Pod,再創(chuàng)建ReplicaSet,查看所有Pod發(fā)現(xiàn)ReplicaSet已經(jīng)獲取到了這兩個(gè)自主創(chuàng)建的Pod,并根據(jù)其Spec創(chuàng)建了新的Pod直到Pod副本數(shù)達(dá)到期望數(shù)目為止,這樣ReplicaSet就擁有了一組非同構(gòu)的Pod:
四、更新ReplicaSet
可以通過(guò)修改ReplicaSet的Pod模板來(lái)更新ReplicaSet,如下圖所示,將Pod使用的鏡像由mynginx:v1改為mynginx:v2,重載ReplicaSet可以進(jìn)行更新,但由于新舊ReplicaSet的spec.selector是相同的,新的ReplicaSet將接管老ReplicaSet的Pod,所以需要?jiǎng)h除老ReplicaSet所創(chuàng)建的Pod,新的ReplicaSet就會(huì)根據(jù)其Pod模板創(chuàng)建新的Pod,達(dá)到期望副本數(shù)為止:
先準(zhǔn)備一個(gè)mynginx:v2鏡像,創(chuàng)建一個(gè)名為mynginx2的Dockerfile文件:
構(gòu)建mynginx:v2鏡像:
docker build -t mynginx:v2 -f mynginx2 .先刪除之前創(chuàng)建的ReplicaSet再重新創(chuàng)建,然后修改Pod模板以進(jìn)行更新。如下所示,修改ReplicaSet資源清單文件,將鏡像mynginx:v1改為mynginx:v2:
template:metadata:labels:app: mynginxenv: testcreator: rtxtitanvspec:containers:- name: nginximage: mynginx:v2imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80執(zhí)行apply命令重載ReplicaSet,然后執(zhí)行下面的命令查看Pod所用鏡像,發(fā)現(xiàn)沒(méi)有更新,如下圖所示:
kubectl get pod -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
這是因?yàn)檫@些Pod是在ReplicaSet重載之前創(chuàng)建的,需要手動(dòng)刪除ReplicaSet管理的Pod。下面手動(dòng)刪除ReplicaSet管理的Pod后再次查看Pod所用鏡像,發(fā)現(xiàn)已經(jīng)更新:
五、縮放ReplicaSet
通過(guò)更新spec.replicas字段,ReplicaSet可以被輕松的進(jìn)行縮放。可以通過(guò)編輯資源清單文件修改spec.replicas字段,也可以通過(guò)kubect edit命令修改,kubectl還提供了一個(gè)子命令scale用于實(shí)現(xiàn)應(yīng)用規(guī)模的伸縮,支持從資源清單文件中獲取新的目標(biāo)副本數(shù)量,也可以直接在命令行通過(guò)--replicas選項(xiàng)進(jìn)行讀取。下面先查看ReplicaSet和Pod:
然后執(zhí)行以下命令將Pod副本擴(kuò)容為5個(gè):
查看ReplicaSet和Pod:
執(zhí)行以下命令將Pod副本收縮至3個(gè):
查看ReplicaSet和Pod:
ReplicaSet也可以被HPA(Horizontal Pod Autoscaler)自動(dòng)縮放。例如以下HPA資源清單:
創(chuàng)建該HPA資源對(duì)象就能根據(jù)Pod的CPU利用率對(duì)目標(biāo)ReplicaSet自動(dòng)縮放,當(dāng)CPU利用率超過(guò)50%,Pod最多不能擴(kuò)容至超過(guò)10個(gè),當(dāng)CPU利用率低于50%,Pod最少不能縮減至少于3個(gè)。也可以使用kubectl autoscale命令完成相同的操作,更加簡(jiǎn)單:
kubectl autoscale rs mynginx-rs --max=10 --min=3 --cpu-percent=50由于HPA需要獲取CPU內(nèi)存等指標(biāo),需要部署監(jiān)控系統(tǒng)來(lái)收集這些指標(biāo),這里就不進(jìn)行演示了。
六、將Pod從ReplicaSet隔離
可以通過(guò)改變Pod標(biāo)簽來(lái)從ReplicaSet中移除Pod。這種技術(shù)可以用來(lái)從服務(wù)中去除Pod,以便進(jìn)行排錯(cuò)、數(shù)據(jù)恢復(fù)等。如果期望的副本數(shù)沒(méi)有改變的話,以這種方式移除的Pod將被自動(dòng)替換。如下圖所示:
先查看Pod及其標(biāo)簽:
執(zhí)行下面的命令修改其中一個(gè)pod的標(biāo)簽,然后查看Pod及標(biāo)簽,發(fā)現(xiàn)ReplicaSet又新建了一個(gè)標(biāo)簽為env=test的pod,如下圖所示:
因?yàn)镽eplicaSet管理所有標(biāo)簽與標(biāo)簽選擇器匹配的Pod,當(dāng)有一個(gè)pod的標(biāo)簽改變,不再與標(biāo)簽選擇器匹配,這個(gè)Pod將從ReplicaSet中移除,而ReplicaSet發(fā)現(xiàn)管理的pod少了一個(gè),就會(huì)新建一個(gè)以維持期望副本數(shù)。而app=mynginx1的pod就變?yōu)榱俗灾鱬od,刪除了也不會(huì)創(chuàng)建出一個(gè)新的Pod。下面刪除修改了標(biāo)簽的Pod,發(fā)現(xiàn)并沒(méi)有再創(chuàng)建Pod:
七、刪除ReplicaSet
要?jiǎng)h除ReplicaSet和它的所有Pod,使用kubectl delete命令。默認(rèn)情況下,垃圾收集器會(huì)自動(dòng)刪除所有依賴的Pod。執(zhí)行以下命令刪除ReplicaSet和它的所有Pod,然后查看ReplicaSet和Pod,發(fā)現(xiàn)均已經(jīng)被刪除,如下圖所示:
kubectl delete rs mynginx-rs
如果只想刪除ReplicaSet而不刪除它的Pod,可以使用kubectl delete命令并設(shè)置--cascade=false選項(xiàng)。先創(chuàng)建ReplicaSet,查看ReplicaSet和Pod:
執(zhí)行以下命令只刪除ReplicaSet,然后查看ReplicaSet和Pod,發(fā)現(xiàn)ReplicaSet被刪了,Pod沒(méi)有被刪除,如下圖所示:
總結(jié)
以上是生活随笔為你收集整理的Kubernetes控制器之ReplicaSet的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何在VScode中实现markdown
- 下一篇: serialplot虚拟串口示波器使用方