【K8S】初探Kubernetes

最近阿猩在Windows環境中,使用Docker Desktop,大量的測試docker及K8S,測試建立.NET6專案容器,也將.NET5專案微痛升級至.NET6容器。在Docker的基礎知識下,延伸至K8S,將關注點從容器擴大至Node。本篇阿猩除了操作流程之外,最後也概略性的,將阿猩對於K8S運作流程重點做筆記。

環境安裝流程


安裝K8S
K8S官網查詢安裝指令,例如

curl.exe -LO https://dl.k8s.io/v1.27.1/bin/windows/amd64/kubectl-convert.exe.sha256


因阿猩已安裝Docker Desktop,故還可以使用Docker Desktop安裝Kubernetes(圖1)。

圖1 使用Docker Desktop 安裝Kubernetes

 

環境檢視入門


確認安裝是否成功
開啟cmd 或powershell,輸入下列指令

kubectl version

看的到Client Version及Server Version就代表成功啦。

 


K8S相關的基礎概念


應用程式部屬演進
早期應用程式部署,會將應用程式執行於硬體伺服器,後來引進了虛擬化的概念,利用不同的虛擬機,實現OS層隔離,並可隨時設定、調整一台VM可用的硬體資源。因VM包含OS所需檔案,且需要透過Hypervisor與OS層溝通,故占的儲存空間,以及使用的硬體資源都比容器要多。近幾年則進入到容器部屬,因容器少了Hypervisor,直接與OS層溝通,容器本身沒有OS的檔案,故容量較小,執行速度也較快(圖2)。

 

圖2 VM與容器的差別(來源:https://docs.docker.com/get-started/)

 

K8S是什麼
Kubernetes(常簡稱K8S)。原為Google設計的開源系統,主要用於自動部屬、擴展和管理容器化應用程式。基於容器技術,發展出更多部署的功能,例如:監測、自動擴展、負載平衡、滾動式換版等。在K8S中,最小部屬單位稱為POD,一個POD中可包含1個至多個Container。

 

YAML檔是什麼
YAML是一種資料序列化的格式,常見的資料序列化格式還有XMLJSON

  • XML:以Tag方式定義資料。
  • JSON:以Key-Vvalue的方式定義資料。
  • YAML:以Dictionary的方式定義資料,以每行開頭空格數表示物件階級。
     

XML、JSON、YAML分別表示2台Server,且描述各自的ServerName及IP,則會像圖3。

 

圖3 XML、JSON、YAML結構比較示意圖

 

 

YAML、POD、Service、Deployment


練習撰寫YAML
一開始接觸K8S,可能還沒有自己專案的映像檔,所以阿猩先使用dockerhub上的image作測試。新增一個檔案,命名為nginx.yaml,在裡面寫入下列內容

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: yaml-test
  name: yaml-test
spec:
  containers:
  - image: nginx
    name: nginx
    ports:
    - containerPort: 80
  1. 將POD名稱命名為yaml-test
  2. 在POD內部,從dockerhub下載nginx的image
  3. 在POD內部,建立1個名為nginx的容器。
  4. 將容器內部對node的開啟port設為80

 


此範例yaml的步驟流程為
 

  1. 將POD名稱命名為yaml-test
  2. 在POD內部,從dockerhub下載nginx的image
  3. 在POD內部,建立1個名為nginx的容器。
  4. 將容器內部對node的開啟port設為80

YAML欄位說明,可自行Google或使用kubectl explain指令查看說明,例如

kubectl explain pod
kubectl explain pod.apiVersion

 

建立POD
開啟cmd或powershell,進到nginx.yaml所在目錄,執行

kubectl apply -f nginx.yaml

kubectl get pod

若成功則會顯示目前擁有的POD(圖4)。

圖4 get pod


 

 

 

 

建立暫時性的port-forward
因CLI不可以直接跟POD溝通,所以需要額外對外可連線的PORT,一般會透過SVC進行設定,這裡測試暫時使用port-forward測試。

kubectl port-forward yaml-test 8080:80 

開啟瀏覽器並輸入localhost:8080,可看到圖5代表成功。

圖5 Nginx容器開啟成功畫面

 

認識其他可建立對象 
POD為K8S最小部屬單位K8S也可用於自動部屬、擴展和管理容器化應用程式,故在YAML檔中的Kind欄位,也可指定POD以外的類型,用於不同的時機,例如DeploymentService、DaemonSetJobsCronJob等(圖6)。因這裡的資訊太過龐大,一時之間阿猩也無法完整說明,僅紀錄使用時機及重點。

  1. Deployment可作滾動式換版、設定replicas數量,kube-controller-manager會確保POD數量不小於replicas設定的數量。
  2. Service可用於設定port, Type可指定為Cluster IPNodePortLoadBalance等。
  3. DaemonSet: 新增node時,會主動建立一個特定用途的POD,例如kube-proxy、log處理。
  4. Jobs:處理一次性任務。
  5. CronJob:類似排程服務,基於時間做管理。
圖6 YAML Kind種類

 

 

 

K8S的運作流程概要


K8S的運作流程水很深,阿猩只能盡可能的整理,釐清概念性的脈絡,如有不正確的地方,也請大家不吝於告訴我。K8S大致運作概念為圖7。

圖7 K8S運作概念圖

Node
K8S主要可依職責分為Master NodeWork Node。Master node包含kube-apiserverController Managerscheduleretcd,用於管理Work Node。而Work Node則包含與應用程式相關的Pod、kubelet、kube-proxy等。

 

Controller Manager
監聽容器狀態,確保健康度、replicas數量、滾動式換版等工作。YAML檔會長得像是

apiVersion: apps/v1
kind: Deployment
metadata:
 name: deployment-test
 labels:
  app: deployment-test
spec:
 replicas: 2
 selector:
  matchLabels:
   app: deployment-test
 template: 
  metadata:
   labels:
    app: deployment-test
  spec:
    containers:
      - name: testapi
        image: testapi
        imagePullPolicy: Never
        ports:
        - containerPort: 80 

 

kube-apiserver
開發者在CLI下kubectl 指令時,會以Restful API作為協定向Master Node溝通,再由Master Node透過kube-apiserver向Work Node溝通(圖8)。Master Node內部溝通、Master Node與Work Node溝通,大多屬Protobuf協定。
 

圖8


 

 

 

 

 

 

 

 

kubelet

Kubelet會依照yaml.spc的設定,對Node內部的Pod進行管理。Kubelet 會詢問 kube-apiserver ,會依照yaml.spc的設定,對Node內部的Pod進行管理,確保容器的狀態,例如在此Node啟動Pod。後續透過不同的協定,如ProtobufCNICRIOCI等協定,完成不同性質的工作。例如

CNI:調用容器網路接口,取得網路資訊,如IP等
CRI:定義了容器與鏡像檔接口,用於建立容器,並把網路資訊設定帶入容器
OCI:開放容器的標準,CRI會調用OCI用於創建容器,常見的就是大家所使用的Docker,但可以使用其他技術。

Pod
K8S中最小的單位,可包含1個至多個容器。

 

Kube-proxy
因外部不可以直接與Pod進行溝通,故應用程式若要開發給其他使用者,需另外設定proxy,K8S 可透過Service利用Cluster IP、LoadBalance等設定。YAML內容會像是

apiVersion: v1
kind: Service
metadata:
 name: svc-testapi
spec:
 type: LoadBalancer
 selector:
  app: testapi
 ports:
  - port: 80
    targetPort: 80