Linkerd 2.10(Step by Step)—多集群通信
- 2021 年 6 月 21 日
- 筆記
Linkerd 2.10 系列
- 快速上手 Linkerd v2.10 Service Mesh(服務網格)
- 騰訊雲 K8S 集群實戰 Service Mesh—Linkerd2 & Traefik2 部署 emojivoto 應用
- 詳細了解 Linkerd 2.10 基礎功能,一起步入 Service Mesh 微服務架構時代
- Linkerd 2.10—將您的服務添加到 Linkerd
- Linkerd 2.10—自動化的金絲雀發佈
- Linkerd 2.10—自動輪換控制平面 TLS 與 Webhook TLS 憑證
- Linkerd 2.10—如何配置外部 Prometheus 實例
- Linkerd 2.10—配置代理並發
- Linkerd 2.10—配置重試
- Linkerd 2.10—配置超時
- Linkerd 2.10—控制平面調試端點
- Linkerd 2.10—使用 Kustomize 自定義 Linkerd 的配置
- Linkerd 2.10—使用 Linkerd 進行分佈式跟蹤
- Linkerd 2.10—調試 502s
- Linkerd 2.10—使用每個路由指標調試 HTTP 應用程序
- Linkerd 2.10—使用請求跟蹤調試 gRPC 應用程序
- Linkerd 2.10—導出指標
- Linkerd 2.10—暴露 Dashboard
- Linkerd 2.10—生成您自己的 mTLS 根證書
- Linkerd 2.10—獲取每條路由指標
- Linkerd 2.10—混沌工程之注入故障
- Linkerd 2.10—優雅的 Pod 關閉
- Linkerd 2.10—Ingress 流量
- Linkerd 2.10—安裝多集群組件
- Linkerd 2.10—安裝 Linkerd
- Linkerd 2.10—使用 Helm 安裝 Linkerd
- Linkerd 2.10—Linkerd 和 Pod 安全策略 (PSP)
- Linkerd 2.10—手動輪換控制平面 TLS 憑證
- Linkerd 2.10—修改代理日誌級別
Linkerd 2.10 中文手冊持續修正更新中:
本指南將引導您安裝和配置 Linkerd
,以便兩個集群可以與託管在兩個集群上的服務通信。
在本指南結束時,您將了解如何在不同集群上的服務之間分配流量。
您將:
- 安裝 Linkerd,在具有共享信任錨(
shared trust anchor
)的兩個集群上。 - 準備集群。
- 鏈接集群。
- 安裝 demo。
- 暴露 demo services, 以控制可見性。
- 驗證集群的安全性。
- 拆分流量,將從源集群 (
west
) 上的 pod 的流量拆分到目標集群 (east
)。
前提條件
- 兩個集群。我們將在本指南中將它們稱為
east
和west
。
在您瀏覽本指南時,請跟隨
博客文章!
為開發執行此操作的最簡單方法是在您的筆記本電腦上本地運行一個
kind
或 k3d 集群,
並在雲提供商(例如 AKS)
上遠程運行一個集群。 - 這些集群中的每一個都應配置為
kubectl
contexts。
我們建議您使用east
和west
的名稱,
以便您可以按照本指南進行操作。
使用kubectl
rename contexts
很容易,所以不要覺得你需要永遠保持這種命名方式。 - 兩個集群上的提升權限。我們將創建服務帳戶並授予擴展權限,
因此您需要能夠在測試集群上執行此操作。 - 應安裝 Linkerd 的
viz
擴展,以便運行stat
命令、
查看 Grafana 或 Linkerd 儀錶板並
運行linkerd multicluster gateways
命令。 - 支持
east
集群中的LoadBalancer
類型的服務。
查看集群提供商的文檔或查看
inlets。
這是west
集群將用於通過網關與east
通信的內容。
安裝 Linkerd
Linkerd 需要在所有相互通信的集群中的安裝之間存在共享
trust anchor。
這用於加密集群之間的流量並授權到達網關的請求,以便您的集群不對公共互聯網開放。
我們需要生成憑據並將它們用作 install
命令的配置,而不是讓 linkerd
生成所有內容。
我們喜歡使用 step CLI 來生成這些證書。
如果您更喜歡 openssl
,請隨意使用它!
要使用 step
生成信任錨,您可以運行:
step certificate create root.linkerd.cluster.local root.crt root.key \
--profile root-ca --no-password --insecure
該證書將構成所有集群之間的共同信任基礎。
每個代理都將獲得此證書的副本,並使用它來驗證從對等方收到的證書,
作為 mTLS 握手的一部分。有了共同的信任基礎,
我們現在需要生成一個證書,可以在每個集群中使用該證書向代理頒發證書。
我們生成的信任錨是一個自簽名證書,可用於創建新證書(證書頒發機構)。
要使用信任錨生成 issuer credentials
,請運行:
step certificate create identity.linkerd.cluster.local issuer.crt issuer.key \
--profile intermediate-ca --not-after 8760h --no-password --insecure \
--ca root.crt --ca-key root.key
集群中的 identity
服務將使用您在此處生成的證書(certificate)和
密鑰(key)來生成每個單獨代理使用的證書。
雖然我們將在本指南的每個集群上使用相同的頒發者憑據,
但最好為每個集群使用不同的頒發者憑據。
有了有效的信任錨(trust anchor)和發行人憑據(issuer credentials),
我們現在就可以在您的 west
和 east
集群上安裝 Linkerd。
linkerd install \
--identity-trust-anchors-file root.crt \
--identity-issuer-certificate-file issuer.crt \
--identity-issuer-key-file issuer.key \
| tee \
>(kubectl --context=west apply -f -) \
>(kubectl --context=east apply -f -)
install
的輸出將應用於每個集群並出現!
您可以使用 check
來驗證一切是否成功。
for ctx in west east; do
echo "Checking cluster: ${ctx} .........\n"
linkerd --context=${ctx} check || break
echo "-------------\n"
done
準備集群
為了在集群之間路由流量,Linkerd 利用了 Kubernetes services,
因此您的應用程序代碼無需更改,也無需學習任何新內容。
這需要一個網關組件,將傳入請求路由到正確的內部服務。
網關將通過 LoadBalancer
類型的 Service
暴露給公共互聯網。
僅允許通過 Linkerd 的 mTLS(具有共享信任錨)驗證的請求通過此網關。
要在 west
和 east
上安裝多集群組件,您可以運行:
for ctx in west east; do
echo "Installing on cluster: ${ctx} ........."
linkerd --context=${ctx} multicluster install | \
kubectl --context=${ctx} apply -f - || break
echo "-------------\n"
done
網關安裝在 linkerd-multicluster
命名空間中,
是一個簡單的
NGINX proxy,
它已經注入了 Linkerd 代理。 在入站端,Linkerd 負責驗證連接是否
使用了作為信任錨一部分的 TLS 證書。 NGINX 接收請求並將其轉發到 Linkerd 代理的出站端。
此時,Linkerd 代理像數據平面中的任何其他代理一樣運行,
並將請求轉發到正確的服務。通過運行以下命令確保網關成功啟動:
for ctx in west east; do
echo "Checking gateway on cluster: ${ctx} ........."
kubectl --context=${ctx} -n linkerd-multicluster \
rollout status deploy/linkerd-gateway || break
echo "-------------\n"
done
通過運行以下命令仔細檢查負載均衡器是否能夠分配公共 IP 地址:
for ctx in west east; do
printf "Checking cluster: ${ctx} ........."
while [ "$(kubectl --context=${ctx} -n linkerd-multicluster get service \
-o 'custom-columns=:.status.loadBalancer.ingress[0].ip' \
--no-headers)" = "<none>" ]; do
printf '.'
sleep 1
done
printf "\n"
done
每個集群現在都在運行多集群控制平面(multicluster control plane
)並準備啟動鏡像服務。
我們現在想要將集群鏈接在一起!
鏈接集群
為了讓 west
從 east
鏡像服務,west
集群需要有憑據,
以便它可以監視要暴露的 east
服務。
畢竟,您不希望任何人能夠內省集群上運行的內容!
憑據包括用於驗證服務鏡像的服務帳戶以及
允許監視服務的 ClusterRole
和 ClusterRoleBinding
。
總的來說,服務鏡像組件使用這些憑證來觀察 east
或目標集群上的服務,
並從自身(west
)添加/刪除它們。
作為 linkerd multicluster install
的一部分添加了一個默認設置,
但是如果您想為每個集群擁有單獨的憑據,
您可以運行 linkerd multicluster allow
。
下一步是將 west
鏈接到 east
。
這將創建一個 credentials secret、Link resource 和 service-mirror controller。
憑證密鑰包含一個 kubeconfig,可用於訪問目標(east
)集群的 Kubernetes API。
Link resource 是配置服務鏡像的自定義資源,
包含網關地址(gateway address)、網關標識(gateway identity)
和在確定要鏡像哪些服務時使用的標籤選擇器等內容。
服務鏡像控制器(service-mirror controller)使用 Link 和 secret 在
目標集群上查找與給定標籤選擇器匹配的服務,
並將它們複製到源(本地)集群中。
要將 west
集群鏈接到 east
集群,請運行:
linkerd --context=east multicluster link --cluster-name east |
kubectl --context=west apply -f -
Linkerd 將查看您當前的 east
context,
提取包含服務器位置(server location)以及 CA 包的 cluster
配置。
然後它將獲取 ServiceAccount
token 並
將這些配置合併到一個 kubeconfig 的 secret 中。
再次運行 check
將確保服務鏡像(service mirror)已經
發現了這個 secret 並且可以到達 east
。
linkerd --context=west multicluster check
此外,east
網關現在應該顯示在列表中:
linkerd --context=west multicluster gateways
link
假設兩個集群將使用與您在本地使用的配置相同的配置相互連接。
如果不是這種情況,您將需要為 link
使用 --api-server-address
標誌。
安裝測試服務
是時候測試這一切了!
第一步是添加一些我們可以鏡像的服務。
要將這些添加到兩個集群,您可以運行:
for ctx in west east; do
echo "Adding test services on cluster: ${ctx} ........."
kubectl --context=${ctx} apply \
-k "github.com/linkerd/website/multicluster/${ctx}/"
kubectl --context=${ctx} -n test \
rollout status deploy/podinfo || break
echo "-------------\n"
done
您現在將擁有一個 test
命名空間,在每個集群中運行兩個部署 – frontend 和 podinfo。
podinfo
在每個集群中的配置略有不同,具有不同的名稱和顏色,以便我們可以知道請求的去向。
要立即從 west
集群中查看它的樣子,您可以運行:
kubectl --context=west -n test port-forward svc/frontend 8080
通過 //localhost:8080 提供的 podinfo 登錄頁面,
您現在可以看到它在 west
集群中的外觀。
或者,運行 curl //localhost:8080
將返回一個類似於以下內容的 JSON 響應:
{
"hostname": "podinfo-5c8cf55777-zbfls",
"version": "4.0.2",
"revision": "b4138fdb4dce7b34b6fc46069f70bb295aa8963c",
"color": "#6c757d",
"logo": "//raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/cuddle_clap.gif",
"message": "greetings from west",
"goos": "linux",
"goarch": "amd64",
"runtime": "go1.14.3",
"num_goroutine": "8",
"num_cpu": "4"
}
請注意,message
引用了 west
集群名稱。
暴露 services
為確保敏感服務(sensitive services
)不被鏡像並且
集群性能受到服務的創建或刪除的影響,我們要求顯式暴露服務。
出於本指南的目的,我們將把 podinfo
服務從 east
集群導出到 west
集群。
為此,我們必須首先導出 east
集群中的 podinfo
服務。
你可以通過添加 mirror.linkerd.io/exported
標籤來做到這一點:
kubectl --context=east label svc -n test podinfo mirror.linkerd.io/exported=true
您可以通過在 linkerd multicluster link
命令上使用 --selector
標誌或
通過編輯由 linkerd multicluster link
命令創建
的 Link resource 來配置不同的標籤選擇器。
查看服務鏡像控制器(service mirror controller)剛剛創建的服務!
kubectl --context=west -n test get svc podinfo-east
從
architecture
中,您會記得服務鏡像(service mirror)組件所做的不僅僅是移動服務。
它還管理鏡像服務上的端點。
要驗證設置是否正確,您可以檢查 west
的端點並驗證它們
是否與 east
網關的公共 IP 地址匹配。
kubectl --context=west -n test get endpoints podinfo-east \
-o 'custom-columns=ENDPOINT_IP:.subsets[*].addresses[*].ip'
kubectl --context=east -n linkerd-multicluster get svc linkerd-gateway \
-o "custom-columns=GATEWAY_IP:.status.loadBalancer.ingress[*].ip"
此時,我們可以從 west
集群中訪問 east
中的 podinfo
服務。
這需要對客戶端進行網格化,因此讓我們從前端 pod 中運行 curl
:
kubectl --context=west -n test exec -c nginx -it \
$(kubectl --context=west -n test get po -l app=frontend \
--no-headers -o custom-columns=:.metadata.name) \
-- /bin/sh -c "apk add curl && curl //podinfo-east:9898"
你會看到 greeting from east
的消息!
來自在 west
運行的 frontend
pod 的請求被透明地轉發到 east
。
假設您仍然在上一步進行端口轉發,
您也可以從瀏覽器訪問 //localhost:8080/east。
刷新幾次,您也可以從 linkerd viz stat
中獲取指標。
linkerd --context=west -n test viz stat --from deploy/frontend svc
我們還提供了一個 grafana 儀錶板來了解這裡發生的事情。
您可以通過運行 linkerd --context=west viz dashboard
並轉到
//localhost:50750/grafana/
來訪問它。
安全
默認情況下,請求將通過公共互聯網。
Linkerd 跨集群擴展其自動 mTLS
,
以確保通過公共互聯網進行的通信是加密的。
但是,要快速檢查,您可以運行:
linkerd --context=west -n test viz tap deploy/frontend | \
grep "$(kubectl --context=east -n linkerd-multicluster get svc linkerd-gateway \
-o "custom-columns=GATEWAY_IP:.status.loadBalancer.ingress[*].ip")"
tls=true
告訴你請求正在被加密!
由於 linkerd edge
適用於具體資源,並且不能同時看到兩個集群,
因此目前無法顯示 east
和 west
中 pod 之間的邊緣。
這就是我們在這裡使用 tap
來驗證 mTLS 的原因。
除了確保您的所有請求都被加密之外,阻止任意請求進入您的集群也很重要。
我們通過驗證請求來自網格中的客戶端來做到這一點。
為了進行這種驗證,我們依賴集群之間的共享信任錨。
要查看當客戶端在網格之外時會發生什麼,您可以運行:
kubectl --context=west -n test run -it --rm --image=alpine:3 test -- \
/bin/sh -c "apk add curl && curl -vv //podinfo-east:9898"
流量拆分
讓服務自動出現在集群中並能夠明確地處理它們是非常有用的,
但是這僅涵蓋操作多個集群的一個用例。
多集群的另一個場景是故障轉移。
在故障轉移場景中,您沒有時間更新配置。
相反,您需要能夠不理會應用程序,而只需更改路由即可。
如果這聽起來很像我們進行 canary 部署的方式,那麼您是對的!
TrafficSplit
允許我們定義多個服務之間的權重並在它們之間拆分流量。
在故障轉移場景中,您希望緩慢執行此操作,以確保不會因為
增加的延遲而使其他集群過載或跳閘任何 SLO。
為了讓這一切都適用於我們的場景,
讓我們在 west
和 east
中的 podinfo
服務之間進行拆分。
要配置它,您將運行:
cat <<EOF | kubectl --context=west apply -f -
apiVersion: split.smi-spec.io/v1alpha1
kind: TrafficSplit
metadata:
name: podinfo
namespace: test
spec:
service: podinfo
backends:
- service: podinfo
weight: 50
- service: podinfo-east
weight: 50
EOF
對 podinfo
的任何請求現在將有 50% 的時間轉發到 podinfo-east
集群,
另外 50% 的時間會轉發到本地 podinfo
服務。
發送到 podinfo-east
的請求最終會出現在 east
集群中,
因此我們現在已經有效地使從 west
到 east
的 50% 以上的流量失敗了。
如果您仍在運行 port-forward
,
則可以將瀏覽器發送到 //localhost:8080。
刷新頁面應該顯示兩個集群。
或者,對於命令行方法,curl localhost:8080
會
給你一條來自 west
和 east
的問候消息。
您還可以通過指標觀察發生的情況。要查看事物的源頭(west
),您可以運行:
linkerd --context=west -n test viz stat trafficsplit
也可以通過運行從目標(east
)側觀察:
linkerd --context=east -n test viz stat \
--from deploy/linkerd-gateway \
--from-namespace linkerd-multicluster \
deploy/podinfo
甚至還有一個儀錶板! 運行 linkerd viz dashboard
並將瀏覽器發送到
localhost:50750。
清理
要清理多集群控制平面,您可以運行:
for ctx in west east; do
linkerd --context=${ctx} multicluster uninstall | kubectl --context=${ctx} delete -f -
done
如果您還想刪除 Linkerd 安裝,請運行:
for ctx in west east; do
linkerd --context=${ctx} uninstall | kubectl --context=${ctx} delete -f -
done
我是為少
微信:uuhells123
公眾號:黑客下午茶
加我微信(互相學習交流),關注公眾號(獲取更多學習資料~)