做者 | 王夕寧 阿里雲高級技術專家json
導讀:本文摘自於阿里雲高級技術專家王夕寧撰寫的《Istio 服務網格技術解析與實戰》一書,講述瞭如何使用 Istio 進行多集羣部署管理來闡述服務網格對多雲環境、多集羣即混合部署的支持能力。api
前文詳情:服務器
在多控制平面拓撲的配置中,每一個 Kubernetes 集羣都會安裝相同的 Istio 控制平面,而且每一個控制平面只會管理本身集羣內的服務端點。經過使用 Istio 網關、公共根證書頒發機構(CA)以及服務條目 ServiceEntry,能夠將多個集羣配置組成一個邏輯上的單一服務網格。這種方法沒有特殊的網絡要求,所以一般被認爲是在 Kubernetes 集羣之間沒有通用網絡鏈接時的一種最簡單方法。網絡
在這種拓撲配置下,Kubernetes 跨集羣通訊須要服務之間的雙向 TLS 鏈接,要在集羣之間啓用雙向 TLS 通訊,每一個集羣的 Citadel 將配置由共享的根 CA 生成的中間 CA 證書,如圖所示。app
(多控制平面)負載均衡
從共享的根 CA 爲每一個集羣的 Citadel 生成中間 CA 證書,共享的根 CA 啓用跨不一樣集羣的雙向 TLS 通訊。爲了便於說明,咱們將 samples/certs 目錄下 Istio 安裝中提供的示例根 CA 證書用於兩個集羣。在實際部署中,你可能會爲每一個集羣使用不一樣的 CA 證書,全部 CA 證書都由公共根 CA 簽名。less
在每一個 Kubernetes 集羣中實施如下步驟,以在全部集羣中部署相同的 Istio 控制平面配置。curl
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
for i in install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl apply -f $i; done
helm template install/kubernetes/helm/istio --name istio --namespace istio-system \ -f install/kubernetes/helm/istio/values-istio-multicluster-gateways.yaml > ./istio.yaml kubectl apply -f ./istio.yaml
確保上述步驟在每一個 Kubernetes 集羣中都執行成功。固然,經過 helm 生成 istio.yaml 的命令執行一次便可。ide
爲遠程集羣中的服務提供 DNS 解析,則現有應用程序不須要作修改就能夠運行,由於應用程序一般指望經過其 DNS 名稱來解析服務並訪問所獲得的 IP 地址。Istio 自己不使用 DNS 在服務之間路由請求,同一個 Kubernetes 集羣下的服務會共享一個相同的 DNS 後綴(例如 svc.cluster.local)。Kubernetes DNS 爲這些服務提供 DNS 解析能力。爲了給遠程集羣中的服務提供類似的設置,將遠程集羣中的服務以 <name>.<namespace>.global 的格式命名。微服務
Istio 安裝包中附帶了一個 CoreDNS 服務器,該服務器將爲這些服務提供DNS解析能力。爲了利用這個 DNS 解析能力,須要配置 Kubernetes 的 DNS 服務指向該 CoreDNS 服務。該 CoreDNS 服務將做爲 .global DNS 域的 DNS 服務器。
對於使用 kube-dns 的集羣,請建立如下配置項或更新現有的配置項:
kubectl apply -f - <<EOF apiVersion: v1 kind: ConfigMap metadata: name: kube-dns namespace: kube-system data: stubDomains: | {"global": ["$(kubectl get svc -n istio-system istiocoredns -o jsonpath={.spec.clusterIP})"]} EOF
對於使用 CoreDNS 的集羣,請建立如下配置項或更新現有的配置項:
kubectl apply -f - <<EOF apiVersion: v1 kind: ConfigMap metadata: name: coredns namespace: kube-system data: Corefile: | .:53 { errors health kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure upstream fallthrough in-addr.arpa ip6.arpa } prometheus :9153 proxy . /etc/resolv.conf cache 30 reload loadbalance } global:53 { errors cache 30 proxy . $(kubectl get svc -n istio-system istiocoredns -o jsonpath={. spec.clusterIP}) } EOF
爲了演示跨集羣訪問,在一個 Kubernetes 集羣中部署 sleep 應用服務,在第二個集羣中部署 httpbin 應用服務,而後驗證 sleep 應用是否能夠調用遠程集羣的 httpbin 服務。
kubectl create namespace app1 kubectl label namespace app1 istio-injection=enabled kubectl apply -n app1 -f samples/sleep/sleep.yaml export SLEEP_POD=$(kubectl get -n app1 pod -l app=sleep -o jsonpath={.items..metadata.name})
kubectl create namespace app2 kubectl label namespace app2 istio-injection=enabled kubectl apply -n app2 -f samples/httpbin/httpbin.yaml
export CLUSTER2_GW_ADDR=$(kubectl get svc --selector=app=istio-ingressgateway \ -n istio-system -o jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}")
對於 *.global 域下服務的 DNS 解析,須要爲這些服務分配一個 IP 地址,而且保證 .globalDNS 域中的每一個服務在集羣中必須具備惟一的 IP 地址。這些 IP 地址在 pod 以外是不可路由的。在這個例子中,咱們將使用網段 127.255.0.0/16 來避免與其餘的IP衝突。這些 IP 的應用流量將由 Sidecar 代理捕獲並路由到適當的其餘遠程服務。
在集羣 cluster1 中建立該 httpbin 服務對應的 ServiceEntry,執行以下命令:
kubectl apply -n app1 -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: httpbin-app2 spec: hosts: # must be of form name.namespace.global - httpbin.app2.global # Treat remote cluster services as part of the service mesh # as all clusters in the service mesh share the same root of trust. location: MESH_INTERNAL ports: - name: http1 number: 8000 protocol: http resolution: DNS addresses: # the IP address to which httpbin.bar.global will resolve to # must be unique for each remote service, within a given cluster. # This address need not be routable. Traffic for this IP will be captured # by the sidecar and routed appropriately. - 127.255.0.2 endpoints: # This is the routable address of the ingress gateway in cluster2 that # sits in front of sleep.bar service. Traffic from the sidecar will be # routed to this address. - address: ${CLUSTER2_GW_ADDR} ports: http1: 15443 # Do not change this port value EOF
上面的配置將會使集羣 cluster1 中訪問 httpbin.app2.global 的全部流量,包括訪問它的任何端口的流量,都會被路由到啓用了雙向 TLS 鏈接的端點 <IPofCluster2IngressGateway>:15443 上。
端口 15443 的網關是一個特殊的 SNI 感知的 Envoy 代理,它是在前面開始部分中做爲多集羣 Istio 安裝步驟的一部分預先配置和安裝的。進入端口 15443 的流量將在目標集羣的適當內部服務的 pod 中進行負載均衡。
在集羣 cluster1 下執行以下命令查看容器 istiocoredns,能夠看到上述 ServiceEntry 的域名映射關係已經被加載:
export ISTIO_COREDNS=$(kubectl get -n istio-system po -l app=istiocoredns -o jsonpath={.items..metadata.name}) kubectl logs --tail 2 -n istio-system ${ISTIO_COREDNS} -c istio-coredns-plugin
執行結果以下所示:
kubectl exec $SLEEP_POD -n app1 -c sleep -- curl httpbin.app2.global:8000/headers
執行結果以下所示:
至此,集羣 cluster1 與 cluster2 在多控制平面配置下完成了連通。
經過前面的文章,咱們已經瞭解了 Istio 的不少功能,例如基本版本的路由等,能夠在單個 Kubernetes 集羣上很容易地實現。而不少真實的業務場景中,基於微服務的應用程序並不是那麼簡單,而是須要在多個位置跨集羣去分配和運行服務。那麼問題就來了,是否 Istio 的這些功能一樣能夠很簡單地運行在這些真實的複雜環境中呢?
下面咱們將會經過一個示例來了解 Istio 的流量管理功能如何在具備多個控制平面拓撲的多集羣網格中正常運行。
kubectl create namespace hello kubectl label namespace hello istio-injection=enabled kubectl apply -n hello -f samples/sleep/sleep.yaml kubectl apply -n hello -f samples/helloworld/service.yaml kubectl apply -n hello -f samples/helloworld/helloworld.yaml -l version=v1
kubectl create namespace hello kubectl label namespace hello istio-injection=enabled kubectl apply -n hello -f samples/helloworld/service.yaml kubectl apply -n hello -f samples/helloworld/helloworld.yaml -l version=v2 kubectl apply -n hello -f samples/helloworld/helloworld.yaml -l version=v3
在咱們的例子中,它是 helloworld.hello.global,因此咱們須要在集羣 cluster1 中建立服務條目 ServiceEntry 和目標規則 DestinationRule。服務條目 ServiceEntry 將使用集羣 cluster2 的入口網關做爲端點地址來訪問服務。
經過使用如下命令在集羣 cluster1 中建立 helloworld 服務對應的服務條目 ServiceEntry 和目標規則DestinationRule:
kubectl apply -n hello -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: helloworld spec: hosts: - helloworld.hello.global location: MESH_INTERNAL ports: - name: http1 number: 5000 protocol: http resolution: DNS addresses: - 127.255.0.8 endpoints: - address: ${CLUSTER2_GW_ADDR} labels: cluster: cluster2 ports: http1: 15443 # Do not change this port value --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: helloworld-global spec: host: helloworld.hello.global trafficPolicy: tls: mode: ISTIO_MUTUAL subsets: - name: v2 labels: cluster: cluster2 - name: v3 labels: cluster: cluster2 EOF
kubectl apply -n hello -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: helloworld spec: host: helloworld.hello.svc.cluster.local trafficPolicy: tls: mode: ISTIO_MUTUAL subsets: - name: v1 labels: version: v1 EOF
而在集羣 cluster2 中建立子集 v2 和 v3 對應的目標規則,執行以下命令:
kubectl apply -n hello -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: helloworld spec: host: helloworld.hello.svc.cluster.local trafficPolicy: tls: mode: ISTIO_MUTUAL subsets: - name: v2 labels: version: v2 - name: v3 labels: version: v3 EOF
應用下面的虛擬服務將會使得來自用戶 jason 對 helloworld 的流量請求指向位於集羣 cluster2 中的版本 v2 和 v3,其中 v2 比例爲 70%,v3 比例爲 30%;來自任何其餘用戶對 helloworld 的流量請求都將轉到位於集羣 cluster1 中的版本 v1:
kubectl apply -n hello -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: helloworld spec: hosts: - helloworld.hello.svc.cluster.local - helloworld.hello.global http: - match: - headers: end-user: exact: jason route: - destination: host: helloworld.hello.global subset: v2 weight: 70 - destination: host: helloworld.hello.global subset: v3 weight: 30 - route: - destination: host: helloworld.hello.svc.cluster.local subset: v1 EOF
執行屢次調用,能夠從下面的執行結果中看出,上述流量路由的規則生效,這也說明了在多控制平面拓撲下,用於路由的規則定義與在本地集羣的使用方式是同樣的:
設置多集羣網格的最簡單方法是使用多控制平面拓撲,由於它沒有特殊的網絡要求。經過上述示例能夠看出,在單個 Kubernetes 集羣上運行的路由功能一樣很容易地在多個集羣中使用運行。
《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 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,作最懂雲原生開發者的公衆號。」