在 Kubernetes 環境中,應用程式的高用性和穩定性至關重要。ReadinessProbe 和 LivenessProbe 是確保 Pod 健康狀態的關鍵機制。ReadinessProbe 用於判斷 Pod 是否已準備好接收流量,而 LivenessProbe 則用於檢測 Pod 是否正常執行。這兩種探針都支援命令執行、HTTP 請求和 TCP 連線三種檢查方式,可以根據應用程式的特性選擇合適的方式。此外,持久儲存對於有狀態應用程式尤為重要。Kubernetes 提供了多種持久儲存方案,例如 ConfigMap 和 Secret,可以將組態檔案和敏感資訊與容器分離,提高應用程式的可移植性和安全性。ConfigMap 可以將組態檔案掛載到 Pod 中,方便應用程式讀取組態資訊,同時也方便了組態的更新和管理。

使用 Services 暴露 Pod

在 Kubernetes 中,確保應用程式的可用性和健康狀況非常重要。為了實作這一點,Kubernetes 提供了兩種探針(Probe):ReadinessProbe 和 LivenessProbe。本篇文章將詳細介紹這兩種探針的作用、組態方法以及它們在實際應用中的重要性。

ReadinessProbe:確保 Pod 準備就緒

ReadinessProbe 用於檢查 Pod 是否已經準備好接收流量。它可以透過三種方式進行檢查:

  • 命令(Command):在 Pod 內執行一個命令,如果命令的離開碼為 0,則表示 Pod 已經準備就緒。
  • HTTP 請求(HTTP):向 Pod 傳送一個 HTTP 請求,如果傳回的 HTTP 狀態碼在 200 到 400 之間,則表示 Pod 已經準備就緒。
  • TCP 連線(TCP):嘗試與 Pod 建立 TCP 連線,如果連線成功,則表示 Pod 已經準備就緒。

以下是一個使用 HTTP ReadinessProbe 的範例 YAML 組態檔案:

# nginx-pod-with-readiness-http.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-with-readiness-http
spec:
  containers:
  - name: nginx-pod-with-readiness-http
    image: nginx
    readinessProbe:
      initialDelaySeconds: 5
      periodSeconds: 5
      httpGet:
        path: /ready
        port: 80

內容解密:

  • initialDelaySeconds:探針在開始第一次健康檢查之前等待的秒數。
  • periodSeconds:探針執行兩次健康檢查之間的間隔秒數。
  • httpGet:定義 HTTP 請求的路徑和埠。

ReadinessProbe 的作用是確保 Pod 在完全準備就緒之前不會接收到流量。例如,可以呼叫一個內部開啟 MySQL 連線的頁面,以確保應用程式能夠與其資料函式庫進行通訊。

LivenessProbe:確保 Pod 健康執行

LivenessProbe 用於檢查 Pod 是否處於健康狀態。它與 ReadinessProbe 類別似,也可以透過命令、HTTP 請求和 TCP 連線等方式進行檢查。

LivenessProbe 的主要目的是檢測 Pod 是否已經損壞或進入了不可還原的狀態。如果 LivenessProbe 檢測到 Pod 不健康,Kubernetes 將會終止該 Pod。

以下是 LivenessProbe 的幾種檢查方式:

  • 命令(Command):在容器內執行一個命令,如果命令的離開碼不為 0,則表示 Pod 不健康。
  • HTTP 請求(HTTP):向 Pod 傳送一個 HTTP 請求,如果傳回的 HTTP 狀態碼不在 200 到 400 之間,則表示 Pod 不健康。
  • TCP 連線(TCP):嘗試與 Pod 建立 TCP 連線,如果連線失敗,則表示 Pod 不健康。
  • GRPC:如果應用程式支援並實作了 gRPC 健康檢查協定,則可以使用 GRPC 進行檢查。

以下是一個使用 HTTP LivenessProbe 的範例 YAML 組態檔案:

# nginx-pod-with-liveness-http.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-with-liveness-http
spec:
  containers:
  - name: nginx-pod-with-liveness-http
    image: nginx
    livenessProbe:
      initialDelaySeconds: 5
      periodSeconds: 5
      httpGet:
        path: /healthcheck
        port: 80

內容解密:

  • initialDelaySecondsperiodSeconds 的作用與 ReadinessProbe 中的相同。
  • httpGet 定義了用於檢查 Pod 健康狀態的 HTTP 請求路徑和埠。

為什麼需要 ReadinessProbe 和 LivenessProbe?

ReadinessProbe 和 LivenessProbe 是 Kubernetes 中非常重要的功能,它們可以幫助您確保應用程式的可用性和健康狀況。

  • ReadinessProbe 確保了 Pod 在完全準備就緒之前不會接收到流量,從而避免了因為應用程式尚未就緒而導致的錯誤。
  • LivenessProbe 可以檢測出已經損壞或不可還原的 Pod,並由 Kubernetes 終止它們,從而保持叢集的整體健康狀態。

透過合理地組態和使用 ReadinessProbe 和 LivenessProbe,您可以提高應用程式的可靠性和可用性,為使用者提供更好的體驗。

使用LivenessProbe確保Pod健康檢查

