1. 程式人生 > 實用技巧 >Kubernetes Pod學習

Kubernetes Pod學習

Kubernetes-Pod 學習

K8s有很多技術概念,同時對應很多API物件,最重要的也是最基礎的是微服務Pod。Pod是在K8s叢集中執行部署應用或服務的最小單元,它是可以支援多容器的。Pod的設計理念是支援多個容器在一個Pod中共享網路地址和檔案系統,可以通過程序間通訊和檔案共享這種簡單高效的方式組合完成服務。Pod對多容器的支援是K8s最基礎的設計理念。比如你執行一個作業系統發行版的軟體倉庫,一個Nginx容器用來發布軟體,另一個容器專門用來從源倉庫做同步,這兩個容器的映象不太可能是一個團隊開發的,但是他們一塊兒工作才能提供一個微服務;這種情況下,不同的團隊各自開發構建自己的容器映象,在部署的時候組合成一個微服務對外提供服務。

Pod是K8s叢集中所有業務型別的基礎,可以看作執行在K8s叢集中的小機器人,不同型別的業務就需要不同型別的小機器人去執行。目前K8s中的業務主要可以分為長期伺服型(long-running)、批處理型(batch)、節點後臺支撐型(node-daemon)和有狀態應用型(stateful application);分別對應的小機器人控制器為Deployment、Job、DaemonSet和PetSet,本文後面會一一介紹。

什麼是POD

Pod是Kubernetes中能夠建立和部署的最小單元,是Kubernetes叢集中的一個應用例項,總是部署在同一個節點Node上。Pod中包含了一個或多個容器,還包括了儲存、網路等各個容器共享的資源。Pod支援多種容器環境,Docker則是最流行的容器環境。

Pod並不提供保證正常執行的能力,因為可能遭受Node節點的物理故障、網路分割槽等等的影響,整體的高可用是Kubernetes叢集通過在叢集內排程Node來實現的。通常情況下我們不要直接建立Pod,一般都是通過Controller來進行管理,但是瞭解Pod對於我們熟悉控制器非常有好處。

Pod帶來的好處

  • Pod做為一個可以獨立執行的服務單元,簡化了應用部署的難度,以更高的抽象層次為應用部署管提供了極大的方便。
  • Pod做為最小的應用例項可以獨立執行,因此可以方便的進行部署、水平擴充套件和收縮、方便進行排程管理與資源的分配。
  • Pod中的容器共享相同的資料和網路地址空間,Pod之間也進行了統一的資源管理與分配。

Pod是如何管理多個容器的

Pod中可以同時執行多個程序(作為容器執行)協同工作。同一個Pod中的容器會自動的分配到同一個 node 上。同一個Pod中的容器共享資源、網路環境和依賴,所以它們總是被同時排程。在一個Pod中同時執行多個容器是一種比較高階的用法。只有當你的容器需要緊密配合協作的時候才考慮用這種模式。

Pod的永續性

Pod在設計⽀持就不是作為持久化實體的。在排程失敗、節點故障、缺少資源或者節點維護的狀態下都會死掉會被驅逐。 通常,⽤戶不需要⼿動直接建立Pod, ⽽是應該使⽤controller(例如Deployments) , 即使是在建立單個Pod的情況下。 Controller可以提供叢集級別的⾃愈功能、 複製和升級管理。

Pod的啟動流程分析

kubelet 通過 API Server 監聽 etcd 目錄,同步 pod 列表。如果發現有新的 pod 繫結到本節點,則按照 pod 清單要求建立 pod,如果是發現 pod 被更新,則做出相應更改。讀取到 pod 的資訊之後,如果是建立和修改 pod 的任務,則做如下處理:

  1. 為該 pod 建立一個數據目錄
  2. 從 API Server 讀取該 pod 清單
  3. 為該 pod 掛載外部卷
  4. 下載 pod 所需的 Secret
  5. 檢查已經執行在節點中 pod,如果該 pod 沒有容器或者 Pause 容器沒有啟動,則先停止pod裡所有的容器程序。
  6. 使用 pause 映象為每個pod建立一個容器,該容器用於接管 Pod 中所有其他容器的網路。
  7. 為 pod 中的每個容器做如下處理:1.為容器計算一個 hash 值,然後用容器的名字去查詢對於 docker 容器的 hash 值。若查詢到容器,且兩者的 hash 值不同,則停止 docker 中容器中程序,並停止與之關聯的 pause 容器,若相同,則不做處理。若容器被終止了,且容器沒有指定的重啟策略,則不做任何處理呼叫 docker client 下載容器映象,並啟動容器。

