「大使」模式是一種特化的邊車,負責隱藏複雜度、並為「存取 Pod 之外的服務」提供統一介面。它扮演代理(proxy),把主 Pod 與「直接存取外部依賴」這件事解耦。
問題#
容器化服務不會孤立存在,經常必須存取其他服務,而這些服務未必容易可靠地連上。困難可能來自:
- 位址是動態且會變的
- 需要對叢集化的服務實例做負載平衡
- 協定不可靠
- 資料格式棘手
理想上,容器應該是單一目的、且能在不同脈絡中重用的。
但如果一個容器既提供商業功能、又以某種特殊方式消費外部服務,它就背負了不只一項職責。
消費外部服務可能需要一套特殊的服務發現函式庫,而我們不想把它塞進自己的容器;或者我們想用不同的服務發現函式庫與方法來抽換不同種類的服務。把「存取外部世界其他服務」的邏輯抽象並隔離出來,正是大使模式的目標。
解法#
以應用的快取為例:在開發環境存取本地快取可能只是簡單的組態,但在正式環境,我們可能需要一套能連上快取各個分片(shard)的客戶端組態。其他例子還有:
- 透過在註冊表中查詢來消費服務,執行客戶端服務發現。
- 透過 HTTP 這類不可靠協定消費服務,為了保護應用必須使用斷路器(circuit-breaker)邏輯、設定逾時、執行重試等。
在所有這些情況下,我們都可以用一個大使容器來隱藏存取外部服務的複雜度,並透過 localhost 為主應用容器提供簡化的視圖與存取方式。

圖 17-1:用大使容器存取遠端分散式快取——資料存取可委派給 Etcd 這類完全分散式的遠端儲存

圖 17-2:用大使容器存取本地快取——開發用途下,這個大使容器可以輕易換成本地執行的記憶體內鍵值儲存(如 memcached)
這個模式的好處與邊車相似:讓容器保持單一目的且可重用。應用容器可以專注於商業邏輯,把消費外部服務的職責與細節委派給另一個專門容器;同時也讓我們能打造專門且可重用的大使容器,與其他應用容器自由組合。
以下範例中,大使與一個 REST 服務並行執行。REST 服務在回傳回應之前,會把產生的資料送到固定 URL http://localhost:9009 記錄下來;大使行程監聽這個埠並處理資料。範例中它只是把資料印到主控台,但也可以做更精緻的事,例如把資料轉發到完整的日誌基礎設施。
apiVersion: v1
kind: Pod
metadata:
name: random-generator
labels:
app: random-generator
spec:
containers:
# 主應用容器:提供產生亂數的 REST 服務
- image: k8spatterns/random-generator:1.0
name: main
env:
- name: LOG_URL
value: http://localhost:9009 # 透過 localhost 與大使溝通的連線 URL
ports:
- containerPort: 8080
protocol: TCP
# 大使容器:平行執行,監聽 9009 埠(該埠不對 Pod 外部曝露)
- image: k8spatterns/random-generator-log-ambassador
name: ambassador討論#
從更高層次看,大使就是一種邊車模式。
兩者的主要差異在於:大使不為主應用增添額外能力,它只是扮演通往外部世界的智慧代理——名稱由此而來(這個模式有時也被稱為 Proxy 模式)。
更多資訊#
- Ambassador Example
- How to Use the Ambassador Pattern to Dynamically Configure Services
- Dynamic Docker Links with an Ambassador Powered
- Link via an Ambassador Container
- Modifications to the CoreOS Ambassador Pattern