- ReplicaSet控制器
- 創建ReplicaSet
- ReplicaSet管控下的Pod物件
- 更新ReplicaSet
- Deployment控制器
- 創建Deployment
- 更新策略
- 升級Deployment
- 金絲雀發布
- 擴容、縮容
- DaemonSet控制器
- Job控制器
- 串行、并行控制
- 洗掉Job
- CornJob控制器
- Pod中斷預算
自主式Pod物件由調度器系結至目標作業節點后即由相應節點上的kubelet負責監控其容器的存活性,容器主行程崩潰后,kubelet能夠自動重啟相應的容器,基于存活性探測,在容器出現其他問題時也能作出回應,但如果Pod被意外洗掉、或者作業節點發生故障,kubelet就無能為力了,
Pod控制器可應對這類情況,Pod控制器由master的kube-controller-manager組件提供,kube-controller-manager是一個獨立的單體守護行程,它包含了眾多功能不同的控制器,除了Pod Controller,還有NodeLifecycle Controller、Namespace Controller、Service Controller等等,這些控制器不間斷地監控著由其負責的資源,并在因故障、更新或其他原因導致系統狀態發生變化時,嘗試讓資源的當前狀態向期望狀態遷移和逼近,
ReplicaSet控制器
ReplicaSet替代了早期的ReplicationController,用于確保由其管控的Pod物件副本數在任一時刻都能精確滿足期望的數量
通過控制器創建的Pod與用戶手動創建的Pod功能相同,但相比于手動創建來說,ReplicaSet能夠實作以下功能:
- 確保Pod資源物件的數量精確反映期望值
- 確保Pod健康運行,在探測到由其管控的Pod物件因其所在的作業節點故障而不可用時,自動請求由調度器于其他作業節點創建缺失的Pod副本
- 彈性伸縮:在資源需求存在較大波動時,可以通過ReplicaSet控制器動態調整相關Pod資源物件的數量,還可以配合HPA(HroizontalPodAutoscaler)實作Pod資源規模的自動伸縮,
創建ReplicaSet
通常一個Pod控制器的資源清單的spec包含如下基本屬性:
- selector:標簽選擇器,匹配并關聯Pod資源物件,并據此完成受其管控的Pod資源計數
- replicas:期望的副本數,期望在集群中精確運行著的Pod資源的物件數量
- template:Pod模板,用于新建Pod資源物件的Pod模板資源
例如:
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
imagePullPolicy: Never
ports:
- name: http
containerPort: 80
protocol: TCP
將這份配置清單apply后,使用kubectl get pods -l app=rs-demo查看,會看到有兩個容器,狀態從ContainerCreating轉為Running,兩個pod名稱以控制器的名稱rs-example為前綴,rs-example-j98fp、rs-example-wj8zg,
運行kubectl get replicaset rs-example,配合-o json\wide等選項可查看控制器的詳細狀態,
ReplicaSet管控下的Pod物件
ReplicaSet之所以能對Pod物件數目的例外及時做出回應,是因為它向API Server注冊監聽了相關資源及其串列的變動資訊,于是API Server會在變動發生時立即通知給監聽方,
缺少、多出Pod副本
任何原因導致的相關Pod物件丟失,都會由ReplicaSet控制器自動補足,
手動洗掉一個Pod,ReplicaSet馬上會新建一個;之前創建的ReplicaSet依賴標簽app: rs-demo來管理Pod,那么強制修改這個標簽也會觸發副本的新建:
kubectl label pods rs-example-wj8zg app=others --overwrite
之前的Pod rs-example-wj8zg還存在,如果它能被別的控制器通過標簽選擇器選中,就會隸屬于這個控制器,否會成為自助式Pod,
多余的部分則會被控制器自動洗掉,經測驗Age最小的會被首先洗掉,
kubectl describe replicasets/rs-example命令可列印出ReplicaSet的詳細狀態以及Events,
更新ReplicaSet
更改template:升級應用
更改template對已經創建完成的活動物件無效,但可以逐個手動關閉其舊版本的Pod資源來實作滾動升級,
相比于ReplicaSet的手動操作方式,Deployment控制器能夠自動實作更完善的滾動更新和回滾,并為用戶提供自定義更新策略的介面,
更改replicas:擴容和縮容
通過修改replicas屬性并apply,可實作應用規模的水平伸縮;kubectl還提供了一個專用的子命令scale用于實作應用規模的伸縮,比如:
kubectl scale replicasets rs-example --replicas=2
使用--current-replicas選項還可實作在副本數量為指定值時才變更replicas,比如下面的命令,如果當前副本數量不等于4就不會執行成功:
kubectl scale replicasets rs-example --current-replicas=4 --replicas=2
如果讓ReplicaSet管控有狀態應用,例如主從架構的Redis集群,那么上述這些升降級、擴縮容操作都需要精心編排和參與才能進行,針對這類需求,可以使用K8S專門提供的StatefulSet,ReplicaSet通常僅用于管理無狀態的應用,如HTTP服務程式等,
洗掉ReplicaSet資源
洗掉命令:
kubectl delete -f ...
或者
kubectl delete replicaset ...
洗掉ReplicaSet物件時默認會一并洗掉其管控的各Pod物件,但有時考慮到這些Pod資源未必由其創建,或者Pod資源后續可能會再次用到時,可以添加--cascade=false選項取消級聯洗掉,
Deployment控制器
Deployment控制器構建于ReplicaSet控制器之上,可為Pod和ReplicaSet資源提供宣告式更新,Pod和ReplicaSet是較低級別的資源,很少被直接使用,
Deployment控制器在ReplicaSet的基礎上,添加了多種增強的功能:
- 事件和狀態查看:必要時可以查看Deployment物件升級的詳細進度和狀態
- 回滾:在升級發現問題時,可以使用回滾機制將應用回傳到前一個或由指定的歷史版本
- 版本記錄:保存每一次操作記錄,以供后續可能執行的回滾操作使用
- 暫停和啟動:對于每一次升級,都能夠隨時暫停和啟動
- 多種自動更新方案:
- Recreate,重建更新機制,全面停止、洗掉舊有的Pod后用新版本替代
- RollingUpdate,滾動升級機制,逐步替換舊有的Pod至新的版本,
創建Deployment
Deployment將ReplicaSet物件作為其二級資源,配置清單中除了kind、name,其它欄位與ReplicaSet的相同,示例:
kind: Deployment
metadata:
name: myapp-deploy
創建完成后可用kubectl get deployments myapp-deploy查看其狀態:
NAME READY UP-TO-DATE AVAILABLE AGE
myapp-deploy 2/2 2 2 15s
UP-TO-DATE表示已經達到期望狀態的Pod副本數量,AVAILABLE則表示當前處于可用狀態的應用程式的數量,
查看相關的ReplicaSet資源:
~ kubectl get replicasets -l app=myapp
NAME DESIRED CURRENT READY AGE
myapp-deploy-7cfbdc886d 2 2 2 2m53s
ReplicaSet資源的命名格式為[DEPLOYMENT-NAME]-[POD-TEMPLATE-HASH-VALUE]
查看相關的Pod資源:
~ kubectl get pods -l app=myapp
NAME READY STATUS RESTARTS AGE
myapp-deploy-7cfbdc886d-8lw6f 1/1 Running 0 4m55s
myapp-deploy-7cfbdc886d-xn7xp 1/1 Running 0 4m55s
Pod資源的名稱以ReplicaSet資源的名稱為前綴,加5位隨機字符,
更新策略
Deployment控制器支持RollingUpdate和Recreate兩種更新策略,默認為滾動更新,
Recreate
類似于使用ReplicaSet時一次性洗掉全部Pod物件,而后由控制器基于新模板重新創建出新版本資源物件,這種方式通常只應該在應用的新舊版本不兼容(如依賴的后端資料庫的schema不同且無法兼容)時才使用,因為它會導致應用替換期間暫時不可用,但好處在于它不存在中間狀態,
RollingUpdate
滾動升級是在洗掉一部分舊版本Pod資源的同時,補充創建一部分新版本的Pod物件,使用這種方式時,容器中應用提供的服務不會中斷,但要求應用程式能夠應對新舊版本同時作業的情形,例如新舊版本兼容同一個資料庫方案等,
滾動升級時會同時存在新舊版本的ReplicaSet,舊版ReplicaSet的Pod物件數量不斷減少的同時,新版ReplicaSet的Pod物件數量不斷增加,直到舊版ReplicaSet不再擁有Pod物件,而新版ReplicaSet的副本數量變得完全符合預期,
升級期間還要確保可用的Pod物件數量不低于某閾值以確保可以持續處理客戶端的服務請求,變動的方式和Pod物件的數量范圍將通過spec.strategy.rollingUpdate下的maxSurge和maxUnavailable兩個屬性協同定義:
- maxSurge:升級期間存在的總Pod物件數量最多可超出期望值的個數,其值可以是0或正整數,也可以是一個期望值的百分比
- maxUnavailable:升級期間正常可用的Pod副本數(包括新舊版本)最多不能低于期望數值的個數,其值可以是0或正整數,也可以是一個期望值的百分比,默認值為1,
maxSurge和maxUnavailable相當于定義了pod數量的波動范圍,所以它們的值不可同時為0,兩者作用方式如下圖舉例:

此外,還可以設定spec.minReadySeconds屬性:
- ,控制應用升級的速度,滾動升級時默認新的Pod物件只要就緒探測成功就可用,于是開始開始下一輪的替換操作,而minReadySeconds能夠定義在新的Pod物件創建后至少要等待多久才會將其視作就緒,在此期間,更新操作會被阻塞,
升級Deployment
修改Pod模板相關的配置引數便能完成Deployment控制器資源的更新,可以通過apply和patch命令來修改;如果只是修改容器鏡像,可以直接使用set image命令,
為了使得升級程序更易于觀測,先使用“kubectl patch”命令指定minReadySeconds=6s:
kubectl patch deployments myapp-deploy -p '{"spec":{"minReadySeconds":6}}'
修改Deployment控制器的minReadySeconds、replicas和strategy等欄位的值并不會觸發Pod資源的更新操作,因為它們不會對現存的Pod物件不產生任何影響,
使用set image命令更新鏡像版本:
kubectl set image deployments myapp-deploy myapp=ikubernetes/myapp:v2
隨后使用如下命令可以觀察滾動升級的程序:
kubectl rollout status deployments myapp-deploy --watch
升級完成后,舊版本的ReplicaSet控制器會保留在歷史記錄中,但其此前的管控Pod物件將會被洗掉,
金絲雀發布
Deployment控制器支持更新操作的暫停、繼續,再結合maxSurge和maxUnavailable,可以實作金絲雀發布(Canary Release),即待第一批新的Pod資源創建完成后立即暫停更新程序,此時,僅存在一小部分新版本的應用,主體部分還是舊的版本,然后將一小部分流量導到新版本的Pod應用,并持續觀察其是否能穩定地按期望的方式運行,確定沒有問題后再繼續完成余下Pod資源的滾動更新,否則立即回滾更新操作,
為了盡可能地降低對現有系統的影響,金絲雀發布程序通常建議采用“先添加、再洗掉,且可用Pod資源物件總數不低于期望值”的方式進行,首次添加的Pod物件數量取決于其接入的第一批請求的規則及單個Pod的承載能力,
接下來的試驗中將maxSurge和maxUnavailable分別設定為1和0,并通過修改升級鏡像版本來觸發更新,但要在第一批更新啟動后就暫停,由于設定了minReadySeconds,可以在這個程序中發出暫停命令,對于kubectl來說,也可以直接以“&&”符號在Shell中連接兩個命令:
kubectl set image deployments myapp-deploy myapp=ikubernetes/myapp:v2 --record=true&& kubectl rollout pause deployments myapp-deploy
查看狀態可知更新操作已經暫停:
kubectl rollout status deployments myapp-deploy
此時,通過Service或Ingress資源及相關路由策略等設定,即可將一部分用戶的流量引入到這些Pod之上進行發布驗證,確認沒有問題后即可繼續更新:
kubectl rollout resume deployments myapp-deploy
回滾
如果因各種原因導致滾動更新無法正常進行,如鏡像檔案獲取失敗、“金絲雀”遇險等,則應該將應用回滾到之前的版本或者指定的歷史記錄中的版本,直接回滾至上一版本:
kubectl rollout undo deployments myapp-deploy
加上--to-revision選項可以回滾至指定版本,如下命令可以查看保存的歷史版本:
kubectl rollout history deployments myapp-deploy
需要注意的是,只有回滾至被保存的歷史版本,spec.revisionHistoryLimit定義了保存的版本數量,默認為10個,另外rollout history顯示的CHANGE-CAUSE一列的內容默認為空,在執行命令時加上--record=true選項,可以記錄觸發更新的命令的內容,此外,處于暫停狀態的更新無法回滾,
擴容、縮容
直接修改配置清單中的spec.replicas并apply可以改變Pod資源的副本數量,也可以使用專用的命令kubectl scale:
kubectl scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)
比如在當前Pod副本數為4個時,調整為2個:
kubectl scale --current-replicas=4 --replicas=2 deployment/myapp-deploy
DaemonSet控制器
DaemonSet用于在集群中的全部或指定節點上同時運行一份指定的Pod資源副本,后續新加入集群的作業節點也會自動創建一個相關的Pod物件,當從集群移除節點時,此類Pod物件也將被自動回收而無須重建,
DaemonSet是一種特殊的控制器,它有特定的應用場景,通常運行那些執行系統級操作任務的應用,如集群存盤的守護行程、日志收集守護行程、監控系統的代理守護行程等,
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: daemonset-demo
spec:
selector:
matchLabels:
app: daemonset-pod
template:
metadata:
labels:
app: daemonset-pod
spec:
nodeSelector:
kubernetes.io/hostname: docker-desktop
containers:
- name: myapp
image: ikubernetes/myapp:v1
imagePullPolicy: Never
Job控制器
Job控制器用于調配Pod物件運行一次性任務,容器中的行程在正常運行結束后,Pod物件會被置于Completed狀態,Job控制器的配置清單相對簡單:
apiVersion: batch/v1
kind: Job
metadata:
name: job-example
spec:
completions: 5
parallelism: 5
template:
metadata:
labels:
app: job1
spec:
restartPolicy: Never
containers:
- name: job1
image: alpine
command: ["/bin/sh", "-c", "sleep 5"]
Pod模板中的spec.restartPolicy默認為“Always”,但對Job控制器來說只支持“Never”或“OnFailure”,因此必須顯式設定restartPolicy屬性的值,
apply資源清單后,job便開始執行,如果順利執行完畢,會處于Succeed狀態,job資源會被自動添加標簽job-name='name',如job-name=job-example,可據此使用標簽選擇器查看job狀態
串行、并行控制
spec.completions表示總任務數,spec.parallelism表示并行度,默認都是1,所以job在執行一次后即完成,如果parallelism設為1,completions設為5,則job會以串行的方式運行5次,如果parallelism也設為5,則會并行運行5個job實體,如果completions大于parallelism,Job控制器就會以串行方式運行多任務,
可以使用--watch選項監控job的運行狀態
kubectl get jobs -l job-name=job-example --watch
洗掉Job
Job控制器待其Pod資源運行完成后,將不再占用系統資源,用戶可按需保留或使用資源洗掉命令將其洗掉,但如果某Job控制器的容器應用總是無法正常結束運行,而其restartPolicy又定為了重啟,則它可能會一直處于不停地重啟和錯誤的回圈當中,下面兩個屬性用于抑制這種情況的發生:
spec.activeDeadlineSeconds,用于指定job的最大執行時長,超出將被終止;
spec.backoffLimit,最大重試次數,超出后被標記為失敗,默認值為6,
activeDeadlineSeconds要比backoffLimit優先級高,如果時間到了,但是backoffLimit還未到,該Job也會被強制停止,
CornJob控制器
CronJob控制器用于管理Job控制器資源的運行時間,Job控制器定義的作業任務在其控制器資源創建之后便會立即執行,但CronJob可以以類似于Linux作業系統的周期性任務作業計劃(crontab)的方式控制其運行的時間點及重復運行的方式,
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: cronjob-example
labels:
app: cronjob1
spec:
schedule: "* * * * *"
jobTemplate:
metadata:
labels:
app: cronjob1-job
spec:
template:
spec:
restartPolicy: Never
containers:
- name: job1
image: alpine
command: ["/bin/sh", "-c", "date; echo Hello from the kubernetes cluster; sleep 1"]
這個cronjob沒分鐘運行一次,schedule的語法可參照這里,schedule的時間基于 kube-controller-manager的時區,
任務啟動一段時間后,可使用log命令查看pod輸出:
kubectl logs cronjob-example-1620082920-vg7p8
Pod中斷預算
Pod中斷可大體分為兩種:
- 非自愿中斷,是指那些由不可控外界因素導致的Pod中斷退出操作,例如,硬體或系統內核故障、網路故障以及節點資源不足導致Pod物件被驅逐等;
- 自愿中斷,是指那些由用戶特地執行的管理操作導致的Pod中斷,例如排空節點、人為洗掉Pod物件、由更新操作觸發的Pod物件重建等,
盡管Deployment或ReplicaSet一類的控制器能夠確保相應Pod物件的副本數量不斷逼近期望的數量,但它卻無法保證在某一時刻一定會存在指定數量或比例的Pod物件,然而這種需求在某些強調服務可用性的場景中卻是必備的,
Pod中斷預算(PodDisruptionBudget,PDB)可用于為自愿中斷做好預算方案(Budget),限制可自愿中斷的最大Pod副本數或確保最少可用的Pod副本數,以確保服務的高可用性,
定義PDB資源時,spec欄位主要嵌套使用以下三個欄位:
- selector,當前PDB物件使用的標簽選擇器,一般是與相關的Pod控制器使用同一個選擇器,
- minAvailable,Pod自愿中斷的場景中,至少要保證可用的Pod物件數量或比例,要阻止任何Pod物件發生自愿中斷,可將其設定為100%
- maxUnavailable,Pod自愿中斷的場景中,最多可轉換為不可用狀態的Pod物件數量或比例,0值意味著不允許Pod物件進行自愿中斷,此欄位與minAvailable互斥,
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: pdb1
spec:
minAvailable: 2
selector:
matchLabels:
app: myapp
學習資料
《Kubernetes實戰進階》 馬永亮著
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/282824.html
標籤:其他