Pod的生命週期

初始化容器

pod 內主容器啟動之前要執行的容器,主要是做一些前置工作,初始化容器具有以下特徵:

  • 初始化容器必須首先執行,若初始化容器執行失敗,叢集會一直重啟初始化容器直至完成,注意,如果 pod 的重啟策略為 Never,那初始化容器啟動失敗後就不會重啟。
  • 初始化容器必須按照定義的順序執行,初始化容器可以通過 pod 的 spec.initContainers 進行定義。

生命週期鉤子

Kubernetes 為容器提供了兩種生命週期鉤子

  • Poststart:於容器建立完成之後立即執行的鉤子程式。
  • preStop:容器終止之前立即執行的程式,是以同步方式的進行,因此其完成之前會阻塞 刪除容器的呼叫

容器探測

容器探測分為存活性探測和就緒性探測容器探測是kubelet對容器健康狀態進行診斷,容器探測的方式主要以下三種

  • ExecAction:在容器中執行命令,根據返回的狀態碼判斷容器健康狀態,返回0即表示成功,否則為失敗。
  • TCPSocketAction: 通過與容器的某TCP埠嘗試建立連線進行診斷,埠能開啟即為表示成功,否則失敗。
  • HTTPGetAction:向容器指定 URL 發起 HTTP GET 請求,響應碼為2xx或者是3xx為成功,否則失敗。

Pod終止

Pod終止包含如下幾個步驟

  1. 使用者發出刪除 pod 命令
  2. Pod 物件隨著時間的推移更新,在寬限期(預設情況下30秒),pod 被視為“dead”狀態
  3. 將 pod 標記為“Terminating”狀態
  4. 第三步同時執行,監控到 pod 物件為“Terminating”狀態的同時啟動 pod 關閉過程
  5. 第三步同時進行,endpoints 控制器監控到 pod 物件關閉,將pod與service匹配的 endpoints 列表中刪除
  6. 如果 pod 中定義了 preStop 鉤子處理程式,則 pod 被標記為“Terminating”狀態時以同步的方式啟動執行;若寬限期結束後,preStop 仍未執行結束,第二步會重新執行並額外獲得一個2秒的小寬限期
  7. Pod 內物件的容器收到 TERM 訊號
  8. 寬限期結束之後,若存在任何一個執行的程序,pod 會收到 SIGKILL 訊號
  9. Kubelet 請求 API Server 將此 Pod 資源寬限期設定為0從而完成刪除操作

pause容器主要功能

每個Pod裡執行著一個特殊的被稱之為Pause的容器,其他容器則為業務容器,這些業務容器共享Pause容器的網路棧和Volume掛載卷,因此他們之間通訊和資料交換更為高效,在設計時我們可以充分利用這一特性將一組密切相關的服務程序放入同一個Pod中。同一個Pod裡的容器之間僅需通過localhost就能互相通訊。
  • PID名稱空間:Pod中的不同應用程式可以看到其他應用程式的程序ID。
  • 網路名稱空間:Pod中的多個容器能夠訪問同一個IP和埠範圍。
  • IPC名稱空間:Pod中的多個容器能夠使用SystemV IPC或POSIX訊息佇列進行通訊。
  • UTS名稱空間:Pod中的多個容器共享一個主機名;Volumes(共享儲存卷):
  • Pod中的各個容器可以訪問在Pod級別定義的Volumes。

配置

Pod的配置資訊中有幾個重要部分,apiVersion、kind、metadata(元資料)、spec以及status。其中apiVersion和kind是比較固定的,status是執行時的狀態,所以最重要的就是metadata和spec兩個部分。
apiVersion: v1
kind: Pod
metadata:
  name: first-pod
  labels:
    app: bash
