天天看點

如何使用 Istio 進行多叢集部署管理:多控制平面

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

如何使用 Istio 進行多叢集部署管理:多控制平面

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

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

前文詳情:

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

在多控制平面拓撲的配置中,每個 Kubernetes 叢集都會安裝相同的 Istio 控制平面,并且每個控制平面隻會管理自己叢集内的服務端點。通過使用 Istio 網關、公共根證書頒發機構(CA)以及服務條目 ServiceEntry,可以将多個叢集配置組成一個邏輯上的單一服務網格。這種方法沒有特殊的網絡要求,是以通常被認為是在 Kubernetes 叢集之間沒有通用網絡連接配接時的一種最簡單方法。

在這種拓撲配置下,Kubernetes 跨叢集通信需要服務之間的雙向 TLS 連接配接,要在叢集之間啟用雙向 TLS 通信,每個叢集的 Citadel 将配置由共享的根 CA 生成的中間 CA 證書,如圖所示。

如何使用 Istio 進行多叢集部署管理:多控制平面

(多控制平面)

部署控制平面

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

在每個 Kubernetes 叢集中實施以下步驟,以在所有叢集中部署相同的 Istio 控制平面配置。

  1. 使用以下的指令為生成的 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
           
  1. 安裝 Istio 的 CRD 并等待幾秒鐘,以便将它們送出給 Kubernetes API 伺服器,如下所示:
for
i in install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl apply -f $i;
done
           
  1. 部署 Istio 控制平面:如果 helm 依賴項缺失或者不是最新的,可以通過 helm dep update 來更新這些依賴項。注意因為沒有使用 istio-cni,可以暫時将其從依賴項 requirements.yaml 中去掉再執行更新操作。具體執行指令如下:
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 的指令執行一次即可。

設定 DNS

為遠端叢集中的服務提供 DNS 解析,則現有應用程式不需要做修改就可以運作,因為應用程式通常期望通過其 DNS 名稱來解析服務并通路所得到的 IP 位址。Istio 本身不使用 DNS 在服務之間路由請求,同一個 Kubernetes 叢集下的服務會共享一個相同的 DNS 字尾(例如 svc.cluster.local)。Kubernetes DNS 為這些服務提供 DNS 解析能力。為了給遠端叢集中的服務提供相似的設定,将遠端叢集中的服務以 ..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 服務。

  1. 部署 sleep 服務到第一個叢集 cluster1 中,執行如下指令:
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})
           
  1. 部署 httpbin 服務到第二個叢集 cluster2 中,執行如下指令:
kubectl
create namespace app2
kubectl
label namespace app2 istio-injection=enabled
kubectl
apply -n app2 -f samples/httpbin/httpbin.yaml
           
  1. 擷取叢集 cluster2 的入口網關位址,如下所示:
export
CLUSTER2_GW_ADDR=$(kubectl get svc --selector=app=istio-ingressgateway \
  -n istio-system -o
jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}")
           
  1. 為了讓在叢集 cluster1 中的服務 sleep 能夠通路叢集 cluster2 中的服務 httpbin,我們需要在叢集 cluster1 中為服務 httpbin 建立一個服務條目 ServiceEntry 資源。服務條目 ServiceEntry 的主機名應該是..globalname,其中 name 和 namespace 分别對應于叢集 cluster2 中的遠端服務的名稱和命名空間。

對于 *.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 連接配接的端點 :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
           

執行結果如下所示:

如何使用 Istio 進行多叢集部署管理:多控制平面
  1. 驗證在叢集 cluster1 中的 sleep 服務是否可以正常調用位于叢集 cluster2 中的 httpbin 服務,在叢集 cluster1 執行如下指令:
kubectl
exec $SLEEP_POD -n app1 -c sleep -- curl httpbin.app2.global:8000/headers
           
如何使用 Istio 進行多叢集部署管理:多控制平面

至此,叢集 cluster1 與 cluster2 在多控制平面配置下完成了連通。

跨叢集的版本路由

通過前面的文章,我們已經了解了 Istio 的很多功能,例如基本版本的路由等,可以在單個 Kubernetes 叢集上很容易地實作。而很多真實的業務場景中,基于微服務的應用程式并非那麼簡單,而是需要在多個位置跨叢集去配置設定和運作服務。那麼問題就來了,是否 Istio 的這些功能同樣可以很簡單地運作在這些真實的複雜環境中呢?

下面我們将會通過一個示例來了解 Istio 的流量管理功能如何在具有多個控制平面拓撲的多叢集網格中正常運作。

  1. 首先,部署版本 v1 的 helloworld 服務到第一個叢集 cluster1 中,執行如下指令:
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
           
  1. 部署版本 v2 與 v3 的 helloworld 服務到第二個叢集 cluster2 中,執行如下指令:
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
           
  1. 如前面章節中所述,多控制平面下,需要使用以 .global 為字尾的 DNS 名稱通路遠端服務。

在我們的例子中,它是 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
           
  1. 在兩個叢集上建立目标規則。在叢集 cluster1 中建立子集 v1 對應的目标規則,執行如下指令:
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
           
  1. 建立虛拟服務以路由流量。

應用下面的虛拟服務将會使得來自使用者 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
           

執行多次調用,可以從下面的執行結果中看出,上述流量路由的規則生效,這也說明了在多控制平面拓撲下,用于路由的規則定義與在本地叢集的使用方式是一樣的:

如何使用 Istio 進行多叢集部署管理:多控制平面

設定多叢集網格的最簡單方法是使用多控制平面拓撲,因為它沒有特殊的網絡要求。通過上述示例可以看出,在單個 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 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的公衆号。”

繼續閱讀