返回文章列表

Kubernetes 佈署策略與健康檢查機制

本文探討 Kubernetes 的佈署策略,涵蓋滾動更新、重建以及進階的藍綠佈署和金絲雀發布。同時,詳細解析了 Kubernetes 的健康檢查機制,包括 Liveness、Readiness 和 Startup Probes,以及如何組態這些探針來確保應用程式的高用性和穩定性。此外,還介紹了自定義 Pod

容器技術 DevOps

Kubernetes 提供了多種佈署策略,從基本的滾動更新和重建到更進階的藍綠佈署和金絲雀發布,可以滿足不同應用場景的需求。滾動更新允許逐步更新應用程式,最大限度地減少停機時間;重建策略則適用於需要快速替換所有 Pod 的場景。對於更複雜的佈署需求,藍綠佈署和金絲雀發布提供了更精細的控制和更高的可靠性。同時,Kubernetes 的健康檢查機制,包括 Liveness、Readiness 和 Startup Probes,對於確保應用程式的高用性和穩定性至關重要。Liveness Probe 檢測應用程式是否存活,Readiness Probe 判斷應用程式是否準備好接收流量,而 Startup Probe 則專注於應用程式的啟動階段。結合這些探針和自定義 Readiness Gates,可以實作更精細的應用程式生命週期管理。

Kubernetes 佈署策略與進階佈署技術

在現代化的軟體開發與佈署流程中,Kubernetes 已成為容器協調的標準。其 Deployment 資源提供了基本的佈署策略,如滾動更新(Rolling Update)與重建(Recreate)。然而,對於更複雜的佈署需求,例如藍綠佈署(Blue-Green Deployment)與金絲雀發布(Canary Release),則需要更進階的技術與工具來實作。

佈署策略概述

Kubernetes 的 Deployment 資源簡化了應用程式的佈署與更新流程。基本的佈署策略包括:

  1. 滾動更新(Rolling Update):逐步替換舊的 Pod 例項,以最小化應用程式的停機時間。此策略確保在更新過程中,應用程式始終保持可用狀態。
  2. 重建(Recreate):先終止所有舊的 Pod 例項,然後建立新的 Pod 例項。此策略可能會導致短暫的停機時間,但適用於某些特定場景。

滾動更新程式碼範例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example-container
        image: example-image:latest
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1

內容解密:

  • strategy.type 指定了佈署策略為 RollingUpdate
  • rollingUpdate.maxUnavailable 定義了更新過程中最多允許有多少個 Pod 處於不可用狀態。
  • rollingUpdate.maxSurge 定義了更新過程中最多允許有多少個額外的 Pod 被建立。

進階佈署技術

對於需要更高階別佈署控制的場景,Kubernetes 社群發展出了多種進階佈署技術。

藍綠佈署(Blue-Green Deployment)

藍綠佈署涉及執行兩個相同的生產環境(藍色和綠色),其中一個執行現有的應用程式版本,另一個執行新的版本。流量可以透過切換服務指向不同的環境來實作零停機時間的佈署。

金絲雀發布(Canary Release)

金絲雀發布是一種逐步發布新版本應用程式的技術,透過將一小部分流量引導到新版本來進行測試。如果新版本表現良好,則可以逐漸增加流量比例,直到完全替換舊版本。

Kubernetes 中的金絲雀發布實作

在 Kubernetes 中,可以透過建立一個新的 Deployment 並調整其副本數量來實作金絲雀發布。服務(Service)可以組態為將部分流量引導到新的 Pod 例項。

圖表說明:金絲雀發布流程

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Kubernetes 佈署策略與健康檢查機制

package "Kubernetes Cluster" {
    package "Control Plane" {
        component [API Server] as api
        component [Controller Manager] as cm
        component [Scheduler] as sched
        database [etcd] as etcd
    }

    package "Worker Nodes" {
        component [Kubelet] as kubelet
        component [Kube-proxy] as proxy
        package "Pods" {
            component [Container 1] as c1
            component [Container 2] as c2
        }
    }
}

