控制器
正式開始之前集币,先來回顧一下上節(jié)課的內(nèi)容偶妖。
再來用上帝視角看一下今天要講的2個主角Deployment和ReplicaSet之間的關(guān)系是什么董虱?
ReplicationController(rc)
Replication Controller簡稱RC溃槐,RC是Kubernetes系統(tǒng)中的核心概念之一牺弄,簡單來說柑爸,RC可以保證在任意時間運行Pod的副本數(shù)量,能夠保證Pod總是可用的阔挠。如果實際Pod數(shù)量比指定的多那就結(jié)束掉多余的晃跺,如果實際數(shù)量比指定的少就新啟動一些Pod,當Pod失敗衅疙、被刪除或者掛掉后翁逞,RC都會去自動創(chuàng)建新的Pod來保證副本數(shù)量必怜,所以即使只有一個Pod胧后,我們也應(yīng)該使用RC來管理我們的Pod存哲。
解釋上面這個圖:
- PodA是直接通過pod方式創(chuàng)建的。
- PodB是通過rc、rs或者deploy創(chuàng)建的。
- 當node1出現(xiàn)問題時掺涛,因為PodB有控制器保障數(shù)量减拭,會自動找合適的節(jié)點進行調(diào)度啥纸,而PodA并不會盾致。
如上圖所示穗酥,ReplicationController主要包含三個部分:
- Pod selector(用來定位pod)
- replicas(定義副本梳理)
- pod template(被控制pod的模板)
如上圖所示,我們來看一下當一個pod被刪除時草丧,ReplicationController的工作過程委粉。當kubia-53thy被刪除后忿墅,ReplicationController發(fā)現(xiàn)數(shù)量不匹配(期望3個)扁藕,立刻在創(chuàng)建一個新的pod出來。
ReplicaSet(rs)
Replication Set簡稱RS疚脐,隨著Kubernetes的高速發(fā)展亿柑,官方已經(jīng)推薦我們使用RS和Deployment來代替RC了,實際上RS和RC的功能基本一致棍弄,目前唯一的一個區(qū)別就是RC只支持基于等式的selector(env=dev或environment!=qa)望薄,但RS還支持基于集合的selector(version in (v1.0, v2.0)。
代用戶創(chuàng)建指定數(shù)量的pod副本數(shù)量呼畸,確保pod副本數(shù)量符合預期狀態(tài)痕支,并且支持滾動式自動擴容和縮容功能。
ReplicaSet主要三個組件組成:
- 用戶期望的pod副本數(shù)量
- 標簽選擇器役耕,判斷哪個pod歸自己管理
- 當現(xiàn)存的pod數(shù)量不足,會根據(jù)pod資源模板進行新建
幫助用戶管理無狀態(tài)的pod資源聪廉,精確反應(yīng)用戶定義的目標數(shù)量瞬痘,但是RelicaSet不是直接使用的控制器,而是使用Deployment板熊。(大家想想這是什么原因)
apiVersion: apps/v1 #api版本定義
kind: ReplicaSet #定義資源類型為ReplicaSet
metadata: #元數(shù)據(jù)定義
name: myapp
namespace: default
spec: #ReplicaSet的規(guī)格定義
replicas: 2 #定義副本數(shù)量為2個
selector: #標簽選擇器框全,定義匹配pod的標簽
matchLabels:
app: myapp
release: canary
template: #pod的模板定義
metadata: #pod的元數(shù)據(jù)定義
name: myapp-pod #自定義pod的名稱
labels: #定義pod的標簽,需要和上面定義的標簽一致干签,也可以多出其他標簽
app: myapp
release: canary
environment: qa
spec: #pod的規(guī)格定義
containers: #容器定義
- name: myapp-container #容器名稱
image: ikubernetes/myapp:v1 #容器鏡像
ports: #暴露端口
- name: http
containerPort: 80
Deployment(deploy)
工作在ReplicaSet之上津辩,用于管理無狀態(tài)應(yīng)用,目前來說最好的控制器容劳。支持滾動更新和回滾功能喘沿,還提供聲明式配置。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
generation: 14
labels:
app: fbs-cc-v2
mode: new-production
role: default
tier: backend
name: fbs-cc-v2
namespace: new-production
spec:
progressDeadlineSeconds: 600
replicas: 8 #是可以選字段竭贩,指定期望的pod數(shù)量蚜印,默認是1。
revisionHistoryLimit: 10
selector: #是可選字段留量,用來指定 label selector 窄赋,圈定Deployment管理的pod范圍哟冬。
matchLabels:
app: fbs-cc-v2
mode: new-production
role: default
tier: backend
strategy: #指定新的Pod替換舊的Pod的策略。 .spec.strategy.type 可以是"Recreate"或者是 "RollingUpdate"忆绰。"RollingUpdate"是默認值浩峡。
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template: #是 pod template. 它跟 Pod有一模一樣的schema,除了它是嵌套的并且不需要apiVersion 和 kind字段错敢。
……
strategy(更新策略):
- Recreate: 重建式更新翰灾,就是刪一個建一個。類似于ReplicaSet的更新方式伐债,即首先刪除現(xiàn)有的Pod對象预侯,然后由控制器基于新模板重新創(chuàng)建新版本資源對象。
- rollingUpdate:滾動更新峰锁,簡單定義 更新期間pod最多有幾個等萎馅。可以指定maxUnavailable 和 maxSurge 來控制 rolling update 進程虹蒋。
- maxSurge:.spec.strategy.rollingUpdate.maxSurge 是可選配置項糜芳,用來指定可以超過期望的Pod數(shù)量的最大個數(shù)。該值可以是一個絕對值(例如5)或者是期望的Pod數(shù)量的百分比(例如10%)魄衅。當MaxUnavailable為0時該值不可以為0峭竣。
- maxUnavailable:.spec.strategy.rollingUpdate.maxUnavailable 是可選配置項,用來指定在升級過程中不可用Pod的最大數(shù)量晃虫。該值可以是一個絕對值(例如5)皆撩,也可以是期望Pod數(shù)量的百分比(例如10%)。通過計算百分比的絕對值向下取整哲银。
例如扛吞,該值設(shè)置成30%,啟動rolling update后新的ReplicatSet將會立即擴容荆责,新老Pod的總數(shù)不能超過期望的Pod數(shù)量的130%滥比。舊的Pod被殺掉后,新的ReplicaSet將繼續(xù)擴容做院,舊的ReplicaSet會進一步縮容盲泛,確保在升級的所有時刻所有的Pod數(shù)量和不會超過期望Pod數(shù)量的130%。
例如键耕,該值設(shè)置成30%寺滚,啟動rolling update后舊的ReplicatSet將會立即縮容到期望的Pod數(shù)量的70%。新的Pod ready后屈雄,隨著新的ReplicaSet的擴容玛迄,舊的ReplicaSet會進一步縮容確保在升級的所有時刻可以用的Pod數(shù)量至少是期望Pod數(shù)量的70%。
[root@master1 ~]# kubectl get deploy fbs-cc-v2 -n new-production
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
fbs-cc-v2 8 8 8 8 29d
- DESIRED:用戶期望的 Pod 副本個數(shù)(spec.replicas 的值)棚亩;
- CURRENT:當前處于 Running 狀態(tài)的 Pod 的個數(shù)蓖议;
- UP-TO-DATE:當前處于最新版本的 Pod 的個數(shù)虏杰,所謂最新版本指的是 Pod 的 Spec 部分與 Deployment 里 Pod 模板里定義的完全一致;
- AVAILABLE:當前已經(jīng)可用的 Pod 的個數(shù)勒虾,即:既是 Running 狀態(tài)纺阔,又是最新版本,并且已經(jīng)處于 Ready(健康檢查正確)狀態(tài)的 Pod 的個數(shù)修然。
控制循環(huán)(調(diào)諧)
實際上笛钝,k8s的控制器它們都遵循 Kubernetes 項目中的一個通用編排模式,即:控制循環(huán)愕宋。
比如玻靡,現(xiàn)在有一種待編排的對象 X,它有一個對應(yīng)的控制器中贝。那么囤捻,我就可以用一段 Go 語言風格的偽代碼,為你描述這個控制循環(huán):
for {
實際狀態(tài) := 獲取集群中對象 X 的實際狀態(tài)(Actual State)
期望狀態(tài) := 獲取集群中對象 X 的期望狀態(tài)(Desired State)
if 實際狀態(tài) == 期望狀態(tài){
什么都不做
} else {
執(zhí)行編排動作邻寿,將實際狀態(tài)調(diào)整為期望狀態(tài)
}
}
實際狀態(tài)
實際狀態(tài)往往來自于 Kubernetes 集群本身蝎土。
比如,kubelet 通過心跳匯報的容器狀態(tài)和節(jié)點狀態(tài)绣否,或者監(jiān)控系統(tǒng)中保存的應(yīng)用監(jiān)控數(shù)據(jù)誊涯,或者控制器主動收集的它自己感興趣的信息,這些都是常見的實際狀態(tài)的來源蒜撮。
期望狀態(tài)
期望狀態(tài)一般來自于用戶提交的 YAML 文件暴构。
比如,Deployment 對象中 Replicas 字段的值段磨。很明顯取逾,這些信息往往都保存在 Etcd 中。
接下來薇溃,以 Deployment 為例:
- Deployment 控制器從 Etcd 中獲取到所有攜帶了“app: nginx”標簽的 Pod菌赖,然后統(tǒng)計它們的數(shù)量缭乘,這就是實際狀態(tài)沐序;
- Deployment 對象的 Replicas 字段的值就是期望狀態(tài);
- Deployment 控制器將兩個狀態(tài)做比較堕绩,然后根據(jù)比較結(jié)果策幼,確定是創(chuàng)建 Pod,還是刪除已有的 Pod奴紧。
可以看到特姐,一個 Kubernetes 對象的主要編排邏輯,實際上是在第三步的“對比”階段完成的黍氮。這個操作唐含,通常被叫作調(diào)諧(Reconcile)浅浮。這個調(diào)諧的過程,則被稱作“Reconcile Loop”(調(diào)諧循環(huán))或者“Sync Loop”(同步循環(huán))捷枯。
k8s使用的是一種“用一種對象管理另一種對象”的“藝術(shù)”滚秩。
其中,這個控制器對象本身淮捆,負責定義被管理對象的期望狀態(tài)郁油。比如,Deployment 里的 replicas=2 這個字段攀痊。
而被控制對象的定義桐腌,則來自于一個“模板”。比如苟径,Deployment 里的 template 字段案站。可以看到涩笤,Deployment 這個 template 字段里的內(nèi)容嚼吞,跟一個標準的 Pod 對象的 API 定義,絲毫不差蹬碧。而所有被這個 Deployment 管理的 Pod 實例舱禽,其實都是根據(jù)這個 template 字段的內(nèi)容創(chuàng)建出來的。像 Deployment 定義的 template 字段恩沽,在 Kubernetes 項目中有一個專有的名字誊稚,叫作 PodTemplate。
如上圖所示罗心,類似 Deployment 這樣的一個控制器里伯,實際上都是由上半部分的控制器定義(包括期望狀態(tài)),加上下半部分的被控制對象的模板組成的渤闷。
現(xiàn)在疾瓮,請思考一個問題,假如我把其中一個pod的label改了飒箭,會發(fā)生什么狼电?
對pod模板內(nèi)容進行修改,只有在刪除pod弦蹂,rc嘗試重新創(chuàng)建pod時才會用新的pod模板肩碟。
在刪除一個rc時,如果不想同步刪除pod 要加上--cascade=false凸椿,當rc刪除后削祈,這些pod會變成沒人管的“孤兒”。
實戰(zhàn)體驗
#查看deploy
kubectl get deploy -n mengtms1
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
boss-dahai-com 1 1 1 1 41d
cc-dahai-com 1 1 1 1 41d
libs-dahai-com 1 1 1 1 41d
#查看replicaset
kubectl get rs -n mengtms1
NAME DESIRED CURRENT READY AGE
boss-dahai-com-68788f7775 0 0 0 41d
boss-dahai-com-6f5987c966 1 1 1 3d
cc-dahai-com-77f7bf5867 0 0 0 41d
cc-dahai-com-78df67c954 1 1 1 41d
libs-dahai-com-5db64968f7 1 1 1 41d
#查看pod
kubectl get pods --show-labels -n mengtms1
NAME READY STATUS RESTARTS AGE LABELS
boss-dahai-com-6f5987c966-d2zkn 1/1 Running 0 3d app=boss-dahai-com,pod-template-hash=2915437522,tier=frontend
cc-dahai-com-78df67c954-qr6zq 1/1 Running 0 41d app=cc-dahai-com,pod-template-hash=3489237510,tier=backend
libs-dahai-com-5db64968f7-nxw26 1/1 Running 0 41d app=libs-dahai-com,pod-template-hash=1862052493,tier=backend
# 擴容
## 通過scale命令
kubectl scale deployment cc-dahai-com --replicas 3 -n mengtms1
deployment "cc-dahai-com" scaled
## 通過修改yaml文件/修改deploy文件
kubectl edit deployment cc-dahai-com -n mengtms1
……
replicas: 3
……
## 查看pod數(shù)變化
kubectl get deploy -n mengtms1
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
boss-dahai-com 1 1 1 1 41d
cc-dahai-com 3 3 3 3 41d
libs-dahai-com 1 1 1 1 41d
## 滾動升級/藍綠部署
kubectl scale deployment cc-dahai-com --replicas 10 -n mengtms1
kubectl edit deployment cc-dahai-com -n mengtms1
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
boss-dahai-com 1 1 1 1 41d
cc-dahai-com 10 10 10 10 41d
libs-dahai-com 1 1 1 1 41d
### fbs-cc:master-20190704174559
### fbs-cc:master-20190704103840
## 觀察滾動升級過程
kubectl rollout status deployment cc-dahai-com -n mengtms1
Waiting for rollout to finish: 2 out of 10 new replicas have been updated...
# 金絲雀環(huán)境/灰度發(fā)布/ABTest
## 將deploy設(shè)置為pause
kubectl set image deploy cc-dahai-com cc-dahai-com=image.docker.dahai.com/apps/fbs-cc:master-20190704174559 -n mengtms1 && kubectl rollout pause deploy cc-dahai-com -n mengtms1
## 觀察滾動升級過程,發(fā)現(xiàn)不再持續(xù)更新
kubectl rollout status deployment cc-dahai-com -n mengtms1
Waiting for rollout to finish: 0 out of 10 new replicas have been updated...
## 查看pod
kubectl get pods -l app=cc-dahai-com -n mengtms1 -w
## 確保更新的pod沒問題了髓抑,繼續(xù)更新咙崎,恢復滾動升級過程
kubectl rollout resume deploy cc-dahai-com -n mengtms1
# 回滾
## 查看版本
kubectl rollout history deploy cc-dahai-com -n mengtms1
deployments "cc-dahai-com"
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
6 <none>
7 <none>
## 查看對應(yīng)版本的信息
kubectl rollout history deploy cc-dahai-com -n mengtms1 --revision=2
deployments "cc-dahai-com" with revision #2
Pod Template:
Labels: app=cc-dahai-com
pod-template-hash=3489237510
tier=backend
Containers:
cc-dahai-com:
Image: image.docker.xxxxx/apps/cc-dahai-com:latest
Port: <none>
Limits:
cpu: 400m
memory: 1Gi
Requests:
cpu: 20m
memory: 100Mi
Liveness: http-get http://:9001/ping delay=0s timeout=1s period=10s #success=1 #failure=3
Readiness: http-get http://:9001/ping delay=0s timeout=1s period=10s #success=1 #failure=3
Environment:
NAMESPACE: (v1:metadata.namespace)
CLUSTER: dev
OCEAN_ENV: Test
ENV_TYPE:
BASE_MODE: super
OCEAN_MODE: mengtms1
SERVER_USER_ENV: mengtms1
OCEAN_APP: cc-dahai-com
SYSTEM_NAME: cc.xxxxx
Mounts:
/libs.xxxxx from libs-vol (rw)
Volumes:
libs-vol:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: mengtms1-libs-pvc
ReadOnly: false
## 回到上個版本
kubectl rollout undo deploy cc-dahai-com -n mengtms1
## 回到特定版本
kubectl rollout undo deploy cc-dahai-com -n mengtms1 --to-revision=1
DaemonSet
DaemonSet:用于確保集群中的每一個節(jié)點只運行特定的pod副本,通常用于實現(xiàn)系統(tǒng)級后臺任務(wù)吨拍。
Job
只要完成就立即退出叙凡,不需要重啟或重建。
Cronjob
周期性任務(wù)控制密末,不需要持續(xù)后臺運行握爷,
StatefulSet
管理有狀態(tài)應(yīng)用