在Kubernetes中,LivenessProbe是一種重要的機制,用於檢查Pod的健康狀態。透過定期執行健康檢查,Kubernetes能夠自動檢測並重啟不健康的Pod,從而提高應用的可用性和可靠性。

HTTP LivenessProbe

HTTP LivenessProbe透過對指定的URL路徑發起HTTP請求來檢查Pod的健康狀態。以下是一個範例:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-with-liveness-http
spec:
  containers:
  - name: nginx-pod-with-liveness-http
    image: nginx
    livenessProbe:
      initialDelaySeconds: 5
      periodSeconds: 5
      httpGet:
        path: /healthcheck
        port: 80
        httpHeaders:
        - name: My-Custom-Header
          value: My-Custom-Header-Value

內容解密:

  1. initialDelaySeconds: 5 表示在容器啟動後5秒才開始進行第一次健康檢查。
  2. periodSeconds: 5 表示每隔5秒執行一次健康檢查。
  3. httpGet 指定了要對 /healthcheck 路徑發起HTTP GET請求,連線埠為80。
  4. httpHeaders 可以新增自定義的HTTP標頭,這裡增加了一個名為 My-Custom-Header 的標頭。

Command LivenessProbe

Command LivenessProbe透過執行指定的命令來檢查Pod的健康狀態。如果命令執行成功(傳回碼為0),則認為Pod是健康的。以下是一個範例:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-with-liveness-command
spec:
  containers:
  - name: nginx-pod-with-liveness-command
    image: nginx
    livenessProbe:
      initialDelaySeconds: 5
      periodSeconds: 5
      exec:
        command:
        - cat
        - /hello/world

內容解密:

  1. exec 指定了要執行的命令,這裡是 cat /hello/world
  2. 如果 /hello/world 檔案存在且 cat 命令成功執行,則健康檢查透過。
  3. 如果檔案不存在或命令執行失敗,則健康檢查失敗,Pod將被視為不健康。

TCP LivenessProbe

TCP LivenessProbe透過嘗試連線指定的TCP連線埠來檢查Pod的健康狀態。如果連線成功,則認為Pod是健康的。以下是一個範例:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-with-liveness-tcp
spec:
  containers:
  - name: nginx-pod-with-liveness-tcp
    image: nginx
    livenessProbe:
      initialDelaySeconds: 5
      periodSeconds: 5
      tcpSocket:
        port: 80

內容解密:

  1. tcpSocket 指定了要連線的TCP連線埠,這裡是80。
  2. 如果連線埠80的連線成功,則健康檢查透過。

使用命名連線埠的LivenessProbe

在HTTP和TCP LivenessProbe中,可以使用命名連線埠。以下是一個範例:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-with-liveness-http-named-port
spec:
  containers:
  - name: nginx-pod-with-liveness-http-named-port
    image: nginx
    ports:
    - name: liveness-port
      containerPort: 8080
      hostPort: 8080
    livenessProbe:
      initialDelaySeconds: 5
      periodSeconds: 5
      httpGet:
        path: /healthcheck
        port: liveness-port

內容解密:

  1. ports 部分定義了一個名為 liveness-port 的連線埠,對映到容器的8080連線埠。
  2. livenessProbe 中,使用 liveness-port 作為連線埠名稱。

使用StartupProbe

對於啟動時間較長的應用,可以使用StartupProbe來延遲LivenessProbe的啟動時間。StartupProbe與LivenessProbe類別似,但具有更長的容忍失敗次數和檢查間隔。以下是一個範例:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-with-startupprobe
spec:
  containers:
  - name: nginx-pod-with-startupprobe
    image: nginx
    ports:
    - name: liveness-port
      containerPort: 8080
      hostPort: 8080
    livenessProbe:
      initialDelaySeconds: 5
      periodSeconds: 5
      httpGet:
        path: /healthcheck
        port: liveness-port
    startupProbe:
      httpGet:
        path: /healthz
        port: liveness-port
      failureThreshold: 30
      periodSeconds: 10

內容解密:

  1. startupProbe 定義了一個啟動探針,使用HTTP GET請求檢查 /healthz 路徑。
  2. failureThresholdperiodSeconds 定義了在認為啟動失敗之前的最大嘗試次數和檢查間隔。

同時使用ReadinessProbe和LivenessProbe

在同一個Pod中,可以同時使用ReadinessProbe和LivenessProbe。它們具有相似的組態引數,但服務於不同的目的。以下是一些共同的引數:

  • initialDelaySeconds: 第一次探測執行的延遲時間。
  • periodSeconds: 探測之間的間隔時間。
  • timeoutSeconds: 等待探測超時的時間。
  • successThreshold: 認為Pod就緒(對於ReadinessProbe)或健康(對於LivenessProbe)的成功次數門檻。
  • failureThreshold: 認為Pod未就緒(對於ReadinessProbe)或需要被終止(對於LivenessProbe)的失敗次數門檻。

第9章:Kubernetes 中的持久儲存

