Pod控制器:
ReplicationController:早期K8s只有這一個控制器,但后來發現讓這一個來完成所有任務,太復雜.因此被廢棄.
ReplicaSet: 它用於幫助用戶創建指定數量的Pod副本,並確保Pod副本數量一直滿足用戶期望的副本數量。
副本數量"多退少補"等機制。【它可認為就是ReplicationController的新版本。】
它由三個主要組件組成:
1. 用戶期望的Pod的副本數量.
2. 標簽選擇器: 使用它來選擇自己管理的Pod
3. Pod模板: 若標簽選擇器選擇的副本數量不足,則根據Pod模板來新建.
Deployment: 它用於幫我們管理無狀態Pod的最好的控制器.
它支持滾動更新,回滾,它還提供了聲明式配置的功能,它允許我們將來根據聲明的配置邏輯來定義,
所有定義的資源都可隨時進行重新聲明,只要該資源定義允許動態更新。
DaemonSet:用於確保集群節點上只運行一個Pod的控制器。它一般用於構建系統級應用時使用。
它不能定義副本數量,副本數量要根據集群的規模來自動創建, 即: 若集群中新加入了一個
node節點,DaemonSet將自動使用Pod模板在新節點上創建一個Pod,並精確保障每個節點上僅
運行一個Pod. 所以此控制器,必須要有Pod模板 和 標簽選擇器。
它還有另一個作用:就是用於控制Pod僅運行在指定滿足條件的節點上,並精確確保其只運行一個Pod.
它所管理的Pod:
1. 必須是守護進程,要持續運行在后台。
2. 它沒有終止那一刻,即便不忙,它也監聽文件的變動 或 用戶對某套接字的請求
Job: 主要用於創建一個完整指定任務的Pod,一旦任務完成,就會退出;但是若任務未完成,則會重新啟動,直到任務完成.
Cronjob: 它是定義一個周期性任務,Pod啟動后,和Job啟動的Pod類似,也是任務執行完成后才會終止重啟。
同時它還會自動處理一個任務還未完成,下一個啟動時間已經到了的問題。
控制器示例:
ReplicaSet控制器示例:
#若想了解下面每個參數的含義,可查看 kubectl explain replicaset
vim replicaset.yaml
apiVersion: apps/v1 #一般來說,一個清單文件的基本格式:
kind: ReplicaSet #apiVersion,kind,metadata這是必須的,下面對 spec是replicaSet的一個必要參數.
metadata: #要查看spec支持那些參數: kubectl explain replicaset.spec 即可.
name: myapp
namespace: default
spec:
replicas: 2 #這里是定義ReplicaSet的副本數量.
selector:
matchLabels:
app: myapp
release: canary
template: #查看template支持那些參數: kubectl explain replicaset.spec.template即可查看.
metadata:
name: myapp-pod #通常Pod的名稱空間必須和控制器的名稱空間一致,故可省略.
labels: #這里創建Pod的標簽必須和selector的標簽符合,否則此Pod將永久被創建下去。
app: myapp
release: canary
spec:
containers:
- name: myapp-container
image: busybox
ports:
- name:http
containerPort: 80
#啟動:
kubectl create -f replicaSet.yaml
kubectl get pods
kubectl get rs
kubectl delete pods PodName
kubectl get pods #可以查看控制器控制下的Pod個數少了,會自動被創建.
#接下來測試,控制器控制下的Pod多了會怎么
kubectl label pods PodName release=canary,app=myapp #給Pod添加標簽
kubectl get pods --show-labels
注:
此測試也說明: 在定義控制器所管理的Pod時,一定要精確定義Pod的標簽,
盡量避免出現,用戶創建的Pod標簽正好和你定義的控制器符合,產生悲劇!
另外:
service 和 控制器它們沒有直接關系,只是它們都使用標簽選擇器來獲取Pod,
這也意味着一個Service可管理多個控制器所創建的Pod.
#控制器的配置是支持動態更新的.
kubectl edit rs replicaset #將其副本數量修改一個再查看效果。
#它還支持動態更新Pod的鏡像版本.
kubectl edit rs replicaset
kubectl get rs -o wide
注:
這里查看到Pod鏡像版本修改了,但實際上正在運行的Pod的鏡像版本並沒有改變.
這時若你手動刪除一個Pod,新建的Pod將使用新版本創建.
這樣就可以輕松實現 金絲雀 發布更新了,即: 先刪除一個,讓一個Pod使用新版本,使用新版本Pod
會得到一部分流量,這一部分流量就可以作為測試流量,若2天后,沒有發現用戶抱怨Bug,則可以
手動將Pod一個一個刪除,並替換成新版本的Pod。
Deployment:

