Istio 中的 Kubernetes 原生 Sidecar

使用 Istio 演示新的 SidecarContainers 功能。

2023 年 8 月 15 日|作者:John Howard - Google

如果你聽過任何關於服務網格的事情,那就是它們使用 sidecar 模式運作:一個代理伺服器與你的應用程式碼一同部署。sidecar 模式只是一種模式。在此之前,Kubernetes 完全沒有正式支援 sidecar 容器。

這導致了一些問題:如果你的工作(Job)按照設計會終止,但 sidecar 容器不會呢?這個確切的用例是 Kubernetes 問題追蹤器上最受歡迎的問題

在 2019 年提出了在 Kubernetes 中加入 sidecar 支援的正式提案。經過多次停頓和重新啟動,在去年重新啟動該專案後,對 sidecar 的正式支援將在 Kubernetes 1.28 中以 Alpha 版本發布。Istio 已經實作了對此功能的支援,你可以在這篇文章中了解如何利用它。

Sidecar 的困境

Sidecar 容器提供了很多功能,但也帶來了一些問題。雖然 Pod 中的容器可以共享一些東西,但它們的生命週期是完全解耦的。對 Kubernetes 來說,這兩個容器在功能上是相同的。

然而,在 Istio 中,它們並不相同 - Istio 容器是主要應用程式容器運作所必需的,如果沒有主要應用程式容器,它就沒有價值。

這種期望上的不匹配導致了各種問題

Istio 社群及其他社群花了無數時間來解決這些問題,但效果有限。

解決根本原因

雖然 Istio 中越來越複雜的解決方案可以幫助 Istio 用戶減輕痛苦,但理想情況下,這一切應該都可以正常運作 - 而且不僅適用於 Istio。幸運的是,Kubernetes 社群一直在努力直接在 Kubernetes 中解決這些問題。

在 Kubernetes 1.28 中,新增了原生 sidecar 支援的新功能,結束了五年多的持續工作。有了這個功能,我們所有的問題都可以在沒有變通方法的情況下解決!

當我們在「GitHub 問題名人堂」時,兩個 問題 分別佔據了 Kubernetes 歷史上問題的第 1 名和第 6 名,並且終於被關閉了!

特別感謝參與完成這項工作的龐大團隊。

試用一下

雖然 Kubernetes 1.28 剛發布,但新的 SidecarContainers 功能是 Alpha 版(因此,預設為關閉),並且 Istio 中對該功能的支援尚未發布,我們今天仍然可以試用它 - 只是不要在生產環境中嘗試!

首先,我們需要啟動一個 Kubernetes 1.28 叢集,並啟用 SidecarContainers 功能

$ cat <<EOF | kind create cluster --name sidecars --image gcr.io/istio-testing/kind-node:v1.28.0 --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
  SidecarContainers: true
EOF

然後我們可以下載最新的 Istio 1.19 預發布版本(因為 1.19 尚未發布)。我這裡使用的是 Linux。這是 Istio 的預發布版本,所以再次強調 - 不要在生產環境中嘗試!當我們安裝 Istio 時,我們將啟用原生 sidecar 支援的功能標誌,並開啟存取日誌,以便稍後演示。

$ TAG=1.19.0-beta.0
$ curl -L https://github.com/istio/istio/releases/download/$TAG/istio-$TAG-linux-amd64.tar.gz | tar xz
$ ./istioctl install --set values.pilot.env.ENABLE_NATIVE_SIDECARS=true -y --set meshConfig.accessLogFile=/dev/stdout

最後,我們可以部署一個工作負載

$ kubectl label namespace default istio-injection=enabled
$ kubectl apply -f samples/sleep/sleep.yaml

讓我們看看 Pod

$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
sleep-7656cf8794-8fhdk   2/2     Running   0          51s

乍看之下一切正常... 如果我們深入了解,我們可以看到其中的奧妙。

$ kubectl get pod -o "custom-columns="\
"NAME:.metadata.name,"\
"INIT:.spec.initContainers[*].name,"\
"CONTAINERS:.spec.containers[*].name"

NAME                     INIT                     CONTAINERS
sleep-7656cf8794-8fhdk   istio-init,istio-proxy   sleep

在這裡,我們可以查看 Pod 中的所有 containersinitContainers

