如何使用 Istio 进行多集群部署管理:单控制平面 Gateway 连接拓扑
作者 | 王夕寧? 阿里巴巴高級技術專家
**導讀:**本文摘自于由阿里云高級技術專家王夕寧撰寫的《Istio 服務網格技術解析與實踐》一書,講述了如何使用?Istio?進行多集群部署管理來闡述服務網格對多云環境、多集群即混合部署的支持能力。
前文詳情:
如何使用?Istio?進行多集群部署管理:單控制平面?VPN?連接拓撲
單控制平面拓撲下,多個?Kubernetes?集群共同使用在其中一個集群上運行的單個?Istio?控制平面。控制平面的?Pilot?管理本地和遠程集群上的服務,并為所有集群配置?Envoy Sidecar?代理。
集群感知的服務路由
Istio 1.1?中引入了集群感知的服務路由能力,在單一控制平面拓撲配置下,使用?Istio?的?Split-horizon EDS(水平分割端點發現服務)功能可以通過其入口網關將服務請求路由到其他集群。基于請求源的位置,Istio?能夠將請求路由到不同的端點。
在該配置中,從一個集群中的?Sidecar?代理到同一集群中的服務的請求仍然被轉發到本地服務?IP。如果目標工作負載在其他集群中運行,則使用遠程集群的網關?IP?來連接到該服務。
(集群感知的服務路由)
如圖所示,主集群?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.pemIstio?控制平面組件
在部署全套?Istio?控制平面組件的集群?cluster1?中,按照以下步驟執行:
1.安裝?Istio?的?CRD?并等待幾秒鐘,以便將它們提交給?Kubernetes API?服務器,如下所示:
for i in install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl apply -f $i; done2.然后開始在集群?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-gatewaynamespace: istio-system spec:selector:istio: ingressgatewayservers:- port:number: 15443name: tlsprotocol: TLStls:mode: AUTO_PASSTHROUGHhosts:- "*" 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.yaml2. 將?Istio remote?組件部署到?cluster2,如下所示:
kubectl apply -f ./istio-remote-auth.yaml確保上述步驟在?Kubernetes?集群中執行成功。
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} EOF5.將集群?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=v23.登錄到命名空間?istio-system?下的?istio-pilot?容器中,運行?curl localhost:8080/v1/registration | grep helloworld -A 11 -B 2?命令,如果得到如下類似的結果就說明版本?v1?與?v2?的?helloworld?服務都已經注冊到?Istio?控制平面中了:
4.驗證在集群?cluster1?中的?sleep?服務是否可以正常調用本地或者遠程集群的?helloworld?服務,在集群?cluster1?下執行如下命令:
kubectl exec -it -n app1 $SLEEP_POD sh登錄到容器中,運行?curl helloworld.app1:5000/hello。
如果設置正確,則在返回的調用結果中可以看到兩個版本的?helloworld?服務,同時可以通過查看?sleep?容器組中的?istio-proxy?容器日志來驗證訪問的端點?IP?地址,返回結果如下所示:
《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 等技術領域、聚焦云原生流行技術趨勢、云原生大規模的落地實踐,做最懂云原生開發者的公眾號。”
總結
以上是生活随笔為你收集整理的如何使用 Istio 进行多集群部署管理:单控制平面 Gateway 连接拓扑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: KubeCon 改为线上举办 | 云原生
- 下一篇: 如何轻松学习 Kubernetes?