api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2

note right of api
  核心 API 入口
  所有操作經由此處
end note

@enduml

此圖示展示了金絲雀發布的基本流程,包括流量分配、監控與評估,以及根據評估結果進行的後續操作。

高階佈署工具

由於 Kubernetes 原生的 Deployment 資源對於某些進階佈署需求支援有限,社群開發了多種工具來增強佈署功能,例如:

  1. Flagger:支援金絲雀發布和藍綠佈署,並可與多種 ingress 控制器和服務網格整合。
  2. Argo Rollouts:提供了一種全面的持續交付(CD)解決方案,支援多種進階佈署策略。
  3. Knative:一個根據 Kubernetes 的無伺服器平台,提供了簡化的佈署模型和流量分割功能。

這些工具透過 Operator 模式實作了更靈活的佈署策略,並且能夠根據應用程式的實際執行狀況進行自動化的滾動更新或回復。

健康探針(Health Probe)

健康探針模式(Health Probe pattern)說明瞭應用程式如何向 Kubernetes 溝通其健康狀態。要實作完全自動化,雲原生應用程式必須具備高度的可觀察性,以便讓 Kubernetes 能夠判斷應用程式是否啟動並準備好處理請求。這些觀察結果會影響 Pod 的生命週期管理以及流量路由到應用程式的方式。

問題

Kubernetes 會定期檢查容器程式的狀態,如果發現問題則會重新啟動它。然而,實務上我們知道,僅檢查程式狀態不足以確定應用程式的健康狀況。在許多情況下,應用程式可能會掛起,但其程式仍在執行。例如,Java 應用程式可能會丟擲 OutOfMemoryError,但 JVM 程式仍然執行。又或者,應用程式可能會因為陷入無限迴圈、死鎖或某些耗盡資源的情況(如快取、堆積、程式)而凍結。為了檢測這些情況,Kubernetes 需要一種可靠的方式來檢查應用程式的健康狀況——即,不需要了解應用程式內部的工作原理,而是檢查應用程式是否按預期運作並能夠為消費者提供服務。

解決方案

軟體產業已經接受了無法編寫完全無錯誤程式碼的事實。此外,在處理分散式應用程式時,失敗的機率甚至更高。因此,處理失敗的重點已經從避免失敗轉移到檢測故障和還原。

檢測失敗並不是一項簡單的任務,不能對所有應用程式都採用統一的方式,因為每個人對失敗的定義都不同。此外,各種型別的失敗需要不同的糾正措施。暫時性失敗可能會在給予足夠時間後自我還原,而其他一些失敗可能需要重新啟動應用程式。讓我們來看看 Kubernetes 用於檢測和糾正失敗的檢查。

程式健康檢查

程式健康檢查是 Kubelet 對容器程式進行的最簡單的健康檢查。如果容器程式未執行,則會在 Pod 分配到的節點上重新啟動容器。因此,即使沒有其他健康檢查,應用程式也會因為這種通用的檢查而變得稍微更具穩健性。如果您的應用程式能夠檢測到任何型別的失敗並自行關閉,那麼程式健康檢查就足夠了。然而,在大多數情況下,這還不夠,還需要其他型別的健康檢查。

存活探針(Liveness Probes)

如果您的應用程式遇到死鎖,從程式健康檢查的角度來看,它仍然被視為健康的。為了檢測這種問題以及根據您的應用程式業務邏輯的其他型別的失敗,Kubernetes 提供了存活探針——由 Kubelet 代理定期執行的檢查,要求您的容器確認它仍然是健康的。從外部而不是在應用程式本身進行健康檢查非常重要,因為有些失敗可能會阻止應用程式的監控工具報告其失敗。至於糾正措施,這種健康檢查與程式健康檢查類別似,因為如果檢測到失敗,則會重新啟動容器。然而,它提供了更多關於使用哪些方法來檢查應用程式健康狀況的靈活性,如下所示:

  • HTTP 探針:對容器的 IP 地址執行 HTTP GET 請求,並期望收到介於 200 和 399 之間的成功 HTTP 回應碼。
  • TCP Socket 探針:假設建立成功的 TCP 連線。
  • Exec 探針:在容器的使用者和核心名稱空間中執行任意命令,並期望收到成功的離開碼(0)。
  • gRPC 探針:利用 gRPC 對健康檢查的內建支援。

