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