Rethink:爲什麼微服務沒有 sidecar 不行?

作者 | 蔡芳芳

採訪嘉賓 | 蔡書  

幾乎是隨着 Service Mesh 概念的普及,“sidecar”這個詞被容器從業者提到的頻率也越來越高。甚至可以說,sidecar proxy 已經是 Service Mesh 的第一技術特徵。今天我們就和 Flomesh 團隊負責人蔡書一起來聊聊爲什麼會出現 sidecar proxy,以及除了 proxy 還有哪些 sidecar,最後展望一下 “理想化” 的 sidecar 應該是什麼樣子。

InfoQ:能否先簡單解釋下什麼叫 sidecar?

**蔡書:**Sidecar 本意是指三輪摩托旁邊的那個挎鬥。Kubernetes 在形成初期,就把 “容器” 這個模型演化成了 “pod” 模型。Pod 就是多個容器 “編組使用”,或者簡單地說,如果把一個“pod” 類比成一個“虛擬機”,那麼多個容器就是這個虛擬機裏邊的多個進程。這些進程裏邊,那些配合業務進程的其他進程我們一般就稱爲 sidecar。比如 pod 運行的是一個 Spring Boot 的進程,在這個 pod 裏邊我們部署了採集日誌的 Filebeat 進程,部署了代理流量的 proxy 進程,那麼這個採集日誌和代理進程都叫做“sidecar”。

在 sidecar 這個說法被廣泛使用之前,其實 sidecar 這種用法就已經被普遍使用了,比如上邊例子說的有些容器玩家會在容器內部署採集日誌的進程。但是 sidecar 這個叫法是隨着 Service Mesh 出現而流行起來的。在幾乎所有討論 Serivce Mesh 的材料和文章中都會出現 sidecar 這個詞,如果從自然語言分析角度看,“Service Mesh”和 “sidecar” 是關聯度極高的兩個詞彙。事實上,和 Service Mesh 一起說的 sidecar,是 “sidecar proxy” 的一個簡化說法。所以當討論的上下文是 “Service Mesh” 的時候,說到“sidecar”,一般就是指“sidecar proxy”。

InfoQ:這麼說 sidecar 其實不算是個新事物了~

**蔡書:**雖然這個詞彙是最近幾年隨着服務網格開始在容器圈流行,但是 sidecar 模式其實早就存在,甚至可以說從操作系統進入了 “多任務” 以後就出現了。

InfoQ:能詳細說說 sidecar 的歷史淵源嗎?

**蔡書:**這個話題非常有趣,我試着從三個方面聊下,一個是操作系統,一個是應用服務器,一個是容器時代的 pod,他們之間內在有時間上的先後順序,邏輯上他們的模型也有共性之處。

這裏先做一個假設,就是我的目標是運行一個 “業務程序”,比如一個 SpringBoot 的 Java 程序,當啓動這個 SpringBoot 程序的時候,我需要用 Java springboot.jar 之類的命令來啓動這個進程。在典型的 Linux 上,通常我們會把這個命令包裝到一個腳本里邊,用類似 start-springboot.sh 之類的腳本來啓動。事實上,在我們啓動這個 Java 進程之前,就有很多進程在運行了,典型的比如說監控進程,比如 zabbix agent;還有比如日誌收集的進程,比如 filebeat,等等。

其實除了這些大家常見的進程,還有一些大家可能未必留意的進程,也在運行了。典型的比如 crond,大家都用 crontab 做一些定時任務,crond 進程就是管理這個的。記得以前常常有用戶問我們 “能不能給我一個最小最乾淨的操作系統”,其實他指的就是在運行業務進程的時候,只有最少的其他進程在運行。這些 “其他進程”,從邏輯模型看,都可以認爲是業務進程的 sidecar。從功能的角度來說,我們會發現,這些 sidecar 進程可以分爲幾類,一類是輔助業務的,比如定時任務;一類是管理員需要的,比如日誌採集、監控;一類是系統本身需要的,操作系統在啓動內核後,會啓動一個 “超級進程”,稱爲 initd 進程,後來的 systemd 進程是 initd 的替代品,這個超級進程會啓動一些進程用來輔助操作系統的功能,最典型的比如 kdump,用來在程序崩潰時候收集信息。概括地說,早期使用單機操作系統運行業務進程的時候,我們有三類 “sidecar”,#1 是業務自身需要的,#2 是管理員需要的,#3 是操作系統需要的。