在前面的章節中,我們已經瞭解了 Kubernetes 的關鍵概念,本章將是最後一個關於這些概念的章節。到目前為止,我們已經發現 Kubernetes 是透過在 etcd 資料儲存中建立物件來表示所有傳統 IT 層的期望狀態,這些物件將被轉換為叢集內的實際運算資源。

本章將重點關注有狀態應用的持久儲存。與其他資源抽象一樣,這將是另一組我們需要掌握的物件,以在叢集中獲得持久儲存。Kubernetes 中的持久儲存是透過使用 PersistentVolume 資源型別實作的,它有自己的機制。老實說,這些機制最初可能相對難以理解,但我們將探討並全面介紹它們!

在本章中,我們將涵蓋以下主要主題:

  • 為什麼使用持久儲存?
  • 瞭解如何將 PersistentVolume 掛載到 Pod
  • 瞭解 Kubernetes 中 PersistentVolume 物件的生命週期
  • 瞭解靜態和動態 PersistentVolume 組態
  • 高階儲存主題

技術需求

  • 一個可用的 Kubernetes 叢集(本地或根據雲)
  • 一個可用的 kubectl CLI,組態為與叢集通訊

如果您不滿足這些技術需求,可以參考第 2 章《Kubernetes 架構 - 從容器映像到執行中的 Pod》和第 3 章《安裝您的 Kubernetes 叢集》,以取得這兩個先決條件。

為什麼使用持久儲存?

儲存是 IT 世界中的重要資源,因為它提供了一種邏輯方式來建立、讀取、更新和刪除(CRUD)資訊,從員工薪資單的 PDF 檔案到海量的醫療保健記錄。雖然儲存是向使用者提供相關資訊的關鍵元素,但容器和微服務應該是無狀態的。換句話說,當容器被重新排程或移動到不同的叢集時,其中儲存的任何資訊都將不可用。微服務也是如此;資料元件應該被解耦,使微服務保持微小的狀態,並且在被重新排程時不必關心資料的狀態和可用性。

那麼,我們應該在哪裡儲存應用程式資料呢?在任何型別的資料儲存中,從業務連續性的角度來看,如果相關的資料儲存與微服務執行在相同的 Kubernetes 叢集中,則應該具有應用程式感知的複製機制。但請記住,Kubernetes 是一個資源協調器,它將根據您為應用程式定義的期望狀態採取行動。在組態 Pod 時,您有機會定義要使用的儲存元件,為容器提供建立、讀取、更新和刪除資料的方式。讓我們來探討一下 Kubernetes 為持久化資料提供的不同選項。

介紹 Volume

第一層儲存抽象是存取 Kubernetes 物件並將其掛載到容器中,如資料卷。這可以透過以下方式實作:

  • ConfigMap
  • Secret
  • ServiceAccount token(與 Secret 相同)

這允許應用程式團隊將微服務的組態與容器或佈署定義解耦。如果我們考慮應用程式的生命週期,憑證、憑證或外部服務的 token 可能需要重新整理,或者組態引數可能需要更新。出於明顯的安全原因,我們不希望這些被硬編碼在佈署清單或容器映像中。

讓我們來看一個 ConfigMap 的範例,使用的清單檔案是 nginx-configmap.yaml

# nginx-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-hello
  labels:
    app: test
  immutable: false
data:
  hello1.html: |
    <html>
      hello world 1
    </html>
  hello2.html: |
    <html>
      hello world 2
    </html>

這個 ConfigMap 有兩個定義,分別對應兩個不同的檔案,我們將把它們掛載到 NGINX Pod 中,使用的清單檔案是 nginx-pod.yaml

# nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-hello
  labels:
    app: test
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-hello
      mountPath: "/usr/share/nginx/html/hello"
  volumes:
  - name: nginx-hello
    configMap:
      name: nginx-hello

程式碼解析:

這個範例展示瞭如何使用 ConfigMap 將檔案掛載到 NGINX Pod 中。首先,我們建立了一個名為 nginx-hello 的 ConfigMap,其中包含了兩個 HTML 檔案的定義。然後,我們建立了一個 NGINX Pod,並將 ConfigMap 掛載到 /usr/share/nginx/html/hello 目錄下。

$ kubectl apply -f nginx-configmap.yaml
configmap/nginx-hello created
$ kubectl apply -f nginx-pod.yaml
pod/nginx-hello created

讓我們驗證一下兩個物件的狀態:

$ kubectl get pod,cm
NAME                  READY   STATUS    RESTARTS   AGE
pod/nginx-hello       1/1     Running   0          7m26s

詳細解析:

  1. 建立 ConfigMap:使用 nginx-configmap.yaml 清單檔案建立了一個名為 nginx-hello 的 ConfigMap。
  2. 建立 Pod:使用 nginx-pod.yaml 清單檔案建立了一個名為 nginx-hello 的 NGINX Pod。
  3. 掛載 ConfigMap:Pod 中的 NGINX 容器將 ConfigMap 中的檔案掛載到 /usr/share/nginx/html/hello 目錄下。
  4. 驗證狀態:使用 kubectl get 命令驗證了 Pod 和 ConfigMap 的狀態。

這個範例展示瞭如何使用 ConfigMap 將檔案掛載到容器中,實作了組態與容器的解耦。