除了探針動作之外,健康檢查行為還可以透過以下引數進行影響:

  • initialDelaySeconds:指定在執行第一次存活探針檢查之前要等待的秒數。
  • periodSeconds:存活探針檢查之間的間隔秒數。
  • timeoutSeconds:允許探針檢查傳回的最大時間,超過此時間則視為失敗。
  • failureThreshold:指定連續多少次探針檢查失敗後,容器才被視為不健康並需要重新啟動。

範例如下(範例 4-1):

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-liveness-check
spec:
  containers:
  - image: k8spatterns/random-generator:1.0
    name: random-generator
    env:
    - name: DELAY_STARTUP
      value: "20"
    ports:
    - containerPort: 8080
      protocol: TCP
    livenessProbe:
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 30

#### 內容解密:

此範例定義了一個名為 pod-with-liveness-check 的 Pod,其中包含一個名為 random-generator 的容器。該容器使用 k8spatterns/random-generator:1.0 映象,並設定了一個環境變數 DELAY_STARTUP"20"。容器監聽 TCP 協定的 8080 連線埠。同時,定義了一個 HTTP 存活探針,定期對容器的 /actuator/health 端點發出 HTTP GET 請求以檢查其健康狀態。initialDelaySeconds 設定為 30,表示在容器啟動後等待 30 秒才開始第一次存活檢查,以給予應用程式一些時間來初始化。

根據您的應用程式特性,您可以選擇最合適的方法。由您的應用程式決定是否認為自己是健康的。然而,請記住,未透過健康檢查的結果是您的容器將被重新啟動。如果重新啟動容器無法解決問題,那麼具有失敗的健康檢查並沒有任何好處,因為 Kubernetes 會重新啟動您的容器而無法修復底層問題。

就緒探針(Readiness Probes)

存活檢查有助於透過終止不健康的容器並用新的容器替換它們來保持應用程式的健康。但是,有時當一個容器不健康時,重新啟動它可能沒有幫助。一個典型的例子是仍在啟動中的容器,它尚未準備好處理任何請求。另一個例子是仍在等待依賴項(如資料函式庫)可用的應用程式。此外,容器可能過載,從而增加其延遲,因此您希望它暫時遮蔽額外的負載,並指示它尚未準備好,直到負載減少。

對於這種場景,Kubernetes 提供了就緒探針。就緒檢查的方法(HTTP、TCP、Exec、gRPC)和執行時機選項與存活檢查相同,但糾正措施不同。就緒探針用於指示容器是否準備好接收流量。當容器的就緒探針檢查失敗時,該容器的 Pod 將被從服務的負載平衡池中移除,直到就緒探針再次成功。

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-readiness-check
spec:
  containers:
  - image: k8spatterns/random-generator:1.0
    name: random-generator
    readinessProbe:
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 30

#### 內容解密:

此範例定義了一個名為 pod-with-readiness-check 的 Pod,其中包含一個名為 random-generator 的容器。同樣使用 k8spatterns/random-generator:1.0 映象,並定義了一個 HTTP 就緒探針,與存活探針類別似,對容器的 /actuator/health 端點發出 HTTP GET 請求以檢查其是否準備好接收請求。同樣設定了 initialDelaySeconds 為 30,以給予應用程式一些時間來初始化。這確保了只有在應用程式完全啟動並準備好後,才將流量路由到該 Pod。

Kubernetes 健康檢查機制:Liveness、Readiness 與 Startup Probes 詳解

