iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 6
1
DevOps

從題目中學習k8s系列 第 6

【從題目中學習k8s】-【Day6】奇怪的Pod - Static Pod


title: 【從題目中學習k8s】-【Day6】奇怪的Pod - Static Pod
description: 以無比的恆毅力堅持30天鍊成鐵人--連續30天,一天發表一篇IT技術文章

【從題目中學習k8s】-【Day6】奇怪的Pod - Static Pod

tags: DevOps CICD K8s Docker

前言

不知道你有沒有好奇過把kube-apiserver刪除過?筆者就曾經好奇把它刪掉過,想看看會發生甚麼事XD,結果發現根本刪不掉阿!一旦刪除之後,馬上就會重建一個新的。而且不只是kube-apiserver而已喔,像kube-scheduler也是,到底是為甚麼哩?這其中肯定有甚麼,我們今天就來看看吧~
首先要先了解Pod的創建過程為何。

Pod創建過程及種類

當一個Pod被創立時,是由Control Plane節點建立Pod的YAML檔,假設名為 pod-def.yaml file,輸入kubectl apply -f命令創建該Pod後(或以kubectl run命令創建),是透過kube-apiserver命令Node中的kubelet元件,kubelet透過啟動一個名為k8s.gcr.io/pause:3.2image來創建此Pod

docker images 命令可以看到這個image

PodContainer名稱不能大寫哦~

但是Pod創建方式其實不只上述一種。舉例來說,假設這個K8s Cluster只有一個Node,既沒有Control Plane,也沒有第二個Node,是個單一節點的集群。那麼,這個集群即無法透過kube-apiserver通知kubelet創建Pod(因為沒有Control Plane)。所以有另一種創建Pod的方式:

將pod-def.yaml file放在特定路徑的目錄下,由kubelet定期掃描這個目錄下的YAML file來創建Pod。用這種方式創建的Pod,稱為Static Pod
Static Pod是由kubelet進行管理的只存在特定Node上的Pod

kubelet是創建Pod的主要元件,kubelet會有兩種input

  • 透過特定路徑下的 pod-def.yaml file,創建Static Pod
  • Control Plane利用kube-apiserver並通過HTTP API endpoint的方式

所以,Pod依創建方式可分為兩種

  • Static Pod
  • kube-apiserver

kubelet創建Static Pod時,會在同集群的kube-apiserver中創建一個新的mirror object。Control Plane可透過kubectl 觀察這個Pod,但是無法操作(修改、刪除),這是因為kubectl指令必須搭配kube-apiserver使用,而這時看到的Pod只是該Static Podmirror object


為何需要static pod ?

你可能會好奇為甚麼需要Static Pod,直接使用一般Pod不行嗎?這是因為Static Pod不需依靠Controller Plane的物件,所以可以透過Static Pod創建屬於自己Node中的controller plane物件,例如,Control Plane中的controller.yaml, etcd.yaml等等,其實都算是一種Static PodStatic Pod還有另一個好處,就是不用擔心Controller Plane server crash。而就算 Static Pod 發生crash,kubelet也會自動restart一個新的。

這就是為甚麼在 Control Plane 上使用kubectl get all --namespace=kube-system指令時,看到的所有物件都是Pod,這些就是以Static Pod的形式運行在K8s集群中的。Control Plane 節點上的物件基本上都是以Static Pod的方式創建,畢竟Control Plane若crash掉整個Cluster就完蛋了~

當使用 kubectl get po -A 時,要如何得知那些PodStatic Pod,那些不是呢? 其實很簡單,只要Pod name後面跟著 <Control Plane-Name> 的,就都是Static Pod。像是下圖中的kube-apiserver-g8master, kube-controller-manager-g8master等等都是Static Pod哦~

-A: All namespaces


Static Pod路徑

剛剛有提到,Static Pod的創建方式是由kubelet定期掃描特定目錄下的YAML file來創建,那麼,這個目錄是甚麼目錄呢?

配置文件就是放在特定目錄下 YAML 格式的 Pod 定義文件。用 kubelet --pod-manifest-path = 來啟動kubeletkubelet 定期的去掃描這個目錄,根據這個目錄下出現或消失的 YAML 文件來創建或刪除Static Pod,那麼,要如何知道這個目錄在哪裡呢?可以通過以下指令 ps -aux | grep kubelet 來觀察

也可先進入/etc/systemd/system/kubelet.service.d目錄下查看10-kubeadm.conf這個檔案

$ ps -aux | grep kubelet
root        665  3.9  1.5 1705920 64016 ?       Ssl  00:50  50:30 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --cgroup-driver=cgroupfs --pod-infra-container-image=k8s.gcr.io/pause:3.1 --resolv-conf=/run/systemd/resolve/resolv.conf
root       3100  6.3  6.2 496088 248664 ?       Ssl  00:50  81:37 kube-apiserver --advertise-address=192.168.17.131 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt --enable-admission-plugins=NodeRestriction --enable-bootstrap-token-auth=true --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --insecure-port=0 --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=6443 --service-account-key-file=/etc/kubernetes/pki/sa.pub --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/etc/kubernetes/pki/apiserver.crt --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
george    15571  0.0  0.0  21532  1060 pts/0    S+   22:15   0:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn kubelet