它是ReplicaSet控制器的控制器,即: Deployment控制器它不直接用於管理Pod,它是用來管理
ReplicaSet控制器的,這樣做的好處是,可實現動態更新和回滾,如上圖所示,它能實現
多種更新方式,上圖顯示的是 灰度更新 過程,它將ReplicaSetV1控制的Pod,每次一個的
刪除,並在ReplicaSetV2上重建,若ReplicaSetV2上線后,有問題,還能快速回滾到V1.
通常來說Deployment不會直接刪除ReplicaSet,它會保留10個版本,以便回滾使用。
它通過更新Pod的粒度來實現 灰度更新,金絲雀更新,藍綠更新。
它控制Pod創建粒度是 比如:
1.在刪除時,必須保障有5個Pod,但可臨時多一個Pod,則它會創建一個,刪除一個. 直到全部替換。
2.必須保障有5個,但可臨時少一個Pod,則它會先刪除一個,在創建一個,直到全部替換。
3.必須保障有5個,但可多一個,也可少一個,此時它會創建一個,刪除兩個,再創建2個,再刪除2個,直到全部替換。
4.還有一種是允許臨時多出一倍,則它會一次性創建5個,然后直接替換使用新的Pod,在把老的Pod刪除。
Deployment控制參數:
strategy: #設置更新策略
type <Recreate|RollingUpdate> #指定更新策略類型.Recreate: 它是刪除一個,重建一個.
RollingUpdate: 這是滾動更新。
rollingUpdate:
maxSurge: 用於定義滾動更新時,副本最多允許增加幾個. 它支持兩種值:
5: 表示副本數最多增加5個。
20%: 若你有10個Pod副本, 20%就是最多增加2個副本.
maxUnavailable: 最多允許幾個不可用.它也支持整數 或 百分比.
revisionHistoryLimit <Int> #設置保存幾個歷史ReplicaSet版本.默認10個
paused <boolean> #是否在更新前先暫停
vim myapp-deploy.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: cantainers: - name: myapp image: busybox ports: - name:http containerPort: 80
#編寫以上清單文件后,就可以執行:
kubectl apply -f deploy-demo.yaml
kubectl get deploy
kubectl get rs
vim deploy-demo.yaml
#修改副本數量為4
kubectl apply -f deploy-demo.yaml #修改后再次apply是運行,apply可應用配置多次,並且它會自動反映出清單的變化.
kubectl describe deploy myapp-deploy #查看Annotaions,RollingUpdateStrategy.
#測試動態滾動更新
vim deploy-demo.yaml
修改鏡像的版本為新版本.
終端2:
kubectl get pods -l app=myapp -w
終端1:
kubectl apply -f deploy-demo.yaml
再到終端2上查看滾動更新的效果。
kubectl get rs -o wide #可查看到多了一個rs,而且舊版rs的數據都是0.
kubectl rollout history deployment myapp-deploy #查看滾動更新的歷史
#通過給配置文件打補丁的方式來動態更新:
kubectl patch deployment myapp-deploy -p '{"spec":{"replicas":5}}'
注: 這樣也可以動態修改 myapp-deploy這個Deployment控制器的參數.
kubectl get pods #可看到Pod個數已經動態創建了。
#動態修改Deployment控制器滾動更新的策略:
kubectl patch deployment myapp-deploy -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
kubectl describe deploy myapp-deploy #查看更新策略
#修改Deployment控制器下Pod的鏡像為新版本,然后實現金絲雀更新.
終端1:
kubectl get pods -l app=myapp -w
終端2:
kubectl set image deployment myapp-deploy myapp=busybox:v3
kubectl rollout pause deployment myapp-deploy
終端3:
kubectl rollout status deployment myapp-deploy
終端2:
kubectl rollout resume deployment myapp-deploy
kubectl get rs -o wide
#回滾到指定版本
kubectl rollout history deployment myapp-deploy
deployment.extensions/myapp-deploy
REVISION CHANGE-CAUSE
0 <none>
2 <none>
3 <none>
4 <none>
5 <none>
kubectl rollout undo deployment myapp-deploy --to-revision=3
kubectl rollout history deployment myapp-deploy #可以看到第一版成為第四版.
deployment.extensions/myapp-deploy
REVISION CHANGE-CAUSE
0 <none>
4 <none>
5 <none>
6 <none> #先回到3版本,這里顯示為第6版
7 <none> #接着又嘗試回到2版本, 這里顯示就是7版本.
daemonSet控制器:
#查看daemonSet控制器的語法
kubectl explain ds
kubectl explain ds.spec
vim ds-demo.yaml 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: #env的用法: kubectl explain pods.spec.containers.env - name: REDIS_HOST value: redis.default.svc.cluster.local - name: REDIS_LOG_LEVEL value: info
#接着使用apply來應用daemonSet控制器的配置清單創建Pod資源.
kubectl apply -f ds-demo.yaml
#將多個相關的資源定義在一起的方式,這是工作中常用的方式. vim ds-demo.yaml apiVersion: apps/v1 kind: Deployment metadata: name: redis namespace: default spec: replicas: 1 selector: matchLabels: app: redis role: logstor template: metadata: labels: app: redis role: logstor spec: containers: - name: redis image: redis:4.0-alpine ports: - name: redis containerPort:6379 --- #這表示分隔符. 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.default.svc.cluster.local #fiebeat通過環境變量找到redis的前端service,注意這里指定的名字是redis的前端服務名,而非隨意寫! - name: REDIS_LOG_LEVEL value: info
#因為此前通過daemonSet創建了兩個Pod資源,為了避免沖突,先刪除Pod資源.
kubectl delete -f ds-demo.yaml
#接着再同時創建redis和fliebeat兩個Pod資源.
kubectl apply -f ds-demo.yaml
#接着為redis創建一個服務,來暴露redis的服務端口,以便filebeat可以將日志發送給服務,服務再將日志轉發給redis.
kubectl expose deployment redis --port=6379
kubectl get svc #查看創建的service
#驗證redis是否可以收到filebeat的日志.
kubectl get pods #等redis處於running狀態就可以登陸查看了.
kubectl exec -it redis-5b5d.... -- /bin/sh
/ data # netstat -tnl
/ data # nslookup redis.default.svc.cluster.local #解析redis的域名.
/ data # redis-cli -h redis.default.svc.cluster.local #驗證能否通過域名直接登陸redis
/ data # keys * #登陸redis成功后,查看是否有key被創建.
#登陸filebeat查看狀態
kubectl exec -it filebeat-ds-h776m -- /bin/sh
/ # ps uax
/ # cat /etc/filebeat/filebeat.yml #查看其配置文件中redis的定義.
/ # printenv #查看環境變量.
/ # kill -1 1 #使用-1信號 讓filebeat重讀配置文件,這會導致Pod重啟,不過沒事.
#另外,通過-o wide 可以看到daemonSet定義的Pod一定是一個節點上運行一個Pod.
kubectl get pods -l app=filebeat -o wide #daemonSet定義的Pod不運行在主節點上,
#主要是因為前面部署時,定義了Master節點是不調度的.
#測試時,發現以下問題:
# kubectl get node
NAME STATUS ROLES AGE VERSION
192.168.111.80 Ready node 2d21h v1.13.5
192.168.111.81 Ready node 2d21h v1.13.5
192.168.111.84 Ready,SchedulingDisabled master 2d21h v1.13.5 #主節點配置了,不調度,即污點.
192.168.111.85 NotReady,SchedulingDisabled master 2d21h v1.13.5
# kubectl get pod -l app=filebeat -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
filebeat-ds-8gfdr 1/1 Running 0 13m 10.10.171.2 192.168.111.81 <none> <none>
filebeat-ds-ml2bk 1/1 Running 1 13m 10.10.240.193 192.168.111.84 <none> <none> #竟然運作在主節點上了!!
filebeat-ds-zfx57 1/1 Running 0 13m 10.10.97.58 192.168.111.80 <none> <none>
#從運行狀態上看, 符合DaemonSet的特性,每個節點都運行一個. 但為啥它能運行在Master上,原因不明?
#daemonSet也是支持滾動更新的,怎么更新?
kubectl explain ds.spec.updatestrategy.rollingUpdate #它只支持先刪一個在創建一個, 因為一個節點只能運行一個Pod.
#定義daemonSet控制器filebeat-ds 滾動更新其下管理的Pod的image 升級到filebeat:5.6.6-alpine
kubectl set image daemonsets filebeat-ds filebeat=ikubernetes/filebeat:5.6.6-alpine
#查看Pod的更新過程
kubectl get pods -w
DaemonSet的更新策略:
updateStrategy:
type <RollingUpdate |OnDelete> #OnDelete: 即刪除時創建。
#動態更新DaemonSet:
kubectl get ds
kubectl set image daemonSets filebeat-ds filebeat=ikubernetes/filebeat:5.6.6-alpine
終端2:
kubectl get pods -w
#讓pod和宿主機的共享名稱空間:
Pods:
hostNetwork <boolean> #讓Pod共享宿主機的網絡名稱空間,啟動Pod后,可直接訪問宿主機的80,來訪問容器.
hostPID <boolean> #這其實就是Docker網絡模型中與宿主機共享網絡名稱空間的模型.
hostIPC <boolean>