說完操作系統,我們再說應用服務器。千禧年之後,隨着 Java 進入企業領域,也就是當時的 J2EE,應用服務器開始普及。以 Java 應用服務器來說(事實上幾乎各種語言都有自己的 “應用服務器”),應用服務器有自己的啓動過程,在這個過程中,應用服務器會啓動很多 “線程”,這些線程也是輔助完成業務邏輯或者實現管理功能的,他們的本質也是 sidecar。

進入容器時代以後,尤其是 K8s 提出 pod 的概念,圍繞業務進程的輔助進程模式更加清晰和明確,這些輔助進程就是 sidecar。同樣,這些 sidecar 也還是完成着傳統的三方面功能,一方面是輔助業務的;一方面是面向管理員的;一方面是面向系統的。容器環境是典型的雲環境,所以這裏的 “面向管理員” 和“面向系統”又有了新的含義和進一步的需求。

InfoQ:感覺當前對於 Service Mesh、微服務,甚至可以擴大到雲原生,似乎都是沒有 sidecar 不行?爲什麼 sidecar 這麼重要?

**蔡書:說 “沒有 sidecar 不行” 不如說“sidecar 的普遍使用是客觀現實,是剛需”。**這種剛需的產生我覺得有這麼幾個因素,一個是不同角色需要不同能力的進程協助完成工作,比如業務進程、應用運維、系統運維,彼此工作的和角色的差異,導致了每個角色用自己的 sidecar 輔助進程是一種分工,也是一種清晰的工作邊界。

另一方面,有些需求是在業務上線後出現的,那麼這個時候,用一個附加的 sidecar 進程完成管理工作就很順理成章。還有一點,進程是現代 Unix 和類 Unix 系統的基本管理單位,進程級的管理是非常成熟的技術。作爲一個對比,其實上一代應用服務器,比如 JEE 應用服務器,嘗試把很多輔助管理能力放到線程級,但是後來又都逐漸分離到外部進程了。所謂 “一個快速、簡潔的 Java 進程”。這些客觀的需求,使得 sidecar 輔助進程成爲一種剛需。

InfoQ:使用 sidecar 模式的優勢是什麼?

**蔡書:**就像上一個問題裏說到的,sidecar 輔助進程的出現很多時候是順理成章、水到渠成的,是一種最佳選擇。簡單來說,sidecar 本質就是分而治之,並且天然具有 “分工” 的屬性,還可以用來解決很多 “上線時候還沒有的管理需求”,扮演了管理上的補丁角色。從 sidecar proxy 的角度看,proxy 提供一種“切片管理” 的能力,這個是非常經典的設計模式。

InfoQ:前面回顧 sidecar 歷史淵源的時候,您最後提到容器環境帶來的 “新的含義和進一步需求”,這個怎麼理解?能不能具體說說?

**蔡書:**容器和 K8s 的普及,使得 “雲” 距離用戶更近了一步,這裏,我總結了一些和 sidecar 相關的技術變化,以及 “雲” 本身帶來的一些變化。很多時候,我認爲這些變化和特徵也是 “雲原生” 的特徵和驅動力的一部分。

