控制器
- Pod 的分類:
- 自主式 Pod:Pod 退出後不會被創建
- 控制器管理的 Pod:在控制器的生命週期裏,始終要維持 Pod 的副本數目
- 控制器類型:
- Replication Controller和ReplicaSet
- Deployment
- DaemonSet
- StatefulSet
- Job //定時任務
- CronJob //重複任務
- HPA全稱Horizontal Pod Autoscaler
Replication Controller和ReplicaSet
- ReplicaSet 是下一代的 Replication Controller,官方推薦使用ReplicaSet。
- ReplicaSet 和 Replication Controller 的唯一區別是選擇器的支持,ReplicaSet支持新的基於集合的選擇器需求。
- ReplicaSet 確保任何時間都有指定數量的 Pod 副本在運行。
- 雖然 ReplicaSets 可以獨立使用,但今天它主要被Deployments 用作協調 Pod 創
建、刪除和更新的機制。
Deployment
- Deployment 爲 Pod 和 ReplicaSet 提供了一個申明式的定義方法。
典型的應用場景:
- 用來創建Pod和ReplicaSet
- 滾動更新和回滾
- 擴容和縮容
- 暫停與恢復
DaemonSet
- DaemonSet 確保全部(或者某些)節點上運行一個 Pod 的副本。當有節點加入集羣時, 也會爲他們新增一個 Pod 。當有節點從集羣移除時,這些Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod。
DaemonSet 的典型用法:
- 在每個節點上運行集羣存儲 DaemonSet,例如 glusterd、ceph。
- 在每個節點上運行日誌收集 DaemonSet,例如 fluentd、logstash。
- 在每個節點上運行監控 DaemonSet,例如 Prometheus Nodexporter、zabbix agent等
- 一個簡單的用法是在所有的節點上都啓動一個 DaemonSet,將被作爲每種
類型的 daemon 使用。 - 一個稍微複雜的用法是單獨對每種 daemon 類型使用多個 DaemonSet,
但具有不同的標誌, 並且對不同硬件類型具有不同的內存、CPU 要求。
StatefulSet
- StatefulSet 是用來管理有狀態應用的工作負載 API 對象。實例之間有不對
等關係,以及實例對外部數據有依賴關係的應用,稱爲“有狀態應用” - StatefulSet 用來管理 Deployment 和擴展一組 Pod,並且能爲這些 Pod
提供序號和唯一性保證。 - StatefulSets 對於需要滿足以下一個或多個需求的應用程序很有價值:
- 穩定的、唯一的網絡標識符。
- 穩定的、持久的存儲。
- 有序的、優雅的部署和縮放。
- 有序的、自動的滾動更新。
Job
- 執行批處理任務,僅執行一次任務,保證任務的一個或多個Pod成功結束。
CronJob
- Cron Job 創建基於時間調度的 Jobs。
- 一個 CronJob 對象就像 crontab (cron table) 文件中的一行,它用 Cron
格式進行編寫,並週期性地在給定的調度時間執行 Job。
HPA
- 根據資源利用率自動調整service中Pod數量,實現Pod水平自動縮放。
Replicaset控制器示例
[root@server2 manifest]# vim rs.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-example
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1
[root@server2 manifest]# kubectl apply -f rs.yml
replicaset.apps/replicaset-example created
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
replicaset-example-dcrwh 1/1 Running 0 16s 10.244.2.38 server4 <none> <none>
replicaset-example-l8gw8 1/1 Running 0 16s 10.244.1.63 server3 <none> <none>
replicaset-example-mlx8p 1/1 Running 0 16s 10.244.2.39 server4 <none> <none>
[root@server2 manifest]# vim rs.yml
spec:
replicas: 2
[root@server2 manifest]# kubectl apply -f rs.yml 直接應用,不用刪除之前的副本
replicaset.apps/replicaset-example configured
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
replicaset-example-dcrwh 1/1 Running 0 2m19s 10.244.2.38 server4 <none> <none>
replicaset-example-l8gw8 1/1 Running 0 2m19s 10.244.1.63 server3 <none> <none>
replicaset-example-mlx8p 0/1 Terminating 0 2m19s 10.244.2.39 server4 <none> <none>
//這個正在回收,默認會回收最新的pod
[root@server2 manifest]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/replicaset-example-dcrwh 1/1 Running 0 9m11s
pod/replicaset-example-l8gw8 1/1 Running 0 9m11s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
NAME DESIRED CURRENT READY AGE
replicaset.apps/replicaset-example 2 2 2 9m11s
// 多了一個控制器在前面
那我們讓副本數不變,更換鏡像哪?
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2 // 改成v2
[root@server2 manifest]# kubectl apply -f rs.yml
replicaset.apps/replicaset-example configured
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
replicaset-example-dcrwh 1/1 Running 0 11m
replicaset-example-l8gw8 1/1 Running 0 11m
// 還是這兩個pod,沒有變。
[root@server2 manifest]# vim rs.yml
replicas: 4 //再將副本改稱4個
...
image: myapp:v2
[root@server2 manifest]# kubectl apply -f rs.yml
replicaset.apps/replicaset-example configured
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
replicaset-example-bsckv 1/1 Running 0 2m 10.244.1.64 server3 <none> <none>
replicaset-example-dcrwh 1/1 Running 0 15m 10.244.2.38 server4 <none> <none>
replicaset-example-jkvfb 1/1 Running 0 2m 10.244.2.40 server4 <none> <none>
replicaset-example-l8gw8 1/1 Running 0 15m 10.244.1.63 server3 <none> <none>
// 新開起了兩個容器,我們進行訪問:
[root@server2 manifest]# curl 10.244.2.40
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@server2 manifest]# curl 10.244.1.64
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@server2 manifest]# curl 10.244.1.63
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@server2 manifest]# curl 10.244.2.38
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
//通過訪問我們發現,副本數不變更改鏡像,不會發生改變,增加副本數改變鏡像,新增的副本使用改變後的鏡像。
若要想直接全部更新,就需要使用deployment
控制器了。
Deployment控制器
[root@server2 manifest]# vim deployment.yml
apiVersion: apps/v1
kind: Deployment //和rs控制器寫法一致,只有這裏改變,因爲deployment調用的底層就是rs控制器
metadata:
name: deployment-example
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1
[root@server2 manifest]# kubectl apply -f deployment.yml
deployment.apps/deployment-example created
[root@server2 manifest]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/deployment-example-7449b5b68f-cnxsw 1/1 Running 0 18s
pod/deployment-example-7449b5b68f-kv7zb 1/1 Running 0 18s
pod/deployment-example-7449b5b68f-rfbtf 1/1 Running 0 18s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment-example 3/3 3 3 18s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-example-7449b5b68f 3 3 3 18s
我們可以看到不止有deployment控制器
,還有rs控制器
。
pod/deployment-example-7449b5b68f-cnxsw
這個pod的名稱是由 pod 名 + rs名 + pod唯一標示
組成的.
[root@server2 manifest]# vim deployment.yml
...
spec:
containers:
- name: myapp
image: myapp:v2 //將鏡像換爲v2
[root@server2 manifest]# kubectl apply -f deployment.yml
kubec deployment.apps/deployment-example configured
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-example-67764dd8bd-bqxt4 1/1 Running 0 7s
deployment-example-67764dd8bd-z8mf4 1/1 Running 0 5s
deployment-example-67764dd8bd-zwdgr 0/1 ContainerCreating 0 2s
deployment-example-7449b5b68f-cnxsw 0/1 Terminating 0 7m32s
deployment-example-7449b5b68f-kv7zb 1/1 Running 0 7m32s
deployment-example-7449b5b68f-rfbtf 1/1 Terminating 0 7m32s
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-example-67764dd8bd-bqxt4 1/1 Running 0 16s
deployment-example-67764dd8bd-z8mf4 1/1 Running 0 14s
deployment-example-67764dd8bd-zwdgr 1/1 Running 0 11s
現在我們在更換鏡像的時候會直接刪除原來的三個容器,重新打開三個pod。
而且:
[root@server2 manifest]# kubectl get all
...
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment-example 3/3 3 3 10m
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-example-67764dd8bd 3 3 3 3m4s
replicaset.apps/deployment-example-7449b5b68f 0 0 0 10m
生成了一個新的rs控制器,但是原來的rs還保留着,這是用於回滾的。
新生成的三個pod都使用的是新的rs控制器生成的。
- 回滾
[root@server2 manifest]# vim deployment.yml
...
spec:
containers:
- name: myapp
image: myapp:v1 //改回v1
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-example-7449b5b68f-c94st 1/1 Running 0 23s
deployment-example-7449b5b68f-f59mw 1/1 Running 0 20s
deployment-example-7449b5b68f-lwq2k 1/1 Running 0 17s
它就會使用原來的那個rs。
- pod更新
當我們發現一個pod的狀態不正常時,我們可以直接刪除這個pod,控制器回自動的拉取一個新的pod:
[root@server2 manifest]# kubectl delete pod deployment-example-7449b5b68f-c94st
pod "deployment-example-7449b5b68f-c94st" deleted
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-example-7449b5b68f-f59mw 1/1 Running 0 4m14s //新pod
deployment-example-7449b5b68f-lwq2k 1/1 Running 0 4m11s
deployment-example-7449b5b68f-wwpgp 1/1 Running 0 17s
- pod刪除
[root@server2 manifest]# kubectl delete -f deployment.yml
deployment.apps "deployment-example" deleted
[root@server2 manifest]# kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
// 連同控制器,rs,pod一塊刪除了
多個控制器
多個控制器和多個資源的放時一樣,用—分割開就行了
[root@server2 manifest]# vim deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-v1
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1
--- //分割線
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-v2
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2
[root@server2 manifest]# kubectl apply -f deployment.yml
deployment.apps/deployment-v1 created
deployment.apps/deployment-v2 created
[root@server2 manifest]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
deployment-v1 3/3 3 3 10s
deployment-v2 3/3 3 3 10s
[root@server2 manifest]# kubectl get rs
NAME DESIRED CURRENT READY AGE
deployment-v1-7449b5b68f 3 3 3 105s
deployment-v2-67764dd8bd 3 3 3 105s
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-v1-7449b5b68f-csldb 1/1 Running 0 119s 10.244.1.73 server3 <none> <none>
deployment-v1-7449b5b68f-srkxx 1/1 Running 0 119s 10.244.2.49 server4 <none> <none>
deployment-v1-7449b5b68f-x5c59 1/1 Running 0 119s 10.244.2.50 server4 <none> <none>
deployment-v2-67764dd8bd-bmmrc 1/1 Running 0 119s 10.244.2.51 server4 <none> <none>
deployment-v2-67764dd8bd-m5c2g 1/1 Running 0 119s 10.244.1.75 server3 <none> <none>
deployment-v2-67764dd8bd-zf8wx 1/1 Running 0 119s 10.244.1.74 server3 <none> <none>
- 刪除
[root@server2 manifest]# kubectl delete deployments.apps deployment-v1
deployment.apps "deployment-v1" deleted
[root@server2 manifest]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/deployment-v1-7449b5b68f-g2s28 1/1 Terminating 0 87s
pod/deployment-v1-7449b5b68f-l4z8q 0/1 Terminating 0 87s
pod/deployment-v1-7449b5b68f-mqkqc 1/1 Terminating 0 87s
pod/deployment-v2-67764dd8bd-89t2z 1/1 Running 0 87s
pod/deployment-v2-67764dd8bd-rqsjn 1/1 Running 0 87s
pod/deployment-v2-67764dd8bd-sqrzg 1/1 Running 0 87s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment-v2 3/3 3 3 87s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-v2-67764dd8bd 3 3 3 87s
刪除v1,v2還在。
Daemonset控制器
Daemonset控制器適用於每個節點運行一個的pod。
我們之前使用的控制器不是在每個結點運行一個的,而是有可能都再一個結點運行:
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-v1-7449b5b68f-jz5h9 0/1 ContainerCreating 0 3s <none> server4 <none> <none>
deployment-v1-7449b5b68f-lmksm 0/1 ContainerCreating 0 3s <none> server4 <none> <none>
deployment-v1-7449b5b68f-v9d64 0/1 ContainerCreating 0 3s <none> server4 <none> <none>
[root@server2 manifest]# vim daemonset.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: daemonset-example
labels:
k8s-app: zabbix-agent
spec:
selector:
matchLabels:
name: zabbix-agent
template:
metadata:
labels:
name: zabbix-agent
spec:
containers:
- name: zabbix-agent
image: zabbix-agent
[root@server2 manifest]# kubectl apply -f daemonset.yml
daemonset.apps/daemonset-example created
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
daemonset-example-67tmd 1/1 Running 0 6s 10.244.1.78 server3 <none> <none>
daemonset-example-qjtks 1/1 Running 0 6s 10.244.2.56 server4 <none> <none>
//一個結點一個,新加入的結點頁回自動拉起一個這個pod
job控制器
[root@server2 manifest]# vim job.yml
apiVersion: batch/v1
kind: Job
metadata:
name: example-job
spec:
template:
metadata:
name: example-job
spec:
containers:
- name: pi
image: perl
command: ["perl"]
args: ["-Mbignum=bpi", "-wle", "print bpi(2000)"] //計算pi的值.2000位
restartPolicy: Never
[root@server2 manifest]# kubectl apply -f job.yml
job.batch/example-job created
[root@server2 manifest]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
example-job-9vzb9 0/1 ContainerCreating 0 42s //正在拉取鏡像,比較大
example-job-9vzb9 1/1 Running 0 50s //正在計算
example-job-9vzb9 0/1 Completed 0 54s //計算完畢
[root@server2 manifest]# kubectl logs example-job-9vzb9
3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384
[root@server2 manifest]# kubectl get job
NAME COMPLETIONS DURATION AGE
example-job 1/1 54s 3m16s
[root@server2 manifest]# kubectl delete -f job.yml
job.batch "example-job" deleted
[root@server2 manifest]# kubectl get job
No resources found in default namespace.
cronjob控制器
執行週期性任務。
[root@server2 manifest]# vim cronjob.yml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: cronjob-example
spec:
schedule: "* * * * *" //每分鐘
jobTemplate:
spec:
template:
spec:
containers:
- name: cronjob
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from k8s cluster
restartPolicy: OnFailure
[root@server2 manifest]# kubectl apply -f cronjob.yml
cronjob.batch/cronjob-example created
No resources found in default namespace.
[root@server2 manifest]# kubectl get pod //每分鐘執行一次,所以等待一分鐘
No resources found in default namespace.
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
cronjob-example-1593239100-hd4mk 0/1 Completed 0 3s
[root@server2 manifest]# kubectl logs cronjob-example-1593239100-hd4mk
Sat Jun 27 06:25:03 UTC 2020
Hello from k8s cluster
//再等待一分鐘
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
cronjob-example-1593239100-hd4mk 0/1 Completed 0 60s
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
cronjob-example-1593239100-hd4mk 0/1 Completed 0 66s
cronjob-example-1593239160-mzwrz 0/1 Completed 0 5s //又拉起一個