詳細瞭解 Linkerd 2.10 基礎功能,一起步入 Service Mesh 微服務架構時代

為少發表於2021-06-12

Linkerd 提供了許多功能,如:自動 mTLS自動代理注入分散式追蹤故障注入高可用性HTTP/2 和 gRPC 代理負載均衡多叢集通訊重試和超時遙測和監控流量拆分(金絲雀、藍/綠部署)等。

Linkerd 2.10 中文手冊持續修正更新中:

Linkerd 2.10 系列

功能概述

  • 自動 mTLS:Linkerd 自動為網格應用程式之間的所有通訊啟用相互傳輸層安全性 (TLS)。
  • 自動代理注入:Linkerd 會自動將資料平面代理注入到基於 annotations 的 pod 中。
  • 容器網路介面外掛:Linkerd 能被配置去執行一個 CNI 外掛,該外掛自動重寫每個 pod 的 iptables 規則。
  • 儀表板和 Grafana:Linkerd 提供了一個 Web 儀表板,以及預配置的 Grafana 儀表板。
  • 分散式追蹤:您可以在 Linkerd 中啟用分散式跟蹤支援。
  • 故障注入:Linkerd 提供了以程式設計方式將故障注入服務的機制。
  • 高可用性:Linkerd 控制平面可以在高可用性 (HA) 模式下執行。
  • HTTP、HTTP/2 和 gRPC 代理:Linkerd 將自動為 HTTP、HTTP/2 和 gRPC 連線啟用高階功能(包括指標、負載平衡、重試等)。
  • Ingress:Linkerd 可以與您選擇的 ingress controller 一起工作。
  • 負載均衡:Linkerd 會自動對 HTTP、HTTP/2 和 gRPC 連線上所有目標端點的請求進行負載平衡。
  • 多叢集通訊:Linkerd 可以透明且安全地連線執行在不同叢集中的服務。
  • 重試和超時:Linkerd 可以執行特定於服務的重試和超時。
  • 服務配置檔案:Linkerd 的服務配置檔案支援每條路由指標以及重試和超時。
  • TCP 代理和協議檢測:Linkerd 能夠代理所有 TCP 流量,包括 TLS 連線、WebSockets 和 HTTP 隧道。
  • 遙測和監控:Linkerd 會自動從所有通過它傳送流量的服務收集指標。
  • 流量拆分(金絲雀、藍/綠部署):Linkerd 可以動態地將一部分流量傳送到不同的服務。

HTTP、HTTP/2 和 gRPC 代理

Linkerd 可以代理所有 TCP 連線,並將自動為 HTTP、HTTP/2 和 gRPC 連線
啟用高階功能(包括指標、負載平衡、重試等)。

  • 由於早期版本中的 bug,使用 grpc-go 的 gRPC 應用程式必須使用 1.3 或更高版本。
  • 由於早期版本中的 bug,使用 @grpc/grpc-js 的 gRPC 應用程式必須使用 1.1.0 或更高版本。

TCP 代理和協議檢測

Linkerd 能夠代理所有 TCP 流量,包括 TLS 連線、WebSockets 和 HTTP 隧道。

大多數情況下,Linkerd 無需配置即可完成此操作。
為此,Linkerd 執行 protocol detection(協議檢測) 以確定
流量是 HTTP 還是 HTTP/2(包括 gRPC)。如果 Linkerd 檢測到連線
是 HTTP 或 HTTP/2,Linkerd 將自動提供 HTTP 級別的指標(metrics)和路由(routing)。

如果 Linkerd 不能確定連線是使用 HTTP 還是 HTTP/2,
Linkerd 會將連線代理為普通 TCP 連線,
應用 mTLS 並像往常一樣提供位元組級指標(byte-level metrics)。

客戶端啟動的 HTTPS(Client-initiated HTTPS) 將被視為 TCP,而不是 HTTP,
因為 Linkerd 將無法觀察連線上的 HTTP 事務。

配置協議檢測

在某些情況下,Linkerd 的協議檢測無法執行,
因為它沒有提供足夠的客戶端資料。
這可能會導致建立連線延遲 10 秒,
因為協議檢測程式碼會等待更多資料。
在使用“伺服器優先(server-speaks-first)”協議或伺服器
在客戶端傳送資料之前傳送資料的協議時,經常會遇到這種情況 ,
可以通過為 Linkerd 提供一些額外的配置來避免。

不管底層協議是什麼,客戶端發起的 TLS 連線不需要任何額外的配置,
因為 TLS 本身是一個客戶端優先協議(client-speaks-first)。

