1. 程式人生 > 實用技巧 >04-K8S資源編排

04-K8S資源編排

一. 資源清單檔案-YAML

1. YAML 概述

K8S叢集中對資源管理和資源物件編排部署都可以通過宣告樣式(YAML)檔案來解決,我們把這種檔案叫做資原始檔清單語法格式:
  • 通過縮排表示層級關係
  • 不能使用Tab進行縮排,只能使用空格,一般縮排2個空格
  • 字元後縮排一個空格,比如: 冒號,逗號後面
  • 使用---表示新的yaml段開始
  • 使用#註釋

2. K8S中的資源

1. 名稱空間: 僅在此空間有效。K8S中所有內容都抽象為資源,資源例項化之後,叫做物件
  • 工作負載型資源: Pod, ReplicaSet, Deployment, StatefulSet, DaemonSet, Jobs...
  • 服務發現及負載均衡型資源: Service, Ingress, LoadBalance...
  • 配置與儲存型資源: Volume(儲存卷)...
  • 特殊型別的儲存卷: ConfigMap(配置中心), Secret(加密資料)...
2. 叢集級別: 全叢集可見。Namespace, Node, Role, ClusterRole, RoleBinding, ClusterRoleBinding3. 元資料型: 指標。NPA, PodTemplate, LomitRange

3. 常用欄位

1. 必選
引數名型別描述
apiVersionStringK8S Api 版本
kindString指定建立資源的Controller型別和角色
matadataObject元資料物件
matadata.nameString
元資料物件的名字
matadata.namespaceString指定名稱空間
specObject詳細定義資源的規格
spec.containers[]List定義容器的列表
spec.containers[].nameString定義容器的名字
spec.containers[].imageString定義映象名稱
2. 容器
引數名型別描述
spec.containers[].imagePullPolicyString定義映象拉取的策略, 預設是IfNotPresent 1. Always: 意思是每次都嘗試拉取映象 2. Never: 表示僅使用本地映象 3. ifNotPresent: 如果本地有就使用本地,沒有在拉取
spec.containers[].command[]List指定容器啟動命令,可以指定多個
spec.containers[].args[]List指定容器啟動命令引數
spec.containers[].workingDirString指定容器的工作目錄
spec.containers[].volumeMounts[]List指定容器內部的儲存卷配置
spec.containers[].volumeMounts[].nameString指定儲存卷名稱
spec.containers[].volumeMounts[].mountPathString指定被容器掛載的儲存卷的路徑
spec.containers[].volumeMounts[].readOnlyString是否只讀,預設是讀寫
spec.containers[].ports[]List指定容器需要的埠列表
spec.containers[].ports[].nameString指定埠名稱
spec.containers[].ports[].containerPortString指定容器需要監聽的埠號
spec.containers[].ports[].hostPortString指定容器所在主機需要監聽的埠號,預設跟containerPort相同,注意設定了hostPort同一臺主機無法啟動相同副本
spec.containers[].ports[].protocolString指定埠協議,支援TCP和UDP,預設值為TCP
spec.containers[].evn[]List環境變數列表
spec.containers[].evn[].nameString指定環境變數名稱
spec.containers[].evn[].valueString指定環境變數值
spec.containers[].resourcesObject指定資源限制和資源請求的值
spec.containers[].resources.limitsObject設定容器執行時資源的執行上限
spec.containers[].resources.limits.cpuString指定CPU的限制,單位core數 1c = 1000m
spec.containers[].resources.limits.memoryString指定MEM記憶體的限制,單位為MiB, GiB
spec.containers[].resources.requestsObject指定容器啟動和排程時的限制設定
spec.containers[].resources.requests.cpuStringCPU請求, 單位為core數, 容器啟動時初始化可以數量
spec.containers[].resources.requests.memoryString記憶體請求, 單位為MiB, GiB. 容器啟動的初始化可以數量
3. 額外
引數名欄位型別描述
spec.restartPolicyString定義Pod的重啟策略, 可選值為Always, OnFailure 預設值為Always 1. Always: Pod一旦終止執行, 則無論容器時如何終止的, kubelet 服務都將重啟 2. OnFailure: 只有Pod以非0退出碼終止才會重啟 3. Never: Pod 終止後,kubelet將退出碼報告給Master,不會重啟該Pod
spec.nodeSelectorObject定義Node的Label過濾標籤
spec.imagePullSecretsObject定義pull映象時, 使用的secret名稱
spec.hostNetworkBoolean定義是否使用主機網路模式,預設值false
# 控制器定義
apiVersion: apps/v1       # API版本
kind: Deployment          # 資源型別
metadata:                 # 元資料
  name: nginx-deployment
  namespace: default
