一、Pod控制器類別
1.1 ReplicaSet
ReplicaSet控制器用來管理無狀態的Pod資源,核心作用在於代用戶創建指定數量的Pod副本,並確保Pod副本數量一直等於用戶期望的數量。而且還支持Pod滾動更新、及自動擴縮容等機制;它被稱新一代的ReplicationCtroller。
ReplicaSet主要有三個組件組成:
- 用戶期望的Pod副本數量;
- 標籤選擇器,用來選定由自己管理或控制的Pod副本,如果通過標籤選擇器挑選到的Pod少於定義的Pod副本數量,則會利用Pod資源模版來創建Pod副本,以達到規定的Pod數量;
- Pod資源模版。
但是Kubernetes卻不建議用戶直接使用ReplicaSet,而是應該使用Deployment。
1.2 Deployment
Deployment也是Pod控制器,但是它是工作在ReplicaSet之上的。Deployment是通過控制ReplicaSet,從而來控制Pod。Deployment能夠提供比ReplicaSet更爲強大的功能。比如:Pod版本回滾、聲明式配置(聲明式配置是已經創建的Pod可以隨時更改配置並應用到Pod)。Deployment是目前管理無狀態應用最好的控制器。
1.3 DaemonSet
DaemonSet用於確保集羣中的每一個節點只運行一個特定的Pod副本,這種特定的Pod通常是用來實現系統級的後臺任務。把這樣的任務託管在Kubernetes之上的好處是:如果這個後臺任務宕了以後,會由DaemonSet控制器自動重建一個Pod;新建一個Node節點,它也會在新節點上創建一個這樣的Pod運行。
約束:我們也可以根據自己的需求,在K8S羣集中的部分滿足條件的節點上僅運行一個Pod副本。
總結: Deployment和DaemonSet管理的Pod中運行的服務都是無狀態的,且是守護進程類的(必須始終持續運行在後臺)。但是對於那種只希望運行一次就結束的任務,顯然以上兩種控制器是不能夠使用的。例如:我們需要對數據庫進行備份,備份結束後,任務就應該結束了,而不是讓任務持續運行在後臺。那麼對於這種任務只運行一次,只要任務完成就正常退出,沒有完成纔會重建,這就應該選擇使用Job這種控制器了。
1.4 Job
Job控制器控制只能執行一次作業的任務,它確保這個任務確實是正常完成而退出的,如果是異常退出,則Job控制器會重建任務再次執行直到任務正常完成。
那麼對於週期性的任務呢?顯然Job控制器也是無法勝任的。這就需要CronJob了。
1.5 CronJob
CronJob與Job類似,也是運行一次就退出。不同之處在於,Job是隻運行一次,CronJob是週期性運行。但每次運行都會有正常退出的時間。如果前一次任務還沒執行完成,又到了下一次任務執行的時間點了怎麼辦呢?CronJob也可以解決這種問題。
1.6 StatufulSet
StatufulSet控制器能夠管理有狀態的Pod副本,而且每一個Pod副本都是被單獨管理的,它擁有自己獨有的標誌和獨有的數據集。一旦這個副本故障了,在重建Pod之前會做許多初始化操作。以Redis羣集爲例:如果Redis集羣中三個節點中的某一個節點宕機了,爲了確保每個節點宕機後數據不丟失,我們傳統的做法就是對每個節點做主從複製,當主節點宕機後,需要人爲的把從節點提升爲主節點,想要恢復從節點,就需要很多運維操作了。
但是利用StatufulSet去定義管理Redis或Mysql或者Zookeeper,它們的配置是不一樣的。例如:配置管理Redis主從複製和配置管理Mysql主從複製中間的操作步驟是不一樣的。所以這樣的配置沒有任何規律可循。StatufulSet給我們提供了一個封裝,用戶把需要人爲操作的複雜的執行邏輯定義成腳本,放置在StatufulSet的Pod模板中。這樣在每次Pod節點故障後,能通過腳本自動恢復過來。
總結:真正想把有狀態的應用託管在Kubernetes之上,還是有相當的難度。
1.7 CDR
Custom Defined Resources K8S 1.8+,用戶自定義資源。
1.8 Helm
任何不把用戶當傻瓜的應用,都難以取得成功。K8S資源清單定義起來,門檻過高,難度大。這就誕生了Helm,Helm對於Kubernetes來說,就相當於Linux系統中的yum。以後在再部署大型的應用,就可以用Helm直接安裝部署。不過Helm到目前爲止,誕生也不超過兩年的時間。到目前爲止,許多大型主流的應用,已經可以通過Helm去部署。
二、ReplicaSet資源清單
ReplicaSet資源清單定義時的一級字段:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
spec:
spec下一級核心字段主要的有三個:
replicas <integer> # 定義Pod副本數量
selector <Object> # 選擇器
template <Object> # 模板
template字段中嵌套的就是Pod資源清單定義的字段:
metadata <Object> # 這是定義Pod的元數據
spec <Object> # Pod的spec
接下來,我們來定義一個ReplicaSet的資源清單:rs-demo.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp
namespace: default
spec:
replicas: 2 #pod副本數量爲2
selector:
matchLabels: #pod模板中的labels必須能被ReplicaSet的標籤選擇匹配到
app: myapp
release: canary
template:
metadata:
name: myapp-pod
labels: #pod模板中的labels必須能被ReplicaSet的標籤選擇匹配到
app: myapp
release: canary
environment: qa
spec:
containers:
- name: myapp-container
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
利用上述清單創建一個名爲myapp的ReplicaSet:
[root@s1 ~]# kubectl create -f rs-demo.yaml
replicaset.apps/myapp created
[root@s1 ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
myapp 2 2 2 16s
myapp-7c468db58f 2 2 2 23h
ReplicaSet可以簡寫爲rs。
值得注意的是,在Pod模板中定義的Pod名稱(如上代碼:
name: myapp-pod
)實際上是不起作用的。因爲通過控制器清單文件創建的Pod名稱是由按照控制器名稱-隨機字符串
這樣的形式命名的。如下圖:
獲取創建的Pod:
[root@s1 ~]# kubectl get pods -o wide -l app
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-fdb9l 1/1 Running 0 3m35s 10.244.2.15 n2 <none> <none>
myapp-ngm2v 1/1 Running 0 3m35s 10.244.1.16 n1 <none> <none>
三、Deployment資源清單
Deployment管理保留的ReplicaSet版本數量可以由用戶自定義,默認保留10個歷史版本。Deployment能夠使用聲明式配置,聲明式配置是使用kubectl apply -f demo.yaml
命令。對於聲明式配置的資源,將來還可以在命令行使用patch
子命令去打補丁實現配置修改更新。
Deployment在控制Pod滾動更新時,還可以配置Pod的滾動更新邏輯。
Deployment、ReplicaSet、Pod三者之間的關係:
更新Pod容器的鏡像後,新版本Pod更新示意圖:
Deployment可以簡寫爲deploy
接下來看看Deployment資源清單一級字段:
apiVersion: apps/v1
kind: Deployment
metadata:
spec:
Deployment的spec與ReplicaSet的spec區別不大。
Deployment中的spec字段:
replicas <integer> # Pod副本數量
selector <Object> # 標籤選擇器
template <Object> -required- # Pod模板
strategy <Object> # 定義Pod更新策略
paused <boolean>
revisionHistoryLimit <integer>
3.1 strategy(Pod更新策略)
spec:
strategy:
type: # <string>
rollingUpdate: # <Object>
strategy.type字段取值:
Recreate
: 重建更新,就是刪除一個Pod,再重建一個Pod。當type
爲recreate
時,與type同級的rollingUpdate字段就失效了。當type
爲rollingUpdate
,與type同級的rollingUpdate
字段定義滾動更新的策略。RollingUpdate
:滾動更新strategy.rollingUpdate字段:
maxSurge
:Pod滾動更新時,最多能超出replicas定義的Pod副本數的個數。有兩種取值方式:1. 直接指定一個數字(ex: 5);2. 指定一個百分比(ex: 10%)。maxUnavailable
:Pod滾動更新時,最多有幾個不可用。假設replicas
值爲5,maxUnavailable
值爲1,那麼可用的Pod數量至少爲5-1=4個。此字段同樣可以指定一個百分比做爲值。
例如:Pod滾動更新時,多則只能多2個,少則只能少1個,則可以這樣定義:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
3.2 revisionHistoryLimit
revisionHistoryLimit <integer>
表示要保留以允許回滾的舊ReplicaSet的數量。默認是10個。如果值爲0,表示不保存舊版本。
3.3 paused
paused <boolean>
表示部署Pod時是否暫停,通常情況下是不暫停的,執行命令後會立即部署Pod。
3.4 template
template <Object> -required-
Pod模板與ReplicaSet中Pod模板定義一致。
3.5 Deployment資源清單示例
編輯yaml文件:deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
這裏我們用聲明式創建:
[root@s1 ~]# kubectl create -f deploy-demo.yaml
deployment.apps/myapp-deploy created
[root@s1 ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
myapp-deploy-7d574d56c7 2 2 2 92s
[root@s1 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-deploy-7d574d56c7-rwrxv 1/1 Running 0 5s
myapp-deploy-7d574d56c7-znnvg 1/1 Running 0 5s
pod-demo 0/2 Terminating 0 6m
自動創建的ReplicaSet命名規則:
deploy名稱-Pod模板hash值
。Pod的命令規則:
deploy名稱-Pod模板hash值-隨機字符串
。
這時我們想要改變Pod副本數量,可以直接vim deploy-demo.yaml
修改replicas: 4
,然後再執行kubectl apply -f deploy-demo.yaml
。
注意:聲明式創建,相同的yaml文件可以多次執行
kubectl apply
。而kubectl create
只能執行一次。
上述示例清單中,有很多字段我們都沒有定義。Kubernetes會自動填充默認值。可以通過命令:kubectl get deploy myapp-deploy -o yaml
查看。
3.5.1 更新操作
我們先修改deploy-demo.yaml,將容器的鏡像版本修改爲v2:
[root@s1 ~]# vim deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80
再次部署:
[root@s1 ~]# kubectl apply -f deploy-demo.yaml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
deployment.apps/myapp-deploy configured
[root@s1 ~]# kubectl get pods -l app=myapp -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-798dc9b584-r9rpm 1/1 Running 0 23s 10.244.2.17 n2 <none> <none>
myapp-deploy-798dc9b584-vm6w8 1/1 Running 0 24s 10.244.1.19 n1 <none> <none>
訪問pod,查看版本號:
[root@s1 ~]# curl 10.244.2.17
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@s1 ~]# curl 10.244.1.19
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
查看滾動歷史記錄:
[root@s1 ~]# kubectl rollout history deployment myapp-deploy
deployment.apps/myapp-deploy
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3.5.2 通過打補丁的方式更新資源清單配置
可以看到Pod副本個數立即更新到5個了
[root@s1 ~]# kubectl patch deployment myapp-deploy -p '{"spec": {"replicas": 5}}'
deployment.apps/myapp-deploy patched
[root@s1 ~]# kubectl get pod -l release=canary
NAME READY STATUS RESTARTS AGE
myapp-deploy-798dc9b584-h9tch 1/1 Running 0 32s
myapp-deploy-798dc9b584-hn8bk 1/1 Running 0 32s
myapp-deploy-798dc9b584-r9rpm 1/1 Running 0 5m37s
myapp-deploy-798dc9b584-vm6w8 1/1 Running 0 5m38s
myapp-deploy-798dc9b584-z4tzh 1/1 Running 0 32s
通過打補丁的方式修改滾動更新策略:
[root@s1 ~]# kubectl patch deployment myapp-deploy -p '{"spec": {"strategy": {"type": "RollingUpdate", "rollingUpdate": {"maxSurge": 1, "maxUnavailable": 0}}}}'
deployment.apps/myapp-deploy patched
查看一下滾動更新策略,已經應用修改:
3.5.3 暫停Pod更新
爲了做這個示例,我們可以先修改鏡像版本,然後立即暫停滾動更新。
修改鏡像版本除了使用vim
命令直接編輯yaml文件或使用kubectl patch
打補丁外,還可以使用kubectl set image
直接修改鏡像。示例:kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
命令如下:
[root@s1 ~]# kubectl set image deployment myapp-deploy myapp=ikubernetes/myapp:v3 && kubectl rollout pause deployment myapp-deploy
deployment.apps/myapp-deploy image updated
deployment.apps/myapp-deploy paused
另開啓一個終端,監控label爲app=myapp
的Pod:
[root@s1 ~]# kubectl get pods -l app=myapp -w
NAME READY STATUS RESTARTS AGE
myapp-deploy-798dc9b584-h9tch 1/1 Running 0 16m
myapp-deploy-798dc9b584-hn8bk 1/1 Running 0 16m
myapp-deploy-798dc9b584-r9rpm 1/1 Running 0 21m
myapp-deploy-798dc9b584-vm6w8 1/1 Running 0 21m
myapp-deploy-798dc9b584-z4tzh 1/1 Running 0 16m
myapp-deploy-5dc9c974d7-kk5vg 0/1 Pending 0 0s
myapp-deploy-5dc9c974d7-kk5vg 0/1 Pending 0 0s
myapp-deploy-5dc9c974d7-kk5vg 0/1 ContainerCreating 0 0s
myapp-deploy-5dc9c974d7-kk5vg 1/1 Running 0 2s
通過上圖可以看到,滾動更新暫停命令執行後,會先創建一個新Pod並運行,然後就暫停住了,舊Pod也沒有刪除一個。此時有6個Pod,如下圖:
其中一個使用是新版本v3的image,其餘的是v2:
[root@s1 ~]# kubectl get deployment myapp-deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
myapp-deploy 6/5 1 6 30m myapp ikubernetes/myapp:v3 app=myapp,release=canary
通過命令:kubectl rollout status deployment myapp-deploy
可以看到滾動更新的狀態,如下圖:
[root@s1 ~]# kubectl rollout status deployment myapp-deploy
Waiting for deployment "myapp-deploy" rollout to finish: 1 out of 5 new replicas have been updated...
圖中提示信息告訴我們:等待部署“myapp-deploy”部署完成:5個新副本中的1個已更新...
接下來我們恢復Pod更新...
3.5.4 恢復Pod更新
恢復Pod更新使用命令:
[root@s1 ~]# kubectl rollout resume deployment myapp-deploy
deployment.apps/myapp-deploy resumed
[root@s1 ~]# kubectl rollout status deployment myapp-deploy
deployment "myapp-deploy" successfully rolled out
從圖中可以看出,滾動更新完成。
看一下ReplicaSet的狀態:
從上圖中可以看到鏡像已經更新到v3版了,而且有5個Pod已經準備就緒了。
接下來執行回滾操作。。。
3.5.5 回滾操作
假如新版本的應用Pod有問題,想要回滾,就要使用命令:kubectl rollout undo,默認回滾前一個版本。
[root@s1 ~]# kubectl rollout undo deployment myapp-deploy --to-revision=1
deployment.apps/myapp-deploy rolled back
--to-revision=1
表示回滾到第1版,如果不指定--to-revision選項,則默認是回滾到前一個版本。可以通過命令kubectl rollout history deployment myapp-deploy
查看。
[root@s1 ~]# kubectl rollout history deployment myapp-deploy
deployment.apps/myapp-deploy
REVISION CHANGE-CAUSE
4 <none>
5 <none>
6 <none>
再來 看看ReplicaSet狀態:
從上圖中可以看到,已經回滾到v1版了,v1版有5個Pod準備就緒了。而v3版的Pod數爲0 。
四、DaemonSet資源清單
DaemonSet控制器能夠在指定節點上運行能夠實現系統級的管理功能的Pod,而且每個指定節點只運行一個這樣的Pod副本。還可以把節點的目錄掛載至Pod中,通過Pod實現某些管理功能。
DaemonSet定義資源清單時,不再需要用replicas
字段指定副本數量了。
DaemonSet資源清單文件中spec字段包含的子字段:
revisionHistoryLimit <integer> # rs歷史版本保存個數,與Deployment中的此字段意義相同。
selector <Object> # 標籤選擇器
template <Object> -required- # Pod模板
updateStrategy <Object> # Pod更新策略
DaemonSet的Pod更新策略有兩種:
"RollingUpdate"
和"OnDelete"
,只有類型爲RollingUpdate
時,與type同級的字段rollingUpdate
才生效。rollingUpdate
字段下只有maxUnavailable
一個字段。也就是說DaemonSet的Pod更新時,只能少,不能多。
DaemonSet資源清單示例:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat-ds
namespace: default
spec:
selector:
matchLabels:
app: filebeat
release: stable
template:
metadata:
labels:
app: filebeat
release: stable
spec:
containers:
- name: filebeat
image: ikubernetes/filebeat:5.6.5-alpine
env:
- name: REDIS_HOST
value: redis-svc
- name: REDIS_LOG_LEVEL
value: info