驚喜!istio-proxy 現在是一個 initContainer

更具體地說,它是一個設定了 restartPolicy: AlwaysinitContainer(一個新欄位,由 SidecarContainers 功能啟用)。這會告訴 Kubernetes 將其視為 sidecar。

這表示清單中稍後的 initContainers 以及所有正常的 containers 都會在代理容器準備好後才會啟動。此外,即使代理容器仍在執行,Pod 也會終止。

初始化容器流量

為了測試這一點,讓我們讓我們的 Pod 實際執行一些操作。在這裡,我們部署一個簡單的 Pod,它在 initContainer 中發送請求。通常,這會失敗。

apiVersion: v1
kind: Pod
metadata:
  name: sleep
spec:
  initContainers:
  - name: check-traffic
    image: istio/base
    command:
    - curl
    - httpbin.org/get
  containers:
  - name: sleep
    image: istio/base
    command: ["/bin/sleep", "infinity"]

檢查代理容器,我們可以發現請求成功,並且通過了 Istio sidecar

$ kubectl logs sleep -c istio-proxy | tail -n1
[2023-07-25T22:00:45.703Z] "GET /get HTTP/1.1" 200 - via_upstream - "-" 0 1193 334 334 "-" "curl/7.81.0" "1854226d-41ec-445c-b542-9e43861b5331" "httpbin.org" ...

如果我們檢查 Pod,我們可以發現我們的 sidecar 現在在 check-traffic initContainer 之前執行

$ kubectl get pod -o "custom-columns="\
"NAME:.metadata.name,"\
"INIT:.spec.initContainers[*].name,"\
"CONTAINERS:.spec.containers[*].name"

NAME    INIT                                  CONTAINERS
sleep   istio-init,istio-proxy,check-traffic   sleep

正在退出的 Pod

先前,我們提到當應用程式退出(Job 中常見)時,Pod 會永遠存活。幸運的是,這個問題也得到了解決!

首先,我們部署一個在 1 秒後退出且不會重新啟動的 Pod

apiVersion: v1
kind: Pod
metadata:
  name: sleep
spec:
  restartPolicy: Never
  containers:
- name: sleep
  image: istio/base
  command: ["/bin/sleep", "1"]

我們可以觀察其進度

$ kubectl get pods -w
NAME    READY   STATUS     RESTARTS   AGE
sleep   0/2     Init:1/2   0          2s
sleep   0/2     PodInitializing   0          2s
sleep   1/2     PodInitializing   0          3s
sleep   2/2     Running           0          4s
sleep   1/2     Completed         0          5s
sleep   0/2     Completed         0          12s

在這裡,我們可以看到應用程式容器已退出,不久之後,Istio 的 sidecar 容器也退出。以前,Pod 會卡在 Running 狀態,而現在它可以轉換為 Completed 狀態。不再有殭屍 Pod 了!

Ambient 模式呢?

去年,Istio 宣布了 Ambient 模式 - 一種新的 Istio 資料平面模式,不依賴 sidecar 容器。因此,隨著 Ambient 模式的出現,這一切還有意義嗎?

我會說「是的」!

雖然在工作負載使用 Ambient 模式時,sidecar 的影響會減輕,但我認為幾乎所有大規模 Kubernetes 用戶在其部署中都有某種 sidecar。這可能是他們不想遷移到 Ambient 的 Istio 工作負載,他們尚未遷移的工作負載,或與 Istio 無關的事物。因此,雖然可能只有少數情況需要用到,但對於使用 sidecar 的情況來說,它仍然是一個巨大的改進。

你可能會想反過來問 - 如果我們所有的 sidecar 問題都解決了,為什麼我們還需要 Ambient 模式?在解決這些 sidecar 限制的同時,Ambient 仍然帶來了各種好處。例如,這篇部落格文章詳細介紹了為什麼將代理與工作負載分離是有利的。

自己試試看

我們鼓勵喜歡冒險的讀者在測試環境中親自試用!這些實驗性和 Alpha 版功能的回饋對於確保它們穩定並在推廣之前滿足期望至關重要。如果你嘗試過,請在 Istio Slack 中告訴我們你的想法!

特別是,Kubernetes 團隊有興趣了解更多關於

分享這篇文章