如何使用 Istio 进行多集群部署管理(一)
作者 | 王夕寧? 阿里云高級技術專家
參與阿里巴巴云原生公眾號文末留言互動,即有機會獲得贈書福利!
**導讀:**本文摘自于由阿里云高級技術專家王夕寧撰寫的《Istio?服務網格技術解析與實踐》一書,在展望服務網格未來的同時,講述了如何使用 Istio 進行多集群部署管理,來闡述服務網格對多云環境、多集群即混合部署的支持能力。你只需開心參與阿里巴巴云原生公眾號文末互動,我們負責買單!技術人必備書籍《Istio 服務網格技術解析與實踐》免費領~
服務網格作為一個改善服務到服務通信的專用基礎設施層,是云原生范疇中最熱門的話題。隨著容器愈加流行,服務拓撲也頻繁變動,這就需要更好的網絡性能。服務網格能夠通過服務發現、路由、負載均衡、心跳檢測和支持可觀測性,幫助我們管理網絡流量。服務網格試圖為無規則的復雜的容器問題提供規范化的解決方案。
服務網格也可以用于混沌工程 —— “一門在分布式系統上進行實驗的學科,目的是構建能夠應對極端條件的可靠系統”。服務網格能夠將延遲和錯誤注入到環境中,而不需要在每個主機上安裝一個守護進程。
容器是云原生應用的基石,通過應用容器化,使得應用開發部署更加敏捷、遷移更加靈活,并且這些實現都是基于標準化的。而容器編排則是更近一步,能夠更加有效地編排資源、更加高效地調度利用這些資源。而到了云原生時代,在?Kubernetes?基礎架構之上,結合?Istio?服務網格,提供了多云、混合云的支持能力,針對微服務提供了有效的治理能力,并以?Kubernetes?和?Istio?為基礎,提供了針對特定應用負載的不同支持,例如針對?Kubeflow?服務的流量治理、為?Knative?提供負載的路由管理能力等。
盡管?Service Mesh?在云原生系統方面的應用已經有了快速的增長,但仍然存在巨大的提升空間。無服務器(Serverless)計算正好需要?Service Mesh?的命名和鏈接模型,這讓?Service Mesh?在云原生生態系統中的角色得到了彰顯。服務識別和訪問策略在云原生環境中仍顯初級,而?Service Mesh?毫無疑問將成為這方面不可或缺的基礎。就像?TCP/IP?一樣,Service Mesh?將在底層基礎設施這條道路上更進一步。
混合云可以采用多種形式。通常,混合云指的是跨公有云和私有(內部部署)云運行,而多云意味著跨多個公有云平臺運行。
采用混合云或多云架構可以為你的組織帶來諸多好處。例如,使用多個云提供商可以幫助你避免供應商鎖定,能夠讓你為實現目標選擇最佳的云服務。使用云和本地環境,你可以同時享受云的優勢(靈活性、可擴展性、成本降低)和本地的好處(安全性、低延遲、硬件復用)。如果你是首次遷移到云端,采用混合云步驟可以讓你按照自己的節奏,以最適合你業務的方式進行。
根據我們在公有云上的實踐經驗及從客戶那里得到的信息,我們認為采用混合服務網絡是簡化云和本地環境中應用程序管理、安全性和可靠性的關鍵,無論你的應用程序是在容器中運行,或是在虛擬機中運行。
Istio?的一個關鍵特性是它為你的工作負載(例如?pod、job、基于?VM?的應用程序)提供服務抽象。當你轉向混合拓撲時,這種服務抽象變得更加重要,因為現在你不只需要關注一個環境,而是需要關注若干個環境。
當你在一個?Kubernetes?集群上使用?Istio?時,可以獲得包括可見性、細粒度流量策略、統一遙測和安全性在內的微服務的所有管理優勢。但是當你在多個環境中使用?Istio?時,實際上是為應用程序提供了一個新的超級能力。因為?Istio?不僅僅是?Kubernetes?的服務抽象,也是一種在整個環境中標準化網絡的方法。它是一種集中?API?管理并將?JWT?驗證與代碼分離的方法。它是跨云提供商的安全、零信任網絡的快速通道。
那么所有這些魔法是如何發生的呢?混合?Istio?是指一組?Istio Sidecar?代理,每一個?Envoy?代理位于所有服務的旁邊,而這些服務可能運行在不同環境中的每一個虛擬機、每一個容器中,而且這些?Sidecar?代理之前互相知道如何跨邊界交互。這些?Envoy Sidecar?代理可能由一個中央?Istio?控制平面管理,或由每個環境中運行的多個控制平面管理。
多集群部署管理
服務網格本質上是將一組單獨的微服務組合成單個可控的復合應用程序,Istio?作為一種服務網格,也是旨在單一管理域下監視和管理協作微服務網絡。對于特定大小的應用程序,所有微服務是可以在單個編排平臺如一個?Kubernetes?集群上運行的。然而,由于規模不斷增大或者冗余等原因,大多數應用程序最終將需要分發一些服務在其他地方運行。
社區越來越關注在多個集群上運行工作負載,以實現更好的擴展,故障可以更好地隔離,從而提升應用程序的敏捷性。Istio v1.0?開始支持一些多集群功能,并在之后的版本中添加了新功能。
Istio?服務網格支持許多可能的拓撲結構,用于在單個集群之外分發應用程序的服務,有兩種常見的模式或用例:單網格和網格聯合。顧名思義,單個網格將多個集群組合成一個單元,由一個?Istio?控制平面管理;它可以實現為一個物理控制平面,也可以實現為一組控制平面,同時所有控制平面都能通過復制配置保持同步。而網格聯合則會將多個集群分離作為單獨的管理域,有選擇地完成集群之間的連接,僅將服務的子集暴露給其他集群;自然它的實現會包含多個控制平面。
具體來說,這些不同的拓撲結構包括以下幾個方面:
- 網格中的服務可以使用服務條目(Service Entry)來訪問獨立的外部服務或訪問由另一個松散耦合的服務網格公開的服務,通常稱為網格聯邦(Mesh Federation)。這種拓撲適合于互相獨立并且網絡隔離、只能通過公網交互的多集群的場景;
- 支持在虛擬機或物理裸機上運行的服務進行服務網格擴展,通常稱為網格聯合(Mesh Expansion)。在前面章節中,我們已經講述了這種?Kubernetes?集群與虛擬機、物理裸機之間混合部署的場景;
- 把來自多個集群的服務組合到單個服務網格中,通常稱為多集群網格(Multicluster Mesh)。根據網絡拓撲結構的不同,多集群網格通常分為單控制平面?VPN?連接、單控制平面網關連接以及多控制平面拓撲。
單控制平面?VPN?連接拓撲
作為基準,在?Istio?的?1.1?版本之前,Istio 1.0?多集群僅支持使用單網格設計。它允許多個集群連接到網格中,但所有集群都在一個共享網絡上。也就是說,所有集群中所有?pod?和服務的?IP?地址都是可直接路由的,不會發生沖突,同時保證在一個集群中分配的IP地址不會在另一個集群中同時重用。
在這種拓撲配置下,在其中一個集群上運行單個?Istio?控制平面。該控制平面的?Pilot?管理本地和遠程集群上的服務,并為所有集群配置?Envoy?代理。這種方法在所有參與集群都具有?VPN?連接的環境中效果最佳,因此可以使用相同的?IP?地址從其他任何地方訪問網格中的每個?pod。
在此配置中,Istio?控制平面部署在其中一個集群上,而所有其他集群運行更簡單的遠程?Istio?配置,該配置將它們連接到單個?Istio?控制平面,該平面將所有?Envoy?管理為單個網格。各個集群上的?IP?地址不允許重疊,并且遠程集群上的服務的?DNS?解析不是自動的。用戶需要在每個參與集群上復制服務,這樣每個集群中的?Kubernetes?集群服務和應用程序都能夠將其內部?Kubernetes?網絡暴露給其他集群。一旦一個或多個遠程?Kubernetes?集群連接到?Istio?控制平面,Envoy?就可以與單個控制平面通信并形成跨多個集群的網狀網絡。
前提約束
事實上,我們已經了解到網格、集群和網絡之間的存在各種約束,例如,在某些環境中,網絡和集群直接相關。Istio單網格設計下的單控制平面VPN連接拓撲需要滿足以下幾個條件:
- 運行?Kubernetes 1.9?或更高版本的兩個或更多集群;
- 能夠在其中一個集群上部署?Istio?控制平面;
- RFC1918?網絡、VPN?或滿足以下要求的更高級網絡技術:
- 單個集群?pod CIDR?范圍和服務?CIDR?范圍在多集群環境中必須是唯一的,并且應當不重疊;
- 每個集群中的所有?pod CIDR?必須可以相互路由;
- 所有?Kubernetes?控制平面?API?服務器必須可以相互路由。
此外,為了跨集群支持?DNS?名稱解析,必須確保在所有需要跨集群服務調用的集群中定義對應的命名空間、服務和服務賬戶;例如,集群?cluster1?中命名空間?ns1?的服務?service1?需要調用集群?cluster2?中命名空間?ns2?的服務?service2,那么在集群 cluster1 中為了支持服務名的?DNS?解析,需要在集群 cluster1 中創建一個命名空間?ns2?以及該命名空間下的服務?service2。
以下示例中的兩個?Kubernetes?集群的網絡假定已經滿足上述要求,每個集群中的?pod?都能夠互相路由,也就是說網絡可通并且端口是可訪問的(如果采用的是類似于阿里云的公有云服務,請確保這些端口在安全組規則下是可以訪問的;否則服務間的調用會受到影響)。
兩個?Kubernetes?集群的?pod CIDR?范圍和服務 CIDR 范圍定義如下表所示:
(CIDR?范圍定義)
拓撲架構
(Istio?中單控制平面?VPN?連接拓撲的多集群支持的調用關系)
從圖中可以看到整個多集群拓撲中只會在一個?Kubernetes?集群上安裝?Istio?控制平面。這個安裝?Istio?控制平面的集群通常被稱為本地集群,所有其它集群稱為遠程集群。
這些遠程集群只需要安裝?Istio?的?Citadel?和?Sidecar Injector?準入控制器,具有較小的?Istio?占用空間,Citadel?用于這些遠程集群的安全管理,Sidecar Injector?準入控制器用于控制平面中的自動注入和數據平面中工作負載的?Sidecar?代理功能。
在這個架構中,Pilot?可以訪問所有集群中的所有?Kubernetes API?服務器,因此它具有全局網絡訪問視圖。Citadel?和?Sidecar Injector?準入控制器則只會在集群本地范圍內運行。每個集群都有唯一的?pod?和服務?CIDR,除此之外,集群之間還有一個共享的扁平網絡,以保證能直接路由到任何工作負載,包括到?Istio?的控制平面。例如,遠程集群上的?Envoy?代理需要從?Pilot?獲得配置,檢查并報告給?Mixer?等。
啟用雙向?TLS?通信
如果在多個集群中啟用跨集群的雙向?TLS?通信,就需要按照如下方式在各個集群中進行部署配置。首先,從共享的根?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當然,如果你的環境只是開發測試或者不需要啟用雙向?TLS?通信,上述步驟完全可以跳過。
部署本地控制平面
在所謂的本地集群上安裝一個?Istio?控制平面的過程,與在單集群上安裝?Istio?并沒有太多差別,需要注意的一點是如何配置?Envoy?代理用于管理直接訪問某個?IP?范圍內的外部服務的參數。如果是使用?Helm?安裝?Istio,那么在?Helm?中有一個名為?global.proxy.includeIPRanges?的變量,確保該變量為“*”或者包括本地集群、所有遠程集群的?pod CIDR?范圍和服務?CIDR。
可以通過查看命名空間?istio-system?下的配置項?istio-sidecar-injector 中的 traffic.sidecar.istio.io/includeOutboundIPRanges?來確認?global.proxy.includeIPRanges?參數設置,如下所示:
kubectl get configmap istio-sidecar-injector -n istio-system -o yaml| grep includeOutboundIPRanges'traffic.sidecar.istio.io/includeOutboundIPRanges' \"*\" ]]\"\n - \"-x\"\n在部署?Istio?控制平面組件的集群?cluster1?中,按照以下步驟執行。
修改?Istio?服務?istio-pilot、istio-telemetry、istio-policy?及?zipkin?的類型為內網負載均衡,將這些服務以內網方式暴露給遠程集群使用。不同的云廠商實現機制不盡相同,但大都是通過修改?annotation?的方式實現。針對阿里云容器服務來說,設置為內網負載均衡的方式非常簡單,只需要添加如下?annotation?到服務的?YAML?定義中即可:
service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet。
此外,需要按照圖中的端口定義為每一個服務進行設置。
(服務設置)
istio-pilot?服務端口如表?1?所示。
(表?1 istio-pilot?服務端口說明)
istio-telemetry?服務端口如表?2?所示
(表?2 istio-telemetry?服務端口說明)
istio-policy?服務端口如表?3?所示。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HiRY4BiM-1588041922894)(https://ucc.alicdn.com/pic/developer-ecology/a88bb9a0cf5b483cb0c3b5276773a826.png)]
(表?3 istio-policy?服務端口說明)
zipkin?服務端口如表?4?所示。
(表?4 zipkin?服務端口說明)
安裝?istio-remote
在本地集群中安裝完控制平面之后,必須將?istio-remote?組件部署到每個遠程?Kubernetes?集群。等待?Istio?控制平面完成初始化,然后再執行本節中的步驟。你必須在?Istio?控制平面集群上運行這些操作以捕獲?Istio?控制平面服務端點,例如上述提到的?Istio?服務?istio-pilot、istio-telemetry、istio-policy?以及?zipkin。
在遠程集群?cluster2?中部署?Istio-remote?組件,按照以下步驟執行:
1.在本地集群上使用以下命令設置環境變量:
export PILOT_IP=$(kubectl -n istio-system get service istio-pilot -o jsonpath='{.status.loadBalancer.ingress[0].ip}') export POLICY_IP=$(kubectl -n istio-system get service istio-policy -o jsonpath='{.status.loadBalancer.ingress[0].ip}') export TELEMETRY_IP=$(kubectl -n istio-system get service istio-telemetry -o jsonpath='{.status.loadBalancer.ingress[0].ip}') export ZIPKIN_IP=$(kubectl -n istio-system get service zipkin -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo $PILOT_IP $POLICY_IP $TELEMETRY_IP $ZIPKIN_IP2.如果在多個集群中啟用跨集群的雙向?TLS?通信,就需要在集群中進行部署配置。
當然,如果你的環境只是開發測試或者不需要啟用雙向?TLS?通信的話,該步驟完全可以跳過。在遠程?Kubernetes?集群?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.pem3.在遠程?Kubernetes?集群?cluster2?上,通過執行以下命令,使用?Helm?創建?Istio remote?部署?YAML?文件。
如果啟用了雙向?TLS?通信,則需要如下配置參數:
helm template install/kubernetes/helm/istio \--name istio-remote \--namespace istio-system \--values install/kubernetes/helm/istio/values-istio-remote.yaml \--set global.mtls.enabled=true \--set security.selfSigned=false \--set global.controlPlaneSecurityEnabled=true \--set global.remotePilotCreateSvcEndpoint=true \--set global.remotePilotAddress=${PILOT_IP} \--set global.remotePolicyAddress=${POLICY_IP} \--set global.remoteTelemetryAddress=${TELEMETRY_IP}--set global.remoteZipkinAddress=${ZIPKIN_IP} > istio-remote-auth.yaml然后將?Istio remote?組件部署到?cluster2,如下所示:
kubectl apply -f ./istio-remote-auth.yaml如果不需要啟用雙向?TLS?通信,配置參數則需要做出如下修改:
helm template install/kubernetes/helm/istio \--name istio-remote \--namespace istio-system \--values install/kubernetes/helm/istio/values-istio-remote.yaml \--set global.mtls.enabled=false \--set security.selfSigned=true \--set global.controlPlaneSecurityEnabled=false \--set global.remotePilotCreateSvcEndpoint=true \--set global.remotePilotAddress=${PILOT_IP} \--set global.remotePolicyAddress=${POLICY_IP} \--set global.remoteTelemetryAddress=${TELEMETRY_IP}--set global.remoteZipkinAddress=${ZIPKIN_IP} > istio-remote-noauth.yaml然后將?Istio remote?組件部署到?cluster2,如下所示:
kubectl apply -f ./istio-remote-noauth.yaml確保上述步驟在?Kubernetes?集群中執行成功。
4.創建集群?cluster2?的?Kubeconfig。
安裝?Istio-remote Helm chart?后,在遠程集群中創建了一個叫?istio-multi?的?Kubernetes?服務帳號,該服務帳號用于最小化?RBAC?訪問請求,對應的集群角色定義如下:
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata:name: istio-reader rules:- apiGroups: ['']resources: ['nodes', 'pods', 'services', 'endpoints']verbs: ['get', 'watch', 'list']下面的過程通過使用先前所述的?istio-multi?服務帳號憑證生成一個遠程集群的?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 Pilot?所在集群中。
在集群?dusterl?執行以下命令,將上述生成的集群?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 multicluster/sleep/sleep.yaml kubectl apply -n app1 -f multicluster/helloworld/service.yaml kubectl apply -n app1 -f multicluster/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 multicluster/helloworld/service.yaml kubectl apply -n app1 -f multicluster/helloworld/helloworld.yaml -l version=v23.驗證在集群?cluster1?中的?sleep?服務是否可以正常調用本地或者遠程集群的?helloworld?服務,在集群?cluster1?下執行如下命令:
kubectl exec $SLEEP_POD -n app1 -c sleep -- curl helloworld.app1:5000/hello如果設置正確,則在返回的調用結果中可以看到兩個版本的?helloworld?服務,同時可以通過查看?sleep?容器組中的?istio-proxy?容器日志來驗證訪問的端點?IP?地址,返回結果如下所示:
4.驗證?Istio?路由規則是否生效。
創建針對上述兩個版本的?helloworld?服務的路由規則,以便驗證?Istio?配置是否可以正常工作。
創建?Istio?虛擬服務?VirtualService,執行如下命令:
kubectl apply -n app1 -f multicluster/helloworld/virtualservice.yaml接著,創建?Istio?目標規則?DestinationRule:
- 如果啟用了雙向?TLS?通信,則需要如下配置參數:
- 如果不需要啟用雙向?TLS?通信,配置參數則需要做出修改,在?YAML?定義中添加trafficPolicy.tls.mode:ISTIO_MUTUAL,定義如下所示:
通過執行命令?kubectl apply?創建啟用雙向?TLS?的?Istio?目標規則,如下所示:
kubectl apply -n app1 -f multicluster/helloworld/destinationrule-auth.yaml多次調用?helloworld?服務,只會返回版本?v2?的響應結果,如下所示:
**《Istio服務網格技術解析與實戰》讀者可免費體驗 ASM 產品進行學習!**點擊了解阿里云服務網格產品 ASM:www.aliyun.com/product/servicemesh
作者簡介
王夕寧 阿里云高級技術專家,阿里云服務網格產品 ASM 及 Istio on Kubernetes 技術負責人,專注于 Kubernetes、云原生、服務網格等領域。曾在 IBM 中國開發中心工作,擔任過專利技術評審委員會主席,擁有 40 多項相關領域的國際技術專利。《Istio 服務網格解析與實戰》一書由其撰寫,詳細介紹了?Istio 的基本原理與開發實戰,包含大量精選案例和參考代碼可以下載,可快速入門 Istio 開發。Gartner 認為,2020?年服務網格將成為所有領先的容器管理系統的標配技術。本書適合所有對微服務和云原生感興趣的讀者,推薦大家對本書進行深入的閱讀。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MLC1jraa-1588041922897)(https://ucc.alicdn.com/pic/developer-ecology/70feb2eb51a74f968fe19a13f690536a.png)]
贈書福利
4 月 30?日 10:00 前在阿里巴巴云原生公眾號文章留言區寫下對阿里云服務網格產品 ASM 的想法或是對服務網格技術 Istio 的疑惑:
- 收獲贊最多的前 3 名,將獲得《Istio 服務網格技術解析與實踐》一書?;
- 收獲贊最多的第 4-6 名,將獲得阿里云數據線;
- 收獲贊最多的第 7-10 名,將獲得 CNCF 官方正版指尖陀螺。
“阿里巴巴云原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦云原生流行技術趨勢、云原生大規模的落地實踐,做最懂云原生開發者的公眾號。”
總結
以上是生活随笔為你收集整理的如何使用 Istio 进行多集群部署管理(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IDEA 中 30 秒生成 Spring
- 下一篇: KubeCon 改为线上举办 | 云原生