具體包括這麼幾個部分:

  1. 容器啓動的時候,有一個 PID=1 的進程。通常而言,這個進程就是 “業務進程”(實際上 pod 啓動還有個 init 進程,叫做 pause)。當我們想啓動 sidecar 進程的時候,目前的做法是通過 hook,在啓動過程中啓動 sidecar。實際上,這個時候 K8s(或者具體的說 Kubelet)其實是一個超級進程,它負責啓動業務進程和 sidecar。很多時候,sidecar 和業務進程,甚至是 sidecar 之間,是有啓動順序的。但是目前在 K8s 的體系內,缺少對這種依賴的管理。如果大家熟悉 Linux 的 initd 和 systemd,會知道系統的啓動過程是由一堆腳本控制的,也包含了一些優先關係。在操作系統時代,這些 sidecar 的啓動是個“準標準”,也是可以通過 Shell 腳本“定製化” 的。總結來說:pod 的 init 過程在標準化、定製化、擴展方面比較簡單,在一個 pod 內容器多且有依賴和關聯的時候,當前的機制不夠靈活。所以第一個 “新” 需求就是 pod 內多進程的啓動依賴及順序,目前容器平臺沒有提供相應的機制。

  2. 容器快速被認可,背後最主要的原因是容器 “輕量化”,而輕量化是“敏捷” 的前提。當我們需要通過 sidecar 進程來完成某一種輔助功能的時候,我們需要這個輔助進程儘可能輕量化,否則就會有一種頭重腳輕的感覺。前幾天有個技術分享,提到他們業務容器的資源配置是 4C8G,然後 sidecar 資源配置是 4C4G。對這種配置,我只能感慨“有錢真好”。大多數用戶還是希望 sidecar 是很輕量化的。概括地說,第二個 “進階” 需求是,pod 內的 sidecar 輔助進程需要比傳統主機上更輕量化。

  3. 權限。當我們在虛擬機或者物理機上部署 sidecar 這些輔助進程的時候,有時候我們需要特權,因爲讀寫一些系統信息需要高權限。在主機(虛擬機、物理機)時代,超級用戶加上業務用戶的兩級權限很好地滿足了不同用戶運行不同進程權限管理的需求。但是在容器時代,這個事情變難了。容器環境裏,除了宿主機的管理(通常是特權用戶)和業務進程(通常是普通用戶)之外,多了這些 sidecar 輔助進程。這些 sidecar 輔助進程,有些也需要特權、更多的最好是用普通用戶。相當於在容器環境和 pod 裏,其實出現了 3 個等級的權限需求:宿主機的 root、容器的 “root”、容器的普通用戶。這層權限的出現,本質上是雲的多租戶導致的。目前來看,這個中間層的權限比較難處理,因爲業務進程和輔助 sidecar 進程是共享 namespace 的。概括起來,第三個 “新” 需求是 sidecar 輔助進程通常要求一種介於宿主機 root 和業務進程之間的權限能力。

  4. 擴展性。主機上傳統的 sidecar 輔助進程,一般都有自己的配置方式(配置文件格式),以及一些擴展方式,比如 zabbix 可以運行腳本等。這些傳統的輔助進程進入到容器後,管理其實更難了。之前積累的很多管理工具,可以通過配置工具如 ansible 之類下發,而容器一般提供的方式是 configMap,這種配置和擴展的變化導致了嚴重的碎片化,而且方式改變也帶來了新的困難。Sidecar 輔助進程的功能,很多是需要這種客戶化和現場定製化的,這部分需要通用、簡單的擴展機制和方式。因此,第四個 “進階” 需求是 sidecar 輔助進程通常需要比傳統主機上更簡單、易用、且強大的擴展能力。

大概總結這麼幾個,其實還有一些,以後想起來再討論。

InfoQ:針對上面這些問題和需求,業內現在有什麼可行的解決辦法嗎?

**蔡書:**這是個好問題,在我看來,整個行業都發現了這些新問題——就是說,pod 里正在被塞進越來越多的 sidecar。因此整個行業也都在探索可行的解決辦法。這裏介紹下我們開源項目 pipy 的探索:我們通過 infra container 的方式爲每個容器提供了 PID=1 的 sidecar,這個 pipy 進程類似 Linux 中的 initd 或者 systemd,它的作用是根據需要引入和執行其他的功能;通過 pipy repo 和 pipy js 的能力,pipy 可以提供目前我們已經識別的各種 sidecar 所需要的功能,比如服務註冊 / 註銷、服務發現、日誌採集、指標採集、主動健康檢查、定時任務、提供網絡代理(也就是 sidecar proxy 能力)等。這是一種嘗試,也歡迎大家一起來探討。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/sRDlcqiKwlX-_chQqn2vzg