Kubernetes - Pod 學習紀錄

Posted by Kubeguts on 2021-05-21

Kubernetes- Pod 學習紀錄

本節會學習到

  • Pod的核心概念
  • 如何創建pods
  • 檢查pod的健康狀態

Pod的核心概念

Pod的概念,引述K8S官網

Pods are the smallest deployable units of computing that you can create and manage in Kubernetes.

最小運行單位

簡單來說就是,K8S運行的最小單元,包含著一個或多個containers,這些container

  • 彼此共享同樣的儲存與網路資源
  • 都吃著同樣的設定

Pod有著自己的IP

可以說Pods提供了Containers運行所必要的環境,Pod擁有自己的

  • IP address
    • 這些在同一個pod內的container都共享著同樣的loopback network interface (localhost)
      • 容器間可以透過 localhost (127.0.0.1)溝通
    • 不同的container必須要在不同的port監聽服務
    • 不同的container在不同pod可以有相同的port

pic01

  • memory usage
  • storage volumes

Pods都會運行在一個Node環境內,且為Node定義ReplicaSet,必須要滿足N個運行正常的pods,若pods有問題,k8s會置換掉

Pod就像是之前透過Docker Compose,管理一組container的啟動與運作

透過組成多個container的pod,來打造輕量級的VM

不過通常來說一個Pod內只會運行一個container服務,運行多個container的情況是少見的

Pods不會跨不同的Node,這點要注意

pic02

為何要有Node這個角色??

通常Node扮演管控底下Pods的角色,因為某些Pods需要特定機器規格的資源。

例如我們有Node專門訓練AI models的Pods,以及有Node專門運行區塊鏈節點的Pods,每個Node所具備的硬體資源就會因應不同需求而有所不同

這篇文章講述了Pod在Node的角色,可以瀏覽看看

Medium: DevOps: Where is My PodPod — Pod Arrangement by smalltown

對於Node內,每個Pod的資源控管就非常重要, 萬一若有一個Pod將全部資源資掉,會導致整個Node掛掉, 使其他Pod陣亡

如何創建一個pod

以直接方式創建

  • 直接創造一個pod:
    • kubectl run [podname] --image=imageName:version

本範例會創建一個有nginx的pod

nginx是可用來架設web services的工具,nginx official site 任意門

1
2
$ k run nginx-pod --image=nginx:alpine
pod/nginx-pod created

透過yaml方式創建

  • kubectl create/apply [yaml file]

此方法好處是,可以把每次的創建過程透過yaml給記錄到版本控制中

yaml是什麼?? 請看這裡 -> link

範例: 用yaml檔案定義一個nginx pod

指令

1
$ kubectl create -f file.pod.yml --dry-run --validate=true
  • -f yaml檔案
  • --validate 預設為true,驗證yaml檔案是否合規
  • --dry-run 會先試驗產出建立後結果,但不會真的建立

範例: 用apply方式套用yaml設定,並創造出pod

指令

1
$ kubectl apply -f file.pod.yml

要注意這方法,要在一開始用kubectl create時,需搭配--save-config才能夠用kubectl apply

  • --save-config 會將pod的資訊儲存到 yaml檔案中的annotations

yaml範例

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
app: nginx
spec:
containers:
- name: my-nginx
image: nginx:alpine
resources: {}
ports:
- containerPort: 80
1
2
$ k create -f nginx.yaml
pod/my-nginx created

查看pod資訊

1
2
3
$ k get pods
NAME READY STATUS RESTARTS AGE
my-nginx 1/1 Running 0 64s

指定剛創建好的nginx pod,因為創建時有透過--save-config,可看到有annotation,說明目前版本是什麼
pic03

透過kubectl describe pod my-nginx查看pod運行資訊

  • ip address
  • event: 創建pod時發生的事件,可用來除錯用
    pic04

接著再使用kubectl apply來變更pod

1
2
$ kubectl apply -f nginx.yaml
pod/my-nginx unchanged

透過 kubectl exec [pod] 進入pod內的環境

1
2
3
$ kubectl exec my-nginx -it sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ #

取得pods資訊

1
$ kubectl get pods

輸出結果

1
2
3
4
$ kubectl get pods

NAME READY STATUS RESTARTS AGE
nginx-pod 0/1 ContainerCreating 0 6s

將pods對外開放連接

