Server-Speaks-First 有點(diǎn)坑,Linkerd 2.10 中的協(xié)議檢測和不透明端口
本文轉(zhuǎn)載自微信公眾號「黑客下午茶」,作者為少。轉(zhuǎn)載本文請聯(lián)系黑客下午茶公眾號。
協(xié)議檢測(Protocol detection),顧名思義,允許 Linkerd 自動檢測 TCP 連接中使用的協(xié)議。 Linkerd 的設(shè)計(jì)原則之一是“just work”,協(xié)議檢測是 Linkerd 如何實(shí)現(xiàn)這一目標(biāo)的重要組成部分。
什么是協(xié)議檢測?
簡而言之,協(xié)議檢測是通過檢查連接上的流量來確定 TCP 連接上使用的協(xié)議的能力。
Linkerd 使用 Protocol detection 來避免要求用戶指定協(xié)議。 Linkered 的代理不需要用戶配置每個(gè)端口使用的協(xié)議,而是簡單地執(zhí)行協(xié)議檢測來回答問題。
Linkerd 的 Protocol detection 通過查看客戶端連接的前幾個(gè)字節(jié)來獲取有關(guān)流量的信息來工作。這種實(shí)現(xiàn)有一些后果,我們將在下面介紹。
但首先,讓我們首先回答為什么 Linkerd 關(guān)心任何協(xié)議的問題。
可觀察性、可靠性和安全性
我們通常將 Linkerd 的廣泛功能分為三類:可觀察性(Observability)、可靠性(reliability)和安全性(security)。了解連接(connection)上使用的協(xié)議是每個(gè)類別的基礎(chǔ)。
可觀察性
Linkerd 可觀察性功能的核心是流量檢測。這種儀器需要了解正在使用的協(xié)議,因?yàn)閰f(xié)議的知識可以提供豐富的指標(biāo)。例如,知道連接正在使用 HTTP,Linkerd 就可以解析請求、響應(yīng)和響應(yīng)代碼,并報(bào)告響應(yīng)延遲、請求量和錯誤率等指標(biāo)。這些指標(biāo)非常有價(jià)值,以至于它們成為谷歌 SRE 書中所謂的“黃金信號”的一部分。另一方面,如果 Linkerd 只知道連接是 TCP,則它僅限于記錄非?;镜男畔?,例如讀取和寫入的字節(jié)數(shù)——無法進(jìn)一步解釋字節(jié)。
Linkerd 可觀察特性的核心是流量的測量。這種檢測需要理解正在使用的協(xié)議,因?yàn)閷f(xié)議的了解可以提供豐富的度量。例如,知道一個(gè)連接正在使用 HTTP,就允許 Linkerd 解析請求、響應(yīng)和響應(yīng)代碼,并報(bào)告響應(yīng)延遲、請求量和錯誤率等指標(biāo)。這些指標(biāo)非常有價(jià)值,它們是谷歌的 SRE 書中所謂的“黃金信號”的一部分。另一方面,如果 Linkerd 只知道一個(gè)連接是 TCP,那么它只能記錄非?;镜男畔?,比如讀取和寫入的字節(jié)數(shù)——沒有進(jìn)一步解釋字節(jié)的能力。
安全
雙向 TLS (mTLS) 是 Linkerd 的核心功能。從 Linkerd 2.9 開始,網(wǎng)狀端點(diǎn)(meshed endpoints)之間的所有 TCP 流量默認(rèn)由 Linkerd 代理進(jìn)行 mTLS。(有一些警告 - 請參閱下面有關(guān) skip-ports 的部分。)
在這里,再次了解連接的協(xié)議至關(guān)重要。例如,如果連接已經(jīng)是 TLS 的(例如,通過應(yīng)用程序),則沒有理由重新 TLS。(嚴(yán)格來說,TLS 是一種傳輸層協(xié)議,而不是像 HTTP 那樣的應(yīng)用層協(xié)議,但就本文而言,兩者之間的區(qū)別并不重要。)
可靠性
最后,了解底層連接的協(xié)議允許 Linkerd 提供復(fù)雜的可靠性功能。這里的一個(gè)例子是負(fù)載平衡。在不知道連接協(xié)議的情況下,Linkerd 僅限于平衡連接(balancing connections):一旦與服務(wù)器建立了 TCP 連接,它就無法進(jìn)一步操作該連接。
但是,如果 Linkerd 知道連接是 HTTP,它可以從連接平衡(connection balancing)轉(zhuǎn)移到請求平衡(request balancing)。Linkerd 將建立一個(gè)跨端點(diǎn)的連接池,并平衡這個(gè)池中的請求。由于它現(xiàn)在可以訪問 requests 和 responses,Linkerd 在平衡請求方面可以非常復(fù)雜;事實(shí)上,它根據(jù)每個(gè)可能端點(diǎn)的最近性能(使用稱為“指數(shù)加權(quán)移動平均(exponentially weighted moving average)”或 EWMA 的指標(biāo))來平衡請求,以避免從慢速端點(diǎn)引起尾部延遲(tail latency)。
( Linkerd 也是 Kubernetes 中負(fù)載平衡 gRPC 連接的一個(gè)簡單解決方案。)
當(dāng)協(xié)議檢測失敗時(shí)
雖然協(xié)議檢測旨在允許 Linkerd “just work”,但在某些情況下它不能:臭名昭著的服務(wù)器優(yōu)先協(xié)議(server-speaks-first)。這些協(xié)議(包括 MySQL 和 SMTP)通過讓客戶端建立連接然后等待服務(wù)器響應(yīng)來工作。從 TCP 的角度來看,這是一種完全合法的行為,但這意味著 Linkerd 無法檢測到協(xié)議,因?yàn)橄嚓P(guān)信息來自服務(wù)器,而不是客戶端。
(為什么不簡單地使用服務(wù)器的字節(jié)來檢測協(xié)議?因?yàn)樵跈z測協(xié)議的時(shí)候,Linkerd 甚至還沒有建立到服務(wù)器的連接。選擇與哪個(gè)服務(wù)器對話是負(fù)載均衡器的一個(gè)功能,而使用哪個(gè)負(fù)載均衡器是協(xié)議的一個(gè)功能。這是一個(gè) delicious、帶有 TCP-flavored 的“先有雞還是先有蛋(chicken-and-egg)”問題。)
為了避免這種情況,Linkerd 引入了 skip-inbound-ports 和 skip-outbound-ports 配置選項(xiàng)。這些選項(xiàng)指示 Linkerd 通過修改 Linkerd 用于通過其 sidecar 代理連接 pod 的 iptables 規(guī)則來完全繞過某些端口的代理。例如,將 annotation config.linkerd.io/skip-outbound-ports: 3306 添加到工作負(fù)載的 PodSpec 指示 Linkerd 創(chuàng)建一個(gè) iptables 規(guī)則,以確保 Linkerd 代理永遠(yuǎn)不會處理到端口 3306(MySQL 端口)的任何流量 . 同樣,annotation config.linkerd.io/skip-inbound-ports: 3306 將編寫一個(gè) iptables 規(guī)則,以便代理永遠(yuǎn)不會處理發(fā)送給它的 MySQL 流量。
Skip Ports 配置
這些選項(xiàng)為 protocol detection 無法處理 server-speaks-first 協(xié)議提供了一種解決方法。然而,它們有一個(gè)明顯的缺點(diǎn):因?yàn)樗鼈兺耆@過 Linkerd 代理,Linkerd 無法應(yīng)用 mTLS 或捕獲這些端口的任何指標(biāo)。
Linkerd 2.10 中的不透明端口和改進(jìn)的協(xié)議檢測
為了解決 skip-ports 的不足,在 2.10 版本中,Linkerd 將添加不透明端口(opaque ports)的概念(以及相應(yīng)的 opaque-ports annotation)。不透明端口就是 Linkerd 將代理而不執(zhí)行協(xié)議檢測的端口。雖然這種方法仍然需要配置,但將端口標(biāo)記為不透明允許 Linkerd 應(yīng)用 mTLS 并報(bào)告 TCP-level metrics —— 這比完全跳過它是一個(gè)很大的改進(jìn)。
Opaque Ports 配置
Linkerd 2.10 還將通過使其“fail open”來改進(jìn)協(xié)議檢測的工作方式:如果協(xié)議檢測代碼在 10 秒后沒有看到客戶端字節(jié),它會將連接視為 TCP 連接并繼續(xù),而不是像 2.9 那樣失敗 . 這意味著不使用 opaque-ports(或 skip-ports)annotating server-speaks-first 端口的最壞情況行為是 10 秒的連接時(shí)間延遲,而不是連接失敗。
總結(jié)
Protocol detection 是 Linkerd 最強(qiáng)大的功能之一,也是 Linkerd “just works” 原則的基礎(chǔ)。雖然協(xié)議檢測不是萬靈藥,但 Linkerd 2.10 中引入的 opaque-ports 應(yīng)該解決早期 skip-ports 特性的大部分缺點(diǎn),并允許 Linkerd 使用者在整個(gè) Kubernetes 環(huán)境中擴(kuò)展 mTLS,而不管協(xié)議是什么。
Refs
- Protocol Detection and Opaque Ports in Linkerd
https://linkerd.io/2021/02/23/protocol-detection-and-opaque-ports-in-linkerd