配置協議檢測有兩種基本機制:
不透明埠(opaque ports)和跳過埠(skip ports)。
將埠標記為不透明(opaque)會指示 Linkerd 將連線代理為 TCP 流,而不是嘗試協議檢測。
將埠標記為跳過(skip)會完全繞過代理。
不透明埠通常是首選(因為 Linkerd 可以提供 mTLS、TCP 級別的指標等),
但至關重要的是,不透明埠只能用於叢集內部的服務。

預設情況下,Linkerd 會自動將一些埠標記為不透明,
包括 SMTP、MySQL、PostgresQL 和 Memcache 的預設埠。
使用這些協議、使用預設埠且位於叢集內部的服務不需要進一步配置。

下表總結了一些常見的 server-speaks-first 協議以及處理它們所需的配置。
“on-cluster config” 列指的是 destination 在同一個叢集時的配置;
當目的地在叢集外部時,“叢集外配置(off-cluster config)”。

Protocol Default port(s) On-cluster config Off-cluster config
SMTP 25, 587 none* skip ports
MySQL 3306 none* skip ports
MySQL with Galera replication 3306, 4444, 4567, 4568 opaque ports for 3306, 4444; and skip ports for 4567, 4568 skip ports
PostgreSQL 5432 none* skip ports
Redis 6379 opaque ports skip ports
ElasticSearch 9300 opaque ports skip ports
Memcache 11211 none* skip ports

* 如果使用標準埠,則無需配置。如果使用非標準埠,則必須將該埠標記為不透明(opaque)。

將埠標記為不透明

您可以使用 config.linkerd.io/opaque-ports 註釋將埠標記為不透明。
這指示 Linkerd 跳過該埠的協議檢測。

可以在工作負載(workload)、服務(service)或
名稱空間(namespace)上設定此註釋。
在工作負載上設定它會告訴該工作負載的
被 mesh 的客戶端(meshed clients)跳過與工作負載建立的連線的協議檢測,
並告訴 Linkerd 在反向代理(reverse-proxying)傳入連線時跳過協議檢測。
在服務上設定它會告訴被 mesh 的客戶端(meshed clients)在代理連線到服務時跳過協議檢測。
在名稱空間上設定它會將此行為應用於該名稱空間中的所有服務和工作負載。

由於此 annotation 通知被 mesh 的 clients 的行為,
因此它可以應用於使用伺服器優先(server-speaks-first)協議的服務,即使服務本身沒有被網格。

可以在執行 linkerd inject 時使用 --opaque-ports 標誌來
設定 opaque-ports annotation。
例如,對於執行在叢集上的 MySQL 資料庫使用
非標準埠 4406,您可以使用以下命令:

linkerd inject mysql-deployment.yml --opaque-ports=4406 \
  | kubectl apply -f -
 linkerd inject mysql-service.yml --opaque-ports=4406 \
  | kubectl apply -f -

可以以逗號分隔的字串形式提供多個埠。
您提供的值將替換而不是增加不透明埠的預設列表。

跳過代理

有時需要完全繞過代理。例如,當連線到叢集外的 server-speaks-first 目的地時,
沒有可以設定 config.linkerd.io/opaque-ports annotation 的服務資源。

在這種情況下,您可以在執行 linkerd inject
使用 --skip-outbound-ports 標誌來配置資源以在
傳送到這些埠時完全繞過代理。(類似地,--skip-inbound-ports 標誌將
配置資源以繞過代理以連線到這些埠的傳入連線。)

跳過代理對於這些情況以及診斷問題很有用,但除此之外幾乎沒有必要。

與不透明埠一樣,可以以逗號分隔的字串形式提供多個跳過埠。

重試和超時

自動重試是服務網格用於優雅地處理部分或瞬時應用程式故障的最強大和最有用的機制之一。
如果實施不當,重試可能會將小錯誤放大為系統範圍的中斷。
出於這個原因,我們確保它們的實施方式可以提高系統的可靠性,同時限制風險。

超時與重試密切相關。一旦請求被重試一定次數,
限制客戶端在完全放棄之前等待的總時間就變得很重要。
想象多次重試迫使客戶端等待 10 秒。

服務配置檔案可以將某些路由定義為可重試或指定路由超時。
這將導致 Linkerd 代理在呼叫該服務時執行適當的重試或超時。
重試和超時總是在 outbound (client) 端執行。

如果使用無頭服務(headless services),則無法檢索服務配置檔案(service profiles)。
Linkerd 根據目標 IP 地址讀取服務發現資訊,
如果這恰好是 pod IP 地址,則它無法判斷 pod 屬於哪個服務。

