Kubernetes CKA課程筆記 46
使用臨時的Pod來Debug — 使用BusyBox的Pod
- 通常會利用臨時建立的Pod在裡面執行指令來做正常佈署應用程式的Pod的Debug
- 因為由前面學到的,Pods間的網路架構與Cluster Node網路架構很不一樣!!
- 如圖Pods間的網路溝通有一層虛擬的網路
- 可以透過不同Pod來確認另一個Pod的狀態
- 常見附有很多工具的image則如busybox image
busybox image內含以下工具:
- ficonfig
- mslookup
- netstat
- ping
- …etc
也可以直接到busybox wiki查看有哪些指令(連結)如下圖:
但是busybox沒有curl....,所以可以另找curl image:
接著就來用imperative方式建立Busybox的Pod來當作測試用的Pod執行:
kubectl run debug-pod --image=busybox
建立後確認Pod狀態:
過一陣子在看:
所以這時候無法執行如下指令進入Pod內:
kubectl exec -it debug-pod -- sh
詳後面解釋
Container通常為了某些特定的任務運行,例如:
- 運行一個mysql DB
- 啟動一個Web Application
- Syncronize data
並且最終Container隨著任務結束而消失
換句話說Container僅存活到任務的Process結束時
所以可能mysql DB或是Web Application crash了,則Container exits
至於是在哪邊定義Container中的Process的啟動? →要看Dockerfile
譬如來到docker hub找nginx
然後就會看到建立該image的Dockerfile:
同理也可以找到postgres:
下拉看到:
所以其實就是Docker file內的CMD command
在決定Container啟動時執行的Process!
所以同理來看看busybox的image:
下拉
sh並不是啟動Process或應用程式的指令,而是shell等待terminal輸入參數執行
因為並沒有實際的terminal,所以就會exits
所以剛剛如下起的Pod才會結束這麼快,因為根本沒有給任務!
所以該如何讓busybox的Pod持續活著?
選項有二:
1.透過interactive node(-it)建立busybox間的terminal
如下建立另一個名稱的busybox Pod,帶著-it:
kubectl run debug-pod-2 --image=busybox -it
此時就會進入到該Container的terminal內:
試著執行exit指令離開terminal後再次確認Pod狀態:
可以再執行以下再次進入到該Pod:
kubectl exec -it {pod名稱} -- sh
在busybox Pod的terminal模式下,就能夠執行我們要做的測試工作如:
nslookup nginx-servie
或是ping:
ping nginx-service
等等之類的測試活動
然後記得結束後要用指令將其移除,如下:
kubectl delete pod {pod name1} {pod name2}
2.在Configuration File內重新定義"command"與"args"
在透過docker指令運行Container時,可以透過指令直接改寫上述的"CMD":
docker run <image name> <command>
(直接改寫在上面的<command>)
但是如果不想改寫CMD,而是想直接提供一個參數來執行呢!?
比如上面busybox本身CMD內容只有"sh"情況下,我們給予參數變成:
"sh my-script.sh"
上述這種形式是沒辦法透過CMD (instruction)來做到
但是有個地方是"ENTRYPOINT" (instruction)可以允許附加其他commands
總結來說:
- CMD:主要目的是提供預設的Container啟動
- ENTRYPOINT:executable並持續運行,且允許附加commands
- 有些情況甚至允許CMD + ENTRYPOINT
下圖可以看看一些範例:
在如上CMD + ENTRYPOINT範例中:
- ENTRYPOINT是用來定義Container中的Process開始
- CMD則是提供預設的參數給ENTRYPOINT (instruction)
至於以上的模式又如何套用在Kubernetes?
以一個Pod的Configuration File來與Docker File對比:
沒錯!
K8s Pod的command = Docker file的ENTRYPOINT
K8s Pod的args = Docker file的CMD
(完全反過來...!)
也就是K8s Pod來說:
- ENTRYPOINT是"command"
- CMD則是"arguments"
在K8s官網doc也有提到這個問題:
由以上概念後,接著簡單建立一個測試用的busybox的Pod的yaml檔:
名稱取作bb-pod.yaml
並嘗試給予這個Pod一些args內容整體如下:
如上我並沒有定義command(也就是ENTRYPOINT)
但其實也可以只給command如下:
當然也可以兩個(args + command)都來:
最終上述定義的args或command內容將會取代image內原本設定的
其他範例還可以如下定義:
或是:
甚至合併!!!!
執行建立並確認狀態:
再說一次:
透過K8s Configuration File
可以覆寫掉原本image上面定義的ENTRYPOINT與CMD!!!
然後其意義是反著的:
可以彈性的決定執行image本身定義或是自行給予(透過Configuration File)
不進入Pod內執行commands:
以前的學習或如上範例中都曉得如何進入到Pod內執行要跑的指令如下執行:
kubectl exec -it {Pod name} -- sh
(上述sh可以換成bash)
但有時候為了方便簡單測試一下ping
可能不一定會想特地進到測試用的Pod裡面去!
是的!可以! 就是直接給指令!! 範例如下:
kubectl exec -it {Pod name} -- sh -c "{指令}"
例如
kubectl exec -it {Pod name} -- sh -c "printenv"
或執行以下:
kubectl exec -it busybox-pod -- sh -c "while true; do echo hello; sleep 2; done"
當然也可以拿來ping service
kubectl exec -it busybox-pod -- sh -c "ping nginx-service"
或是看看Pod內Conatiner的netstat -lntp如下:
kubectl exec -it busybox-pod -- sh -c "netstat -lntp"
用這樣方式做一些測試工作會相對比較方便!!
另外特別注意
在exec時執行後面帶空格sh或是空格bash
到底該用哪一個?
- bash 可以當作更強的sh
- bash有更多功能語法
其實有些image內不支援bash…,只有經典的shell(sh)
sh就好像瘦身版本後的bash
所以嘗試在沒有bash的image執行bash就會像如下這樣錯誤出現!
所以通常就試試bash,沒有在退而求其次用sh
註:OpenShift類似的解決方案