延遲應用啟動,直到Sidecar準備就緒

2020-06-21     segmentfault官方

原標題:延遲應用啟動,直到Sidecar準備就緒

本文轉載於SegmentFault社區

作者:iyacontrol

Kubernetes在Pod中啟動容器的方式出乎意料。在檢查了原始碼以確認我所看到的內容之後,我意識到我剛剛找到了Istio Service Mesh中一個長期存在的問題的解決方案。

我相信大多數Kubernetes用戶都假定Pod的初始化容器完成後,將並行啟動Pod的常規容器。事實並非如此。

如果檢查啟動容器的Kubelet代碼,則會注意到它是按順序執行的。該代碼在一個線程中執行,並按照容器在pod的spec.containers數組中列出的順序啟動容器。

// Step 7: startcontainers inpodContainerChanges.ContainersToStart. for_, idx := rangepodContainerChanges.ContainersToStart { start( "container", containerStartSpec(&pod.Spec.Containers[idx])) }

但是,假設容器鏡像已經存儲在本地,則在Kubelet啟動第一個容器之後,Kubelet啟動第二個容器所花費的時間可以忽略不計。實際上,它們都是同時啟動的。

當一個容器依賴於另一個容器並要求它完全啟動才能運行時,這是不理想的。

Istio Proxy sidecar容器就是一個例子。由於應用程式的傳出通信是通過代理路由的,因此在啟動應用程式本身之前,代理必須已啟動並正在運行。

您可以在應用程式容器中添加一個Shell腳本,以等待代理啟動,然後運行該應用程式的可執行文件。但這需要更改應用程式本身。理想情況下,我們希望在不對應用程式或其容器鏡像進行任何更改的情況下將代理注入Pod。

事實證明,這可以通過利用Kubernetes中的同步容器啟動來完成。

首先,我們需要將代理指定為spec.containers中的第一個容器,但這只是解決方案的一部分,因為它只能確保首先啟動代理容器,而不會等待其準備就緒。其他容器立即啟動,從而導致容器之間的競爭狀態。我們需要防止Kubelet在代理準備好之前啟動其他容器。

這是啟動後生命周期鉤子出現的地方。事實證明,啟動容器的Kubelet代碼會阻止下一個容器的啟動,直到啟動後處理程序終止為止。

我們可以利用這種行為。不僅在Istio中,而且在必須啟動Sidecar容器並準備就緒的每個Pod中,應用程式容器才能啟動。

簡而言之,Sidecar啟動問題的解決方案如下:

如果sidecar容器提供了一個等待該sidecar就緒的可執行文件,則可以在容器的啟動後掛鉤中調用該文件,以阻止pod中其餘容器的啟動。

下圖應該可以幫助您直觀地看到容器中發生的情況。

具體yaml如下:

apiVersion: v1 kind: Pod metadata: name: sidecar-starts-first spec: containers: -name: sidecar image: my-sidecar lifecycle: postStart: exec: command: -/bin/wait-until-ready.sh -name: application image: my-application

但是,這種方法並不完美。如果在啟動後掛鉤中調用的命令或容器的主進程失敗,則其他容器將立即啟動。儘管如此,在Kubernetes引入對sidecar container的適當支持之前,這應該是一個好的解決方法。或者直到有人決定更改Kubelet的行為,並使其在單獨的goroutine中啟動容器。

儘管此技術可以解決容器啟動順序的問題,但是當您刪除容器時,容器的容器停止順序卻無濟於事。Pod的容器實際上是並行終止的。當它關閉一個Pod時,Kubelet在goroutine中執行容器終止代碼-每個容器一個。與啟動後掛鉤不同,停止前掛鉤因此並行運行。

如果僅在主應用程式容器終止後才需要停靠sidecar,則必須以其他方式處理。

原文連結

https://medium.com/@marko.luksa/delaying-application-start-until-sidecar-is-ready-2ec2d21a7b74

SegmentFault 思否社區和文章作者展開更多互動和交流。

文章來源: https://twgreatdaily.com/zh-mo/a18T1nIBd4Bm1__YHZEm.html

Flutter 知識點

2020-08-10