user containerN user imageN ...... user contaner1 user image1 Pause gcr.io/google_containers/pause-amd64
每個Pod中都可以包含一個或者多個容器,這些容器可以分為兩類:
- 用戶程序所在的容器,數量可多可少
- Pause容器,這是每個Pod都會有一個根容器,它的作用有兩個 : 1.可以以它為依據,評估整個Pod的健康狀態。2.可以在根容器上設置IP地址,其他容器共享此IP,實現pod內部的網絡通信
這里是Pod的內部通信,Pod之間的通信采用虛擬二層網絡技術來實現,當前環境使用的是flanne
Pod的定義
以下是Pod的資源清單,也就是yml配置
apiVersion: v1 #必選,版本號 kind: Pod #必選,資源類型,例如Pod,service,deployment metadata: #必選,元數據 name: string #必選,Pod名稱 namespace: string #Pod所在的名稱空間,默認為“default” labels: #自定義標簽 - name: string spec: #必選,Pod中容器的詳細定義 containers: #必選,Pod中容器列表 - name: string #必選,容器名稱 image: #必選,容器鏡像名稱 imagePillPolicy: [Always|Never|IfNotPresent] #獲取鏡像策略 command: [string] #啟動容器的命令參數列表,如不指定,使用打包時使用的啟動命令 args: [string] #容器啟動的參數列表 workingDir: string #容器的工作目錄 volumeMounts: #掛載到容器內部的存儲卷配置 - name: string #引用pod定義的共享存儲卷民初,需要使用volumes[]部分定義的卷名 mountPath: string #存儲卷在容器mount的絕對路徑 readOnly: boolean #是否為只讀模式 ports: #需要暴露的端口庫號列表 - name: string #端口的名稱 containerPort: int #容器需要監聽的端口號 hostPort: int #容器所在主機需要監聽的端口號,默認於Container相同 protocol: string #端口協議默認TCP env: # 容器運行前設置環境變量列表 - name: staring # 環境變量名稱 value: 環境變量值 resources: #資源現在和請求的設置 limits: #資源限制的設置 cpu: string #cpu限制,單位為core數,將用於docker run --cpu-share參數 memory: string # 內存限制,單位Mib/Gib,將用於docker run --memory參數 requests: #資源請求的設置 cpu: string #cpu請求,容器啟動的初始可用數量 memory: string #內存請求,容器啟動的初始可用量 lifecycle: #生命周期鈎子 postStart: #容器啟動后立即執行此鈎子,如果執行失敗,會根據重啟策略進行重啟 preStop: #容器終止前執行此鈎子,無論結果如何,容器都會終止 livenessProbe: #對Pod內各個容器健康檢查的設置,當探測無響應幾次后將自動重啟該容器 exec: #對Pod容器內檢查方式設置為exec方式 command: [string] #exec方式需要自定的命令或腳本 httpGet: #對Pod內容器檢查方式設置我Httpget,需要制定path,port path: string port: int host: string scheme: string HttpHeaders: - name: string value: string tcpSocket: #對Pod容器健康檢查方式這種問tcpSocket方式 port: number initialDelaySecondes: 0 #容器啟動完成后首次探測的時間,單位為秒 timeoutSeconds: 0 #對容器健康檢查探測等待響應的超時時間,單位秒,默認1秒 periodSeconds: 0 #對容器監控檢查的定期探測時間設置,單位秒,默認10秒一次 successThreshold:0 failuerThreshold:0 securityContext: privileged: false restarPolicy: [Always|Never|OnFailure] #Pod的重啟策略 nodeName: <string> #設置NodeName表示將該Pod調度到指定名稱的node節點上 nodeSeletor: obeject #設置NodeSeletor表示將該Pod調度到包含這個label的node上 imagePullSecrets:#Pull鏡像時使用的Secret名稱,以Key:secretkey格式指定 - name: string hostNetwork: false #是否使用主機網絡模式,默認false voulmes: #在該Pod上定義共享存儲卷列表 - name: string #共享存儲卷名稱(volumes類型有很多種) emptyDir: {} #類型為emtDir的存儲卷,與Pod同生命周期的一個臨時目錄。為空值 hostPath: string #類型為HostPath的存儲卷,表示掛載Pod所在的宿主機的目錄 path: string #pod所在的宿主機的目錄,將被用於同期種mount的目錄 secret: #類型為secret的存儲卷,掛載集群與定義的secret對象到容器內部 secretname: string itmes: - key: string path: string configMap: #類型為configMap的存儲卷,掛載預定義的configMap對象到容器 name:string items: - key: string path: string
可以使用以下命令查詢每種資源的配置方式
# kubectl explain 資源類型 # kubectl explain 資源類型.屬性
Pod配置
創建一個pod-base.yml文件,內容如下
apiVersion: v1 kind: Pod metadata: name: pod-base namespace: dev labels: version: test spec: containers: - name: nginx image: nginx:1.17.2 - name: busybox image: busybox:1.30
上面定義了一個比較簡單的Pod的配置,里面有兩個容器:
- nginx: 用1.17.2版本的nginx鏡像創建
- busybox: 用1.30版本的busybox鏡像創建
#創建Pod kubectl apply -f pod-bose.yml #查看Pod狀態 kubectl get pod -n dev NAME READY STATUS RESTARTS AGE nginx-64777cd554-7p7xt 1/1 Running 2 31h nginx-64777cd554-cqbjd 1/1 Running 1 25h nginx-64777cd554-tv5g2 1/1 Running 2 31h pod-base 1/2 CrashLoopBackOff 5 5m9s #可以通過describe查看內部的詳情 #此時已經運行了一個基本的pod,雖然出現了一些問題 [root@master ~]# kubectl describe pod pod-base -n dev ............ Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 4m34s default-scheduler Successfully assigned dev/pod-base to node1 Normal Pulling 4m31s kubelet, node1 Pulling image "nginx:1.17.2" Normal Pulled 3m42s kubelet, node1 Successfully pulled image "nginx:1.17.2" Normal Created 3m41s kubelet, node1 Created container nginx Normal Started 3m40s kubelet, node1 Started container nginx Normal Pulling 3m40s kubelet, node1 Pulling image "busybox:1.30" Normal Pulled 3m22s kubelet, node1 Successfully pulled image "busybox:1.30" Normal Created 2m39s (x4 over 3m22s) kubelet, node1 Created container busybox Normal Pulled 2m39s (x3 over 3m20s) kubelet, node1 Container image "busybox:1.30" already present on machine Normal Started 2m38s (x4 over 3m22s) kubelet, node1 Started container busybox Warning BackOff 2m8s (x8 over 3m19s) kubelet, node1 Back-off restarting failed container
鏡像拉取
創建pod-imagePullPolicy.yml文件,內容如下
apiVersion: v1 kind: Pod metadata: name: pod-imagepullpolicy namespace: dev spec: containers: - name: nginx image: nginx:1.17.3 imagePullPolicy: Always - name: busybox image: busybox:1.30
imagePullPolicy,用於設置鏡像拉取策略,kubernetes中支持配置的三種拉取策略
- Always:總是從遠程倉庫拉取鏡像
- IfNotPresent: 本地有鏡像則使用本地,沒有則遠程拉取
- Never: 只能使用本地鏡像,從不去遠程拉取
默認值說明:
如果鏡像tag為具體版本號,默認策略就是IfNotPersent
如果鏡像tag為latest,默認策略時always
#創建Pod kubectl apply -f pod-imagePullPolicy.yml # 查看pod kubectl get pod -n dev # 查看詳細信息 kubectl get pod pod-imagepullpolicy -n dev
啟動命令
上面的容器案例中,有一個問題沒有解決,就是busybox運行一直沒有成功,因為busybox並不是一個程序,而是一個類似工具類的集合,kubernetes集群啟動管理后,它會自動關閉,解決辦法就是讓其一直運行,就需要使用到command配置,
vim pod-command.yml apiVersion: v1 kind: Pod metadata: name: pod-command namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 imagePullPolicy: IfNotPresent - name: busybox image: busybox:1.30 command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3;done"] # 創建pod kubectl apply -f pod-command.yml #查看狀態,可以看到兩個Pod都正常運行了 [root@master ~]# kubectl get pod pod-command -n dev NAME READY STATUS RESTARTS AGE pod-command 2/2 Running 0 85s #進入pod中的busybox容器,查看文件內容 kubectl exec pod-command -n dev --it -c busybox /bin/sh
說明:
通過上面方向command已經可用完成啟動命令和傳遞參數的功能,為什么這里還要通過args選項,用於傳遞參數?
這其實和docker有點關系,kubernetes中的comand,arges兩項其實是實現覆蓋DockerfileHon中的ENTRYPOINT的功能。
- 如果command和args均沒有寫,那么就用Dockerfile的配置。
- 如果command寫了,arges沒有寫,那么Dockerfile默認的配置會被忽略,執行輸入的command
- 如果command沒寫,但args寫了,那么Dockerfile中配置的ENTRYPOINT的命令會被執行,使用當前args的參數
- 如果command和args都寫了,那么Dockerfile的配置被忽略,執行command並追加上args參數
環境變量
vim pod-env.yml apiVersion: v1 kind: Pod metadata: name: pod-env namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 imagePullPolicy: IfNotPresent - name: busybox image: busybox:1.30 command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3;done"] env: - name: "username" value: "admin" - name: "password" value: "123456"
env,環境變量,用於Pod中容器設置環境變量
# 創建Pod kubectl create -f pod-env.yml #進入容器查看環境變量 [root@master ~]# kubectl exec pod-env -n dev -it -c busybox /bin/sh / # echo $username admin / # echo $password 123456
不推薦使用這種方式,推薦這些配置在單獨存儲的配置文件中
端口設置
vim pod-ports.yml apiVersion: v1 kind: Pod metadata: name: pod-ports namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 imagePullPolicy: IfNotPresent ports: - name: nginx-port containerPort: 80 protocol: TCP #啟動pod kubectl create -f pod-ports.yml # 查看 kubectl get pod pod-ports -n dev
資源配額
容器中的程序要運行坑,而程序的運行肯定要占用一定的資源,如果不對某一個容器限定資源,可能會在某一瞬間吃掉大量的資源,導致其他容器無法運行。針對這種情況,kuberneters提供了對內存和cpu資源進行配額的機制,這個機制主要是在resources選項實現,其有兩個子選線。
- limits: 用於限制運行時容器的最大占用資源,當容器超過limits時會被終止,並進行重啟
- requests:用於設置容器需要的最小資源,如果環境資源不夠,容器將無法啟動
可用通過以上兩個選項色澤資源的上下限
vim pod-resources.yml apiVersion: v1 kind: Pod metadata: name: pod-resuorces namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 imagePullPolicy: IfNotPresent resources: limits: cpu: "1" memory: "1Gi" requests: cpu: "0.2" memory: "10Mi" # 運行pod kubectl create -f pod-resources.yml # 查看pod kubectl get pod pod-resuorces -n dev
Pod生命周期
我們一般將pod對象從創建至終的這斷時間范圍稱為pod的生命周期,它主要包含下面的過程:
-
Pod創建過程
-
運行初始化容器過程
-
運行主容器過程
容器啟動后鈎子,容器終止前鈎子
容器的存活性探測,就緒性探測
-
pod終止過程
在整個生命周期種Pod會出現5種狀態(相位),分別如下;
-
掛起(Pending):apiserver已經創建了Pod資源對象,但它尚未被調度完成或者仍處於鏡像下載狀態
-
運行中(running):pod已經被調到至某節點,並且所有容器都已經被kubelet創建完成
-
成功(Succeded): pod中的所有容器都已經成功並且不會被重啟
-
失敗(Failed): 所有容器都已經終止,但至少有一個容器終止失敗,即容器返回非0值的退出狀態
-
未知(Unkown): apiserver無法正常獲取到pod對象的狀態信息,通常由網絡通信失敗導致
初始化容器
初始化容器是在pod的主容器啟動前需要運行的容器,主要是做一些主容器的前置工作,它具有兩大特征:
1.初始化容器必選運行完成至結束,若某一個初始化容器運行失敗,那么kubernetes需要重啟直到完成為止。
2.初始化容器必選按照定義的順序執行,當且僅當前一個成功之后,后面一個才能運行
初始化容器由很多的應用場景,下面列出的是最常見的幾個;
-
提供主容器鏡像中不具被的工具程序或自定義代碼
-
初始化容器要選育應用容器串行啟動並運行完成,因此可用於延后應用容器的啟動直至其依賴的條件得到滿足
示例:
假設要以主容器來運行nginx,但是需要在運行nginx之前先要能夠連接上MySQL和redis所在的服務器,為了簡化測試,事先規定號MySQL(192.168.248.4)和redis(192.168.248.24)服務器的地址。
創建pod-initcontainer.yml
apiVersion: v1 kind: Pod metadata: name: pod-initcontainer namespace: dev spec: containers: - name: main-container image: nginx:1.17.2 ports: - name: nginx-port containerPort: 80 initContainers: - name: test-mysql image: busybox:1.30 command: ['sh','-c','until ping 192.168.248.4 -c 1;do echo waiting for mysql ... ;sleep 2;done'] - name: test-redis image: busybox:1.30 command: ['sh','-c','until ping 192.168.248.24 -c 1;do echo waiting for redis ... ;sleep 2;done'] # 啟動pod kubectl create -f pod-initcontainer.yml #查看狀態 [root@master ~]# kubectl get pod pod-initcontainer -n dev NAME READY STATUS RESTARTS AGE pod-initcontainer 0/1 Init:0/2 0 18s #動態查看狀態 [root@master ~]# kubectl get pod pod-initcontainer -n dev -w NAME READY STATUS RESTARTS AGE pod-initcontainer 0/1 Init:0/2 0 52s #新開一個窗口,為當前服務器增加兩個IP ifconfig ens33:1 192.168.248.4 netmask 255.255.255.0 up ifconfig ens33:1 192.168.248.24 netmask 255.255.255.0 up [root@master ~]# kubectl get pod pod-initcontainer -n dev -w NAME READY STATUS RESTARTS AGE pod-initcontainer 0/1 Init:0/2 0 52s pod-initcontainer 0/1 Init:1/2 0 2m37s pod-initcontainer 0/1 Init:1/2 0 2m38s pod-initcontainer 0/1 PodInitializing 0 2m51s pod-initcontainer 1/1 Running 0 2m52s
鈎子函數
鈎子函數能夠感知自身生命周期中的事件,並在相應的時候到來之運行用戶指定的程序代碼。
kubeernetes在主容器啟動之后和停止之前提供了兩個鈎子函數:
- post start: 容器創建之后執行,如果失敗了會重啟容器
- pre stop: 容器終止之前執行,執行完后后容器將成功終止,在其完成之前會刪除阻塞容器的操作
鈎子處理器支持使用下面三種方式定義動作:
Exec命令: 在容器內執行一次命令
...... lifecycle: postStart: exec: command: - cat - /tmp/healthy ......
TCPSocket: 在放棄容器嘗試訪問指定的socket
..... lifecycle: postStart: tcpoSocket: port: 8080 .....
HTTPGet:在當前容器中向某個url發起http請求
..... lifecycle: postStart: httpGet: path: / #url地址 post: 80 #端口號 host: 192.168.248.11 #主機地址 scheme: HTTP #支持協議,http或者https ......
下面以exec方式為例,演示鈎子函數的使用,創建pod-hook-exec.yml文件
apiVersion: v1 kind: Pod metadata: name: pod-hook-exec namespace: dev spec: containers: - name: main-container image: nginx:1.17.2 ports: - name: nginx-pod containerPort: 80 lifecycle: postStart: exec: command: ["/bin/sh","-c","echo postStart... > /usr/share/nginx/html/index.html"] preStop: exec: command: ["/usr/sbin/nginx","-s","quit"] # 創建pod kubectl create -f pod-hook-exec.yml # 查看pod [root@master ~]# kubectl get pod pod-hook-exec -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-hook-exec 1/1 Running 0 57s 10.244.1.43 node1 <none> <none> # 訪問測試 [root@master ~]# curl 10.244.1.43 postStart...
容器探測
容器探測用於檢測容器中的應用示例是否正常工作,是保證業務可用性的一種傳統機制。如果經過探測,示例的狀態不符合預期,那塊kubernetes就會把該問題實例"摘除",不承擔業務流量。kubernetes提供了兩種探針來實現容器探測,分別是:
-
liveness probes:存活性探針,用於檢測應用實例當前是否處於正常運行狀態,如果不是,ks會重啟容器
-
rediness probes: 就緒性探針,用於檢測應用實例當前是否可用接受到請求,如果不能,k8s不會轉發流量
上面兩種探針目前均支持三種探測方式:
Exec命令:在容器內執行一次命令,如果命令執行的退出嗎為0,則程序認為正常,否則不正常
livenessProbe: exec: command: - cat - /tmp/healthy
TCPSocket:將會嘗試訪問一個用戶容器的端口,如果能建立連接,則認為正常,否則不正常
livenessProbe: tcpSocket: port: 8080
HTTPGet:調用web應用url,如果返回在200-399,則認為程序正常,否則不正常
lifecycle: postStart: httpGet: path: / #url地址 post: 80 #端口號 host: 192.168.248.11 #主機地址 scheme: HTTP #支持協議,http或者https
下面以liveness probes為例,做幾個演示:
創建文件pod-liveness.yml
apiVersion: v1 kind: Pod metadata: name: pod-liveness namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 ports: - name: nginx-port containerPort: 80 livenessProbe: exec: command: ["/bin/cat","/tmp/hello.txt"] #創建pod [root@master ~]# kubectl create -f pod-liveness.yml pod/pod-liveness created #查看pod詳情 [root@master ~]# kubectl describe pod pod-liveness -n dev .................... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled <unknown> default-scheduler Successfully assigned dev/pod-liveness to node2 Normal Pulled 28s (x2 over 50s) kubelet, node2 Container image "nginx:1.17.2" already present on machine Normal Created 28s (x2 over 50s) kubelet, node2 Created container nginx Normal Started 28s (x2 over 50s) kubelet, node2 Started container nginx Normal Killing 28s kubelet, node2 Container nginx failed liveness probe, will be restarted Warning Unhealthy 8s (x5 over 48s) kubelet, node2 Liveness probe failed: /bin/cat: /tmp/hello.txt: No such file or directory Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled <unknown> default-scheduler Successfully assigned dev/pod-liveness to node2 Normal Pulled 28s (x2 over 50s) kubelet, node2 Container image "nginx:1.17.2" already present on machine Normal Created 28s (x2 over 50s) kubelet, node2 Created container nginx Normal Started 28s (x2 over 50s) kubelet, node2 Started container nginx Normal Killing 28s kubelet, node2 Container nginx failed liveness probe, will be restarted Warning Unhealthy 8s (x5 over 48s) kubelet, node2 Liveness probe failed: /bin/cat: /tmp/hello.txt: No such file or directory #因為沒有hello.txt文件,存活性探針會一直重啟這個Pod [root@master ~]# kubectl get pod pod-liveness -n dev NAME READY STATUS RESTARTS AGE pod-liveness 1/1 Running 4 2m21s #正確示例 [root@master ~]# kubectl delete -f pod-liveness.yml pod "pod-liveness" deleted [root@master ~]# vim pod-liveness.yml apiVersion: v1 kind: Pod metadata: name: pod-liveness namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 ports: - name: nginx-port containerPort: 80 livenessProbe: exec: command: ["/bin/ls","/tmp"] # 創建pod [root@master ~]# kubectl create -f pod-liveness.yml pod/pod-liveness created #創建成功並沒有重啟 [root@master ~]# kubectl get pod pod-liveness -n dev NAME READY STATUS RESTARTS AGE pod-liveness 1/1 Running 0 11s
TCPSocket
創建pod-liveness-tcpsocket.yml
apiVersion: v1 kind: Pod metadata: name: pod-tcpsocket namespace: dev spec: containers: - name: nginx image: nginx:1.17.1 ports: - name: nginx-port containerPort: 80 livenessProbe: tcpSocket: port: 8080 #嘗試訪問8080端口 # 創建Pod [root@master ~]# kubectl create -f pod-liveness-tcpsocket.yml pod/pod-tcpsocket created #查看信息 [root@master ~]# kubectl describe pod pod-tcpsocket -n dev ........... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled <unknown> default-scheduler Successfully assigned dev/pod-tcpsocket to node1 Normal Pulled 15s kubelet, node1 Container image "nginx:1.17.2" already present on machine Normal Created 15s kubelet, node1 Created container nginx Normal Started 15s kubelet, node1 Started container nginx Warning Unhealthy 9s kubelet, node1 Liveness probe failed: dial tcp 10.244.1.46:8080: connect: connection refused
HTTPGet
創建文件pod-liveness-httpget.yml
apiVersion: v1 kind: Pod metadata: name: pod-httpget namespace: dev spec: containers: - name: nginx image: nginx:1.17.1 ports: - name: nginx-port containerPort: 80 livenessProbe: httpGet: scheme: HTTP port: 80 path: / # 創建pod [root@master ~]# kubectl create -f pod-liveness-httpget.yml pod/pod-httpget created #查看pod詳情 [root@master ~]# kubectl describe pod pod-httpget -n dev ............. Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled <unknown> default-scheduler Successfully assigned dev/pod-httpget to node2 Normal Pulled 29s kubelet, node2 Container image "nginx:1.17.1" already present on machine Normal Created 29s kubelet, node2 Created container nginx Normal Started 29s kubelet, node2 Started container nginx [root@master ~]# vim pod-liveness-httpget.yml
重啟策略
一旦容器探測出現了問題,kubernetes就會對容器所在的Pod進行重啟,其實這是由pod重啟策略決定的,pod的重啟策略有3種,分別是:
-
Always: 容器失效時,自動重啟該容器,這也是默認從值
-
OnFailure: 容器終止運行且退出碼不為0時重啟
-
Never: 不論狀態為何,都不重啟該容器
重啟策略適用於pod對象中的所有容器,首次需要重啟的容器,將在其需要時立即進行重啟,隨后在次需要重啟的操作將由kubelet延遲一段時間后進行,並且反復的重啟操作的延遲時長為10s,20s,40s,80s,160s和300s,300s是最大延遲時長。
創建pod-restarpolicy.yml
apiVersion: v1 kind: Pod metadata: name: pod-restartpolicy namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 ports: - name: nginx-port containerPort: 80 livenessProbe: httpGet: scheme: HTTP port: 80 path: /hello restartPolicy: Never # 創建Pod [root@master ~]# kubectl create -f pod-restartpolicy.yml pod/pod-restartpolicy created # 查看Pod詳情發現nginx容器重啟失敗 [root@master ~]# kubectl describe pod pod-restartpolicy -n dev ....... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled <unknown> default-scheduler Successfully assigned dev/pod-restartpolicy to node1 Normal Pulled 2m20s kubelet, node1 Container image "nginx:1.17.2" already present on machine Normal Created 2m20s kubelet, node1 Created container nginx Normal Started 2m19s kubelet, node1 Started container nginx Warning Unhealthy 114s (x3 over 2m14s) kubelet, node1 Liveness probe failed: HTTP probe failed with statuscode: 404 Normal Killing 114s kubelet, node1 Stopping container nginx # 由於策略定義的是Never所以容器不會重啟 [root@master ~]# kubectl get pod pod-restartpolicy -n dev NAME READY STATUS RESTARTS AGE pod-restartpolicy 0/1 Completed 0 3m41
Pod調度
在默認情況下,一個Pod在那個Node節點上與性能,是由Scheduler組件采用相應的算法計算出來的,這個過程是不受人工控制的,但是在實際使用中,這並不能滿足需求,因為在很多情況下,我們想控制某些Pod到達某些節點上,應該怎么做呢?這就需要了解Kubernetes對Pod的調度規則,kubernetes提供了四大類的調度。
-
自動調度: 運行在那個節點上完全由Scheduler經過一系列是算法得出
-
定性調度: NodeName,NodeSelector
-
親和性調度: NodeAffinity,PodAffinity,PodAntiAffinity
-
污點(容忍)調度: Taints,Toleration
定向調度
定向調度,指的是利用在Pod上聲明的NodeName或者NodeSelector,以此將Pod調度到期望的node節點上。注意,這里的調 是強制的,這就意味着即使要調度的目標Node不存在,也會向上面進行調度,只不過是Pod運行失敗而已。
NodeName
NodeName用於強制約束將Pod調度到指定的node上,着種方式直接跳過了Scheduler的調度邏輯,直接寫入PodList列表中
測試一些,創建一個pod-nodename.yml
apiVersion: v1 kind: Pod metadata: name: pod-nodename namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 nodeName: node1 # 創建pod [root@master ~]# kubectl create -f pod-nodename.yml pod/pod-nodename created # 查看pod調度到Node屬性,確實調度到了node1節點上 [root@master ~]# kubectl get pod pod-nodename -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodename 1/1 Running 0 69s 10.244.1.56 node1 <none> <none>
NodeSeletor
NodeSeletor用於將Pod調度到添加了指定標簽的node節點上,它通過kubernetes的label-selector機制實現,也就是說,在Pod創建之前,會有scheduler使MatchNodeSelector調度策略進行label匹配,找出目標node,然后將Pod調度到目標節點,該匹配規則是強制約束。
示例:
# 首先分別給node節點加上標簽 [root@master ~]# kubectl label nodes node1 nodeenv=pro node/node1 labeled [root@master ~]# kubectl label nodes node2 nodeenv=dev node/node2 labeled # 創建一個pod-nodeselector.yml文件,並使用它創建pod vim pod-nodeselector.yml apiVersion: v1 kind: Pod metadata: name: pod-nodeselector namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 nodeSelector: nodeenv: dev #創建Pod [root@master ~]# kubectl create -f pod-nodeselector.yml pod/pod-nodeselector created #查看pod調度到NODE屬性,確實調度到了node2節點上 [root@master ~]# kubectl get pod pod-nodeselector -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodeselector 1/1 Running 0 22s 10.244.2.74 node2 <none> <none> # 刪除Pod,修改nodeSelector的值為一個不存在的標簽 [root@master ~]# kubectl delete -f pod-nodeselector.yml pod "pod-nodeselector" deleted [root@master ~]# vim pod-nodeselector.yml [root@master ~]# kubectl create -f pod-nodeselector.yml pod/pod-nodeselector created # 再次查看發現Pod我i發正常運行,Node的值問none [root@master ~]# kubectl get pod pod-nodeselector -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodeselector 0/1 Pending 0 56s <none> <none> <none> <none> # 查看詳情發現node selector匹配失敗的提示 [root@master ~]# kubectl describe pod pod-nodeselector -n dev .................... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling <unknown> default-scheduler 0/3 nodes are available: 3 node(s) didn't match node selector. Warning FailedScheduling <unknown> default-scheduler 0/3 nodes are available: 3 node(s) didn't match node selector.
親和性調度
定向調度使用起來非常方便,但是也有一定的問題,那就是如果沒有滿足條件的Node,那么Pod將不會運行,即使在集群中還有可以的Node列表也不行,這就限制了它的使用場景。
基於上面的問題,kubeneter還提供了一種親和性調度(Affinity)。它在NodeSelector的基礎上進行了擴展,可以通過匹配的形式,實現優先選擇滿足條件的Node進行調度,如果沒有,也可以調度到不滿足的節點上,使調度更加靈活。
Affinity主要分為三類:
-
nodeAffinity(node親和性):以node為目標,解決pod可以調度到那些node的問題
-
podAffinity(pod親和性): 以pod為目標,解決Pod可以和那些已存在的Pod部署在同一個拓撲域中的問題
-
podAntiAffinity(pod反親和性): 以pod為目標,解決pod不能和那些已存在pod部署在同一個拓撲域中的問題
關於親和性(反親和性)使用場景說明: 親和性: 如果兩個應用頻繁交互,那就有必要利用親和性讓兩個應用盡可能的靠近,這樣可以減少網絡通信而帶來的性能損耗。 反親和性:當應用采用多副本部署使,有必要采用反親和性讓各個應用實例打散分布在各個node上,這樣可以提高服務的高可用性。
NodeAffinity
首先來看一下NodeAffinity的可配置文件
od.spec.affinity.nodeAffinity requiredDuringSchedulingIgnoredDuringExecution 必須滿足指定的規則才可以調度,相當於應限制 nodeSelectorTerms 節點選擇列表 matchFields 按節點字段列出的節點選擇器要求列表 matchExpressions 按節點標簽列出的節點選擇器要求列表(推薦) key values operator 關系符 支持Exists,DoesNotExist,In,NotIn,Gt,Lt preferredDuringSchedulingIgnoredDuringExecution 優先調度到滿足指定的規則Node,相等於軟限制(傾向) preference 一個節點選擇器,於相應的權重相關聯 matchFields 按節點字段列出的節點選擇器要求列表 matchExpressions 按節點標簽列出的節點選擇器要求列表(推薦) key values operator 關系符 支持In,NotIn,Exists,DoesNotExist,Gt,Lt weight 傾向權重,在范圍1-100 關系符使用說明 - matchExpressions: - key: nodeenv # 匹配存在標簽的key為nodeenv的節點 operator: Exists - key: nodeenv # 匹配標簽的key為nodeenv,且value是"xxx"或"yyy"的節點 operator: In values: ["xxx","yyy"] - key: nodeenv #匹配標簽的key為nodeenv,且value大於"xxx"的節點 operator: Gt values: "xxx"
演示一下requireDuringSchedulingIgnoredDuringExecution
創建pod-nodeaffinity-required.yml
apiVersion: v1 kind: Pod metadata: name: pod-nodeaffinity-required namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: nodeenv operator: In values: ["xxx","yyy"] # 創建pod [root@master ~]# kubectl create -f pod-nodeaffinity-required.yml pod/pod-nodeaffinity-required created # 查看pod狀態發現運行失敗 [root@master ~]# kubectl get pod pod-nodeaffinity-required -n dev NAME READY STATUS RESTARTS AGE pod-nodeaffinity-required 0/1 Pending 0 3m19s # 查看pod發現調度失敗,提示node選擇失敗 [root@master ~]# kubectl describe pod pod-nodeaffinity-required -n dev ................. Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling <unknown> default-scheduler 0/3 nodes are available: 3 node(s) didn't match node selector. Warning FailedScheduling <unknown> default-scheduler 0/3 nodes are available: 3 node(s) didn't match node selector. # 接下來停止pod [root@master ~]# kubectl delete -f pod-nodeaffinity-required.yml pod "pod-nodeaffinity-required" deleted # 修改文件,將values: ["xxx","yyy" ]------->["dev","yyy"]后在次啟動 [root@master ~]# kubectl create -f pod-nodeaffinity-required.yml pod/pod-nodeaffinity-required created #此時查看,發現已經調度成功,已經將pod調度到了node1上 [root@master ~]# kubectl get pod pod-nodeaffinity-required -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodeaffinity-required 1/1 Running 0 42s 10.244.1.73 node1 <none> <none>
下面在演示preferredDuringSchedulingIgnoredDuringExecution
創建pod-nodeaffinity-preferred
apiVersion: v1 kind: Pod metadata: name: pod-nodeaffinity-preferred namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: nodeenv operator: In values: ["xxx","yyy"] # 創建pod [root@master ~]# kubectl create -f pod-nodeaffinity-prefereed.yml pod/pod-nodeaffinity-preferred created # 查看pod狀態(運行成功) [root@master ~]# kubectl get pod pod-nodeaffinity-preferred -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodeaffinity-preferred 1/1 Running 0 44s 10.244.2.83 node2 <none> <none> NodeAffinity規則設置的注意事項: 1.如果同時定義了nodeSelector和nodeAffinity,那么必須兩個條件都得到滿足,Pod才能運行在指定的node上 2.如果nodeAffinity指定了多個nodeSelectorTerms,那么只需要其中一個能夠匹配成功即可 3.如果一個nodeSelectorTerms中有多個matchExperssions,則一個節點必須滿足所有的才能匹配成功 4.如果一個pod所在的Node在Pod運行期間其標簽發生了改變,不再符合該Pod的節點親和性需求,則系統將忽略此變化
podAffinity配置
PodAffinty主要實現以運行的Pod為參照,實現讓新創建的Pod跟參照pod在一個區域的功能。
PodAffinity的可配置項:
pod.spec.affinity.podAffinity requiredDuringSchedulingIgnoredDuringExecution: 硬限制 namespaces 指定參照pod的namespace topologKet 指定調度作用域 labelSelector 標簽選擇器 matcheExpressions 按節點標簽列出的節點選擇器要求列表(推薦) key values operator 關系符 matchLabels 值多個matchExperssions映射的內容 preferredDuringSchedulingIgnoredDuringExecution: 軟限制 podAffinityTerm 選項 namespace topologyKey labelSelector matchExpressions key values operator matchLabels weight: 權重傾向,1-100 topologyKey用於指定調度時作用域,例如: 如果指定為kubernetes.io/hostname,那么就是以Node節點為區分范圍 如果指定為beta.kubernetes.io/os,則是以Node節點的操作系統類型來區分范圍
下面演示一下requiredDuringSchedulingIgnoredDuringExecution
創建一個pod-podaffinity-target.yml文件
apiVersion: v1 kind: Pod metadata: name: pod_podaffinity-target namespace: dev labels: version: v1 spec: containers: - name: nginx image: nginx:1.17.2 nodeName: node1 # 創建pod [root@master ~]# kubectl create -f pod-podaffinity-target.yml pod/pod-podaffinity-target created # 查看pod狀態 [root@master ~]# kubectl get pod pod-podaffinity-target -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-podaffinity-target 1/1 Running 0 39s 10.244.1.83 node1 <none> <none> # 創建pod-podaffinity-required.yml apiVersion: v1 kind: Pod metadata: name: pod-podaffinity-required namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: version operator: In values: ["v1","yyy"] topologyKey: kubernetes.io/hostname 上面配置表達的意思: 新的Pod必須要與擁有標簽version=v1或者version=yyy的pod在一個node上 # 創建Pod [root@master ~]# kubectl create -f pod-podaffinity-required.yml pod/pod-podaffinity-required created # 查看pod [root@master ~]# kubectl get pod pod-podaffinity-required -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-podaffinity-required 1/1 Running 0 89s 10.244.1.84 node1 <none> <none>
PodAntiAffinity
PodAntiAffinity主要實現以運行的Pod為參照,讓新創建的Pod跟參照的pod不在同一個區域中的功能,其配置方式和PodAffinity是一樣的。
繼續使用上一個例子中目標pod
創建pod-podantiaffinity-required.yml
apiVersion: v1 kind: Pod metadata: name: pod-podantiaffinity-required namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: version operator: In values: ["v1","yyy"] topologyKey: kubernetes.io/hostname #創建pod [root@master ~]# kubectl create -f pod-podantiaffinity-required.yml pod/pod-podantiaffinity-required created # 查看pod信息,可以看到調度到了node2上 [root@master ~]# kubectl get pod pod-podantiaffinity-required -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-podantiaffinity-required 1/1 Running 0 47s 10.244.2.93 node2 <none> <none>
污點和容忍
污點(Taints)
前面的調度方式都是站在Pod的角度上,通過在Pod上添加屬性,來確定Pod是否調度到指定的Node上,可以通過在Node上添加污點,來決定是否允許Pod調度。
Node被設置上污點一會就和Pod之間存在一種相斥的關系,從而拒絕Pod的調度,甚至可以將Pod驅逐出去
污點格式為: key=value:effect, key和value是污點的標簽,effect描敘污點的作用,支持如下3個選項:
- PreferNoSchedule: kubernetes將盡量避免把Pod調度都具有該污點的Node上,除非沒有其他可調度的節點
- NoSchedlue: kubernetes將不會把Pod調度到具有該污點的Node上,但不會影響當前Node上存在的Pod
- NoExecute: kubernetes將不會把Pod調度到具有該污點的Node上,同是將Node上已存在的Pod驅逐
使用kubectl設置和去除污點的命令如下:
#設置污點 kubectl taint nodes node1 key=values:effect #去除污點 kubectl taint nodes node1 key:effect- #去除所有污點 kubectl taint nodes node1 key-
下面演示污點效果:
- 准備節點node1(為了演示效果,暫時停止node2)
- 為node1節點設置一個污點: tag=test:PreferNoSchedule,然后創建pod1
- 修改為node1節點設置一個污點: tag=test:NoSchedule,然后創建pod2
- 修改為node1節點設置一個污點: tag=test:NoExectue,然后創建pod2
[root@master ~]# kubectl cordon node2 #為node1設置污點PreferNoSchedule [root@master ~]# kubectl taint nodes node1 tag=test:PreferNoSchedule node/node1 tainted # 創建pod1 [root@master ~]# kubectl run tainit1 --image=nginx:1.17.2 -n dev [root@master ~]# kubectl get pods -n dev -o wide tainit1-68d6b64b66-6bx5k 1/1 Running 0 2m7s 10.244.1.85 node1 <none> <none> #將node1污點修改為NoSchedule [root@master ~]# kubectl taint nodes node1 tag=test:PreferNoSchedule- node/node1 untainted [root@master ~]# kubectl taint nodes node1 tag=test:NoSchedule node/node1 tainted #創建pod2 [root@master ~]# kubectl run tainit2 --image=nginx:1.17.2 -n dev [root@master ~]# kubectl get pods -n dev -o wide tainit2-7f6d6975b-2bc9k 0/1 Pending 0 5s <none> <none> <none> <none> #將node1污點修改為NoExecute [root@master ~]# kubectl taint nodes node1 tag- node/node1 untainted #創建pod3 [root@master ~]# kubectl run tainit3 --image=nginx:1.17.2 -n dev [root@master ~]# kubectl get pods -n dev -o wide tainit1-68d6b64b66-9ps7p 0/1 Pending 0 62s <none> <none> <none> <none> tainit2-7f6d6975b-drvk4 0/1 Pending 0 62s <none> <none> <none> <none> tainit3-6f647d4d94-lj5bn 0/1 Pending 0 36s <none> <none> <none> <none>
容忍(Toleration) 上面介紹了污點的作用,我們可以在Node上添加污點用於拒絕pod調度上了,但是如果就是想將一個pod調度到一個有污點的Node上去,這個時候就可以使用容忍
污點就是拒絕,容忍就是忽略,Node通過污點拒絕pod調度上去,Pod通過容忍忽略拒絕
上面已經在node1上打上了NoExecute的污點,此時pod是調度不上去的,可以通過個pod添加容忍,然后將其調度上去
創建pod-toleration.yml
apiVersion: v1 kind: Pod metadata: name: pod-tolertion namespace: dev spec: containers: - name: nginx image: nginx:1.17.2 tolerations: # 添加容忍 - key: "tag" # 要容忍的污點的key operator: "Equal" # 操作符 value: "test" # 容忍的污點的value effect: "NoExecute" # 容忍規則,必須和標記污點相同 # 創建pod [root@master ~]# kubectl create -f pod-toleration.yml pod/pod-tolertion created [root@master ~]# kubectl get pods pod-tolertion -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-tolertion 1/1 Running 0 19s 10.244.1.93 node1 <none> <none>
Pod控制器詳解
在Kubernetes中,按照Pod的創建方式可以將其分為兩類:
- 自主式pod: kubernetes直接創建出來的pod,這種pod刪除后就沒有了,也不會重建
- 控制器創建的pod: 通過控制器創建的Pod,這種pod刪除了之后還會重建
Pod控制器式管理pod的中間層,使用了pod控制器后,我們只需要告訴pod創建,想要多少個什么樣的pod就可以了,他就會創建滿足條件的pod並確保每一個pod處於用戶期望的狀態,如果pod在運行種出現故障,控制器會基於指定策略重啟或者重建pod。
在kubernetes種,有很多類型的pod控制器,每種都有自己的合適場景,常見的有下面幾種:
-
ReplicationController: 比較原始的pod控制器,已經被廢棄,由ReplicaSet替代
-
ReplicaSet: 保證指定數量的pod運行,並支持pod數量變更,鏡像版本變更
-
Deployment: 通過控制ReplicaSet來控制pod,並支持滾動升級,版本回退
-
Horizontal Pod Autoscaler: 可以根據集群負載自動調整pod的數量,實現削峰填谷
-
DaemonSet:在集群中的指定Node上都運行一個副本,一般用於手好進程類的任務
-
Job: 它創建出來的pod只要完成任務后立即退出,用於執行一次性任務
-
Cronjob: 它創建的pod會周期性的執行,用於執行周期性任務
-
StatefulSet: 管理有狀態的應用
ReplicaSet
ReplicaSet的主要作用式保證一定數量的Pod能夠正常運行,它會持續監聽這些pod的運行狀態,一旦pod發生故障,就會重啟或重建。同時它還支持對pod數量的擴容和版本鏡像的升級。
ReplicaSet的資源清單文件:
apiVersion: apps/V1 #版本號 kind: ReplicaSet #類型 metadata: #元數據 name: #rs名稱 namespace: #所屬名稱空間 labels: #標簽 controller: rs spec: #詳情描述 replicas: 3 #副本數量 selector: #選擇器,通過它自動該控制器管理那些pod matchLabels: #label匹配規則 app: nginx-pod matchExpressions: # Expressions匹配規則 - {key: app,operator: IN, values: [nginx-pod]} template: #模板,當副本數量不足時,會根據下面的模板創建pod metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.2 ports: - containerPort: 80
在這里需要新了解的配置項就是spec下面幾個選項:
- replicas: 指定副本數量,其實就是當前rs創建出來的pod數量,默認為1
- selector: 選擇器,它的作用是建立pod控制器和pod之間的關聯關系,采用了Label Selector機制,在pod模板上定義label,在控制器上定義選擇器,就可以表明當前控制器能管理那些pod了
- template: 模板,就是當前控制器創建pod所使用的模板
創建ReplicaSet
創建pc-replicaset.yml
apiVersion: apps/v1 kind: ReplicaSet metadata: name: pc-replicaset namespace: dev spec: replicas: 3 selector: matchLabels: app: nginx-pod template: metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.2 # 創建rs [root@master ~]# kubectl create -f pc-replicaset.yml replicaset.apps/pc-replicaset created # 查看ReplicaSet信息 [root@master ~]# kubectl get rs pc-replicaset -n dev -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR pc-replicaset 3 3 3 9m22s nginx nginx:1.17.2 app=nginx-pod
擴容縮容
# 編輯rs副本數量,修改spec:replicas:數量即可 [root@master ~]# kubectl edit rs pc-replicaset -n dev replicaset.apps/pc-replicaset edited #查看pod ][root@master ~]# kubectl get pod -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pc-replicaset-4s6rz 0/1 ContainerCreating 0 28s <none> node2 <none> <none> pc-replicaset-5cdzq 1/1 Running 0 62m 10.244.1.98 node1 <none> <none> pc-replicaset-s2wlt 0/1 ContainerCreating 0 28s <none> node2 <none> <none> pc-replicaset-xt7cf 1/1 Running 0 65m 10.244.1.95 node1 <none> <none> pc-replicaset-zhf2z 1/1 Running 0 65m 10.244.1.96 node1 <none> <none> #也可以使用命令直接實現,使用scale命令實現擴縮容,后面--replicas=n直接指定目標數量即可 [root@master ~]# kubectl scale rs pc-replicaset --replicas=2 -n dev replicaset.apps/pc-replicaset scaled #命令運行完畢,查看pod,發現有3個退出 [root@master ~]# kubectl get pod -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pc-replicaset-xt7cf 1/1 Running 0 68m 10.244.1.95 node1 <none> <none> pc-replicaset-zhf2z 1/1 Running 0 68m 10.244.1.96 node1 <none> <none>
鏡像升級
#編輯rs的 容器鏡像 - image: nginx:1.17.3 [root@master ~]# kubectl edit rs pc-replicaset -n dev replicaset.apps/pc-replicaset edite #再次查看,發現鏡像版本已經變更 [root@master ~]# kubectl get rs -n dev -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR pc-replicaset 2 2 2 72m nginx nginx:1.17.3 app=nginx-pod #也可以使用命令完成,kubectl set image rs rs名稱 容器=鏡像版本 -n namespace [root@master ~]# kubectl set image rs pc-replicaset nginx=nginx=1.17.1 -n dev replicaset.apps/pc-replicaset image updated #再次查看,可以看到鏡像版本已經更新 [root@master ~]# kubectl get rs -n dev -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR pc-replicaset 2 2 2 74m nginx nginx=1.17.1 app=nginx-pod
刪除ReplicaSet
#使用kubectl delete命令會三次此RS以及它管理的pod #在kubernetes刪除RS前,會將RS的replicasclear調整為0,等待所有的Pod刪除后,在執行RS對象刪除 [root@master ~]# kubectl delete rs pc-replicaset -n dev replicaset.apps "pc-replicaset" deleted #如果希望僅僅刪除RS對象(保留pod),可以使用kubectl delete命令是添加--cascade=false選項(不推薦) [root@master ~]# kubectl delete rs pc-replicaset -n dev --cascade=false replicaset.apps "pc-replicaset" deleted [root@master ~]# kubectl get pod -n dev NAME READY STATUS RESTARTS AGE pc-replicaset-9556m 0/1 ContainerCreating 0 57s pc-replicaset-qvznw 1/1 Running 0 57s #也可以使用哦那個yml直接刪除 [root@master ~]# kubectl delete -f pc-replicaset.yml
Deployment(Deploy)
為了更好的解決服務編排的問題,kubernetes在v1.2版本開始,引入Deployment控制器。值得一提的是,這種控制器並不直接管理pod,而是通過ReplicaSet來間接管理Pod,即:Deployment管理ReplicaSet,ReplicaSet管理Pod。所以Deployment比ReplicaSet功能更加強大。
Deployment主要功能有下面幾個:
- 支持ReplicaSet的所用功能
- 支持發布的停止,繼續
- 支持版本滾動升級和版本回退
Deploymenr的資源清單文件:
apiVersion: apps/v1 kind: Deployment metadata: name: #rs名稱 namespace: #所屬的名稱空間 spec: replicas: 3 #副本數量 revisionHistoryLimit: 3 #保留歷史版本,默認10 paused: false #暫停部署,默認false progressDeadlineSeconds: 600 #部署超時時間,默認600s strategy: #策略 type: RollingUpdate #滾動更新策略 rolliingUpdate: #滾動更新 maxSurge: 30% #最大額外可以存在的副本數,可以為百分比可以為整數 maxUnavailable: 30% #最大不可以狀態的pod,可以為百分比可以為整數 selector: # 選擇器,通過它指定該控制器管理那些pod matchLabels: #Label匹配規則 app: nginx-pod matchExpressions: # Expressions匹配規則 - {key:app, operator: IN , values:[nginx-pod]} template: #模板 metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.2 ports: containerPorts: 80
創建Deployment
創建文件pc-deployment.yml
apiVersion: apps/v1 kind: Deployment metadata: name: pc-deployment namespace: dev spec: replicas: 3 selector: matchLabels: app: nginx-pod template: metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.2 # 創建deployment # --record=true 記錄每次的版本變化 [root@master ~]# kubectl create -f pc-deployment.yml --record=true deployment.apps/pc-deployment created #查看deployment,UP-TO-DATE最新版本的pod的數量,AVAILABLE 當前可用pod的數量 [root@master ~]# kubectl get deploy -n dev -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR pc-deployment 1/3 3 1 40s nginx nginx:1.17.2 app=nginx-pod #查看rs,發現rs的名稱是在原來deployment的名字后面添加了一個隨機10位數的隨機串 [root@master ~]# kubectl get rs -n dev NAME DESIRED CURRENT READY AGE pc-deployment-675d469f8b 3 3 1 3m37 #查看pod [root@master ~]# kubectl get pod -n dev NAME READY STATUS RESTARTS AGE pc-deployment-675d469f8b-2jqkd 1/1 Running 1 9m55s pc-deployment-675d469f8b-n8vmx 1/1 Running 1 9m55s pc-deployment-675d469f8b-stswc 1/1 Running 0 9m55s
擴縮容
#變更副本數量為5個 [root@master ~]# kubectl scale deploy pc-deployment -n dev --replicas=5 deployment.apps/pc-deployment scaled #查看deployment [root@master ~]# kubectl get deploy -n dev NAME READY UP-TO-DATE AVAILABLE AGE pc-deployment 5/5 5 5 11m #查看pod [root@master ~]# kubectl get pod -n dev NAME READY STATUS RESTARTS AGE pc-deployment-675d469f8b-2jqkd 1/1 Running 1 12m pc-deployment-675d469f8b-fqfld 1/1 Running 0 48s pc-deployment-675d469f8b-khwr2 1/1 Running 0 48s pc-deployment-675d469f8b-n8vmx 1/1 Running 1 12m pc-deployment-675d469f8b-stswc 1/1 Running 0 12m # 編譯deployment的副本數量,修改spec:replicas: 3 [root@master ~]# kubectl edit deploy pc-deployment -n dev deployment.apps/pc-deployment edited # 查看pod [root@master ~]# kubectl get pod -n dev NAME READY STATUS RESTARTS AGE pc-deployment-675d469f8b-2jqkd 1/1 Running 1 13m pc-deployment-675d469f8b-fqfld 1/1 Running 0 2m33s pc-deployment-675d469f8b-stswc 1/1 Running 0 13m
鏡像更新
Deployment支持兩種鏡像更新的策略: 重建鏡像和滾動跟新(默認),可用通過strategy選項進行配置
strategy: 指定新的Pod替換舊的Pod的策略,支持兩個屬性 type: 指定策略類型,支持兩種策略 Recreate: 在創建出新的Pod之前會先殺掉所有已存在的pod RollingUpdate: 滾動跟新,就是殺死部分,就啟動一部分,在更新的過程中存在兩個版本的Pod rollingUpdate: 當type為RollingUpdate是生效,用於為RollingUpdate設置參數,支持兩個屬性: maxUnavailabe: 用來指定在升級過程中不可以pod的最大數量,默認25% maxSurge: 用來指定在升級過程中可用超過期望的Pod的最大數量,默認25%
重建更新:
#1.編輯pc-deployment.yml,在spec節點下添加更新策略 spec: strategy: type: Recrate # 應用策略 [root@master ~]# kubectl apply -f pc-deployment.yml # 2.創建deploy進行驗證 #變更鏡像 [root@master ~]# kubectl set image deployment pc-deployment nginx=nginx:1.17.4 -n dev deployment.apps/pc-deployment image updated root@master ~]# kubectl get pod -n dev -w NAME READY STATUS RESTARTS AGE pc-deployment-675d469f8b-2jqkd 1/1 Running 1 94m pc-deployment-675d469f8b-fqfld 1/1 Running 0 82m pc-deployment-675d469f8b-stswc 1/1 Running 0 94m pc-deployment-675d469f8b-stswc 1/1 Terminating 0 94m pc-deployment-675d469f8b-2jqkd 1/1 Terminating 1 94m pc-deployment-675d469f8b-fqfld 1/1 Terminating 0 83m pc-deployment-675d469f8b-2jqkd 0/1 Terminating 1 94m pc-deployment-675d469f8b-stswc 0/1 Terminating 0 94m pc-deployment-675d469f8b-fqfld 0/1 Terminating 0 83m pc-deployment-675d469f8b-2jqkd 0/1 Terminating 1 94m pc-deployment-675d469f8b-2jqkd 0/1 Terminating 1 94m pc-deployment-675d469f8b-fqfld 0/1 Terminating 0 83m pc-deployment-675d469f8b-fqfld 0/1 Terminating 0 83m pc-deployment-675d469f8b-stswc 0/1 Terminating 0 94m pc-deployment-675d469f8b-stswc 0/1 Terminating 0 94m pc-deployment-6c9f56fcfb-wrdtj 0/1 Pending 0 0s pc-deployment-6c9f56fcfb-zpmv7 0/1 Pending 0 0s pc-deployment-6c9f56fcfb-v2vl6 0/1 Pending 0 0s pc-deployment-6c9f56fcfb-wrdtj 0/1 Pending 0 0s pc-deployment-6c9f56fcfb-zpmv7 0/1 Pending 0 0s pc-deployment-6c9f56fcfb-v2vl6 0/1 Pending 0 0s pc-deployment-6c9f56fcfb-zpmv7 0/1 ContainerCreating 0 0s pc-deployment-6c9f56fcfb-wrdtj 0/1 ContainerCreating 0 0s pc-deployment-6c9f56fcfb-v2vl6 0/1 ContainerCreating 0 0s pc-deployment-6c9f56fcfb-zpmv7 1/1 Running 0 16s pc-deployment-6c9f56fcfb-v2vl6 1/1 Running 0 32s pc-deployment-6c9f56fcfb-wrdtj 1/1 Running 0 47s
滾動更新
1.編輯pc-deployment.yml,在spec節點下添加跟新策略 spec: strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25% #應用 [root@master ~]# kubectl apply -f pc-deployment.yml deployment.apps/pc-deployment configured #變更鏡像 [root@master ~]# kubectl set image deployment pc-deployment nginx=nginx:1.17.1 -n dev deployment.apps/pc-deployment image updated [root@master ~]# kubectl get pod -n dev -w NAME READY STATUS RESTARTS AGE pc-deployment-6c9f56fcfb-v2vl6 1/1 Running 0 3m1s pc-deployment-6c9f56fcfb-wrdtj 1/1 Running 0 3m1s pc-deployment-6c9f56fcfb-zpmv7 1/1 Running 0 3m1s pc-deployment-675d469f8b-gsvgm 0/1 Pending 0 0s pc-deployment-675d469f8b-gsvgm 0/1 Pending 0 0s pc-deployment-675d469f8b-gsvgm 0/1 ContainerCreating 0 0s pc-deployment-675d469f8b-gsvgm 1/1 Running 0 3s pc-deployment-6c9f56fcfb-wrdtj 1/1 Terminating 0 6m5s pc-deployment-675d469f8b-vtgbs 0/1 Pending 0 0s pc-deployment-675d469f8b-vtgbs 0/1 Pending 0 0s pc-deployment-675d469f8b-vtgbs 0/1 ContainerCreating 0 0s pc-deployment-6c9f56fcfb-wrdtj 0/1 Terminating 0 6m6s pc-deployment-6c9f56fcfb-wrdtj 0/1 Terminating 0 6m7s pc-deployment-675d469f8b-vtgbs 1/1 Running 0 2s pc-deployment-6c9f56fcfb-v2vl6 1/1 Terminating 0 6m7s pc-deployment-675d469f8b-4l4zz 0/1 Pending 0 0s pc-deployment-675d469f8b-4l4zz 0/1 Pending 0 0s pc-deployment-675d469f8b-4l4zz 0/1 ContainerCreating 0 0s pc-deployment-6c9f56fcfb-v2vl6 0/1 Terminating 0 6m8s pc-deployment-675d469f8b-4l4zz 1/1 Running 0 2s pc-deployment-6c9f56fcfb-zpmv7 1/1 Terminating 0 6m9s pc-deployment-6c9f56fcfb-wrdtj 0/1 Terminating 0 6m10s pc-deployment-6c9f56fcfb-wrdtj 0/1 Terminating 0 6m10s pc-deployment-6c9f56fcfb-zpmv7 0/1 Terminating 0 6m10s pc-deployment-6c9f56fcfb-zpmv7 0/1 Terminating 0 6m11s pc-deployment-6c9f56fcfb-zpmv7 0/1 Terminating 0 6m11s pc-deployment-6c9f56fcfb-v2vl6 0/1 Terminating 0 6m20s pc-deployment-6c9f56fcfb-v2vl6 0/1 Terminating 0 6m20s pc-deployment-5d89bdfbf9-xt428 0/1 Pending 0 0s pc-deployment-5d89bdfbf9-xt428 0/1 Pending 0 0s pc-deployment-5d89bdfbf9-xt428 0/1 ContainerCreating 0 0s pc-deployment-5d89bdfbf9-xt428 1/1 Running 0 2s pc-deployment-675d469f8b-4l4zz 1/1 Terminating 0 42s pc-deployment-5d89bdfbf9-cjpp2 0/1 Pending 0 0s pc-deployment-5d89bdfbf9-cjpp2 0/1 Pending 0 0s pc-deployment-5d89bdfbf9-cjpp2 0/1 ContainerCreating 0 0s pc-deployment-675d469f8b-4l4zz 0/1 Terminating 0 43s pc-deployment-5d89bdfbf9-cjpp2 1/1 Running 0 1s pc-deployment-675d469f8b-vtgbs 1/1 Terminating 0 45s
鏡像更新中rs的變化:
#查看rs,發現原來的rs依舊存在,只是pod變為了0,然后新產生一個rs,pod數量為3 [root@master ~]# kubectl get rs -n dev NAME DESIRED CURRENT READY AGE pc-deployment-5d89bdfbf9 3 3 3 2m pc-deployment-675d469f8b 0 0 0 103m pc-deployment-6c9f56fcfb 0 0 0 8m47s
版本回退
deployment支持版本升級過程中暫停,繼續功能以及版本回退等諸多功能。
kubectl rollout: 版本升級相關功能,支持下面的選項:
- status 顯示當前升級狀態
- history 顯示升級歷史記錄
- pause 暫停版本升級過程
- resume 繼續以及暫停的版本升級過程
- restart 重啟版本升級過程
- undo 回滾到上一個版本(可用使用--to-revision回滾到指定版本)
# 查看當前升級的版本狀態 [root@master ~]# kubectl rollout status deployment pc-deployment -n dev deployment "pc-deployment" successfully rolled out # [root@master ~]# kubectl rollout history deployment pc-deployment -n dev deployment.apps/pc-deployment REVISION CHANGE-CAUSE 2 kubectl create --filename=pc-deployment.yml --record=true 3 kubectl create --filename=pc-deployment.yml --record=true 4 kubectl create --filename=pc-deployment.yml --record=true # 版本回滾 # 這里直接使用--to-revision=2回滾到2版本,如果省略這個選項就是回退到上一個版本 [root@master ~]# kubectl rollout undo deployment pc-deployment --to-revision=2 -n dev deployment.apps/pc-deployment rolled back #查看發現,通過nginx進行版本可用發現到了1.17.4版本 [root@master ~]# kubectl get rs -n dev -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR pc-deployment-5d89bdfbf9 0 0 0 16m nginx nginx:1.17.1 app=nginx-pod,pod-template-hash=5d89bdfbf9 pc-deployment-675d469f8b 0 0 0 117m nginx nginx:1.17.2 app=nginx-pod,pod-template-hash=675d469f8b pc-deployment-6c9f56fcfb 3 3 3 23m nginx nginx:1.17.4 app=nginx-pod,pod-template-hash=6c9f56fcfb
金絲雀發布 deployment支持更新過程中的控制,如“暫停(pause)”或“繼續(resume)”更新操作
比如有一批新的pod資源創建完成后立即暫停更新過程,此時,僅存在一部分新版本應用,主體部分還是舊版本。然后,在篩選一小部分的用戶請求路由到新版本的pod應用,繼續概觀察能否穩定的按期望的方式運行,確定沒問題后在舉行完成余下的pod資源滾動更新,否則立即回滾更新操作。
# 更新deployment的版本,並配置暫停deployment [root@master ~]# kubectl set image deploy pc-deployment nginx=nginx:1.17.3 -n dev && kubectl rollout pause deployment pc-deployment -n dev deployment.apps/pc-deployment image updated deployment.apps/pc-deployment paused #觀察更新狀態 [root@master ~]# kubectl rollout status deploy pc-deployment -n dev Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated... # 監控更新過程,可用看到已經新增了一個資源,但是並未按照預期的狀態刪除一個舊的資源,就是因為使用了pause暫停命令 [root@master ~]# kubectl get rs -n dev -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR pc-deployment-5d89bdfbf9 0 0 0 25m nginx nginx:1.17.1 app=nginx-pod,pod-template-hash=5d89bdfbf9 pc-deployment-675d469f8b 0 0 0 126m nginx nginx:1.17.2 app=nginx-pod,pod-template-hash=675d469f8b pc-deployment-6c9f56fcfb 3 3 3 31m nginx nginx:1.17.4 app=nginx-pod,pod-template-hash=6c9f56fcfb pc-deployment-6dfdf96cc5 1 1 0 119s nginx ngnix:1.17.3 app=nginx-pod,pod-template-hash=6dfdf96cc5 # 繼續更新 [root@master ~]# kubectl rollout resume deployment pc-deployment -n dev deployment.apps/pc-deployment resumed #查看deploy [root@master ~]# kubectl get rs -n dev NAME DESIRED CURRENT READY AGE pc-deployment-5d89bdfbf9 0 0 0 35m pc-deployment-675d469f8b 0 0 0 136m pc-deployment-6c9f56fcfb 0 0 0 41m pc-deployment-6dfdf96cc5 0 0 0 11m pc-deployment-7865c58bdf 3 3 3 63s
Horizonta Pod Autoscaler(HPA)
可用通過手工執行kubectl scale命令實現Pod擴容,但是這顯然不符合kubernetes的定位目標--自動化、智能化。Kubernetes期望可用通過監測Pod的使用情況,實現pod數量的自動調整,於是就產生了HPA這種控制器。
HPA可以獲取每個pod利用率,然后和PHPA中定義的指標進行對比,同時計算出需要伸縮的具體值,最后實現pod的數量的調整。其實HPA與之前的Deployment一樣,也屬於一種Kubernetes資源對象,它通過追蹤分析目標pod的負載變化情況,來確定是否需要針對性的調整目標Pod的數量
1.安裝metrice-server
metrucs-server可以用來收集集群中的資源使用情況
#安裝git [root@master ~]# yum -y install git #獲取metrics-server,注意使用版本 [root@master ~]# git clone -b v0.3.6 https://github.com/kubernetes-incubator/metrics-server #修改deployment,注意修改的是鏡像和初始化參數 [root@master ~]# cd metrics-server/deploy/1.8+/ [root@master 1.8+]# vim metrics-server-deployment.yaml [root@master 1.8+]# vim metrics-server-deployment.yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: metrics-server namespace: kube-system --- apiVersion: apps/v1 kind: Deployment metadata: name: metrics-server namespace: kube-system labels: k8s-app: metrics-server spec: selector: matchLabels: k8s-app: metrics-server template: metadata: name: metrics-server labels: k8s-app: metrics-server spec: hostNetwork: true serviceAccountName: metrics-server volumes: # mount in tmp so we can safely use from-scratch images and/or read-only containers - name: tmp-dir emptyDir: {} containers: - name: metrics-server image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 imagePullPolicy: Always args: - --kubelet-insecure-tls - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP volumeMounts: - name: tmp-dir mountPath: /tmp #查看pod運行狀態 [root@master 1.8+]# kubectl get pod -n kube-system metrics-server-6b976979db-2hqm6 1/1 Running 0 2m21s #使用kubectl top node 查看資源使用狀態 [root@master 1.8+]# kubectl top node NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% master 111m 5% 970Mi 56% node1 28m 1% 388Mi 44% node2 34m 1% 426Mi 48% [root@master 1.8+]# kubectl top pod -n kube-system NAME CPU(cores) MEMORY(bytes) coredns-6955765f44-sch82 4m 15Mi coredns-6955765f44-thfs7 4m 15Mi etcd-master 15m 86Mi kube-apiserver-master 33m 294Mi kube-controller-manager-master 15m 63Mi .......................... #至此,metrics-server安裝完成
2.准備deployment和service
# 創建deployment vim nginx.yml apiVersion: apps/v1 # 版本號 kind: Deployment # 類型 metadata: # 元數據 name: nginx # deployment的名稱 namespace: dev # 命名類型 spec: # 詳細描述 selector: # 選擇器,通過它指定該控制器可以管理哪些Pod matchLabels: # Labels匹配規則 app: nginx-pod template: # 模塊 當副本數據不足的時候,會根據下面的模板創建Pod副本 metadata: labels: app: nginx-pod spec: containers: - name: nginx # 容器名稱 image: nginx:1.17.1 # 容器需要的鏡像地址 ports: - containerPort: 80 # 容器所監聽的端口 resources: # 資源限制 requests: cpu: "100m" # 100m表示100millicpu,即0.1個CPU #創建Deployment [root@master 1.8+]# kubectl create -f nginx.yml deployment.apps/nginx created #查看Deployment和Pod [root@master 1.8+]# kubectl get pod,deploy -n dev NAME READY STATUS RESTARTS AGE pod/nginx-7b766dbb7-8qrdv 1/1 Running 0 31s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx 1/1 1 1 31s #創建Service [root@master 1.8+]# kubectl expose deployment nginx --name=nginx --type=NodePort --port=80 --target-port=80 -n dev service/nginx exposed #查看Service [root@master 1.8+]# kubectl get svc -n dev NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx NodePort 10.105.180.5 <none> 80:31628/TCP 35s
3.部署HPA
創建pc-hpa.yaml文件
apiVersion: autoscaling/v1 # 版本號 kind: HorizontalPodAutoscaler # 類型 metadata: # 元數據 name: pc-hpa # deployment的名稱 namespace: dev # 命名類型 spec: minReplicas: 1 # 最小Pod數量 maxReplicas: 10 # 最大Pod數量 targetCPUUtilizationPercentage: 3 # CPU使用率指標 scaleTargetRef: # 指定要控制的Nginx的信息 apiVersion: apps/v1 kind: Deployment name: nginx #創建hpa [root@master 1.8+]# kubectl create -f pc-hpa.yaml horizontalpodautoscaler.autoscaling/pc-hpa created #查看hpa [root@master 1.8+]# kubectl get hpa -n dev NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE pc-hpa Deployment/nginx 0%/3% 1 10 1 42s
4.測試
● 使用壓測工具如Jmeter對service的地址http://192.168.248.11:31628進行壓測,然后通過控制台查看hpa和pod的變化
hpa的變化 [root@master ~]# kubectl get hpa -n dev -w NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE pc-hpa Deployment/nginx 0%/3% 1 10 1 3m28s pc-hpa Deployment/nginx 0%/3% 1 10 1 5m18s pc-hpa Deployment/nginx 1%/3% 1 10 1 9m6s pc-hpa Deployment/nginx 0%/3% 1 10 1 10m pc-hpa Deployment/nginx 1%/3% 1 10 1 12m pc-hpa Deployment/nginx 0%/3% 1 10 1 13m pc-hpa Deployment/nginx 0%/3% 1 10 1 18m pc-hpa Deployment/nginx 20%/3% 1 10 1 20m pc-hpa Deployment/nginx 20%/3% 1 10 4 21m pc-hpa Deployment/nginx 20%/3% 1 10 7 21m pc-hpa Deployment/nginx 4%/3% 1 10 7 21m pc-hpa Deployment/nginx 1%/3% 1 10 7 23m
DaemonSet(DS)
DaemonSet類型的控制器可以保證集群中的每一台(或指定)節點上都運行一個副本,一般適用於日志收集、節點監控等場景。也就是說,如果一個Pod提供的功能是節點級別的(每個節點都需要且只需要一個),那么這類Pod就適合使用DaemonSet類型的控制器創建。
DaemonSet控制器的特點:
- 每向集群中添加一個節點的時候,指定的Pod副本也將添加到該節點上。
- 當節點從集群中移除的時候,Pod也會被垃圾回收。
DaemonSet的資源清單:
apiVersion: apps/v1 # 版本號 kind: DaemonSet # 類型 metadata: # 元數據 name: # 名稱 namespace: #命名空間 labels: #標簽 controller: daemonset spec: # 詳情描述 revisionHistoryLimit: 3 # 保留歷史版本 updateStrategy: # 更新策略 type: RollingUpdate # 滾動更新策略 rollingUpdate: # 滾動更新 maxUnavailable: 1 # 最大不可用狀態的Pod的最大值,可用為百分比,也可以為整數 selector: # 選擇器,通過它指定該控制器管理那些Pod matchLabels: # Labels匹配規則 app: nginx-pod matchExpressions: # Expressions匹配規則 - key: app operator: In values: - nginx-pod template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板 metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.1 ports: - containerPort: 80
創建DaemonSet
創建pc-daemonset.yml文件
apiVersion: apps/v1 # 版本號 kind: DaemonSet # 類型 metadata: # 元數據 name: pc-damonset # 名稱 namespace: dev #命名空間 spec: # 詳情描述 selector: # 選擇器,通過它指定該控制器管理那些Pod matchLabels: # Labels匹配規則 app: nginx-pod template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板 metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.1 ports: - containerPort: 80 #創建DaemonSet [root@master ~]# kubectl create -f pc-daemonset.yml daemonset.apps/pc-damonset created #查看DaemonSet [root@master ~]# kubectl get ds -n dev -o wide NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR pc-damonset 2 2 2 2 2 <none> 25s nginx nginx:1.17.1 app=nginx-pod #刪除DaemonSet [root@master ~]# kubectl delete ds pc-damonset -n dev daemonset.apps "pc-damonset" deleted
job
Job主要用於負責批量處理短暫的一次性任務。
Job的特點:
- 當Job創建的Pod執行成功結束時,Job將記錄成功結束的Pod數量。
- 當成功結束的Pod達到指定的數量時,Job將完成執行
job資源清單
apiVersion: batch/v1 # 版本號 kind: Job # 類型 metadata: # 元數據 name: # 名稱 namespace: #命名空間 labels: # 標簽 controller: job spec: # 詳情描述 completions: 1 # 指定Job需要成功運行Pod的總次數,默認為1 parallelism: 1 # 指定Job在任一時刻應該並發運行Pod的數量,默認為1 activeDeadlineSeconds: 30 # 指定Job可以運行的時間期限,超過時間還沒結束,系統將會嘗試進行終止 backoffLimit: 6 # 指定Job失敗后進行重試的次數,默認為6 manualSelector: true # 是否可以使用selector選擇器選擇Pod,默認為false selector: # 選擇器,通過它指定該控制器管理那些Pod matchLabels: # Labels匹配規則 app: counter-pod matchExpressions: # Expressions匹配規則 - key: app operator: In values: - counter-pod template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板 metadata: labels: app: counter-pod spec: restartPolicy: Never # 重啟策略只能設置為Never或OnFailure containers: - name: counter image: busybox:1.30 command: ["/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 20;done"] 關於模板中的重啟策略的說明: # 如果設置為OnFailure,則Job會在Pod出現故障的時候重啟容器,而不是創建Pod,failed次數不變。 # 如果設置為Never,則Job會在Pod出現故障的時候創建新的Pod,並且故障Pod不會消失,也不會重啟,failed次數+1。 #如果指定為Always的話,就意味着一直重啟,意味着Pod任務會重復執行,這和Job的定義沖突,所以不能設置為Always。
創建pc-job.yml文件
apiVersion: batch/v1 # 版本號 kind: Job # 類型 metadata: # 元數據 name: pc-job # 名稱 namespace: dev #命名空間 spec: # 詳情描述 manualSelector: true # 是否可以使用selector選擇器選擇Pod,默認為false selector: # 選擇器,通過它指定該控制器管理那些Pod matchLabels: # Labels匹配規則 app: counter-pod template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板 metadata: labels: app: counter-pod spec: restartPolicy: Never # 重啟策略只能設置為Never或OnFailure containers: - name: counter image: busybox:1.30 command: [ "/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 3;done" ] # 創建job [root@master ~]# kubectl create -f pc-job.yml job.batch/pc-job created # 查看job [root@master ~]# kubectl get job -n dev -o wide -w NAME COMPLETIONS DURATION AGE CONTAINERS IMAGES SELECTOR pc-job 0/1 2s 2s counter busybox:1.30 app=counter-pod pc-job 1/1 28s 28s counter busybox:1.30 app=counter-pod #查看pod [root@master ~]# kubectl get pod -n dev -w NAME READY STATUS RESTARTS AGE pc-job-5s9ck 0/1 Pending 0 0s pc-job-5s9ck 0/1 Pending 0 0s pc-job-5s9ck 0/1 ContainerCreating 0 0s pc-job-5s9ck 1/1 Running 0 1s pc-job-5s9ck 0/1 Completed 0 28s #刪除job [root@master ~]# kubectl delete -f pc-job.yml job.batch "pc-job" deleted
CronJob(CJ)
CronJob控制器以Job控制器為其管控對象,並借助它管理Pod資源對象,Job控制器定義的作業任務在其控制器資源創建之后便會立即執行,但CronJob可以以類似Linux操作系統的周期性任務作業計划的方式控制器運行時間點及重復運行的方式,換言之,CronJob可以在特定的時間點反復去執行Job任務
CronJob的資源清單
apiVersion: batch/v1beta1 # 版本號 kind: CronJob # 類型 metadata: # 元數據 name: # 名稱 namespace: #命名空間 labels: controller: cronjob spec: # 詳情描述 schedule: # cron格式的作業調度運行時間點,用於控制任務任務時間執行 concurrencyPolicy: # 並發執行策略 failedJobsHistoryLimit: # 為失敗的任務執行保留的歷史記錄數,默認為1 successfulJobsHistoryLimit: # 為成功的任務執行保留的歷史記錄數,默認為3 jobTemplate: # job控制器模板,用於為cronjob控制器生成job對象,下面其實就是job的定義 metadata: {} spec: completions: 1 # 指定Job需要成功運行Pod的總次數,默認為1 parallelism: 1 # 指定Job在任一時刻應該並發運行Pod的數量,默認為1 activeDeadlineSeconds: 30 # 指定Job可以運行的時間期限,超過時間還沒結束,系統將會嘗試進行終止 backoffLimit: 6 # 指定Job失敗后進行重試的次數,默認為6 template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板 spec: restartPolicy: Never # 重啟策略只能設置為Never或OnFailure containers: - name: counter image: busybox:1.30 command: [ "/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 20;done" ] schedule:cron表達式,用於指定任務的執行時間。 ● */1 * * * *:表示分鍾 小時 日 月份 星期。 ● 分鍾的值從0到59。 ● 小時的值從0到23。 ● 日的值從1到31。 ● 月的值從1到12。 ● 星期的值從0到6,0表示星期日。 ● 多個時間可以用逗號隔開,范圍可以用連字符給出:* 可以作為通配符,/表示每... concurrencyPolicy:並發執行策略 ● Allow:運行Job並發運行(默認)。 ● Forbid:禁止並發運行,如果上一次運行尚未完成,則跳過下一次運行。 ● Replace:替換,取消當前正在運行的作業並使用新作業替換它。
創建pc-cronjob.yml文件
apiVersion: batch/v1beta1 # 版本號 kind: CronJob # 類型 metadata: # 元數據 name: pc-cronjob # 名稱 namespace: dev #命名空間 spec: # 詳情描述 schedule: "*/1 * * * * " # cron格式的作業調度運行時間點,用於控制任務任務時間執行 jobTemplate: # job控制器模板,用於為cronjob控制器生成job對象,下面其實就是job的定義 metadata: {} spec: template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板 spec: restartPolicy: Never # 重啟策略只能設置為Never或OnFailure containers: - name: counter image: busybox:1.30 command: [ "/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 2;done" ] #創建CronJob [root@master ~]# kubectl create -f pc-cronjob.yml cronjob.batch/pc-cronjob created #查看cronjob [root@master ~]# kubectl get cronjob -n dev -w NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE pc-cronjob */1 * * * * False 0 <none> 0s pc-cronjob */1 * * * * False 1 8s 23s pc-cronjob */1 * * * * False 0 28s 43s pc-cronjob */1 * * * * False 1 8s 83s pc-cronjob */1 * * * * False 0 28s 103s #刪除CronJob [root@master ~]# kubectl delete -f pc-cronjob.yml cronjob.batch "pc-cronjob" deleted