然後,找到 --config=/var/lib/kubelet/config.yaml 這個參數,並且檢查 config.yaml 這個檔案:

$ cat /var/lib/kubelet/config.yaml 
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 0s
    cacheUnauthorizedTTL: 0s
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
cpuManagerReconcilePeriod: 0s
evictionPressureTransitionPeriod: 0s
fileCheckFrequency: 0s
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 0s
imageMinimumGCAge: 0s
kind: KubeletConfiguration
nodeStatusReportFrequency: 0s
nodeStatusUpdateFrequency: 0s
rotateCertificates: true
runtimeRequestTimeout: 0s
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 0s
syncFrequency: 0s
volumeStatsAggPeriod: 0s

找到這一行

staticPodPath: /etc/kubernetes/manifests

這個/etc/kubernetes/manifests路徑就是創建Static Pod的特定目錄啦~

這個路徑一般來說都是固定的,但有些考題會特意將路徑改變,所以建議還是依照上述方法查找路徑比較好喔~

這邊有個觀念很重要

直接用kubectl delete po <static-pod-name> 指令刪除Static Pod 是無法成功的,因為 kubelet 會定期檢查特定目錄下的檔案,即使Static Pod被刪除,但只要其 YAML FILE 還存在,kubelet就會重新創建一個新的Static Pod。若要刪除Static Pod,需刪除其目錄下的 YAML FILE


創建Static Pod

創建Static Pod方式分為兩種:設定檔方式及HTTP方式。

方法一:設定檔

g8node上創建Static Pod,先找到創建的特定目錄,在該目錄下創建Static-Pod.yaml,使用最簡單的nginx image做範例,內容如下:

apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    role: myrole
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP

但是,若直接將此 Static Pod 創建起來,會一直進入CrashBackOff狀態,需要重新config你的kubelet才可以。
輸入 KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --pod-manifest-path=<static-pod-dic>"

KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --pod-manifest-path=/etc/kubernetes/manifest"

## 接著重啟kubelet
systemctl restart kubelet

Control Plane查看,就發現 Pod 處於 Running STATUS囉~

$ kubectl get po
NAME                 READY   STATUS    RESTARTS   AGE
static-web-g8node1   1/1     Running   0          3h31m

方法二:HTTP

這種方式是透過設定kubelet的啟動參數--manifest-urlkubelet定期從該URL位址下載Pod的定義檔案,並以yaml或json的檔案格式進行解析,然後建立Pod

這種方式實現方法和設定檔方式其實是一致的


Control Plane組件

前幾天我們說過Control Plane的組成元件包含:

  • etcd
  • kube-scheduler
  • kube-controller-manager
  • kube-apiserver

從哪裡可以驗證這些元件真的存在呢?
可以進入 /etc/kubernetes/manifests 這麼目錄下查看

$ ls /etc/kubernetes/manifests
etcd.yaml  kube-apiserver.yaml  kube-controller-manager.yaml  kube-scheduler.yaml

確實有這四個元件,我們來看看其中的 kube-scheduler 長甚麼樣

$ cat kube-scheduler.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
  ...

有沒有發現,這些元件都是Pod,又都位於 Control Plane/etc/kubernetes/manifests 目錄下,是不是覺得很熟悉?沒錯,其實這些元件都是以 Static Pod 的方式運行於 K8s 集群中的喔~


結論

簡單整理一下Static Pod 的特性:

  1. 不須透過kuber-apiserver,即使kuber-apiserver故障也能正常創建Static Pod
  2. 沒有 Schedule 的概念,就是固定於某一節點運行
  3. Kubelet 定期掃描特定目錄,一旦該 Pod 結束但YAML還在,則會重新被啟動
  4. Kubelet 本身會 Mirror 該 Pod 的資訊,所以才可以透過 kubectl 等相關資訊去看到

好啦,今天就到這囉~ 謝謝大家~

參考資料

Create static Pods
[Kubernetes] Static Pod 介紹

Thank you!

You can find me on

  • george4908090@gmail.com

上一篇
【從題目中學習k8s】-【Day5】K8s中的resource object(二) - Service
下一篇
【從題目中學習k8s】-【Day7】K8s中的TLS
系列文
從題目中學習k8s31

1 則留言

0
chichi
iT邦新手 5 級 ‧ 2020-10-14 15:48:05

KUBELET_ARGS="--cluster-dns=10.254.0.10 ..." --cluster-dns 需要按照/config.yaml 設置嗎 ?

我要留言

立即登入留言