天天看點

如何使用 Istio 進行多叢集部署管理:單控制平面 Gateway 連接配接拓撲叢集感覺的服務路由Istio 控制平面元件istio-remote 元件部署示例應用課程推薦

如何使用 Istio 進行多叢集部署管理:單控制平面 Gateway 連接配接拓撲叢集感覺的服務路由Istio 控制平面元件istio-remote 元件部署示例應用課程推薦

作者 | 王夕甯  阿裡巴巴進階技術專家

導讀:本文摘自于由阿裡雲進階技術專家王夕甯撰寫的《Istio 服務網格技術解析與實踐》一書,講述了如何使用 Istio 進行多叢集部署管理來闡述服務網格對多雲環境、多叢集即混合部署的支援能力。

前文詳情:

如何使用 Istio 進行多叢集部署管理:單控制平面 VPN 連接配接拓撲

單控制平面拓撲下,多個 Kubernetes 叢集共同使用在其中一個叢集上運作的單個 Istio 控制平面。控制平面的 Pilot 管理本地和遠端叢集上的服務,并為所有叢集配置 Envoy Sidecar 代理。

叢集感覺的服務路由

Istio 1.1 中引入了叢集感覺的服務路由能力,在單一控制平面拓撲配置下,使用 Istio 的 Split-horizon EDS(水準分割端點發現服務)功能可以通過其入口網關将服務請求路由到其他叢集。基于請求源的位置,Istio 能夠将請求路由到不同的端點。

在該配置中,從一個叢集中的 Sidecar 代理到同一叢集中的服務的請求仍然被轉發到本地服務 IP。如果目标工作負載在其他叢集中運作,則使用遠端叢集的網關 IP 來連接配接到該服務。

如何使用 Istio 進行多叢集部署管理:單控制平面 Gateway 連接配接拓撲叢集感覺的服務路由Istio 控制平面元件istio-remote 元件部署示例應用課程推薦

(叢集感覺的服務路由)

如圖所示,主叢集 cluster1 運作全套的 Istio 控制平面元件,同時叢集 cluster2 僅運作 Istio Citadel、Sidecar Injector 和 Ingress 網關。不需要 VPN 連接配接,不同叢集中的工作負載之間也不需要直接網絡通路。

從共享的根 CA 為每個叢集的 Citadel 生成中間 CA 證書,共享的根 CA 啟用跨不同叢集的雙向 TLS 通信。為了便于說明,我們将 samples/certs 目錄下 Istio 安裝中提供的示例根 CA 證書用于兩個叢集。在實際部署中,你可能會為每個叢集使用不同的 CA 證書,所有 CA 證書都由公共根 CA 簽名。

在每個 Kubernetes 叢集中(包括示例中的叢集 cluster1 與 cluster2)使用以下指令為生成的 CA 證書建立 Kubernetes 密鑰:

kubectl
create namespace istio-system
kubectl
create secret generic cacerts -n istio-system \
  --from-file=samples/certs/ca-cert.pem \
  --from-file=samples/certs/ca-key.pem \
  --from-file=samples/certs/root-cert.pem \
  --from-file=samples/certs/cert-chain.pem           

Istio 控制平面元件

在部署全套 Istio 控制平面元件的叢集 cluster1 中,按照以下步驟執行:

1.安裝 Istio 的 CRD 并等待幾秒鐘,以便将它們送出給 Kubernetes API 伺服器,如下所示:

for
i in install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl apply -f $i;
done           

2.然後開始在叢集 cluster1 中部署 Istio 控制平面。

如果 helm 依賴項缺失或者不是最新的,可以通過 helm dep update 來更新這些依賴項。需要注意的是,因為沒有使用 istio-cni,可以暫時将其從依賴項 requirements.yaml 中去掉再執行更新操作。具體指令如下所示:

helm
template --name=istio --namespace=istio-system \
--set
global.mtls.enabled=true \
--set
security.selfSigned=false \
--set
global.controlPlaneSecurityEnabled=true \
--set
global.meshExpansion.enabled=true \
--set
global.meshNetworks.network2.endpoints[0].fromRegistry=n2-k8s-config \
--set
global.meshNetworks.network2.gateways[0].address=0.0.0.0 \
--set
global.meshNetworks.network2.gateways[0].port=15443 \
install/kubernetes/helm/istio
> ./istio-auth.yaml           

請注意,網關位址設定為 0.0.0.0。這是一個臨時占位符值,在叢集 cluster2 部署之後将更新為其網關的公共 IP 值。