k8s創建pods時預設是只能在k8s cluster內連線,意思就是無法透過本機ping到在k8s架設好的nginx pod,所以要透過port-forward方式才行

指令

1
$ kubectl port-forward [name of pod] [external port]:[internal (in k8s) port]

範例

1
2
3
$ kubectl port-forward nginx-pod 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

砍掉pod

指令

1
$ kubectl delete pod [name-of-pod]

範例

1
2
$ kubectl delete pod nginx-pod
pod "nginx-pod" deleted

不過要注意的是,若在deployment中定義replicaSet,要滿足一定pod的運行數量,那砍掉後會在被重新創造出來

正式砍掉pod的方法,也必須把管理pod的deployment給砍掉

1
$ kubectl delete deployment [name-of-deployment]

也可以透過 yaml方式砍掉

1
$ kubectl delete -f [yaml file]

檢查Pod的健康狀態

透過Probe方式,檢查Pod的狀況

有兩種Probe:

  1. Liveness Probe
  • 檢查pod是否運作正常
  1. Readiness Probe
  • 檢查Pod是否可以收到請求

Probe Action種類

  • ExecAction
    • 在container內執行動作
  • TCPSocketAction
    • 以TCP Check方式檢查container的IP address以及port
  • HTTPGETAction
    • 以HTTP GET請求方式對container做測試

會有以下狀態

  • Success
  • Failure
  • Unknown

範例

在yaml檔案中定義要檢查的probe類型

HTTPGETAction類型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
app: nginx
spec:
containers:
- name: my-nginx
image: nginx:alpine
resources: {}
ports:
- containerPort: 80
livenessProbe: # 定義liveness probe
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 15
timeoutSeconds: 2 # 過2秒沒反應就timeout
periodSeconds: 5 # 每5秒檢查一次
failureThreshold: 1 # 若錯一次就認定Pod服務為故障

ExecAction類型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: k8s.gcr.io/busybox
resources:
limits:
memory: "64Mi" #64 MB
cpu: "50m" #50 millicpu (.05 cpu or 5% of the cpu)
args: # 為容器定義參數或打算執行的shell指令
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command: # 定義要執行的指令
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5

這個範例會在pod啟動時,執行以下動作

1
2
3
4
5
$ touch /tmp/healthy; # 創建簡單的檔案 healthy
sleep 30; # 等待30秒後

$ rm -rf /tmp/healthy; # 在把檔案砍掉
sleep 600

tmp/healthy的檔案被砍掉後,liveness probe就無法成功執行 cat /tmp/healthy 指令,就會發生錯誤,通知k8s要重新創建pod服務

pic08

搭配Readiness Probe類型 (也可以與Liveness Probe同時定義)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
app: nginx
rel: stable
spec:
containers:
- name: my-nginx
image: nginx:alpine
resources:
limits:
memory: "128Mi" #128 MB
cpu: "200m" #200 millicpu (.2 cpu or 20% of the cpu)
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 15
timeoutSeconds: 2 # Default is 1
periodSeconds: 5 # Default is 10
failureThreshold: 1 # Default is 3
readinessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 3 # 定義多久後才能收到requst
periodSeconds: 5 # Default is 10
failureThreshold: 1 # Default is 3

實際執行看看,透過kubectl create -f [yaml]來創建pod,可看到nginx服務運作正常

pic05

由於我們在yaml檔案中有定義liveness probe與readiness probe,透過httpGet方式確認網頁服務是否還活著否,這時將nginx內的預設index.html給砍掉,來看看liveness probe會給出怎樣的警告

砍掉後nginx服務也終止了,表示k8s也正準備重新啟動container
pic06

接著透過 kubectl describe pod [pod name]來看看readiness probe的訊息,可以看到liveness probe與readiness probe無法成功讀取index.html首頁。

但liveness probe還會做一件事,那就是失敗次數達到yaml檔案內定義的failureThreshold次數後,會請k8s重新啟動pod的ningx服務

pic07

由於有定義liveness probe,在發現nginx服務沒有index.html時發生錯誤,會重新創建container,所以若在透過 kubectl exec [nginx-pod-name] -it sh ,可以看到nginx內的index.html又復原了

Readiness Probe與Liveness Probe差異

  • Liveness Probe: 定義container什麼時候才重啟

  • Readiness Probe: 定義container什麼時候才能開始接收請求或流量

參考