在寫前四篇的時候並不總是非常順利,有時候會卡在一些奇特蠢笨的問題,今天就來談談我遇到什麼問題, 然後用什麼方式去解好了。
我的方式不一定是最有效率的,僅僅是整理一下查找資料的結果,有更好的解法歡迎在留言區留言。
今天會談到:
<>: must-have
${}: optional
kubectl get <resource type> -n ${namespace} *可以列出資源
kubectl describe <resource type>/<resource name> -n ${namespace} *可以列出資源的詳細資料
kubectl logs <resource type>/<resource name> -n ${namespace} | tail -n <number of line> *可以列出資源(多半是pod)的執行logs
kubectl exec pod/<pod-name> <command> *印出第一個容器的命令執行結果
kubectl exec pod/<pod-name> -c <container in pod> <command> *印出指定容器的命令執行結果
kubectl exec pod/<pod-name> -c <container in pod> -i -t -- bash *容器的Runtime分配一個pseudo-tty(虛擬的終端)並且以bash為一個shell,綁定到Container的標準输入。
kubectl edit <resource type> <resource name> -n ${namespace} *編輯這個資源的描述,儲存完之後如果有改變的話,這個資源會被重新deploy
基本上前四篇在DIY各種Demo的時候用的最多是這六條指令, 尤其是kubectl exec簡直是必會,不然都要進去nodes裡面看。
註1:這邊不講Docker是因為K8s裡面不一定會用Docker當作Container Runtime(容器運行方案),也有可能採用其他的方案如rkt,這等到後幾篇再說。
註2:對Docker exec原理有興趣可以看這邊。
如果這個container的image在包的時候沒有包下這個指令的檔案(linux的指令都是檔案),或是這個image的base image用的是精簡版的OS image就有可能沒有這個指令。
解法: 把指令改成sh, sh是unix上的標準shell,基本上再精簡的image都有sh。
想要查看這個pod和那個pod是否互通,但卻找不到這個那個指令?
這個就要看你的os是哪家的
cat /etc/os-release
然後就跟一般的機器一樣安裝自己想要的工具, 附帶一提, 如果你用的是Alpine Linux, 可以用apk這個套件管理工具。
# How to resolve nslookup, dig , host Command Not
# ubuntu
apt-get install dnsutils
# centos
yum install bind-utils
# alpine
apk update
apk add bind-tools
然而世事豈能盡如人意,有時候你就是會遇到這種情況:
非不得已可以找到原檔的Dockerfile加Root權限,再重新包成你個人的Image,但非常不建議,這是有資安考量的。
當你建立一個Service時,Kubernetes會自動建立一個形如..svc.cluster.local的DNS項。如果叢集中另一個服務呼叫這個服務時,僅僅指定了,那麼Kubernetes會使用呼叫方所在的Namespace將補全。因此如果呼叫方和被呼叫方不處於同一個Namespace,你必須使用包含Namespace的service name
之前在試著執行ExternalName的時候曾經遇過kube-dns怎麼解析也解不出domain name, 於是便照著官方文件實際走了一遍流程, 看看是否Kube-dns元件有問題。
首先創建一個busybox.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
kubectl exec -ti busybox -- nslookup kubernetes.default
顯示這樣的結果是錯的, 原因可能是busybox還沒有起來,或是最新版本的image有問題
這樣的結果才是對的(image版本: 1.28.4 *Issue here)
先查看kube-system裡是否有kube-dns這個元件
kubectl get pods --namespace=kube-system -l k8s-app=kube-dns
接著可以透過這個指令去查看kube-dns元件裡的logs
k logs pod/<pod-name of kube-dns> -n kube-system -c dnsmasq
k logs pod/<pod-name of kube-dns> -n kube-system -c kubedns
k logs pod/<pod-name of kube-dns> -n kube-system -c healthz
之前我測試ExternalName有沒有work的方式便是進入任意容器,並且使用nslookup指令查看是否有指到cheddar.kube-system.svc.cluster.local
Kube-dns Pod裡面會有三個containers: kubedns, dnsmasq, healthz(sidecar)
他們的分工可以參照下圖:
圖源來自Kubernetes從入門到實踐,詳細分工可以參考裡面所寫的,另外可以參閱這份補充資料, 看完對於Kube-dns會有更深一層的了解。
值得一提的是Kube-dns在1.14版本後改變了DNS的部署方式, 改成了Kubedns + dnsmasq, 並且本來存在etcd的數據都會保存在memory中。所以上面提到的那三個容器, 的healthz變成一個叫做sidecar的容器。
不過我比較好奇的是補充資料提到的skydns, 這部分就留到明天來研究好了。