将 Istio 部署到 cluster1,如下所示:

kubectl
apply -f ./istio-auth.yaml           

確定上述步驟在 Kubernetes 叢集中執行成功。

3. 建立網關以通路遠端服務,如下所示:

kubectl
create -f - <<EOF
apiVersion:
networking.istio.io/v1alpha3
kind:
Gateway
metadata:
  name: cluster-aware-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 15443
      name: tls
      protocol: TLS
    tls:
      mode: AUTO_PASSTHROUGH
    hosts:
    - "*"
EOF           

上述網關配置了一個專用端口 15443 用來将傳入流量傳遞到請求的 SNI 标頭中指定的目标服務,從源服務到目标服務一直使用雙向 TLS 連接配接。

請注意雖然該網關定義應用于叢集 cluster1,但因為兩個叢集都與同一個 Pilot 進行通信,此網關執行個體同樣也适用于叢集 cluster2。

istio-remote 元件

在另一叢集 cluster2 中部署 istio-remote 元件,按照以下步驟執行:

1.首先擷取叢集 cluster1 的入口網關位址,如下所示:

export
LOCAL_GW_ADDR=$(kubectl get svc --selector=app=istio-ingressgateway \
  -n istio-system -o
jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}")           

通過執行以下指令,使用 Helm 建立 Istio remote 部署 YAML 檔案:

helm
template --name istio-remote --namespace=istio-system \
--values
install/kubernetes/helm/istio/values-istio-remote.yaml \
--set
global.mtls.enabled=true \
--set
gateways.enabled=true \
--set
security.selfSigned=false \
--set
global.controlPlaneSecurityEnabled=true \
--set
global.createRemoteSvcEndpoints=true \
--set
global.remotePilotCreateSvcEndpoint=true \
--set
global.remotePilotAddress=${LOCAL_GW_ADDR} \
--set
global.remotePolicyAddress=${LOCAL_GW_ADDR} \
--set
global.remoteTelemetryAddress=${LOCAL_GW_ADDR} \
--set
gateways.istio-ingressgateway.env.ISTIO_META_NETWORK="network2" \
--set
global.network="network2" \
install/kubernetes/helm/istio
> istio-remote-auth.yaml           

2. 将 Istio remote 元件部署到 cluster2,如下所示:

kubectl
apply -f ./istio-remote-auth.yaml           

3.更新叢集 cluster1 的配置項 istio,擷取叢集 cluster2 的入口網關位址,如下所示:

export
REMOTE_GW_ADDR=$(kubectl get --context=$CTX_REMOTE svc --selector=app=
istio-ingressgateway
-n istio-system -o jsonpath="{.items[0].status.loadBalancer.ingress
[0].ip}")           

在叢集 cluster1 中編輯命名空間 istio-system 下的配置項 istio,替換 network2 的網關位址,從 0.0.0.0 變成叢集 cluster2 的入口網關位址 ${REMOTE_GW_ADDR}。儲存後,Pilot 将自動讀取更新的網絡配置。

4.建立叢集 cluster2 的 Kubeconfig。通過以下指令,在叢集 cluster2 上建立服務賬号 istio-multi 的 Kubeconfig,并儲存為檔案 n2-k8s-config:

CLUSTER_NAME="cluster2"
SERVER=$(kubectl
config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
SECRET_NAME=$(kubectl
get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
CA_DATA=$(kubectl
get secret ${SECRET_NAME} -n istio-system -o
"jsonpath={.data['ca\.crt']}")
TOKEN=$(kubectl
get secret ${SECRET_NAME} -n istio-system -o
"jsonpath={.data['token']}" | base64 --decode)
cat
<<EOF > n2-k8s-config
apiVersion:
v1
kind:
Config
clusters:
  - cluster:
      certificate-authority-data: ${CA_DATA}
      server: ${SERVER}
    name: ${CLUSTER_NAME}
contexts:
  - context:
      cluster: ${CLUSTER_NAME}
      user: ${CLUSTER_NAME}
    name: ${CLUSTER_NAME}
current-context:
${CLUSTER_NAME}
users:
  - name: ${CLUSTER_NAME}
    user:
      token: ${TOKEN}
EOF           

5.将叢集 cluster2 加入到 Istio 控制平面。

在叢集 clusterl 執行以下指令,将上述生成的叢集 cluster2 的 kubeconfig 添加到叢集 cluster1 的 secret 中,執行這些指令後,叢集 cluster1 中的 Istio Pilot 将開始監聽叢集 cluster2 的服務和執行個體,就像監聽叢集 cluster1 中的服務與執行個體一樣:

kubectl
create secret generic n2-k8s-secret --from-file n2-k8s-config -n istio-system
kubectl
label secret n2-k8s-secret istio/multiCluster=true -n istio-system           

部署示例應用

為了示範跨叢集通路,在第一個 Kubernetes 叢集 cluster1 中部署 sleep 應用服務和版本 v1 的 helloworld 服務,在第二個叢集 cluster2 中部署版本 v2 的 helloworld 服務,然後驗證 sleep 應用是否可以調用本地或者遠端叢集的 helloworld 服務。

1.部署 sleep 和版本 v1 的 helloworld 服務到第一個叢集 cluster1 中,執行如下指令:

kubectl
create namespace app1
kubectl
label namespace app1 istio-injection=enabled
kubectl
apply -n app1 -f samples/sleep/sleep.yaml
kubectl
apply -n app1 -f samples/helloworld/service.yaml
kubectl
apply -n app1 -f samples/helloworld/helloworld.yaml -l version=v1
export
SLEEP_POD=$(kubectl get -n app1 pod -l app=sleep -o
jsonpath={.items..metadata.name})           

2.部署版本 v2 的 helloworld 服務到第二個叢集 cluster2 中,執行如下指令:

kubectl
create namespace app1
kubectl
label namespace app1 istio-injection=enabled
kubectl
apply -n app1 -f samples/helloworld/service.yaml
kubectl
apply -n app1 -f samples/helloworld/helloworld.yaml -l version=v2           

3.登入到命名空間 istio-system 下的 istio-pilot 容器中,運作 curl localhost:8080/v1/registration | grep helloworld -A 11 -B 2 指令,如果得到如下類似的結果就說明版本 v1 與 v2 的 helloworld 服務都已經注冊到 Istio 控制平面中了:

如何使用 Istio 進行多叢集部署管理:單控制平面 Gateway 連接配接拓撲叢集感覺的服務路由Istio 控制平面元件istio-remote 元件部署示例應用課程推薦

4.驗證在叢集 cluster1 中的 sleep 服務是否可以正常調用本地或者遠端叢集的 helloworld 服務,在叢集 cluster1 下執行如下指令:

kubectl
exec -it -n app1 $SLEEP_POD sh           
如何使用 Istio 進行多叢集部署管理:單控制平面 Gateway 連接配接拓撲叢集感覺的服務路由Istio 控制平面元件istio-remote 元件部署示例應用課程推薦

登入到容器中,運作 curl helloworld.app1:5000/hello。

如果設定正确,則在傳回的調用結果中可以看到兩個版本的 helloworld 服務,同時可以通過檢視 sleep 容器組中的 istio-proxy 容器日志來驗證通路的端點 IP 位址,傳回結果如下所示:

如何使用 Istio 進行多叢集部署管理:單控制平面 Gateway 連接配接拓撲叢集感覺的服務路由Istio 控制平面元件istio-remote 元件部署示例應用課程推薦

《Istio服務網格技術解析與實戰》讀者可免費體驗 ASM 産品進行學習!點選了解阿裡雲服務網格産品 ASM:

www.aliyun.com/product/servicemesh

作者簡介

王夕甯 阿裡雲進階技術專家,阿裡雲服務網格産品 ASM 及 Istio on Kubernetes 技術負責人,專注于 Kubernetes、雲原生、服務網格等領域。曾在 IBM 中國開發中心工作,擔任過專利技術評審委員會主席,擁有 40 多項相關領域的國際技術專利。《Istio 服務網格解析與實戰》一書由其撰寫,詳細介紹了 Istio 的基本原理與開發實戰,包含大量精選案例和參考代碼可以下載下傳,可快速入門 Istio 開發。Gartner 認為,2020 年服務網格将成為所有領先的容器管理系統的标配技術。本書适合所有對微服務和雲原生感興趣的讀者,推薦大家對本書進行深入的閱讀。

課程推薦

為了更多開發者能夠享受到 Serverless 帶來的紅利,這一次,我們集結了 10+ 位阿裡巴巴 Serverless 領域技術專家,打造出最适合開發者入門的 Serverless 公開課,讓你即學即用,輕松擁抱雲計算的新範式——Serverless。

點選即可免費觀看課程:

https://developer.aliyun.com/learning/roadmap/serverless
阿裡巴巴雲原生 關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的公衆号。”

繼續閱讀