Linkerd 2.10(Step by Step)—多叢集通訊

為少發表於2021-06-20

Linkerd 2.10 系列

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

本指南將引導您安裝和配置 Linkerd,以便兩個叢集可以與託管在兩個叢集上的服務通訊。
在本指南結束時,您將瞭解如何在不同叢集上的服務之間分配流量。

您將:

  1. 安裝 Linkerd,在具有共享信任錨(shared trust anchor)的兩個叢集上。
  2. 準備叢集。
  3. 連結叢集。
  4. 安裝 demo。
  5. 暴露 demo services, 以控制可見性。
  6. 驗證叢集的安全性。
  7. 拆分流量,將從源叢集 (west) 上的 pod 的流量拆分到目標叢集 (east)。

前提條件

  • 兩個叢集。我們將在本指南中將它們稱為 eastwest
    在您瀏覽本指南時,請跟隨
    部落格文章
    為開發執行此操作的最簡單方法是在您的膝上型電腦上本地執行一個
    kind
    k3d 叢集,
    並在雲提供商(例如 AKS
    上遠端執行一個叢集。
  • 這些叢集中的每一個都應配置為 kubectl
    contexts
    我們建議您使用 eastwest的名稱,
    以便您可以按照本指南進行操作。
    使用 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),
我們現在就可以在您的 westeast 叢集上安裝 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(具有共享信任錨)驗證的請求通過此閘道器。

要在 westeast 上安裝多叢集元件,您可以執行:

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)並準備啟動映象服務。
我們現在想要將叢集連結在一起!

連結叢集

為了讓 westeast 映象服務,west 叢集需要有憑據,
以便它可以監視要暴露的 east 服務。
畢竟,您不希望任何人能夠內省叢集上執行的內容!
憑據包括用於驗證服務映象的服務帳戶以及
允許監視服務的 ClusterRoleClusterRoleBinding
總的來說,服務映象元件使用這些憑證來觀察 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

通過 http://localhost:8080 提供的 podinfo 登入頁面,
您現在可以看到它在 west 叢集中的外觀。
或者,執行 curl http://localhost:8080 將返回一個類似於以下內容的 JSON 響應:

{
  "hostname": "podinfo-5c8cf55777-zbfls",
  "version": "4.0.2",
  "revision": "b4138fdb4dce7b34b6fc46069f70bb295aa8963c",
  "color": "#6c757d",
  "logo": "https://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 http://podinfo-east:9898"

你會看到 greeting from east 的訊息!
來自在 west 執行的 frontend pod 的請求被透明地轉發到 east
假設您仍然在上一步進行埠轉發,
您也可以從瀏覽器訪問 http://localhost:8080/east
重新整理幾次,您也可以從 linkerd viz stat 中獲取指標。

linkerd --context=west -n test viz stat --from deploy/frontend svc

我們還提供了一個 grafana 儀表板來了解這裡發生的事情。
您可以通過執行 linkerd --context=west viz dashboard
並轉到
http://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 適用於具體資源,並且不能同時看到兩個叢集,
因此目前無法顯示 eastwest 中 pod 之間的邊緣。
這就是我們在這裡使用 tap 來驗證 mTLS 的原因。

除了確保您的所有請求都被加密之外,阻止任意請求進入您的叢集也很重要。
我們通過驗證請求來自網格中的客戶端來做到這一點。
為了進行這種驗證,我們依賴叢集之間的共享信任錨。
要檢視當客戶端在網格之外時會發生什麼,您可以執行:

kubectl --context=west -n test run -it --rm --image=alpine:3 test -- \
  /bin/sh -c "apk add curl && curl -vv http://podinfo-east:9898"

流量拆分

讓服務自動出現在叢集中並能夠明確地處理它們是非常有用的,
但是這僅涵蓋操作多個叢集的一個用例。
多叢集的另一個場景是故障轉移。
在故障轉移場景中,您沒有時間更新配置。
相反,您需要能夠不理會應用程式,而只需更改路由即可。
如果這聽起來很像我們進行 canary 部署的方式,那麼您是對的!

TrafficSplit 允許我們定義多個服務之間的權重並在它們之間拆分流量。
在故障轉移場景中,您希望緩慢執行此操作,以確保不會因為
增加的延遲而使其他叢集過載或跳閘任何 SLO。
為了讓這一切都適用於我們的場景,
讓我們在 westeast 中的 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 叢集中,
因此我們現在已經有效地使從 westeast 的 50% 以上的流量失敗了。

如果您仍在執行 port-forward
則可以將瀏覽器傳送到 http://localhost:8080
重新整理頁面應該顯示兩個叢集。
或者,對於命令列方法,curl localhost:8080
給你一條來自 westeast 的問候訊息。

您還可以通過指標觀察發生的情況。要檢視事物的源頭(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
公眾號:黑客下午茶
加我微信(互相學習交流),關注公眾號(獲取更多學習資料~)

相關文章