spec:
  containers:
    - name: bash-container
      image: busybox
      command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 10']Copy to clipboardErrorCopied

執行結果

[root@instance-gvpb80ao docs]# kubectl apply -f test.yaml 
pod/first-pod created
[root@instance-gvpb80ao docs]# kubectl get -f test.yaml 
NAME        READY   STATUS              RESTARTS   AGE
first-pod   0/1     ContainerCreating   0          6sCopy to clipboardErrorCopied

Pod資源清單

apiVersion: v1                             # 必選,API的版本號
kind: Pod                                  # 必選,型別Pod
metadata:                                  # 必選,元資料
  name: nginx                              # 必選,符合RFC 1035規範的Pod名稱
  namespace: web-testing                   # 可選,不指定預設為default,Pod所在的名稱空間
  labels:                                  # 可選,標籤選擇器,一般用於Selector
    - app: nginx
  annotations:                             # 可選,註釋列表
    - app: nginx
spec:                                      # 必選,用於定義容器的詳細資訊
  containers:                              # 必選,容器列表
  - name: nginx                            # 必選,符合RFC 1035規範的容器名稱
    image: nginx:v1                        # 必選,容器所用的映象的地址
    imagePullPolicy: Always                # 可選,映象拉取策略
    workingDir: /usr/share/nginx/html      # 可選,容器的工作目錄
    volumeMounts:                          # 可選,儲存卷配置
    - name: webroot                        # 儲存卷名稱
      mountPath: /usr/share/nginx/html     # 掛載目錄
      readOnly: true                       # 只讀
    ports:                                 # 可選,容器需要暴露的埠號列表
    - name: http                           # 埠名稱
      containerPort: 80                    # 埠號
      protocol: TCP                        # 埠協議,預設TCP
    env:                                   # 可選,環境變數配置
    - name: TZ                             # 變數名
      value: Asia/Shanghai
    - name: LANG
      value: en_US.utf8
    resources:                            # 可選,資源限制和資源請求限制
      limits:                             # 最大限制設定
        cpu: 1000m
        memory: 1024MiB
      requests:                           # 啟動所需的資源
        cpu: 100m
        memory: 512MiB
    readinessProbe:                       # 可選,容器狀態檢查
      httpGet:                            # 檢測方式
        path: /                           # 檢查路徑
        port: 80                          # 監控埠
      timeoutSeconds: 2                   # 超時時間 
      initialDelaySeconds: 60             # 初始化時間
    livenessProbe:                        # 可選,監控狀態檢查
      exec:                               # 檢測方式
        command: 
        - cat
        - /health
      httpGet:                            # 檢測方式
        path: /_health
        port: 8080
        httpHeaders:
        - name: end-user
          value: jason
      tcpSocket:                         # 檢測方式
        port: 80
      initialDelaySeconds: 60            # 初始化時間
      timeoutSeconds: 2                  # 超時時間
      periodSeconds: 5                   # 檢測間隔
      successThreshold: 2                # 檢查成功為2次表示就緒
      failureThreshold: 1                # 檢測失敗1次表示未就緒
    securityContext:                     # 可選,限制容器不可信的行為
      provoleged: false
  restartPolicy: Always                  # 可選,預設為Always
  nodeSelector:                          # 可選,指定Node節點
    region: subnet7
  imagePullSecrets:                      # 可選,拉取映象使用的secret
  - name: default-dockercfg-86258
  hostNetwork: false                     # 可選,是否為主機模式,如是,會佔用主機埠
  volumes:                               # 共享儲存卷列表
  - name: webroot                        # 名稱,與上述對應
    emptyDir: {}                         # 共享卷型別,空
    hostPath:                            # 共享卷型別,本機目錄
      path: /etc/hosts
    secret:                             # 共享卷型別,secret模式,一般用於密碼
      secretName: default-token-tf2jp   # 名稱
      defaultMode: 420                  # 許可權
      configMap:                        # 一般用於配置檔案
      name: nginx-conf
      defaultMode: 420