Linkerd 2-10-Step by Step-—多集羣通信

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

您將:

  1. 安裝 Linkerd,在具有共享信任錨 (shared trust anchor) 的兩個集羣上。

  2. 準備集羣。

  3. 鏈接集羣。

  4. 安裝 demo。

  5. 暴露 demo services, 以控制可見性。

  6. 驗證集羣的安全性。

  7. 拆分流量,將從源集羣 (west) 上的 pod 的流量拆分到目標集羣 (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

通過 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 適用於具體資源,並且不能同時看到兩個集羣, 因此目前無法顯示 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 http://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, 則可以將瀏覽器發送到 http://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
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/GA-oQ-RBuV1MhGxKEqFADQ