在【基礎概念】篇有提到Kubernetes(以下簡稱K8s)的最小單位就是Pod,通常我們不會單獨寫Pod因為實在是沒什麼實質的意義(我是這樣覺得拉XD),但是還是要知道整個Pod的組成再進入Deployment才不會有隔閡哦!



編寫Pod定義檔

首先建立一個my-first-pod.yml的定義檔案,VSCode打開後如果有裝保哥的K8s套件,我們可以直接輸入k-pod」,一個簡單的範例就直接出來了!


接著我們修改一下Pod的內容,這裡我會使用Web APP和ASP Net Core Web API Server當作Pod的容器,我們先將容器替換一下

apiVersion: v1
kind: Pod
metadata:
  name: wadweb
  labels:
    app: wadweb
spec:
  containers:
  - name: wadwebapp
    image: "你的registryURL/wad-web-test:latest"
		imagePullPolicy: Always
    resources:
      limits:
        cpu: 200m
        memory: 500Mi
      requests:
        cpu: 100m
        memory: 200Mi
    ports:
      - containerPort: 80
        name: http
  - name: wadwebapi
    image: "你的registryURL/wad-web-api-test:latest"
		imagePullPolicy: Always
    resources:
      limits:
        cpu: 2000m
        memory: 2Gi
      requests:
        cpu: 1000m
        memory: 1Gi
    env:
      - name: DOTNET_RUNNING_IN_CONATINER
        value: "true"
      - name: ASPNETCORE_ENVIRONMENT
        value: "Development"
      - name: ASPNETCORE_URLS
        value: "http://+:8080"
      - name: ConnectionStrings__DefaultConnection
        value: "Server=你的SQLServer Connection;Initial Catalog=WADREQM;Persist Security Info=False;User ID=你的SQLServer帳號;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=true;Connection Timeout=30;"
      - name: Connection__Key
        value: "我是密碼"
      - name: HostUrl__RemoteHost
        value: "http://192.168.1.34:8080"
      - name: TZ
        value: "Asia/Taipei"
    volumeMounts:
      - name: fileupload
        mountPath: /app/upload
    ports:
      - containerPort: 8080
        name: http        
  volumes:
    - name: fileupload
      hostPath:
        path: /run/desktop/mnt/host/d/Kubernetes/fileupload
        type: DirectoryOrCreate
  restartPolicy: Always
  • metadata.name:Pod的名稱
  • metadata.labels:Pod的標籤
    💡 標籤是一組鍵和值 { key, value },用於對 Pod 進行標記。標籤是一種關聯概念,可以將不同的 Pod 分類為同一組,以便更好地管理和控制它們。從範例來看就是 { app, wadweb },未來Pod多的時候可以用標籤Selector(選擇器功能)來管理我們的Pod
  • containers[].imagepullPolicy:容器鏡像拉取原則,設定Always每次都檢查
    💡 Always:每次都檢查,有新的就會重新拉取新的鏡像
           Nerver:不檢查
           IfNotPresent:如果本地有image就不檢查;沒有就拉取鏡像
  • containers[].resources.limits:最大的計算資源使用量
  • containers[].resources.requests:指派計算資源使用量
    💡 CPU的單位是m,每1000m = 1 vCore,最低是100m
          允許的格式:
           1 (1000m)
           0.5 (500m)
           300m(0.3)
    💡 Memory的單位則是跟電腦單位一樣但是再加一個i,Ei、Pi、Ti、Gi、Mi、Ki
          允許的格式:
          104,857,600(100Mi / 100MB)
          100M(100Mi / 100MB)
          100Mi(100MB)
  • containers[].env:容器環境變數
  • containers[].volumeMounts.name:對應的Volumes名稱
  • containers[].volumeMounts.mountPath:要mount的路徑
    💡 mountPath是指在「容器」內要綁定的路徑
  • volumes:用於持久化存儲的抽象概念,它可以為容器提供一個本地或遠端的存儲介質
    💡 Volume有很多種類型如emptyDir、hostPath、configMap、persistentVolumeClaim、NFS等等,可以依照不同的需求和環境建置自己的Volume
  • volumes.hostPath.path:Pod所在的Node上的路徑
    💡 注意!Docker Desktop Kubernetes上如果要把路徑導到Windows的D槽目錄上可以使用/run/desktop/mnt/host/d,如果在實體機器請記得要換成實體機的正確路徑哦!
  • volumes.hostPath.type:HostPath的規則,這裡使用DirectoryOrCreate意思是沒有資料夾就建立一個
  • restartPolicy:容器重啟策略Always、OnFailure、Never(默認是Always)
    💡 關於restartPolicy的功能可以【點我前往