在 Kubernetes 中,確保應用程式的健康狀態是至關重要的。為了達到這個目的,Kubernetes 提供了三種不同的探針(Probes):Liveness Probe、Readiness Probe 和 Startup Probe。本文將詳細解析這三種探針的用途、組態方法以及它們在實際應用中的重要性。

Liveness Probe:檢查容器是否存活

Liveness Probe 用於檢查容器是否仍在執行。如果 Liveness Probe 失敗,Kubernetes 將重啟容器。這種探針主要用於從失敗中還原,例如,當應用程式進入死鎖狀態或當機時。

Liveness Probe 組態範例

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-liveness-check
spec:
  containers:
  - image: k8spatterns/random-generator:1.0
    name: random-generator
    livenessProbe:
      exec:
        command: [ "stat", "/var/run/random-generator-ready" ]

內容解密:

  • livenessProbe 用於定義 Liveness Probe 的行為。
  • exec.command 指定了用於檢查容器健康狀態的命令。在此範例中,檢查 /var/run/random-generator-ready 檔案是否存在。
  • 如果命令傳回非零值,Kubernetes 將視為探針失敗並重啟容器。

Readiness Probe:檢查容器是否準備好接收流量

Readiness Probe 用於檢查容器是否準備好接收流量。如果 Readiness Probe 失敗,容器將被從伺服器端點移除,不再接收新的請求。這種探針對於在容器啟動初期給予其一定的時間來進行初始化非常有用。

Readiness Probe 組態範例

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-readiness-check
spec:
  containers:
  - image: k8spatterns/random-generator:1.0
    name: random-generator
    readinessProbe:
      exec:
        command: [ "stat", "/var/run/random-generator-ready" ]

內容解密:

  • readinessProbe 定義了 Readiness Probe 的行為。
  • 與 Liveness Probe 類別似,這裡也使用 stat 命令檢查特設定檔案是否存在,以此來判斷容器是否準備好接收請求。
  • 如果檔案不存在,探針失敗,容器將不會接收新的流量。

自定義 Pod Readiness Gates

在某些情況下,僅僅依靠容器級別的 Readiness Probe 是不夠的,例如,當需要等待外部負載平衡器準備就緒時。Kubernetes 允許透過 readinessGates 欄位來指定額外的條件。

Readiness Gates 組態範例

apiVersion: v1
kind: Pod
spec:
  readinessGates:
  - conditionType: "k8spatterns.io/load-balancer-ready"
status:
  conditions:
  - type: "k8spatterns.io/load-balancer-ready"
    status: "False"

內容解密:

  • readinessGates 用於指定 Pod 成為 Ready 狀態所需的額外條件。
  • 在此範例中,新增了一個名為 k8spatterns.io/load-balancer-ready 的條件,需要被外部控制器設定為 True,Pod 才會被視為 Ready。

Startup Probe:處理應用程式啟動延遲

對於啟動時間較長的應用程式,可以使用 Startup Probe 來避免因 Liveness Probe 失敗而被重啟。Startup Probe 允許組態較長的超時時間和重試次數。

Startup Probe 組態範例

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-startup-check
spec:
  containers:
  - image: quay.io/wildfly/wildfly
    name: wildfly
    startupProbe:
      exec:
        command: [ "stat", "/opt/jboss/wildfly/standalone/tmp/startup-marker" ]
      initialDelaySeconds: 60
      periodSeconds: 60
      failureThreshold: 15
    livenessProbe:
      httpGet:
        path: /health
        port: 9990
      periodSeconds: 10
      failureThreshold: 3

內容解密:

  • startupProbe 組態了啟動探針,使用 stat 命令檢查標記檔案是否存在,以此判斷應用程式是否啟動完成。
  • initialDelaySecondsperiodSecondsfailureThreshold 的組態允許應用程式有足夠的時間來啟動。
  • 一旦 Startup Probe 成功,Liveness 和 Readiness Probes 將開始生效。