協議檢測(Protocol detection
),顧名思義,允許 Linkerd
自動檢測 TCP
連線中使用的協議。 Linkerd
的設計原則之一是“just work”
,協議檢測是 Linkerd
如何實現這一目標的重要組成部分。
什麼是協議檢測?
簡而言之,協議檢測是通過檢查連線上的流量來確定 TCP 連線上使用的協議的能力。
Linkerd
使用 Protocol detection
來避免要求使用者指定協議。 Linkered
的代理不需要使用者配置每個埠使用的協議,而是簡單地執行協議檢測來回答問題。
Linkerd
的 Protocol detection
通過檢視客戶端連線的前幾個位元組來獲取有關流量的資訊來工作。 這種實現有一些後果,我們將在下面介紹。
但首先,讓我們首先回答為什麼 Linkerd
關心任何協議的問題。
可觀察性、可靠性和安全性
我們通常將 Linkerd
的廣泛功能分為三類:可觀察性(Observability
)、可靠性(reliability
)和安全性(security
)。 瞭解連線(connection
)上使用的協議是每個類別的基礎。
可觀察性
Linkerd
可觀察性功能的核心是流量檢測。 這種儀器需要了解正在使用的協議,因為協議的知識可以提供豐富的指標。 例如,知道連線正在使用 HTTP
,Linkerd
就可以解析請求、響應和響應程式碼,並報告響應延遲、請求量和錯誤率等指標。 這些指標非常有價值,以至於它們成為谷歌 SRE 書中所謂的“黃金訊號”的一部分。 另一方面,如果 Linkerd 只知道連線是 TCP,則它僅限於記錄非常基本的資訊,例如讀取和寫入的位元組數——無法進一步解釋位元組。
Linkerd
可觀察特性的核心是流量的測量。這種檢測需要理解正在使用的協議,因為對協議的瞭解可以提供豐富的度量。例如,知道一個連線正在使用 HTTP
,就允許 Linkerd
解析請求、響應和響應程式碼,並報告響應延遲、請求量和錯誤率等指標。這些指標非常有價值,它們是谷歌的 SRE
書中所謂的“黃金訊號”的一部分。另一方面,如果 Linkerd
只知道一個連線是 TCP
,那麼它只能記錄非常基本的資訊,比如讀取和寫入的位元組數——沒有進一步解釋位元組的能力。
安全
雙向 TLS (mTLS)
是 Linkerd
的核心功能。從 Linkerd 2.9
開始,網狀端點(meshed endpoints
)之間的所有 TCP
流量預設由 Linkerd 代理進行 mTLS
。 (有一些警告 - 請參閱下面有關 skip-ports
的部分。)
在這裡,再次瞭解連線的協議至關重要。例如,如果連線已經是 TLS
的(例如,通過應用程式),則沒有理由重新 TLS
。(嚴格來說,TLS
是一種傳輸層協議,而不是像 HTTP
那樣的應用層協議,但就本文而言,兩者之間的區別並不重要。)
可靠性
最後,瞭解底層連線的協議允許 Linkerd
提供複雜的可靠性功能。 這裡的一個例子是負載平衡。 在不知道連線協議的情況下,Linkerd
僅限於平衡連線(balancing connections
):一旦與伺服器建立了 TCP
連線,它就無法進一步操作該連線。
但是,如果 Linkerd
知道連線是 HTTP
,它可以從連線平衡(connection balancing
)轉移到請求平衡(request balancing
)。Linkerd
將建立一個跨端點的連線池,並平衡這個池中的請求。 由於它現在可以訪問 requests
和 responses
,Linkerd
在平衡請求方面可以非常複雜; 事實上,它根據每個可能端點的最近效能(使用稱為“指數加權移動平均(exponentially weighted moving average
)”或 EWMA
的指標)來平衡請求,以避免從慢速端點引起尾部延遲(tail latency
)。
( Linkerd
也是 Kubernetes
中負載平衡 gRPC
連線的一個簡單解決方案。)
當協議檢測失敗時
雖然協議檢測旨在允許 Linkerd
“just work”
,但在某些情況下它不能:臭名昭著的伺服器優先協議(server-speaks-first
)。 這些協議(包括 MySQL
和 SMTP
)通過讓客戶端建立連線然後等待伺服器響應來工作。從 TCP
的角度來看,這是一種完全合法的行為,但這意味著 Linkerd
無法檢測到協議,因為相關資訊來自伺服器,而不是客戶端。
(為什麼不簡單地使用伺服器的位元組來檢測協議?因為在檢測協議的時候,Linkerd
甚至還沒有建立到伺服器的連線。選擇與哪個伺服器對話是負載均衡器的一個功能,而使用哪個負載均衡器是協議的一個功能。這是一個 delicious
、帶有 TCP-flavored
的“先有雞還是先有蛋(chicken-and-egg
)”問題。)
為了避免這種情況,Linkerd
引入了 skip-inbound-ports
和 skip-outbound-ports
配置選項。 這些選項指示 Linkerd
通過修改 Linkerd
用於通過其 sidecar
代理連線 pod
的 iptables
規則來完全繞過某些埠的代理。例如,將 annotation
config.linkerd.io/skip-outbound-ports: 3306
新增到工作負載的 PodSpec
指示 Linkerd
建立一個 iptables
規則,以確保 Linkerd
代理永遠不會處理到埠 3306
(MySQL
埠)的任何流量 . 同樣,annotation
config.linkerd.io/skip-inbound-ports: 3306
將編寫一個 iptables
規則,以便代理永遠不會處理髮送給它的 MySQL
流量。
Skip Ports 配置
這些選項為 protocol detection
無法處理 server-speaks-first
協議提供了一種解決方法。 然而,它們有一個明顯的缺點:因為它們完全繞過 Linkerd
代理,Linkerd
無法應用 mTLS
或捕獲這些埠的任何指標。
Linkerd 2.10 中的不透明埠和改進的協議檢測
為了解決 skip-ports
的不足,在 2.10
版本中,Linkerd
將新增不透明埠(opaque ports
)的概念(以及相應的 opaque-ports annotation
)。不透明埠就是 Linkerd
將代理而不執行協議檢測的埠。雖然這種方法仍然需要配置,但將埠標記為不透明允許 Linkerd
應用 mTLS
並報告 TCP-level metrics
—— 這比完全跳過它是一個很大的改進。
Opaque Ports 配置
Linkerd 2.10
還將通過使其“fail open”
來改進協議檢測的工作方式:如果協議檢測程式碼在 10 秒後沒有看到客戶端位元組,它會將連線視為 TCP
連線並繼續,而不是像 2.9
那樣失敗 . 這意味著不使用 opaque-ports
(或 skip-ports
)annotating server-speaks-first
埠的最壞情況行為是 10
秒的連線時間延遲,而不是連線失敗。
總結
Protocol detection
是 Linkerd
最強大的功能之一,也是 Linkerd
“just works”
原則的基礎。雖然協議檢測不是萬靈藥,但 Linkerd 2.10
中引入的 opaque-ports
應該解決早期 skip-ports
特性的大部分缺點,並允許 Linkerd
使用者在整個 Kubernetes
環境中擴充套件 mTLS
,而不管協議是什麼。
我是為少
微信:uuhells123
公眾號:黑客下午茶
加我微信(互相學習交流),關注公眾號(獲取更多學習資料~)