基于多集群實(shí)現(xiàn)跨地域容災(zāi)和流量負(fù)載均衡
服務(wù)網(wǎng)格ASM為應(yīng)用服務(wù)提供了跨地域流量分布和跨地域故障轉(zhuǎn)移能力。跨地域流量分布功能可以將流量按照設(shè)定的權(quán)重路由至多個集群,實(shí)現(xiàn)多地域負(fù)載均衡。跨地域故障轉(zhuǎn)移功能可以在某地域服務(wù)發(fā)生故障時,將該地域流量轉(zhuǎn)移至其他地域,實(shí)現(xiàn)跨地域容災(zāi)。以Bookinfo應(yīng)用為例,本文介紹如何使用跨地域故障轉(zhuǎn)移和流量分布能力實(shí)現(xiàn)跨地域容災(zāi)和流量負(fù)載均衡。
網(wǎng)絡(luò)規(guī)劃
在進(jìn)行操作前,您需要對vSwitch、VPC和集群的網(wǎng)段、名稱等信息進(jìn)行規(guī)劃,本文規(guī)劃如下:
關(guān)于數(shù)據(jù)平面多集群地址規(guī)劃的詳細(xì)介紹,請參見多集群網(wǎng)絡(luò)規(guī)劃。
vSwich和VPC的網(wǎng)絡(luò)規(guī)劃
vSwitch網(wǎng)絡(luò)規(guī)劃
重要為了避免使用CEN打通VPC網(wǎng)絡(luò)后產(chǎn)生路由沖突,兩個vSwitch不能使用相同的網(wǎng)段。
對象
vSwitch名稱
VPC
IPv4網(wǎng)段
集群
vpc-hangzhou-switch-1
vpc-hangzhou
20.0.0.0/16
vpc-shanghai-switch-1
vpc-shanghai
21.0.0.0/16
服務(wù)網(wǎng)格
vpc-hangzhou-switch-2
vpc-hangzhou2
192.168.0.0/24
VPC網(wǎng)絡(luò)規(guī)劃
對象
VPC名稱
Region
IPv4網(wǎng)段
集群
vpc-hangzhou
cn-hangzhou
20.0.0.0/8
vpc-shanghai
cn-shanghai
21.0.0.0/8
服務(wù)網(wǎng)格
vpc-hangzhou2
cn-hangzhou
192.168.0.0/16
集群的Pod和Service網(wǎng)絡(luò)規(guī)劃
集群名稱
Region
VPC
Pod CIDR
Service CIDR
ack-hangzhou
cn-hangzhou
vpc-hangzhou
10.0.0.0/16
172.16.0.0/16
ack-shanghai
cn-shanghai
vpc-shanghai
10.1.0.0/16
172.17.0.0/16
步驟一:創(chuàng)建不同地域的集群
按照以上規(guī)劃創(chuàng)建2個杭州和上海地域的vSwitch,然后使用vSwitch創(chuàng)建VPC。具體操作,請參見創(chuàng)建交換機(jī)和創(chuàng)建專有網(wǎng)絡(luò)和交換機(jī)。
使用上文創(chuàng)建的VPC和網(wǎng)絡(luò)規(guī)劃創(chuàng)建杭州和上海地域的集群。具體操作,請參見創(chuàng)建ACK托管集群。
根據(jù)以上規(guī)劃創(chuàng)建1個杭州地域的ASM實(shí)例。具體操作,請參見創(chuàng)建ASM實(shí)例。
步驟二:使用CEN實(shí)現(xiàn)跨地域VPC網(wǎng)絡(luò)互通
使用CEN打通集群之間的VPC網(wǎng)絡(luò),以及集群和服務(wù)網(wǎng)格之間的VPC網(wǎng)絡(luò)。
登錄云企業(yè)網(wǎng)控制臺,創(chuàng)建CEN實(shí)例。具體操作,請參見創(chuàng)建云企業(yè)網(wǎng)實(shí)例。
創(chuàng)建轉(zhuǎn)發(fā)路由器。
在云企業(yè)網(wǎng)實(shí)例頁面,單擊步驟1創(chuàng)建的云企業(yè)網(wǎng)實(shí)例名稱,然后在基本信息頁簽下方,單擊創(chuàng)建轉(zhuǎn)發(fā)路由器。
在創(chuàng)建轉(zhuǎn)發(fā)路由器對話框,選擇地域,輸入名稱,然后單擊確認(rèn)。
本示例配置了兩個轉(zhuǎn)發(fā)路由器:
地域為華東2(上海),名稱為shanghai-router。
地域為華東1(杭州),名稱為hangzhou-router。
將VPC添加到轉(zhuǎn)發(fā)路由器,為上海和杭州兩個轉(zhuǎn)發(fā)路由器重復(fù)下列步驟,將VPC連接到轉(zhuǎn)發(fā)路由器。
在云企業(yè)網(wǎng)實(shí)例頁面,單擊步驟1創(chuàng)建的云企業(yè)網(wǎng)實(shí)例名稱,然后在基本信息頁簽下方,單擊剛創(chuàng)建的轉(zhuǎn)發(fā)路由器ID,進(jìn)入轉(zhuǎn)發(fā)路由器頁面。
單擊地域內(nèi)連接管理頁簽,然后單擊創(chuàng)建網(wǎng)絡(luò)實(shí)例連接,實(shí)例類型選擇專有網(wǎng)絡(luò)(VPC),網(wǎng)絡(luò)實(shí)例選擇Region對應(yīng)的VPC實(shí)例。
其他選項(xiàng)保持默認(rèn),單擊確定創(chuàng)建。
設(shè)置跨地域帶寬。
添加安全組規(guī)則。
本文以Flannel網(wǎng)絡(luò)插件為例,在兩個集群的安全組內(nèi)添加對方集群的Pod網(wǎng)絡(luò)CIDR,允許對方集群的Pod網(wǎng)段地址的入向通信。
說明Terway網(wǎng)絡(luò)插件請使用集群vSwitch的CIDR。您可以登錄專有網(wǎng)絡(luò)管理控制臺,在交換機(jī)頁面的IPv4網(wǎng)段列,獲取vSwitch的CIDR。
登錄容器服務(wù)管理控制臺,在左側(cè)導(dǎo)航欄選擇集群。
在集群列表頁面,單擊ack-shanghai集群名稱,然后在集群信息頁面的基本信息頁簽,查看ack-shanghai集群的Pod網(wǎng)絡(luò)CIDR。
在集群列表頁面單擊ack-hangzhou集群右側(cè)操作列下的詳情。
在集群信息頁面單擊基本信息頁簽,然后單擊控制面安全組右側(cè)的安全組ID。
在安全組詳情頁簽入方向下單擊手動添加。
設(shè)置協(xié)議類型為全部,源為ack-shanghai集群的Pod網(wǎng)絡(luò)CIDR,其他為默認(rèn)值,然后單擊操作列下的保存。
重復(fù)執(zhí)行以上步驟,查看ack-hangzhou集群的Pod網(wǎng)絡(luò)CIDR,然后在ack-shanghai集群的安全組中,添加ack-hangzhou集群的Pod網(wǎng)絡(luò)CIDR。
登錄任意hangzhou集群的ECS, 使用ping命令測試與shanghai集群中的ECS是否連通。
步驟三:添加集群到ASM實(shí)例并創(chuàng)建托管式的入口網(wǎng)關(guān)
將杭州地域和上海地域的兩個集群添加到ASM實(shí)例。具體操作,請參見添加集群到ASM實(shí)例。
使用以下YAML,創(chuàng)建一個托管式的入口網(wǎng)關(guān)。具體操作,請參見創(chuàng)建入口網(wǎng)關(guān)。
apiVersion: istio.alibabacloud.com/v1beta1 kind: IstioGateway metadata: annotations: asm.alibabacloud.com/managed-by-asm: 'true' name: ingressgateway namespace: istio-system spec: gatewayType: ingress dnsPolicy: ClusterFirst externalTrafficPolicy: Local hostNetwork: false ports: - name: http port: 80 protocol: TCP targetPort: 80 - name: https port: 443 protocol: TCP targetPort: 443 replicaCount: 1 resources: limits: cpu: '2' memory: 2G requests: cpu: 200m memory: 256Mi rollingMaxSurge: 100% rollingMaxUnavailable: 25% runAsRoot: true serviceType: LoadBalancer
步驟四:部署演示應(yīng)用Bookinfo
在ack-hangzhou集群部署B(yǎng)ookinfo應(yīng)用。
使用kubectl連接到ack-hangzhou集群。具體操作,請參見獲取集群KubeConfig并通過kubectl工具連接集群。
使用以下內(nèi)容,創(chuàng)建ack-hangzhou-k8s.yaml。
# Details service apiVersion: v1 kind: Service metadata: name: details labels: app: details service: details spec: ports: - port: 9080 name: http selector: app: details --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-details labels: account: details --- apiVersion: apps/v1 kind: Deployment metadata: name: details-v1 labels: app: details version: v1 spec: replicas: 1 selector: matchLabels: app: details version: v1 template: metadata: labels: app: details version: v1 spec: serviceAccountName: bookinfo-details containers: - name: details image: docker.io/istio/examples-bookinfo-details-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 securityContext: runAsUser: 1000 --- # Ratings service apiVersion: v1 kind: Service metadata: name: ratings labels: app: ratings service: ratings spec: ports: - port: 9080 name: http selector: app: ratings --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-ratings labels: account: ratings --- apiVersion: apps/v1 kind: Deployment metadata: name: ratings-v1 labels: app: ratings version: v1 spec: replicas: 1 selector: matchLabels: app: ratings version: v1 template: metadata: labels: app: ratings version: v1 spec: serviceAccountName: bookinfo-ratings containers: - name: ratings image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 securityContext: runAsUser: 1000 --- # Reviews service apiVersion: v1 kind: Service metadata: name: reviews labels: app: reviews service: reviews spec: ports: - port: 9080 name: http selector: app: reviews --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-reviews labels: account: reviews --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v1 labels: app: reviews version: v1 spec: replicas: 1 selector: matchLabels: app: reviews version: v1 template: metadata: labels: app: reviews version: v1 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v1:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output securityContext: runAsUser: 1000 volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- # Productpage services apiVersion: v1 kind: Service metadata: name: productpage labels: app: productpage service: productpage spec: ports: - port: 9080 name: http selector: app: productpage --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-productpage labels: account: productpage --- apiVersion: apps/v1 kind: Deployment metadata: name: productpage-v1 labels: app: productpage version: v1 spec: replicas: 1 selector: matchLabels: app: productpage version: v1 template: metadata: labels: app: productpage version: v1 spec: serviceAccountName: bookinfo-productpage containers: - name: productpage image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp securityContext: runAsUser: 1000 volumes: - name: tmp emptyDir: {} ---
執(zhí)行以下命令,在ack-hangzhou集群部署B(yǎng)ookinfo應(yīng)用。
kubectl apply -f ack-hangzhou-k8s.yaml
在ack-shanghai集群部署B(yǎng)ookinfo應(yīng)用。
使用kubectl連接到ack-shanghai集群。具體操作,請參見獲取集群KubeConfig并通過kubectl工具連接集群。
說明使用kubectl連接到ack-shanghai集群時,您需要將ack-hangzhou集群的kubeconfig切換成ack-shanghai集群的kubeconfig。
使用以下內(nèi)容,創(chuàng)建ack-shanghai.yaml。
# Details service apiVersion: v1 kind: Service metadata: name: details labels: app: details service: details spec: ports: - port: 9080 name: http selector: app: details --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-details labels: account: details --- apiVersion: apps/v1 kind: Deployment metadata: name: details-v1 labels: app: details version: v1 spec: replicas: 1 selector: matchLabels: app: details version: v1 template: metadata: labels: app: details version: v1 spec: serviceAccountName: bookinfo-details containers: - name: details image: docker.io/istio/examples-bookinfo-details-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 securityContext: runAsUser: 1000 --- # Ratings service apiVersion: v1 kind: Service metadata: name: ratings labels: app: ratings service: ratings spec: ports: - port: 9080 name: http selector: app: ratings --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-ratings labels: account: ratings --- apiVersion: apps/v1 kind: Deployment metadata: name: ratings-v1 labels: app: ratings version: v1 spec: replicas: 1 selector: matchLabels: app: ratings version: v1 template: metadata: labels: app: ratings version: v1 spec: serviceAccountName: bookinfo-ratings containers: - name: ratings image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 securityContext: runAsUser: 1000 --- # Reviews service apiVersion: v1 kind: Service metadata: name: reviews labels: app: reviews service: reviews spec: ports: - port: 9080 name: http selector: app: reviews --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-reviews labels: account: reviews --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v2 labels: app: reviews version: v2 spec: replicas: 1 selector: matchLabels: app: reviews version: v2 template: metadata: labels: app: reviews version: v2 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v2:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output securityContext: runAsUser: 1000 volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- # Productpage services apiVersion: v1 kind: Service metadata: name: productpage labels: app: productpage service: productpage spec: ports: - port: 9080 name: http selector: app: productpage --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-productpage labels: account: productpage --- apiVersion: apps/v1 kind: Deployment metadata: name: productpage-v1 labels: app: productpage version: v1 spec: replicas: 1 selector: matchLabels: app: productpage version: v1 template: metadata: labels: app: productpage version: v1 spec: serviceAccountName: bookinfo-productpage containers: - name: productpage image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp securityContext: runAsUser: 1000 volumes: - name: tmp emptyDir: {} ---
執(zhí)行以下命令,在ack-shanghai集群部署B(yǎng)ookinfo應(yīng)用。
kubectl apply -f ack-shanghai.yaml
使用kubectl連接到ASM。具體操作,請參見通過控制面kubectl訪問Istio資源。
說明使用kubectl連接到ASM時,您需要將ack-shanghai集群的kubeconfig切換成ASM的kubeconfig。
在ASM中創(chuàng)建路由規(guī)則。
使用以下內(nèi)容,創(chuàng)建asm.yaml。
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: bookinfo-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: bookinfo spec: hosts: - "*" gateways: - bookinfo-gateway http: - match: - uri: exact: /productpage - uri: prefix: /static - uri: exact: /login - uri: exact: /logout - uri: prefix: /api/v1/products route: - destination: host: productpage port: number: 9080 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: productpage spec: host: productpage subsets: - name: v1 labels: version: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: reviews spec: host: reviews subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 - name: v3 labels: version: v3 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: ratings spec: host: ratings subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 - name: v2-mysql labels: version: v2-mysql - name: v2-mysql-vm labels: version: v2-mysql-vm --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: details spec: host: details subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 ---
執(zhí)行以下命令,創(chuàng)建路由規(guī)則。
kubectl apply -f asm.yaml
驗(yàn)證Bookinfo應(yīng)用是否部署成功。
在控制臺左側(cè)導(dǎo)航欄,單擊集群。
在集群列表頁面單擊ack-hangzhou集群右側(cè)操作列下的詳情。
在集群管理頁左側(cè)導(dǎo)航欄,選擇 。
在服務(wù)頁面頂部設(shè)置命名空間為Istio-system,查看istio-ingressgateway右側(cè)External IP下端口為80的IP地址。
在瀏覽器地址欄中輸入入口網(wǎng)關(guān)IP地址/productpage。
多次刷新頁面,可以看到以下圖片輪流出現(xiàn)。
步驟五:使用跨地域流量分布和跨地域故障轉(zhuǎn)移
設(shè)置跨地域流量分布
登錄ASM控制臺,在左側(cè)導(dǎo)航欄,選擇 。
在網(wǎng)格管理頁面,單擊目標(biāo)實(shí)例名稱,然后在左側(cè)導(dǎo)航欄,選擇 。
在基本信息頁面,單擊跨地域負(fù)載均衡右側(cè)的啟用跨地域流量分布。
說明如果您已經(jīng)啟用跨地域故障轉(zhuǎn)移,您需要禁用跨地域故障轉(zhuǎn)移后,才能啟用跨地域流量分布。
在跨地域流量分布對話框設(shè)置策略為cn-hangzhou,然后單擊新建策略。
單擊圖標(biāo),然后單擊圖標(biāo),設(shè)置目標(biāo)為cn-hangzhou,權(quán)重為90%。
單擊圖標(biāo),設(shè)置目標(biāo)為cn-shanghai,權(quán)重為10%,單擊確認(rèn)。
執(zhí)行以下命令,循環(huán)請求10次Bookinfo應(yīng)用,驗(yàn)證跨地域流量分布是否成功。
for ((i=1;i<=10;i++));do curl http://<ack-hangzhou集群中80端口的入口網(wǎng)關(guān)地址>/productpage 2>&1|grep full.stars;done
預(yù)期輸出:
<!-- full stars: --> <!-- full stars: -->
可以看到訪問10次,輸出2行
full stars
,說明10次請求中9次路由到了ack-hangzhou集群的v1版本reviews服務(wù),1次路由到了ack-shanghai集群的v2版本reviews服務(wù),流量按照權(quán)重路由到多個集群成功。
設(shè)置跨地域故障轉(zhuǎn)移
停用ack-hangzhou集群的review。
在控制臺左側(cè)導(dǎo)航欄,單擊集群。
在集群管理頁左側(cè)導(dǎo)航欄,選擇 。
在無狀態(tài)頁面設(shè)置命名空間為default,單擊reviews-v1右側(cè)操作列下的伸縮。
在伸縮頁面設(shè)置所需容器組數(shù)量為0,然后單擊確定。
配置DestinationRule。
配置DestinationRule,當(dāng)1s內(nèi)無法請求到reviews服務(wù),該reviews服務(wù)將被移除1min。
登錄ASM控制臺。
在左側(cè)導(dǎo)航欄,選擇 。
在網(wǎng)格管理頁面,找到待配置的實(shí)例,單擊實(shí)例的名稱或在操作列中單擊管理。
在網(wǎng)格詳情頁面左側(cè)導(dǎo)航欄,選擇 。
在目標(biāo)規(guī)則頁面單擊reviews右側(cè)操作列下的YAML。
在編輯面板增加以下內(nèi)容,然后單擊確定。
spec: ...... trafficPolicy: connectionPool: http: maxRequestsPerConnection: 1 outlierDetection: baseEjectionTime: 1m consecutive5xxErrors: 1 interval: 1s
maxRequestsPerConnection:最大連接數(shù)量。
baseEjectionTime:最小的移除時間長度。
consecutive5xxErrors:連續(xù)錯誤數(shù)量。
interval:移除檢測的時間間隔。
啟用跨地域故障轉(zhuǎn)移。
在網(wǎng)格詳情頁面左側(cè)導(dǎo)航欄,選擇 。
在基本信息頁面單擊跨地域負(fù)載均衡右側(cè)的啟用跨地域故障轉(zhuǎn)移。
說明如果您已經(jīng)啟用跨地域流量分布,您需要禁用跨地域流量分布后,才能啟用跨地域故障轉(zhuǎn)移。
在跨地域故障轉(zhuǎn)移對話框中設(shè)置當(dāng)策略源是cn-shanghai,源故障轉(zhuǎn)移至cn-hangzhou,當(dāng)策略源是cn-hangzhou,源故障轉(zhuǎn)移至cn-shanghai,然后單擊確認(rèn)。
執(zhí)行以下命令,循環(huán)請求10次Bookinfo應(yīng)用,并對路由到v2版本reviews服務(wù)的結(jié)果數(shù)量進(jìn)行統(tǒng)計(jì)。
for ((i=1;i<=10;i++));do curl http://<ack-hangzhou集群中80端口的入口網(wǎng)關(guān)地址>/productpage 2>&1|grep full.stars;done|wc -l
預(yù)期輸出:
20
可以看到訪問10次,返回20(每次路由到v2版本reviews服務(wù)會返回兩行包含
full stars
的結(jié)果),說明10次請求全部路由到了ack-shanghai集群的v2版本reviews服務(wù),跨地域故障轉(zhuǎn)移成功。
FAQ
為什么通過云企業(yè)網(wǎng)CEN打通了集群VPC網(wǎng)絡(luò),在ASM中加入K8s集群仍然提示失敗?
當(dāng)您的集群處于不同地域,在打通集群VPC網(wǎng)絡(luò)時,您若未購買跨地域流量包,或者未正確設(shè)置跨地域流量,ASM控制平面將無法連接到數(shù)據(jù)平面集群,導(dǎo)致ASM添加集群失敗。
針對以上這個問題,您需要重新在云企業(yè)網(wǎng)CEN中設(shè)置跨地域流量打通集群VPC網(wǎng)絡(luò),具體操作,請參見步驟二:使用CEN實(shí)現(xiàn)跨地域VPC網(wǎng)絡(luò)互通。