spec:                     # 資源規格
  replicas: 3             # 副本數量
  selector:               # 標籤選擇
    matchLabels:
      app: nginx
  # 被控制物件  
  template:              # Pod模版
    metadata:            # Pod元資料
      labels:
        app: nginx
    spec:                # Pod規格
      containers:        # 容器配置
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80 
快速編寫
# kubectl create 試執行生成
kubectl create deployment web --image=nginx -o yaml --dry-run > nginx.yml
# kubectl get 匯出執行的Pod
kubectl get deploy nginx-deployment -o=yaml > nginx-deployment.yml

二. K8S核心技術-Pod

1. Pod 建立時序圖

1. 建立指令傳送至ApiServer,由ApiServer寫入etcd2. Scheduler監聽到有新的Pod建立,根據演算法分配node節點,繫結Pod。返回結果由ApiServer寫入etcd3. Kubelet 監聽到被分配的Pod,執行docker 執行容器。更新狀態返回ApiServer寫入etcd

2. Pod 排程策略

1. Pod的資源限制
  • 在排程過程中根據resources.request的限制找到能夠滿足的節點排程
2. 節點選擇器: nodeSelector
# 節點新增標籤
kubectl label node node1 env_role=prod
# 檢視節點標籤
kubectl get nodes node1 --show-labels
3. 節點親和性: nodeAffinity,和nodeSelector基本一樣,根據節點標籤的約束來對Pod排程
  • 硬親和性: 約束條件必須滿足
  • 軟親和性: 嘗試滿足
4. 汙點和汙點容忍Taint汙點: 節點不做普通分配排程,是節點屬性
  • NoSchedule: 一定不被排程
  • PreferNoSchedule: 儘量不被呼叫
  • NoExecute: 不會排程,並且還會驅逐已有的Pod

3. Pod 生命週期

Pod能夠具有多個容器,應用執行在容器裡面,但是它也可能有一個或多個先於應用容器啟動的Init容器1. 執行pause基礎容器
2. init Container 初始化容器執行(init C可以有多個,序列執行)
  • Init 容器總是執行到成功完成為止,如果Init容器失敗,K8S會不斷的重啟該Pod,直到Init 容器成功為止。如果Pod對應的restartPolicy為Never,則不會重新啟動
  • 每個Init容器都必須在下一個Init容器啟動之前完成
3. main Container 主容器執行(可以有多個)
  • start: 在容器啟動時,執行一條命令或指令碼
  • liveness: 存活檢測。主要用來確定是否重啟容器
  • readless: 就緒檢測。只有當Pod中所有容器都處於就緒狀態,才會作為Service的後端
  • stop: 在容器關閉時,執行一條命令或指令碼

1. init C 示例

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  initContainers:
  - name: init-myservice
    image: busybox:1.32.0
    # until: 返回非0, 則進入迴圈. 返回0則退出迴圈
    command: ["sh", "-c", "until nslookup myservice;do echo 'waiting for myservice';sleep 2;done;"]
  - name: init-mydb
    image: busybox:1.32.0
    command: ["sh", "-c", "until nslookup mydb;do echo 'waiting for mydb';sleep 2;done;"]
  containers:
  - name: myapp-container
    image: busybox:1.32.0
    command: ["sh", "-c", "echo 'The app is running! && sleep 3600'"]
  • 檢視日誌(-c 指定pod裡的容器)