重試如何出錯

傳統上,在執行重試時,您必須在放棄之前指定最大重試次數。
不幸的是,以這種方式配置重試有兩個主要問題。

選擇最大重試次數是一個猜謎遊戲

你需要選擇一個足夠高的數字來產生影響;
允許多次重試通常是謹慎的,如果您的服務不太可靠,您可能希望允許多次重試。
另一方面,允許過多的重試嘗試會在系統上產生大量額外的請求和額外的負載。
執行大量重試也會嚴重增加需要重試的請求的延遲。
在實踐中,您通常會從一頂帽子中選擇一個最大的重試次數(3?),
然後通過反覆試驗來調整它,直到系統大致按照您希望的方式執行。

以這種方式配置的系統容易受到重試風暴的攻擊

當一項服務啟動(出於任何原因)遇到比正常故障率更高的故障率時,
retry storm 就開始了。
這會導致其客戶端重試那些失敗的請求。
重試帶來的額外負載會導致服務進一步減慢速度並導致更多請求失敗,
從而觸發更多重試。如果將每個客戶端配置為最多重試 3 次,
則傳送的請求數量可能會增加四倍!更糟糕的是,
如果任何客戶端的客戶端配置了重試,重試次數就會成倍增加,
並且可以將少量錯誤變成自我造成的拒絕服務攻擊。

重試預算來救援

為了避免重試風暴和任意重試次數的問題,使用重試預算配置重試。
Linkerd 不是為每個請求指定固定的最大重試次數,
而是跟蹤常規請求和重試之間的比率,並將此數量保持在可配置的限制以下。
例如,您可以指定您希望重試最多增加 20% 的請求。
Linkerd 將在保持該比率的同時儘可能多地重試。

配置重試總是在提高成功率和不給系統增加太多額外負載之間進行權衡。
重試預算通過讓您指定系統願意從重試中接受多少額外負載來明確權衡。

自動 mTLS

預設情況下,Linkerd 通過在 Linkerd 代理之間建立和驗證安全的私有 TLS 連線,
為網狀 Pod 之間的大多數 TCP 流量自動啟用相互傳輸層安全性 (mTLS)。
這意味著 Linkerd 可以向您的應用程式新增經過身份驗證的加密通訊,
而您只需做很少的工作。由於 Linkerd 控制平面也在資料平面上執行,
這意味著 Linkerd 控制平面元件之間的通訊也通過 mTLS 自動保護。

它是如何工作的?

簡而言之,Linkerd 的控制平面向代理頒發 TLS 證書,
這些證書的範圍限定為包含 Pod 的
Kubernetes ServiceAccount
並每 24 小時自動輪換一次。代理使用這些證書來加密和驗證到其他代理的 TCP 流量。

