k8s學習 - 概念 - Pod
這篇繼續看概念,主要是 Pod 這個概念,這個概念非常重要,是 k8s 叢集的最小單位。
怎麼才算是理解好 pod 了呢,基本上把 pod 的所有 describe 和配置檔案的配置項都能看懂就算是對 pod 比較瞭解了。
Pod
我們通過呼叫一個kubectl describe pod xxx
可以檢視某個 pod 的具體資訊。
describe 的資訊我們用註釋的形式來解讀。
Name: task-pv-pod
Namespace: default // 沒有指定namespace的就是default
Node: docker-for-desktop/192.168.65.3 // Pod所在的節點
Start Time: Mon, 08 Jul 2019 14:05:52 +0800 // pod啟動的時間
Labels: <none> // 說明沒有設定標籤
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"task-pv-pod","namespace":"default"},"spec":{"containers":[{"image":"nginx","name":... // 註釋資訊
Status: Running // pod的狀態
IP: 10.1.0.103 // pod的叢集ip
Containers: // 其中包含的容器
task-pv-container:
Container ID: docker://3e9a2ee6b0a13ccee534ec3ffe781adcbff42a7f1851d57e3b374a047a654590
Image: nginx // 容器映象名稱
Image ID: docker-pullable://nginx@sha256:96fb261b66270b900ea5a2c17a26abbfabe95506e73c3a3c65869a6dbe83223a
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Mon, 08 Jul 2019 14:05:58 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts: // 這個容器掛載的兩個volume
/usr/share/nginx/html from task-pv-storage (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-tw8wk (ro)
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
Volumes:
task-pv-storage: // 掛載的資料卷
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) // 這個資料卷是共享持久卷
ClaimName: task-pv-claim // 使用的宣告
ReadOnly: false // 資料卷是否只讀
default-token-tw8wk:
Type: Secret (a volume populated by a Secret) // 這個資料卷是儲存金鑰
SecretName: default-token-tw8wk
Optional: false
QoS Class: BestEffort // Qos的三個級別,Guaranteed/Burstable/BestEffort,分別對pod的資源限制從嚴到弱
Node-Selectors: <none> // pod是可以選擇部署在哪個node上的,比如部署在有ssd的node上。
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s // 節點親和性,它使得pod能有傾向性地分配到不同節點上。
node.kubernetes.io/unreachable:NoExecute for 300s
Events: // 這個pod發生的一些事件
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 21s default-scheduler Successfully assigned task-pv-pod to docker-for-desktop
Normal SuccessfulMountVolume 20s kubelet, docker-for-desktop MountVolume.SetUp succeeded for volume "task-pv-volume"
Normal SuccessfulMountVolume 20s kubelet, docker-for-desktop MountVolume.SetUp succeeded for volume "default-token-tw8wk"
Normal Pulling 19s kubelet, docker-for-desktop pulling image "nginx"
Normal Pulled 15s kubelet, docker-for-desktop Successfully pulled image "nginx"
Normal Created 15s kubelet, docker-for-desktop Created container
Normal Started 14s kubelet, docker-for-desktop Started container
下面我們就看 pod 的配置檔案。有的時候我們可能會忘記了我們啟動的pod的yaml配置檔案地址,我們可以通過kubectl get pod task-pv-pod -o=yaml
命令來獲取某個已經啟動的 pod 的配置檔案,這裡的配置檔案會比我們配置的配置項全很多,因為我們寫配置檔案的時候,很多配置項沒有設定實際上就是使用預設的配置值來實現。
kubectl get pod task-pv-pod -o=yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"task-pv-pod","namespace":"default"},"spec":{"containers":[{"image":"nginx","name":"task-pv-container","ports":[{"containerPort":80,"name":"http-server"}],"volumeMounts":[{"mountPath":"/usr/share/nginx/html","name":"task-pv-storage"}]}],"volumes":[{"name":"task-pv-storage","persistentVolumeClaim":{"claimName":"task-pv-claim"}}]}}
creationTimestamp: 2019-07-08T06:05:51Z
name: task-pv-pod
namespace: default
resourceVersion: "1439249"
selfLink: /api/v1/namespaces/default/pods/task-pv-pod
uid: 7090642e-a146-11e9-89ff-025000000001
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: task-pv-container
ports:
- containerPort: 80
name: http-server
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /usr/share/nginx/html
name: task-pv-storage
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-tw8wk
readOnly: true
dnsPolicy: ClusterFirst
nodeName: docker-for-desktop
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
- name: default-token-tw8wk
secret:
defaultMode: 420
secretName: default-token-tw8wk
status:
conditions:
- lastProbeTime: null
lastTransitionTime: 2019-07-08T06:05:52Z
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: 2019-07-08T06:05:58Z
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: 2019-07-08T06:05:51Z
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://3e9a2ee6b0a13ccee534ec3ffe781adcbff42a7f1851d57e3b374a047a654590
image: nginx:latest
imageID: docker-pullable://nginx@sha256:96fb261b66270b900ea5a2c17a26abbfabe95506e73c3a3c65869a6dbe83223a
lastState: {}
name: task-pv-container
ready: true
restartCount: 0
state:
running:
startedAt: 2019-07-08T06:05:58Z
hostIP: 192.168.65.3
phase: Running
podIP: 10.1.0.103
qosClass: BestEffort
startTime: 2019-07-08T06:05:52Z
幾個比較複雜的配置項我們單獨伶出來理解。
spec.container.imagePullPolicy
spec.container.imagePullPolicy: 這個是容器的映象獲取策略,有幾種策略:
- IfNotPresent: 如果本地沒有,就去遠端 pull 映象
- Always: 每次pod啟動都去遠端pull映象
- Never: 只去本地獲取映象
在區域網本地化搭建映象的時候,應該設定為 Never 。如果 imagePullPolicy 沒有設定,如果設定了映象的 tag,且 tag 不為 :lastest ,就是相當於使用 IfNotPresent。如果 imagePullPolicy 沒有設定,且tag為 :lastest,就相當於是 Always.
spec.container.terminationMessagePath
spec.container.terminationMessagePath: 容器的終止日誌檔案。
spec.container.volumeMounts
spec.container.volumeMounts 其中一個 /usr/share/nginx/html根據 task-pv-storage 掛載到 task-pv-claim 這個共享儲存中。這個pvc 是對應哪個共享儲存呢?
我們可以檢視 kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
task-pv-claim Bound task-pv-volume 1Gi RWO manual 5h
再通過 kubectl get pv
對應到 pv:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 1Gi RWO Retain Bound default/task-pv-claim manual 5h
再檢視這個 pv 的詳細情況:kubectl describe pv task-pv-volume
Name: task-pv-volume
Labels: type=local
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"PersistentVolume","metadata":{"annotations":{},"labels":{"type":"local"},"name":"task-pv-volume","namespace":""},"spec":{"ac...
pv.kubernetes.io/bound-by-controller=yes
Finalizers: [kubernetes.io/pv-protection]
StorageClass: manual
Status: Bound
Claim: default/task-pv-claim
Reclaim Policy: Retain
Access Modes: RWO
Capacity: 1Gi
Node Affinity: <none>
Message:
Source:
Type: HostPath (bare host directory volume)
Path: /Users/yejianfeng/Documents/workspace/kubernets_example/data
HostPathType:
Events: <none>
看到這個pv對應的是宿主機 HostPath 中的 /Users/yejianfeng/Documents/workspace/kubernets_example/data 這個目錄。
所以共享儲存的對映關係是 pod -- volume -- pvc -- pv。
其實這裡我們之所以說是共享儲存,就是說這個儲存應該是一個共享網盤,比如 cephFS,而不應該僅僅只是宿主機上的一個目錄。宿主機上的目錄只是為了除錯方便而已。
說說另外一個 volumeMounts: /var/run/secrets/kubernetes.io/serviceaccount
這個serviceaccount裡面儲存的是什麼呢?我們可以直接kubectl exec -it task-pv-pod -- /bin/sh
到 pod 裡面檢視
~ kubectl exec -it task-pv-pod -- /bin/sh
# cd /var/run/secrets/kubernetes.io/serviceaccount
# ls
ca.crt namespace token
裡面存放的就是 token 。這個 token 是每個 namespace 一個,它表示的是在這個名稱空間的使用者許可權。這個是給 Pod 裡面的程式使用的,如果 pod 裡面的程式需要呼叫這個名稱空間裡面的 K8s 的 api 或者其他服務,它就可以通過獲取這個 token 來發起 http/https 的呼叫。這個 service account 裡面儲存的 token/ca.crt 就代表這個名稱空間的管理員使用者。
dnsPolicy
這個是 pod 的 dns 策略,可以設定有如下值:
- Default : 和宿主機的DNS完全一致
- ClusterFirst: 把叢集的DNS寫入到Pod的DNS配置,但是如果設定了HostNetwork=true,就會強制設定為Default
- ClusterFirstWithHostNet: 把叢集的DNS寫入到Pod的DNS配置,不管是否設定HostNetwork
- None: 忽略所有的DNS配置,一般來說,設定了None之後會自己手動再設定dnsConfig
這裡需要了解,k8s 中的服務發現機制,有幾種方式,一種是通過 service ip,一個服務在叢集中統一存在一個 clusterIP, 所有其他服務需要使用這個服務的時候,就通過呼叫這個 clusterIP 來進行訪問。另外一種是通過 dns,通過給service 設定 subdomain 來給一個服務設定一個域名,而這個域名解析就需要全叢集一致。而這裡的 dnsPolicy 就是做這個用處的。
restartPolicy
pod 的狀態一共有五種,掛起/執行中/成功/失敗/未知。
前一節說node上有個程式 kubelet 會檢測當前 node 上的 pod 是否存活,如果檢測到容器的狀態為失敗,那麼就會啟動重啟策略,這個重啟策略就是這裡 restartPolicy 設定的。
- always: 容器失效時,自動重啟容器
- OnFailure: 容器終止執行,且退出碼不為0時候重啟
- Never: 不重啟
這裡提到一個退出碼,如果這個pod是處於失敗狀態,那麼通過 kubectl describe pod
也是能看到 pod 的退出狀態的。這個退出碼0為正常,非0是不正常。
schedulerName
上節說過,排程器是在 master 節點,控制 pod 應該在哪個 node 上啟動等。這裡就是指定排程器的名字。預設是 default。
securityContext
定義容器 pod 或者 container 的許可權和訪問控制。比如可以控制 pod 使用某個使用者來訪問其內部的檔案,是否開 selinux 等。
serviceAccount
這個概念在 volumeMounts 說過了,儲存的是 pod 要訪問叢集內其他服務的時候的 token。
terminationGracePeriodSeconds
優雅重啟,如果 k8s 要升級,或者由於某個原因要重啟 pod,那麼會先啟動新的P od,然後傳送 SIGTERM 訊號,並且等待 terminationGracePeriodSeconds 個時長,再結束老的 pod。
tolerations
前面也說過,這個是設定 pod 的親緣性,讓排程器把 pod 更好的分配到 node 上去。
status.conditions
這裡再提一下 pod 的生命週期,pod 在初始化,到 pending,到分配到 node 的所有過程,都有個記錄,這裡的 status.conditions 就是這個記錄,記錄各種狀態變更的時間節點:
type欄位是一個包含以下可能值的字串:
- PodScheduled:Pod 已被安排到一個節點;
- Ready:Pod 能夠提供請求,應該新增到所有匹配服務的負載均衡池中;
- Initialized:所有 init 容器 都已成功啟動;
- Unschedulable:排程程式現在無法排程 Pod,例如由於缺少資源或其他限制;
- ContainersReady:Pod 中的所有容器都已準備就緒。
lastTransitionTime 欄位提供 Pod 最後從一個狀態轉換到另一個狀態的時間戳。
qosClass
Qos的三個級別,Guaranteed/Burstable/BestEffort,分別對pod的資源限制從嚴到弱。