kubectl logs myapp-pod -c init-myservice
kubectl logs myapp-pod -c init-myservice -f --tail=10
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377  
  • 在Pod啟動過程中,Init容器會按順序在Pause之後啟動,每個容器必須在下一個容器啟動之前成功推出
  • 如果由於執行時失敗退出,它會根據Pod的restartPolicy指定的策略進行重試
  • 在所有的Init容器沒有成功之前,Pod將不會變成Ready狀態
  • 如果Pod重啟,所有Init容器必須重新執行
  • 對Init容器spec的修改被限制在容器image欄位,修改其他欄位都不會生效。更改Init容器的image欄位,等價於重啟該Pod
  • Init容器具有應用容器的所有欄位。除了readiness
  • 在Pod中的每個app和Init容器的名稱必須唯一

2. 探針

探針是由kubelet 對容器執行的定期診斷。要執行診斷,kubelet呼叫由容器實現的Handler。有三種類型的處理程式:
  • ExecAction: 在容器內執行指定命令。如果命令退出時返回碼為0則認為診斷成功
  • TCPSocketAction: 對指定埠上的容器的IP地址進行TCP檢查。如果埠開啟,則診斷被認為是成功的
  • HTTPGetAction: 對指定的埠和路徑上的容器的IP地址執行HTTP Get請求。如果響應的狀態碼大於等於200且小於400,則診斷被認為是成功的
每次檢測都將獲取三種結果之一:
  • 成功: 容器通過了檢測
  • 失敗: 容器未通過檢測
  • 未知: 診斷失敗,因此不會採取任何行動
探測方式:
  • readinessProbe: 檢測容器是否準備好服務請求。如果就緒探測失敗,端點控制器將從與Pod匹配的所有Service的端點中刪除該Pod的IP地址。初始延遲之前的就緒狀態預設為Failure。如果容器不提供就緒探針,則預設為Success
apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget-pod
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container
    image: nginx:1.19.3
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html
      initialDelaySeconds: 1 # 延時, 啟動後多長時間檢測
      periodSeconds: 3       # 重試
kubectl get pod readiness-httpget-pod -w -o wide
kubectl describe pod readiness-httpget-pod
--- output
Readiness probe failed: HTTP probe failed with statuscode: 404
# 進入容器, 如果多個容器需 -c 指定
kubectl exec -it readiness-httpget-pod -- /bin/bash
  • livenessProbe: 檢測容器是否正在執行。如果存活探測失敗,則kubelet會殺死容器,並且容器將受到其重啟策略的影響。如果容器不提供存活探針,則預設為Success
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
spec:
  containers:
  - name: liveness-exec-container
    image: busybox:1.32.0
    command: ["/bin/sh", "-c", "touch /tmp/live; sleep 60; rm -f /tmp/live;sleep 3600"]
    livenessProbe:
      exec: 
        command: ["test", "-e", "/tmp/live"] # test命令檢查某個條件是否成立. -e如果檔案存在, 則為真
      initialDelaySeconds: 1 # 延時, 啟動後多長時間檢測
      periodSeconds: 3       # 重試
kubectl get pod liveness-exec-pod -w
--- output
NAME                READY   STATUS    RESTARTS   AGE
liveness-exec-pod   1/1     Running   0          71s
liveness-exec-pod   1/1     Running   1          104s

3. Start/Stop

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx:1.19.3
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo 'Hello from the postStart handler' > /tmp/message"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo 'Hello from the preStop handler' > /tmp/message"]

4. Pod 執行狀態

  • Pending: 掛起,Pod已經被K8S系統接受,但是有容器尚未建立
  • Running: 執行,Pod 中所有容器已被建立,至少一個容器正在執行,或處於啟動或重啟狀態
  • Succeeded: 成功,Pod中所有容器都被成功終止,並且不會在重啟
  • Failed: 失敗,Pod中的所有容器都已經終止,並且至少有一個容器是失敗終止
  • Unknown: 未知,因為某些原因無法取得Pod的狀態

三. 控制器-Controller

在叢集上管理和執行容器的物件。用來控制Pod的具體狀態和行為,在控制器的生命週期裡,始終維持Pod的副本數量
  • Pod是通過Controller實現應用的運維比如伸縮,滾動升級等等
  • Pod和Controller之間通過label標籤建立關係