為此,Linkerd 在叢集中維護了一組憑據:信任錨(trust anchor)、
頒發者證書(issuer certificate)和私鑰(private key)。
這些憑據在安裝時由 Linkerd 本身生成,或者由外部源
(例如 Vault
cert-manager
頒發者證書和私鑰放置在
Kubernetes Secret 中。
預設情況下,Secret 放置在 linkerd 名稱空間中,
並且只能由 Linkerd 控制平面 的 identity 元件使用的服務帳戶讀取。

在資料平面方面,每個代理都在環境變數中傳遞信任錨(trust anchor)。
在啟動時,代理會生成一個私鑰,
儲存在
tmpfs emptyDir
中,該私鑰留在記憶體中並且永遠不會離開 pod。
代理連線到控制平面的身份(identity)元件,驗證與信任錨的身份(identity)連線,
併發出證書籤名請求 (CSR)
CSR 包含一個初始證書,其身份設定為 pod 的
Kubernetes ServiceAccount
以及實際的服務帳戶令牌,以便該身份可以驗證 CSR 是否有效。
驗證後,簽名的信任包將返回給代理,代理可以將其用作客戶端和伺服器證書。
這些證書的範圍為 24 小時,並使用相同的機制動態重新整理。

當注入 Pod 的代理從應用程式容器接收到出站連線時,
它會通過使用 Linkerd 控制平面查詢該 IP 地址來執行服務發現。
當目的地在 Kubernetes 叢集中時,控制平面為代理提供目的地的端點地址以及後設資料。
當身份名稱包含在此後設資料中時,這向代理表明它可以啟動雙向 TLS。
當代理連線到目標時,它會發起 TLS 握手,驗證目標代理的證書是否已針對預期的身份名稱進行簽名。

維護

linkerd install 生成的信任錨在 365 天后過期,
必須手動輪換
或者,您可以自己提供信任錨並控制到期日期。

預設情況下,頒發者證書和金鑰不會自動輪換。
您可以使用 cert-manager 設定自動輪換

注意事項和未來工作

Linkeder 自動加密和驗證叢集中所有通訊的能力存在一些已知的缺陷。
這些缺口將在以後的版本中修復:

  • Linkerd 目前不強制執行 mTLS。網格內的任何未加密請求都將隨機升級到 mTLS。
    Linkerd 不會自動對來自網格內部或外部的任何請求進行 mTLS。
    這將在未來的 Linkerd 版本中解決,可能作為選擇加入行為,
    因為它可能會破壞一些現有的應用程式。

  • 理想情況下,Linkerd 使用的 ServiceAccount 令牌不會
    與該令牌的其他潛在用途共享。
    在未來的 Kubernetes 版本中,Kubernetes 將
    支援 audience/time-bound 的 ServiceAccount 令牌,
    Linkerd 將使用這些令牌。

Ingress

為簡單起見,Linkerd 沒有提供自己的 ingress controller。
相反,Linkerd 旨在與您選擇的 ingress controller 一起工作。

遙測和監控

Linkerd 最強大的功能之一是其圍繞可觀察性(observability)的廣泛工具集—
在網格應用程式中測量和報告觀察到的行為。
雖然 Linkerd 沒有直接洞察服務程式碼的內部結構,
但它對服務程式碼的外部行為有著巨大的洞察力。

要訪問 Linkerd 的可觀察性功能,您只需要安裝 Viz 擴充套件:

linkerd viz install | kubectl apply -f -

Linkerd 的遙測和監控功能會自動執行,無需開發人員進行任何工作。這些功能包括:

  • 記錄 HTTP、HTTP/2 和 gRPC 流量的頂級(“黃金”)指標(請求量、成功率和延遲分佈)。
  • 記錄其他 TCP 流量的 TCP 級別指標(輸入/輸出位元組等)。
  • 報告每個服務、每個呼叫方(caller)/被呼叫方(callee)對或每個路由/路徑(使用服務配置檔案)的指標。
  • 生成拓撲圖,顯示服務之間的執行時關係。
  • 實時、按需請求取樣。

可以通過多種方式使用這些資料:

  • 通過 Linkerd CLI,
    例如:使用 linkerd viz statlinkerd viz routes
  • 通過 Linkerd dashboard 和 pre-built Grafana dashboards。
  • 直接來自 Linkerd 的內建 Prometheus 例項

黃金指標

成功率

這是一個時間視窗(預設為 1 分鐘)內成功請求的百分比。

在命令 linkerd viz routes -o wide 的輸出中,
此度量分為 EFFECTIVE_SUCCESS 和 ACTUAL_SUCCESS。
對於配置了重試的路由,前者計算重試後的成功百分比(客戶端感知),
後者計算重試前的成功率(可能暴露服務的潛在問題)。

流量(每秒請求數)

這概述了對 service/route 的需求量。
與成功率一樣,linkerd viz routes --o wide 將此指標
拆分為 EFFECTIVE_RPS 和 ACTUAL_RPS,分別對應於重試前後的比率。

延遲

每個 service/route 的服務請求所花費的時間分為第 50、95 和 99 個百分位數。
較低的百分位數可讓您大致瞭解系統的平均效能,而尾部百分位數有助於捕捉異常行為。

Linkerd 指標的生命週期

Linkerd 並非設計為長期歷史指標儲存。
雖然 Linkerd 的 Viz 擴充套件確實包含一個 Prometheus 例項,
但該例項會在很短的固定時間間隔(目前為 6 小時)內使指標過期。

相反,Linkerd 旨在補充(supplement)您現有的指標儲存。
如果 Linkerd 的指標有價值,您應該將它們匯出到您現有的歷史指標儲存中。

負載均衡

對於 HTTP、HTTP/2 和 gRPC 連線,
Linkerd 會自動在所有目標端點之間對請求進行負載平衡,無需任何配置。
(對於 TCP 連線,Linkerd 會平衡連線。)

Linkerd 使用一種稱為 EWMA 或
指數加權移動平均(exponentially weighted moving average)的演算法來自動將請求傳送到最快的端點。
這種負載平衡可以改善端到端(end-to-end)延遲。

服務發現

對於不在 Kubernetes 中的目的地,Linkerd 將在 DNS 提供的端點之間進行平衡。

對於 Kubernetes 中的目的地,Linkerd 將在 Kubernetes API 中查詢 IP 地址。
如果 IP 地址對應於一個服務,Linkerd 將在該服務的端點之間進行負載平衡,
並應用該服務的服務配置檔案中的任何策略。
另一方面,如果 IP 地址對應一個 Pod,
Linkerd 將不會執行任何負載均衡或應用任何服務配置檔案。

如果使用無頭服務(headless services),則無法檢索服務的端點。
因此,Linkerd 不會執行負載均衡,而是隻路由到目標 IP 地址。

負載均衡 gRPC

Linkerd 的負載均衡對於 Kubernetes 中的 gRPC(或 HTTP/2)服務特別有用,
對於這些服務,Kubernetes 的預設負載均衡是無效的

自動代理注入

當名稱空間或任何工作負載(例如部署或 Pod)上存在
linkerd.io/inject: enabled annotation 時,
Linkerd 會自動將資料平面代理新增到 Pod。這稱為“代理注入(proxy injection)”。

代理注入也是代理配置發生的地方。
雖然很少需要,但您可以通過在注入之前在資源級別
設定額外的 Kubernetes annotations 來配置代理設定。

細節

代理注入是作為 Kubernetes admission
webhook
實現的。
這意味著代理會新增到 Kubernetes 叢集本身內的 pod 中,
而不管 pod 是由 kubectl、CI/CD 系統還是任何其他系統建立的。

對於每個 pod,注入兩個容器:

  1. linkerd-init,一個 Kubernetes Init
    Container
    ,它配置 iptables 以通過代理自動轉發所有傳入和傳出的 TCP 流量。
    (請注意,如果 Linkerd CNI Plugin 已啟用,則此容器不存在。)
  2. linkerd-proxy,Linkerd 資料平面代理本身。

請注意,簡單地將 annotation 新增到具有預先存在的 pod 的資源不會自動注入這些 pod。
您將需要更新 pod(例如使用 kubectl rollout restart 等)以便注入它們。
這是因為 Kubernetes 在需要更新底層資源之前不會呼叫 webhook。

覆蓋注入

通過新增 linkerd.io/inject: disabled annotation,
可以為 pod 或部署禁用自動注入,否則將為其啟用。

手動注入

linkerd inject CLI 命令是一個文字轉換,
預設情況下,它只是將 inject annotation 新增到給定的 Kubernetes 清單。

或者,這個命令也可以使用 --manual 標誌在客戶端執行完全注入。
這是 Linked2.4 之前的預設行為;
但是,向叢集側注入資料可以更容易地確保
資料平面始終存在並正確配置,而不管 pod 是如何部署的。

容器網路介面外掛

Linkerd installs 可以配置去執行一個
CNI plugin
該外掛自動重寫每個 pod 的 iptables 規則。
通過 pod 的 linkerd-proxy 容器路由網路流量需要重寫 iptables。
啟用 CNI 外掛後,單個 Pod 不再需要包含需要 NET_ADMIN 功能來執行重寫的 init 容器。
這在叢集管理員限制該功能的叢集中很有用。

安裝

使用 Linkerd CNI 外掛需要先在叢集上成功安裝 linkerd-cni DaemonSet,
然後再安裝 Linkerd 控制平面。

使用 CLI

要安裝 linkerd-cni DaemonSet,請執行:

linkerd install-cni | kubectl apply -f -

一旦 DaemonSet 啟動並執行,所有包含 linkerd-proxy 容器(包括 Linkerd 控制平面)
的後續安裝都不再需要包含 linkerd-init 容器。
init 容器的省略由控制平面安裝時的 --linkerd-cni-enabled 標誌控制。

安裝 Linkerd 控制平面,使用:

linkerd install --linkerd-cni-enabled | kubectl apply -f -

這將在 linkerd-config ConfigMap 中設定 cniEnabled 標誌。
所有後續代理注入都將讀取此欄位並省略 init 容器。

使用 Helm

首先確保您的 Helm 本地快取已更新:

helm repo update

helm search linkerd2-cni
NAME                      CHART VERSION  APP VERSION    DESCRIPTION
linkerd-edge/linkerd2-cni   20.1.1       edge-20.1.1    A helm chart containing the resources needed by the Linke...
linkerd-stable/linkerd2-cni  2.7.0       stable-2.7.0   A helm chart containing the resources needed by the Linke...

執行以下命令安裝 CNI DaemonSet:

# install the CNI plugin first
helm install linkerd2-cni linkerd2/linkerd2-cni

# ensure the plugin is installed and ready
linkerd check --pre --linkerd-cni-enabled

對於低於 v3 的 Helm 版本,必須專門傳遞 --name 標誌。
在 Helm v3 中,它已被棄用,並且是上面指定的第一個引數。

此時,您已準備好在啟用 CNI 的情況下安裝 Linkerd。
您可以按照使用 Helm 安裝 Linkerd 來執行此操作。

附加配置

linkerd install-cni 命令包括可用於自定義安裝的附加標誌。
有關更多資訊,請參閱 linkerd install-cni --help
請注意,許多標誌類似於執行 linkerd 注入時可用於配置代理的標誌。
如果在執行 linkerd install-cni 時更改了預設值,
則需要確保在執行 linkerd inject 時進行相應的更改。

最重要的標誌是:

  1. --dest-cni-net-dir: 這是 CNI 配置所在節點上的目錄。 預設為: /etc/cni/net.d
  2. --dest-cni-bin-dir: 這是 CNI 外掛二進位制檔案所在的節點上的目錄。預設為:/opt/cni/bin
  3. --cni-log-level: 將此設定為 debug 將允許更詳細的日誌記錄。
    要檢視 CNI 外掛日誌,您必須能夠檢視 kubelet 日誌。
    一種方法是登入節點並使用 journalctl -t kubelet
    字串 linkerd-cni: 可用作查詢外掛日誌輸出的搜尋。

升級 CNI 外掛

由於 CNI 外掛基本上是無狀態的,因此不需要單獨的 upgrade 命令。
如果您使用 CLI 升級 CNI 外掛,您可以執行以下操作:

linkerd install-cni   | kubectl apply --prune -l  linkerd.io/cni-resource=true -f -

請記住,如果您是從實驗版本(experimental version)升級外掛,則需要解除安裝並重新安裝。

儀表板和 Grafana

除了命令列介面,
Linkerd 還提供了一個 Web 儀表板和預配置的 Grafana 儀表板。

要訪問此功能,您需要安裝 Viz 擴充套件:

linkerd viz install | kubectl apply -f -

Linkerd 儀表板

Linkerd 儀表板提供實時服務發生情況的高階檢視。
它可用於檢視“黃金”指標(成功率、請求/秒和延遲)、
視覺化服務依賴關係並瞭解特定服務路由的健康狀況。
拉起它的一種方法是從命令列執行 linkerd viz dashboard

Grafana

作為控制平面的一個元件,Grafana 為您的服務提供開箱即用的可操作儀表板。
可以檢視高階指標並深入瞭解細節,甚至是 pod。

開箱即用的儀表板包括:

Top Line Metrics

Deployment Detail

Pod Detail

Linkerd Health

分散式追蹤

跟蹤可以成為除錯分散式系統效能的寶貴工具,
尤其是用於識別瓶頸和了解系統中每個元件的延遲成本。
Linkerd 可以配置為從代理髮出跟蹤跨度,
允許您準確檢視請求和響應在內部花費的時間。

與 Linkerd 的大多數功能不同,分散式跟蹤需要更改程式碼和配置。

此外,Linkerd 提供了許多通常與分散式跟蹤相關的功能,無需配置或應用程式更改,包括:

  • 實時服務拓撲和依賴關係圖
  • 聚合服務執行狀況、延遲和請求量
  • 聚合 path / route 執行狀況、延遲和請求量

例如,Linkerd 可以顯示服務的所有傳入和傳出依賴項的實時拓撲,
而無需分散式跟蹤或任何其他此類應用程式修改:

Linkerd 儀表板顯示自動生成的拓撲圖

同樣,Linkerd 可以為每個服務和每個 route 提供黃金指標,
同樣不需要分散式跟蹤或任何其他此類應用程式修改:

Linkerd 儀表板顯示自動生成的路由指標

使用分散式跟蹤

也就是說,分散式跟蹤肯定有其用途,Linkerd 使這儘可能簡單。
Linkerd 在分散式跟蹤中的作用實際上非常簡單:
當 Linkerd 資料平面代理(data plane proxy)在代理的 HTTP 請求中
看到跟蹤頭(tracing header)時,
Linkerd 將為該請求發出跟蹤範圍(trace span)。
此跨度將包括有關在 Linkerd 代理中花費的確切時間量的資訊。
當與軟體配合使用來收集、儲存和分析這些資訊時,
這可以提供對 mesh 行為的重要洞察。

要使用此功能,您還需要引入幾個額外的系統中的元件,
包括啟動特定請求跟蹤的入口層(ingress layer)、
應用程式的客戶端庫(或傳播跟蹤頭的機制)、
收集跨度資料並將其轉換為跟蹤的跟蹤收集器,
以及跟蹤後端儲存跟蹤資料並允許使用者檢視/查詢它。

故障注入

故障注入是混沌工程的一種形式,通過人為地增加服務的錯誤率來觀察對整個系統的影響。
傳統上,這需要修改服務的程式碼,以新增一個執行實際工作的錯誤注入庫。
Linkeder 可以做到這一點,而不需要任何服務程式碼更改,只需要一點配置。

高可用性

對於生產工作負載,Linkerd 的控制平面可以在高可用性 (HA) 模式下執行。 這種模式:

  • 執行關鍵控制平面元件的三個副本。
  • 在控制平面元件上設定生產就緒(production-ready) CPU 和記憶體資源請求。
  • 在資料平面代理上設定生產就緒的 CPU 和記憶體資源請求
  • 要求 proxy auto-injector 可用於任何要排程的 pod。
  • 在關鍵控制平面元件上設定反關聯性策略(anti-affinity
    policies)

    以確保在可能的情況下,預設情況下將它們安排在單獨的節點和單獨的區域中。

啟用 HA

您可以在控制平面安裝時使用 --ha 標誌啟用 HA 模式:

linkerd install --ha | kubectl apply -f -

另請注意,視覺化擴充套件還支援具有類似特徵的 --ha 標誌:

linkerd viz install --ha | kubectl apply -f -

您可以在安裝時通過將其他標誌傳遞給 install 命令來覆蓋 HA 行為的某些方面。
例如,您可以使用 --controller-replicas 標誌覆蓋關鍵元件的副本數:

linkerd install --ha --controller-replicas=2 | kubectl apply -f -

請參閱完整的 install CLI 文件以供參考。

linkerd upgrade 命令可用於在現有控制平面上啟用 HA 模式:

linkerd upgrade --ha | kubectl apply -f -

代理注入器故障策略

HA 代理注入器(proxy injector)部署了更嚴格的故障策略(failure policy),
以強制執行 automatic proxy injection。
此設定可確保在沒有 Linkerd 代理的情況下,
不會意外安排帶註解的工作負載在您的叢集上執行。(當代理注入器關閉時可能會發生這種情況。)

如果在准入階段由於無法識別或超時錯誤導致代理注入過程失敗,
則工作負載准入將被 Kubernetes API 伺服器拒絕,部署將失敗。

因此,始終至少有一個執行在叢集上的代理注入器的健康副本非常重要。

如果您不能保證叢集上健康的代理注入器的數量,
您可以通過將其值設定為 Ignore 來放鬆 webhook 故障策略,如 Linkerd
Helm chart
所示。

有關准入 webhook 失敗策略的更多資訊,請參閱 Kubernetes
documentation

排除 kube-system 名稱空間

根據 Kubernetes documentation

的建議,應該為 kube-system 名稱空間禁用代理注入器。

這可以通過使用以下標籤標記 kube-system 名稱空間來完成:

kubectl label namespace kube-system config.linkerd.io/admission-webhooks=disabled

在具有此標籤的名稱空間中工作負載的准入階段,Kubernetes API 伺服器不會呼叫代理注入器。

Pod 反關聯規則

所有關鍵控制平面元件都部署了 pod 反關聯性(anti-affinity)規則以確保冗餘。

Linkerd 使用 requiredDuringSchedulingIgnoredDuringExecution pod anti-affinity 規則
來確保 Kubernetes 排程程式不會將關鍵元件的副本並置在同一節點上。
還新增了一個 preferredDuringSchedulingIgnoredDuringExecution pod anti-affinity 規則,
以嘗試在可能的情況下在不同區域中安排副本。

為了滿足這些反關聯(anti-affinity)規則,HA 模式假設 Kubernetes 叢集中始終至少有三個節點。
如果違反此假設(例如,叢集縮小到兩個或更少的節點),則系統可能會處於非功能(non-functional)狀態。

請注意,這些反關聯性規則不適用於 Prometheus 和 Grafana 等附加元件。

縮放 Prometheus

Linkerd Viz 擴充套件提供了一個預配置的 Prometheus pod,但對於生產工作負載,
我們建議設定您自己的 Prometheus 例項。

在規劃儲存 Linkerd 時間序列資料的記憶體容量時,通常的指導是每個網格 pod 5MB。

如果您的 Prometheus 由於來自資料平面的資料量而遇到定期 OOMKilled 事件,
則可以調整的兩個關鍵引數是:

  • storage.tsdb.retention.time 定義將取樣保留多長時間。
    更高的值意味著需要更多的記憶體來將資料儲存更長時間。
    降低此值將減少 OOMKilled 事件的數量,因為資料保留的時間較短
  • storage.tsdb.retention.size 定義可以為塊儲存的最大位元組數。
    較低的值也將有助於減少 OOMKilled 事件的數量

使用 Cluster AutoScaler

Linkerd 代理將其 mTLS 私鑰儲存在
tmpfs emptyDir 卷中,
以確保此資訊永遠不會離開 pod。
這會導致 Cluster AutoScaler 的預設設定無法縮小具有注入工作負載副本的節點。

解決方法是使用 cluster-autoscaler.kubernetes.io/safe-to-evict: "true" annotation 來注入工作負載。
如果您可以完全控制 Cluster AutoScaler 配置,
則可以使用 --skip-nodes-with-local-storage=false 選項啟動 Cluster AutoScaler。

多叢集通訊

Linkerd 可以以安全、對應用程式完全透明且獨立於網路拓撲的方式
跨叢集邊界連線 Kubernetes 服務。這種多叢集功能旨在提供:

  1. 統一的信任域。 在叢集邊界內和跨叢集邊界的每一步都驗證源和目標工作負載的身份。
  2. 單獨的故障域。 一個叢集的故障允許剩餘的叢集執行。
  3. 支援異構網路。 由於叢集可以跨越雲、VPC、本地資料中心及其組合,
    Linkerd 不會引入除閘道器連線(gateway connectivity)之外的任何 L3/L4 要求。
  4. 叢集通訊中的統一模型。 Linkerd 為叢集內通訊提供的可觀測性(observability)、可靠性(reliability)
    和安全特性(security)也擴充套件到了跨叢集通訊。

就像叢集內連線一樣,Linkerd 的跨叢集連線對應用程式程式碼是透明的。
無論通訊發生在叢集內、資料中心或 VPC 內的叢集之間,
還是通過公共網際網路,Linkerd 都會在叢集之間建立連線,
該連線在雙方都使用 mTLS 進行加密和身份驗證。

工作原理

Linkerd 的多叢集支援通過在叢集之間“映象(mirroring)”服務資訊來工作。
由於遠端服務被表示為 Kubernetes 服務,
Linkerd 的完整可觀察性、安全性和路由功能統一
適用於叢集內和叢集呼叫,應用程式不需要區分這些情況。

Linkerd 的多叢集功能由兩個元件實現:服務映象(service mirror)和閘道器(gateway)。
服務映象(service mirror)元件監視目標叢集中的服務更新,並在源叢集上本地映象這些服務更新。
這提供了對目標叢集的服務名稱的可見性,以便應用程式可以直接定址它們。
多叢集閘道器元件為目標叢集提供了一種從源叢集接收請求的方式。(這允許 Linkerd 支援分層網路)

安裝這些元件後,可以將與標籤選擇器(label selector)匹配的 Kubernetes Service 資源匯出到其他叢集。

服務配置檔案

服務配置檔案是一種自定義 Kubernetes 資源 (CRD),
可以提供有關服務的 Linkerd 附加資訊。
特別是,它允許您定義服務的路由列表。
每個路由都使用一個正規表示式來定義哪些路徑應該與該路由匹配。
定義服務配置檔案使 Linkerd 能夠報告每個路由的指標,
還允許您啟用每個路由的功能,例如重試和超時。

如果使用無頭服務,則無法檢索服務配置檔案。
Linkerd 根據目標 IP 地址讀取服務發現資訊,
如果這恰好是 pod IP 地址,則它無法判斷 pod 屬於哪個服務。

流量拆分(金絲雀、藍/綠部署)

Linkerd 的流量拆分功能允許您將目的地為 Kubernetes 服務的流量的任意部分動態轉移到不同的目的地服務。
此功能可用於實施複雜的部署策略,例如
金絲雀部署
藍/綠部署
例如,通過緩慢地將流量從舊版本的服務轉移到新版本。

如果使用無頭服務,則無法檢索流量拆分。
Linkerd 根據目標 IP 地址讀取服務發現資訊,
如果這恰好是 pod IP 地址,則它無法判斷 pod 屬於哪個服務。

Linkerd 通過 Service Mesh Interface (SMI)
TrafficSplit API 公開此功能。
要使用此功能,您需要按照 TrafficSplit 規範中的描述建立一個 Kubernetes 資源,Linkerd 負責其餘的工作。

通過將流量拆分與 Linkerd 的指標相結合,可以實現更強大的部署技術,
自動考慮新舊版本的成功率和延遲。
有關此示例的一個示例,請參閱 Flagger 專案。

我是為少
微信:uuhells123
公眾號:黑客下午茶
加我微信(互相學習交流),關注公眾號(獲取更多學習資料~)

相關文章