Pod是最小的部署單元,也是后面經常配置的地方,本章節帶你熟悉Pod中常見資源配置及參數。
也就是YAML這部分:
... template: metadata: labels: app: web spec: containers: - image: a13552821243/java-demo:latest imagePullPolicy: Always name: java
6.1 Pod介紹
-
最小部署單元
-
一組容器的集合
-
一個Pod中的容器共享網絡命名空間
-
6.2 Pod存在的意義
Pod為親密性應用而存在。
親密性應用場景:
-
兩個應用之間發生文件交互
-
兩個應用需要通過127.0.0.1或者socket通信
-
兩個應用需要發生頻繁的調用
6.3 Pod實現機制與設計模式
Pod本身是一個邏輯概念,沒有具體存在,那究竟是怎么實現的呢?
眾所周知,容器之間是通過Namespace隔離的,Pod要想解決上述應用場景,那么就要讓Pod里的容器之間高效共享。
具體分為兩個部分:網絡和存儲
-
共享網絡
kubernetes的解法是這樣的:會在每個Pod里先啟動一個infra container
小容器,然后讓其他的容器連接進來這個網絡命名空間,然后其他容器看到的網絡試圖就完全一樣了,即網絡設備、IP地址、Mac地址等,這就是解決網絡共享問題。在Pod的IP地址就是infra container的IP地址。
-
共享存儲
比如有兩個容器,一個是nginx,另一個是普通的容器,普通容器要想訪問nginx里的文件,就需要nginx容器將共享目錄通過volume掛載出來,然后讓普通容器掛載的這個volume,最后大家看到這個共享目錄的內容一樣。
例如:
# pod.yaml apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: write image: centos command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"] volumeMounts: - name: data mountPath: /data - name: read image: centos command: ["bash","-c","tail -f /data/hello"] volumeMounts: - name: data mountPath: /data volumes: - name: data emptyDir: {}
上述示例中有兩個容器,write容器負責提供數據,read消費數據,通過數據卷將寫入數據的目錄和讀取數據的目錄都放到了該卷中,這樣每個容器都能看到該目錄。
kubectl apply -f pod.yaml kubectl logs my-pod -c read -f
在Pod中容器分為以下幾個類型:
-
Infrastructure Container:基礎容器,維護整個Pod網絡空間,對用戶不可見
-
InitContainers:初始化容器,先於業務容器開始執行,一般用於業務容器的初始化工作
-
Containers:業務容器,具體跑應用程序的鏡像
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: java image: a13552821243/java-demo imagePullPolicy: IfNotPresent
imagePullPolicy 字段有三個可選值:
-
IfNotPresent:鏡像在宿主機上不存在時才拉取
-
Always:默認值,每次創建 Pod 都會重新拉取一次鏡像
-
Never: Pod 永遠不會主動拉取這個鏡像
如果拉取公開的鏡像,直接按照上述示例即可,但要拉取私有的鏡像,是必須認證鏡像倉庫才可以,即docker login,而在K8S集群中會有多個Node,顯然這種方式是很不放方便的!為了解決這個問題,K8s 實現了自動拉取鏡像的功能。 以secret方式保存到K8S中,然后傳給kubelet。
Pod資源配額有兩種:
-
申請配額:調度時使用,參考是否有節點滿足該配置
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
-
限制配額:容器能使用的最大配置
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
示例:
apiVersion: v1 kind: Pod metadata: name: web spec: containers: - name: java image: a13552821243/java-demo resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
1核=1000m
1.5核=1500m
那上面限制配置就是1核的二分之一(500m),即該容器最大使用半核CPU。
該值也可以寫成浮點數,更容易理解:
半核=0.5
1核=1
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: java image: a13552821243java-demo restartPolicy: Always
restartPolicy字段有三個可選值:
-
Always:當容器終止退出后,總是重啟容器,默認策略。
-
OnFailure:當容器異常退出(退出狀態碼非0)時,才重啟容器。適於job
-
Never:當容器終止退出,從不重啟容器。適於job
6.7 健康檢查
默認情況下,kubelet 根據容器狀態作為健康依據,但不能容器中應用程序狀態,例如程序假死。這就會導致無法提供服務,丟失流量。因此引入健康檢查機制確保容器健康存活。
健康檢查有兩種類型:
-
livenessProbe
如果檢查失敗,將殺死容器,根據Pod的restartPolicy來操作。
-
readinessProbe
如果檢查失敗,Kubernetes會把Pod從service endpoints中剔除。
這兩種類型支持三種檢查方法:
Probe支持以下三種檢查方法:
-
httpGet
發送HTTP請求,返回200-400范圍狀態碼為成功。
-
exec
執行Shell命令返回狀態碼是0為成功。
-
tcpSocket
發起TCP Socket建立成功。
apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-exec spec: containers: - name: liveness image: busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5
上述示例:啟動容器第一件事創建文件,停止30s,刪除該文件,再停止60s,確保容器還在運行中。
驗證現象:容器啟動正常,30s后異常,會restartPolicy策略自動重建,容器繼續正常,反復現象。
先看下創建一個Pod的工作流程: create pod -> apiserver -> write etcd -> scheduler -> bind pod to node -> write etcd -> kubelet( apiserver get pod) -> dcoekr api,create container -> apiserver -> update pod status to etcd -> kubectl get pods
這里給你介紹調度策略:nodeName、nodeSelector和污點
1、nodeName
nodeName用於將Pod調度到指定的Node名稱上。
apiVersion: v1 kind: Pod metadata: labels: run: busybox name: busybox namespace: default spec: nodeName: k8s-node1 containers: - image: busybox name: bs command: - "ping" - "baidu.com"
kubectl label nodes k8s-node1 team=a kubectl label nodes k8s-node2 team=b
2、nodeSelector
nodeSelector用於將Pod調度到匹配Label的Node上。
先給規划node用途,然后打標簽,例如將兩台node划分給不同團隊使用:
后在創建Pod只會被調度到含有team=a標簽的節點上。
apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: nodeSelector: team: b containers: - image: busybox name: bs command: - "ping" - "baidu.com"
**3、taint(污點)與tolerations(容忍)** 污點應用場景:節點獨占,例如具有特殊硬件設備的節點,如GPU 設置污點命令:
kubectl taint node [node] key=value[effect]
其中[effect] 可取值:
-
NoSchedule :一定不能被調度。
-
PreferNoSchedule:盡量不要調度。
-
NoExecute:不僅不會調度,還會驅逐Node上已有的Pod。
示例:
先給節點設置污點,說明這個節點不是誰都可以調度過來的:
kubectl taint node k8s-node1 abc=123:NoSchedule
apiVersion: v1 kind: Pod metadata: labels: run: busybox name: busybox3 namespace: default spec: tolerations: - key: "abc" operator: "Equal" value: "123" effect: "NoSchedule" containers: - image: busybox name: bs command: - "ping" - "baidu.com"
去掉污點:
kubectl taint node [node] key:[effect]- kubectl taint node k8s-node1 abc:NoSchedule-
# 查看事件,可用於大部分資源 kubectl describe TYPE/NAME # 如果pod啟動失敗,先查看日志 kubectl logs TYPE/NAME [-c CONTAINER] # 進入到容器中debug kubectl exec POD [-c CONTAINER] -- COMMAND [args...]