將 Sidecar 容器帶入新的階段

作者 | 徐迪、張曉宇

導讀:本文根據徐迪和張曉宇在 KubeCon NA 2019 大會分享整理。分享將會從以下幾個方面進行切入:首先會簡單介紹一下什麼是 Sidecar 容器;其次,會分享幾個阿里巴巴經濟體的通用場景,以及他們是如何解決這些挑戰的。

Sidecar 簡介

Sidecar 容器並不是一個新鮮事物。它是一種設計模式,主要用來做一些輔助的工作,比如網絡連通性、下載拷貝文件之類的事情;如果大家熟悉 Docker Swarm 的話,就會發現 Docker Ambassador 其實就是 Sidecar。

1.png

如上所示,Service Consumer 和 Redis Provider 強耦合,部署在同一個節點上。如果這個時候,Redis Provider 出現問題,需要連接到另外一個 Redis 實例上,需要重新配置,並重啓 Service Provider。

2.png

那麼在引入了 Ambassador 以後,問題變得相對簡單些,只需要重啓這裏的 Redis Ambassador 即可,並不需要 Service Consumer 進行任何變動。

當然這種模式,還可以進行跨節點通信,比如下圖。這樣 Service Consumer 和 Redis Provider 就可以部署在不同的節點上。在某種程度上,很容易地就將兩種服務進行了解耦。

3.png

Sidecar 案例分享

1. Sidecar 容器能用來幹什麼?

一般來講,Sidecar 容器可以:

  • 日誌代理/轉發,例如 fluentd;
  • Service Mesh,比如 Istio,Linkerd;
  • 代理,比如 Docker Ambassador;
  • 探活:檢查某些組件是不是正常工作;
  • 其他輔助性的工作,比如拷貝文件,下載文件等;

2. 僅此而已?

事實上,Sidecar 越來越被大家接受,並且使用越來越廣泛。Sidecar 容器通常和業務容器(非 Sidecar 容器)部署在同一個 Pod 裏,共享相同的生命週期,爲業務容器提供輔助功能。這是一個非常好的模式,能夠極大程度解耦應用,並且支持異構組件,降低技術壁壘。

但目前 Kubernetes 對 Sidecar 的管理還不完善,越來越不滿足我們的使用,尤其是在生產環境中使用 Sidecar。

3. 幾個典型案例

順序依賴

假設我們在一個 Pod 內注入了多個 Sidecar,但是 Sidecar 之間或者 Sidecar 和業務容器之間有相互依賴關係。如下這個例子,我們需要先啓動 proxy Sidecar 容器用於建立網絡連接,這樣 mysql client 才能連接到遠端的 mysql 集羣,並在本地暴露服務。而後主的業務容器才能正常工作。

#1 proxy_container (sidecar)
#2 mysql_client
#3 svc_container

當然,有的人會覺得這個地方,可以通過諸如更改鏡像啓動腳本延遲啓動等方法來解決。但是這些方法侵入性太強,不利於擴展,還很難進行準確的配置。

Sidecar 管理

我們來看看另外一個案例。Sidecar 容器和業務容器耦合在同一個 Pod 內,共享相同的生命週期。因此,單獨來管控 Sidecar 容器非常不方,比如更新 Sidecar 的鏡像。

4.png

比如,我們已經給很多 Pod 注入了 Istio Proxy 這樣的 Sidecar 容器,目前運行狀態良好。但是如果這個時候我們想升級這個 Proxy 鏡像的話,該怎麼辦?

如果按照 Istio 社區官方的文檔,我們需要重新注入這些 Sidecar 容器。具體來說,需要刪除原有 Pod,重新生成一份新的 Pod(有些 workload 關聯的 Pod,會由相應的 workload 控制器自動生成)。

那如果我們有很多個這樣的 Pod 需要處理的話,怎麼辦?通過命令行的話,太不方便,而且容易出錯。通過自己單獨寫的代碼的話,可擴展性是個問題,需要頻繁更改這些代碼。

而且這裏還有另外一個問題,我們肯定不會一下子升級所有的 Sidecar,肯定要有個灰度的過程,也就是隻升級一部分 Sidecar,這個時候又該怎麼辦呢?

社區進展

1. 上游社區

這裏我們非常感謝 Joseph Irving (@Joseph-Irving) 提出了一個 Sidecar kep,通過定義 LifecycleType 來區分是否是 Sidecar 容器。

5.png

未來只需要在 Pod Spec 中,按如下方式標記即可:

name: sidecarContainer
image: foo
lifecycle:
  type: Sidecar

Pod 內容器的啓動順序按照:初始化容器->Sidecar 容器->業務容器 的順序依次啓動。

其中上述 kep 的 kubelet 端實現 正在進行中。

爲了支持 Sidecar 更多的使用場景,我們以此爲基礎提出了 PreSidecar 和 PostSidecar,分別用於在業務容器之前和之後啓動。

具體的使用場景見 我們的 PR

爲什麼我們覺得 Sidecar 應該區分前置和後置呢?

這是因爲在一些場景下,我們需要 Sidecar 容器優先於應用容器啓動,幫助做一些準備工作。例如分發證書,創建共享卷,或者拷貝下載一些其他文件等。

6.png

而在另外一些場景下,我們需要一些 Sidecar 容器在應用容器之後啓動。考慮到解耦和版本管理的因素,我們將應用分爲兩部分,應用容器專注於業務本身,而一些數據和個性化的配置放在 Sidecar 容器中。通常情況下,這兩個容器將會共享一個存儲卷,後置的 Sidecar 容器會更新替換掉一些默認和過時數據。

7.png

當然考慮到未來更復雜的場景,我們可能還會對容器的啓動順序做 DAG 編排,當然這個需要視生產實際需要而定。

8.png

2. 螞蟻金服及阿里巴巴如何應對

爲了解決 Sidecar 的管理工作,我們需要一個更細粒度的 workload 方便我們進行管理。這個 workload 我們命名爲 SidecarSet,目前已經開源,生產可用。大家可以訪問 OpenKruise 這個項目,可以在項目的 roadmap 裏瞭解我們目前的一些新進展。OpenKruise 這個項目目前有三個生產可用的 workload,分別是 Advanced StatefulSet、BroadcastJob、SidecarSet。另外2個 workload(AdvancedHPA 和 PodHealer)正在加緊開發中, 很快會開源出來,敬請期待。相關使用 Demo,大家可以觀看 Lachlan Evenson 的嚐鮮視頻

9.png

spec 中的 SidecarContainer 的定義就是 Kubernetes 代碼庫中的 corev1.Container 定義。通過額外的一個 labelSelector,可以很方便地對指定的容器組進行操作。我們支持滾動升級(RollingUpdate)的方式,讓用戶可以分批的升級 Sidecar,同時也提供了 pause 功能,可以在緊急情況下暫停 Sidecar 的升級。

如果只是簡單升級 Sidecar 的鏡像, SidecarSet 控制器僅僅會 patch 原有 pod 的,非常方便的就可以一鍵升級鏡像。

其他的挑戰

我們在生產實踐過程中,還發現了一些其他的挑戰,目前還在尋找比較好的解法。

1. Sidecar 容器的資源管理

一般來講 Sidecar 容器佔用的資源都比較小,那麼這個資源要不要計算到整個 pod 當中?還是可以直接共享業務容器的資源即可?相同的 Sidecar 在和不同的應用容器搭配使用,如何準確給 Sidecar 容器分配資源這些都需要進行考慮。

10.png

2. Sidecar 容器的容錯性

一般來講,Sidecar 容器都是非主要容器,那麼這類容器出現問題時,比如 liveness 探活,要不要對主容器的狀態或者整個 pod 的狀態也產生影響。再或者,Sidecar 鏡像更新出現問題時,要不要直接標記整個 pod 出現問題。當然,還有一些其他的挑戰,我們只是列舉了幾個通用的。對於這些挑戰,我們需要大家一起集思廣益,找到比較合理的解法。

小結

隨着 Sidecar 在生產環境使用越來越廣泛,對其的管理愈發需要重視。Sidecar 雖然和業務容器部署在同一個 Pod 內,但是其本質上只是輔助性的容器。本文介紹了目前 Sidecar 的典型使用案例,以及面臨的挑戰,同時跟上游社區一起合作,將阿里經濟體的技術解決方案在社區落地,幫助更多的用戶.

作者簡介:
徐迪 螞蟻金服技術專家:負責螞蟻金融雲 PaaS 平臺建設,Kubernetes 社區老兵,核心代碼庫貢獻量社區前50;
張曉宇 阿里雲技術專家:負責阿里巴巴雲原生應用容器平臺的生態建設,主要設計和研發節點穩定性和資源利用率相關解決方案,同時也是 Kubernetes 社區熱心的成員和貢獻者。

阿里巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術圈。”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章