執行Pod

建立好定義檔之後就可以使用kubectl來建立Pod,可以先在Docker Desktop上看到目前是沒有任何的容器在執行的


接著執行以下指令
kubectl create -f my-first-pod.yml
kubectl apply -f my-first-pod.yml --推薦使用這個
💡 建立的命令可以是create也可以是apply,create跟apply其實如同字面意思一樣;create只做建立而apply則是建立+覆蓋,因此我會推薦直接用apply才不會要記一大堆的指令造成混亂
💡 -f 是參數 filename的縮寫


建立完成後可以使用指令查看成功建立的Pod容器,最後回到Docker Desktop上也可以看到執行起來的容器哦!
kubectl get pods




與Pod互動

上面範例架設了Web APP和Web API可是卻無法與容器互動,主要是我們沒有替這個Pod加入Service的資源因此外部的網路是無法存取容器,因此無法互動是正常的,不過K8s還是有提供一個指令Port-forward」讓我們把Pod的Port導出來使用
💡 這裡要注意的是由於port-forward指令是線程阻塞的方式,因此我們必須要開兩個命令才可以執行Mapping哦!
kubectl port-forward wadweb 80:80 --這個是Web APP
kubectl port-forward wadweb 8080:8080 --這個是Web API



成功!
💡 Port-forward的方式主要還是Demo用途而已,在實戰上請不要這樣做哦!




刪除Pod

如果不用使用這個Pod想把它刪除掉,可以使用以下指令
kubectl delete pod wadweb


刪除後就可以使用命令查看Pod的列表,回到Docker Desktop上也都沒有容器在執行了!





題外話之K8s在容器命名規則和Namespaces資源管理上的巧思

從Docker Desktop上我們可以看到K8s在容器的命名上也有他的特別之處XD
  • Pod的命名方式就是k8s + Pod + metadata.name + metadata.namespaces + 隨機碼」
    💡 metadata.namespaces預設是default,所以我們在上圖看到的是default
  • 容器的命名方式就是k8s + containers[].name + metadata.name + metadata.namespaces + 隨機碼」
namespaces本身是一個資源物件,如果要修改metadata.namespaces我們可以新增一個namespaces的定義檔
apiVersion: v1
kind: Namespace
metadata:
  name: "my-first-pod"
---
apiVersion: v1
kind: Pod
metadata:
  name: "wadweb"
	namespaces: "my-first-pod" --新增namespaces
  labels:
    app: "wadweb"
.
.
.
//以下略過
接著建立這個Pod時會發現多建立了一個namespaces叫做my-first-pod



接著我們用指令查看一下Pod會發現,奇怪!我明明建立了Pod為什麼會沒有呢?


這裡就要介紹一下namespaces」這個神奇的資源,它是 Kubernetes 中的一個邏輯分割概念,用於區分不同的群組和用戶,以便更好地管理和控制 Kubernetes 中的資源,使用 namespace 可以實現多租戶環境下的資源共享和安全隔離,另外也可以讓不同的Project擁有相同的Deployment、Services等等,關於namespaces的詳細的介紹可以去官網看看【點我前往】,另外需要注意以下限制:
  1. namespace名稱的限制:必須符合DNS命名規則,只能包含小寫字母、數字和 '-',並且必須以小寫字母或數字開頭和結尾
  2. namespace 的命名空間限制:不同的namespace中不能存在相同名稱的資源對象
  3. namespace 的範圍限制:namespace中的資源只能在同一namespace中進行訪問和操作,不同namespace中的資源不能直接訪問

我們透過指令查看目前有的namespace
kubectl get namespaces
kubectl get pods --all-namespaces


如果加了namespace則後續的所有指令操作都需要加入namespace參數哦!
kubectl get pods -n 你的namespace名稱
kubectl delete pod wadweb -n 你的namespace名稱