邊車(Sidecar)容器在不修改既有容器的前提下,擴充並強化它的功能。這是最基礎的容器模式之一,讓單一目的的容器能緊密協作。後續的特化模式「轉接器」與「大使」,是它的兩種變形。
問題#
容器是流行的封裝技術,讓開發者與系統管理員能以統一的方式建置、遞送與執行應用。一個容器代表一個功能單元的自然邊界,擁有獨立的執行期、發布週期、API,以及擁有它的團隊。合格的容器行為像單一 Linux 行程——解決一個問題並把它做好——並且以可替換與可重用為出發點而建立。
最後這點至關重要,因為它讓我們能藉由既有的專門容器,更快地打造應用:今天要發 HTTP 呼叫,我們不必自己寫客戶端函式庫,用現成的就好;同樣地,要提供網站服務,我們不必自己做網頁伺服器容器。這讓開發者避免重造輪子,形成一個「容器數量更少、品質更好」的生態系。
但要擁有單一目的、可重用的容器,就需要擴充容器功能的方式,以及容器之間協作的手段。邊車模式描述的正是這種協作:一個容器強化另一個既有容器的功能。
解法#
Pod 原語讓我們能把多個容器組成單一單元。幕後在執行期,Pod 本身也是一個容器,但它在 Pod 內所有其他容器之前,以一個暫停行程(字面上就是 pause 指令)啟動;它什麼也不做,只是持有所有 Linux 命名空間,供應用容器在 Pod 生命週期中互動之用。
比這個實作細節更有意思的,是 Pod 抽象提供的各種特性。Pod 是如此根本的原語,以至於它在許多雲原生平台上以不同名稱存在,但能力總是相似。作為部署單元,Pod 對其中的容器施加了某些執行期約束——所有容器都被部署到同一節點、共享同一個 Pod 生命週期;同時,Pod 也讓容器能共享 volume,並透過本地網路或主機 IPC 溝通。
「邊車」(有些地方也稱 Sidekick)就是用來描述這種情境:把一個容器放進 Pod,以擴充並強化另一個容器的行為。
展示這個模式的典型例子是「HTTP 伺服器 + Git 同步器」:
- HTTP 伺服器容器只專注於透過 HTTP 提供檔案,不知道也不在乎檔案從哪來、怎麼來。
- Git 同步器容器唯一的目標是把資料從 Git 伺服器同步到本地檔案系統,同步後檔案發生什麼事它一概不管,只關心讓本地資料夾與遠端 Git 伺服器保持同步。
apiVersion: v1
kind: Pod
metadata:
name: web-app
spec:
containers:
- name: app # 主應用容器:透過 HTTP 提供檔案
image: docker.io/centos/httpd
ports:
- containerPort: 80
volumeMounts:
- mountPath: /var/www/html
name: git
- name: poll # 邊車容器:平行執行,從 Git 伺服器拉取資料
image: axeclbr/git
volumeMounts:
- mountPath: /var/lib/data
name: git
env:
- name: GIT_REPO
value: https://github.com/mdn/beginner-html-site-scripted
command:
- "sh"
- "-c"
- "git clone $(GIT_REPO) . && watch -n 600 git pull"
workingDir: /var/lib/data
volumes:
- emptyDir: {} # 邊車與主應用容器交換資料的共享位置
name: git這個範例展示了 Git 同步器如何為 HTTP 伺服器補上要服務的內容、並保持同步。我們也可以說兩個容器是協作關係、同等重要;但在邊車模式中,有一個主容器和一個強化整體行為的輔助容器。
慣例上,主容器是
containers清單中列在第一個的容器,它代表預設容器(例如執行kubectl exec時)。

圖 15-1:邊車模式
這個簡單模式讓容器在執行期協作,同時為兩個容器達成關注點分離——它們可能由不同團隊擁有、使用不同程式語言、有不同的發布週期。它也促進了容器的可替換性與重用:HTTP 伺服器與 Git 同步器都能在其他應用與不同組態中重用,可以是 Pod 中的單一容器,也可以再次與其他容器協作。
討論#
我們曾說容器映像檔像類別、容器像物件導向程式設計(OOP)中的物件。延續這個類比:
| OOP 對應 | 關係 | 特性 | |
|---|---|---|---|
| 擴充容器以強化其功能 | 繼承(inheritance) | is-a | 容器間耦合較緊 |
| 多個容器在 Pod 中協作 | 組合(composition) | has-a | 更靈活,不在建置期把容器綁死,日後可在 Pod 定義中抽換容器 |
但 Pod 中的組合也意味著你有多個容器(行程)在執行,各自被健康檢查、被重啟、並像主應用容器一樣消耗資源。現代邊車容器都很小、資源消耗極少,但你仍必須判斷:值得多跑一個行程,還是併進主容器更好?
換個角度看,容器組合類似面向切面程式設計(aspect-oriented programming):透過額外的容器,我們為 Pod 引入了正交的能力,而完全不必碰主容器。
近年邊車模式的使用越來越普遍,尤其是在處理服務的網路、監控與追蹤面向時——每個服務都會一併帶上邊車容器。
更多資訊#
- Sidecar Example
- Design Patterns for Container-Based Distributed Systems
- Prana: A Sidecar for your Netflix PaaS-based Applications and Services
- Tin-Can Phone: Patterns to Add Authorization and Encryption to Legacy Applications
- The Almighty Pause Container