Build Kuberntes GRPC Health Probe with Pack
在 Kubernetes Pod 完整的生命周期包含了三個部份: Iinit container
Pod Hook
健康檢查
。這三部都會影響到 Pod 的生命周期,而本篇文章說明如何使用 pack 打包 grpc-health-probe 來支援 GRPC 健康檢查
Kubernetes livenessProbe & readinessProbe
Configure Liveness, Readiness and Startup Probes | Kubernetes
在 Kubernetes cluster 中我們可以通過配置 livenessProbe
及 readinessProbe
二個探針來影響容器的生命周期
livenessProbe
: 簡單的來說就是 Kubectl 通過livenessProbe
來判斷容器是否存活 (Running),如果 livenessProbe 探針偵測到容器不健康,Kubectl 就會刪除容器,並依據容器的重啟策略來處理,如果容器不包含 livenessProbe 探針,Kubectl 預設就會認定 livenessProbe 探針回傳值永遠為 SuccessreadinessProbe
: 簡單的來說就是 Kubectl 通過livenessProbe
來判斷容器的可用性 (Ready),只有 Pod 下面所有容器的狀態都是就緒時,Kubectl 才會認定該 Pod 已經處於可工作狀態。如果該 Pod 執行過期中 Ready 狀態變成 False,系統會將其從 Service 的後端 Endpoints 列表中移除,等待 Pod Ready 狀態再度成為 True 時加為 Service Endpoints 列表,這樣可以確認流量不會被導至不可用的 Pod
在配置 livenessProbe
及 readinessProbe
都有三種指定方式
ExecAction
: 在容器中執行指令,回傳值為 0 表示健康TCPSocketAction
: 透過容器的 IP 及 Port 進行檢查,如果可以建立 TCP 連線表示健康HTTPGetAction
: 透過容器的 IP 及 Port 進行 HTTP GET 檢查,如果回傳狀態碼介於 200 - 400 表示健康
Health checking gRPC servers on Kubernetes
(ref: https://kubernetes.io/blog/2018/10/01/health-checking-grpc-servers-on-kubernetes/)
本篇文章因為要檢查 GRPC 服務是否健康,則屬於第一種 ExecAction
的範籌。Health checking gRPC servers on Kubernetes | Kubernetes 文章也說明如何使用 grpc-health-probe 工具來檢查 GRPC 是否健康
在 Pod 中我們可以配置 readinessProbe
及 livenessProbe
|
|
在 exec ommand 中 grpc_health_probe
的執行檔是 /layers/cage1016_github-assets-cnb/github-assets/bin/grpc_health_probe
而非 grpc-health-probe 中看到的 /bin/grpc_health_probe
則是本篇的重點,我們慢慢說明
GPRC Server 健康檢查準備
|
|
在要使用 grpc_health_probe
來檢查 GRCP 狀態是否健康,在 Server 端也需要進行一些配合,實作二個方法 Check
及 Watch
|
|
我們直接使用 google.golang.org/grpc/health
提供的方法進行配置就可以快速完成 GRPC Server 端的準備工具,詳細的程式碼可以至 cage1016/ms-demo/cmd/add/main.go#L76-L77 及 cage1016/ms-demo/cmd/add/main.go#L190-L192
GPRC client 健康檢查準備
|
|
在 local 的部份可以下載 grpc_health_probe 進行測試
建構 Container Image
本篇文章的重點就是如何使用
Pack
來建構含有grpc_health_probe
功能的 container image
方法一 Dockerfile
|
|
在建構 Container image 時下載 grpc_health_probe
執行檔至 /bin/grpc_health_probe
,所以在 Kubernetes Pod livenessProbe
及 readinessProbe
中的 command 才會是 command: ["/grpc_health_probe", "-addr=:5000"]
在之前的文章
都有分享使用 Pack
來建構 container image。那我們如何使用 Pack
提供的方式在建構 container image 時如同寫 Dockerfile
去下載我們所需的 grpc_health_probe
檔案呢?
Github Asset Buildpack
cage1016/github-assets-cnb: A Cloud Native Buildpack that Download Github Assets
buildpack cage1016/[email protected]
提供了一個簡易的方式讓你透過 pack 建構 container image 時動態下載所需的 Github Assets,在這一次的使用情境也派上了用場
建立一個
project.toml
並配置 buildpackcage1016/github-assets-cnb
所需的參數repo
: Github Repoasset
: Github Repo asset nametag
: Release tag name, default set to “latest”token_env
: (optional), Please assign ENV name for private repodestination
: download asset destination path to,bin/<your-asset>
forapplication/x-executable
assetstrip_components
:x-tar
,gzip
,x-zx
suuport StripComponents feature.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
cat <<EOF >> project.toml # assign token [[build.env]] name = "APITEST_TOOLCHAIN_TOKEN" value = "<github-token>" [[metadata.githubassets]] repo = "kkdai/youtube" asset = "youtubedr_2.7.0_linux_arm64.tar.gz" destination = "bin" [[metadata.githubassets]] repo = "qeek-dev/apitest-toolchain" token_env = "APITEST_TOOLCHAIN_TOKEN" asset = "apitest-toolchain-linux-amd64" destination = "bin/apitest-toolchain" tag = "v0.1.0" [[metadata.githubassets]] repo = "stedolan/jq" asset = "jq-linux64" destination = "bin/jq" EOF
明確的指定所需的 buildpack 給
Pack
指令。一般來說,Pack 會跟據 builder 中的配置自動偵測目標目錄下需要載入那幾個 buildpacksbuildpacks/builder.toml at main · GoogleCloudPlatform/buildpacks
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
###### # Go # ###### [[order]] [[order.group]] id = "google.go.runtime" [[order.group]] id = "google.go.functions-framework" [[order.group]] id = "google.go.build" [[order.group]] id = "google.config.entrypoint" optional = true [[order.group]] id = "google.go.clear_source" optional = true [[order.group]] id = "google.utils.label"
以 GoogleCloudPlatform/buildpacks builder.toml 所定義的來說,針對 Golang 語言定義了 6 個 buildpack,而這些 buildpack 也會在 builder 動態偵測目標目錄所需,並不是 Golang 就一定是 6 個
1 2 3 4 5 6 7 8 9 10 11 12 13 14
... Status: Image is up to date for gcr.io/buildpacks/gcp/run:v1 ===> DETECTING 3 of 6 buildpacks participating google.go.runtime 0.9.1 google.go.build 0.9.0 google.utils.label 0.0.1 ===> ANALYZING ===> RESTORING ===> BUILDING === Go - Runtime ([email protected]) === Using runtime version from go.mod: 1.14 Installing Go v1.14 ...
我們可以看到使用
gcr.io/buildpacks/builder:v1
作為 builder 對 Golang 言語基本上就會載入 3 個 buildpack,google.go.runtime
google.go.build
google.utils.label
最後因為我們沒有客製自己的 builder,所以必需明確指定 buildpack,加上下載 Github Asset 用的
cage1016/github-assets-cnb
,原來google.go.runtime
google.go.build
google.utils.label
共記 4 個在
project.toml
增加明確指定所需要的 4 個 buildpack 及 Github Asset 相關的 metadata1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
cat <<EOF >> project.toml [[build.buildpacks]] id = "google.go.runtime" version = "0.9.1" [[build.buildpacks]] id = "google.go.build" version = "0.9.0" [[build.buildpacks]] id = "google.utils.label" version = "0.0.1" [[metadata.githubassets]] repo = "grpc-ecosystem/grpc-health-probe" asset = "grpc_health_probe-linux-amd64" destination = "bin/grpc_health_probe" [[build.buildpacks]] id = "cage1016/github-assets-cnb" version = "2.1.1" EOF
1 2 3
pack build aa -B gcr.io/buildpacks/builder:v1 \ -d=project.toml \ --env GOOGLE_BUILDABLE=cmd/add/main.go
我們可以看到
DETECTING
的階段有正確偵測到我們明確指定的 4 個 buildpack,並在BUILDING
階段也有正確下載 Github grpc-ecosystem/grpc-health-probe asset 至 container image 中而依照
cage1016/github-assets-cnb
中實作 buildpack sepc 所提供的目錄為/layers/cage1016_github-assets-cnb/grpc-ecosystem_grpc-health-prob/bin/grpc_health_probe
如圖所示,而這個路徑也是我們在 Kubernetes Pod 在livenessProbe
及readinessProbe
探針指令執行檔所在基本上二種方式的結果都是一樣的,就看你喜歡那一種
心得
在 Dockerfile
中使用 wget
動態去下載所需要的檔案算是一種常規的作法。反之在 buildapck 的架構之下要下載一個檔案卻有一點複雜,也是常常有需要下載 Github Assets 的剛性需求,特別寫了一個符合 Cloud Native Buildpack 的 cage1016/github-assets-cnb buildpack 來滿足這個需求,當這一個生態越來越豐富時,就會慢慢感覺像是在疊責木一樣
如同 cage1016/ms-demo 這個 gokit microserives demo 一樣,Add
及 Tictac
服務基本上都改用 pack 來建構 container image,為了在 Kubernetes Pod 新增 livenessProbe
及 readinessProbe
探針並使用 grpc_health_probe
來檢查 GRPC 服務的健康狀況,其實就是新增了 project.toml
|
|
及
|
|
剩下的都不用動,Pack 就會操作 builder 按照所載入的 buildpack 完成對應的動作。慢慢體會這種抽換的方便性