Kubernetes 多區(qū)域擴(kuò)展輕松搞定:遠(yuǎn)不像你想象的那么難!
對(duì) Kubernetes 來(lái)說(shuō),跨越多個(gè)地域(Region)部署工作負(fù)載,這是個(gè)有趣的挑戰(zhàn)。雖然從技術(shù)上來(lái)說(shuō),我們可以用分布在多個(gè)地域的節(jié)點(diǎn)創(chuàng)建集群,但因?yàn)闀?huì)造成額外的延遲,通常并不建議這樣做。
一種比較流行的替代方法是在每個(gè)地域部署一個(gè)集群,然后設(shè)法對(duì)多個(gè)集群進(jìn)行必要的編排。
本文將介紹如何:
- 分別在北美、歐洲和東南亞各自創(chuàng)建一個(gè)集群。
- 創(chuàng)建第四個(gè)集群,將其作為上述三個(gè)集群的編排器。
- 設(shè)置一個(gè)將三個(gè)集群連接在一起的網(wǎng)絡(luò),從而實(shí)現(xiàn)跨集群的無(wú)縫通信。
本文涉及的操作均可通過(guò)腳本實(shí)現(xiàn),只需最少量人工介入即可適用于 Terraform。相關(guān)代碼請(qǐng)?jiān)L問(wèn) LearnK8s GitHub。
慶祝 Linode 加入 Akamai 解決方案大家庭,現(xiàn)在注冊(cè) Linode,就可免費(fèi)獲得價(jià)值 100 美元的使用額度,可以隨意使用 Linode 云平臺(tái)提供的各種服務(wù)。立即點(diǎn)擊這里了解詳情并注冊(cè)吧↓↓↓
出海云服務(wù),Akamai 是您的不二之選!
創(chuàng)建集群管理器
首先創(chuàng)建用于管理其余集群的集群。我們可以通過(guò)下列命令創(chuàng)建該集群并保存 Kubeconfig 文件。
bash
$ linode-cli lke cluster-create \
--label cluster-manager \
--region eu-west \
--k8s_version 1.23
$ linode-cli lke kubeconfig-view "insert cluster id here" --text | tail +2 | base64 -d > kubeconfig-cluster-manager
隨后可通過(guò)下列命令驗(yàn)證安裝過(guò)程已成功完成:
bash
$ kubectl get pods -A --kubecnotallow=kubeconfig-cluster-manager
我們還需要在集群管理器中安裝 Karmada,這個(gè)管理系統(tǒng)可以幫助我們跨越多個(gè) Kubernetes 集群或多個(gè)云平臺(tái)運(yùn)行自己的云原生應(yīng)用程序。Karmada 是一種安裝在集群管理器中的控制平面,其他集群中需要安裝代理程序。
該控制平面包含三個(gè)組件:
- 一個(gè) API 服務(wù)器(API Server)
- 一個(gè)控制器管理器(Controller Manager)
- 一個(gè)調(diào)度器(Scheduler)
是否看起來(lái)覺(jué)得很熟悉?這是因?yàn)樗c Kubernetes 控制平面功能其實(shí)是相同組件,只不過(guò) Karmada 能適用于多種集群。
理論部分說(shuō)的差不多了,接下來(lái)開(kāi)始看看具體要用的代碼。我們可以使用 Helm 安裝 Karmada API 服務(wù)器。為此可使用下列命令添加 Helm 倉(cāng)庫(kù):
bash
$ helm repo add karmada-charts https://raw.githubusercontent.com/karmada-io/karmada/master/charts
$ helm repo list
NAME URL
karmada-charts https://raw.githubusercontent.com/karmada-io/karmada/master/charts
由于 Karmada API 服務(wù)器必須能被所有其他集群訪問(wèn),因此我們必須:
- 從節(jié)點(diǎn)上將其暴露出來(lái);并且
- 確保連接是可信任的。
因此首先需要通過(guò)下列命令獲取承載了控制平面的節(jié)點(diǎn)的 IP 地址:
bash
kubectl get nodes -o jsnotallow='{.items[0].status.addresses[?(@.type==\"ExternalIP\")].address}' \
--kubecnotallow=kubeconfig-cluster-manager
隨后即可用下列命令安裝 Karmada 控制平面:
bash
$ helm install karmada karmada-charts/karmada \
--kubecnotallow=kubeconfig-cluster-manager \
--create-namespace --namespace karmada-system \
--versinotallow=1.2.0 \
--set apiServer.hostNetwork=false \
--set apiServer.serviceType=NodePort \
--set apiServer.nodePort=32443 \
--set certs.auto.hosts[0]="kubernetes.default.svc" \
--set certs.auto.hosts[1]="*.etcd.karmada-system.svc.cluster.local" \
--set certs.auto.hosts[2]="*.karmada-system.svc.cluster.local" \
--set certs.auto.hosts[3]="*.karmada-system.svc" \
--set certs.auto.hosts[4]="localhost" \
--set certs.auto.hosts[5]="127.0.0.1" \
--set certs.auto.hosts[6]="<insert the IP address of the node>"
安裝完成后,即可通過(guò)下列命令獲得 Kubeconfig 并連接到 Karmada API:
bash
kubectl get secret karmada-kubeconfig \
--kubecnotallow=kubeconfig-cluster-manager \
-n karmada-system \
-o jsnotallow={.data.kubeconfig} | base64 -d > karmada-config
不過(guò)為什么這里要用另一個(gè) Kubeconfig 文件?
按照設(shè)計(jì),Karmada API 是為了取代標(biāo)準(zhǔn)的 Kubernetes API,同時(shí)依然提供了用戶需要的全部功能。換句話說(shuō),我們可以借助 kubectl 創(chuàng)建橫跨多個(gè)集群的部署。
在測(cè)試 Karmada API 和 kubectl 之前,還需要調(diào)整 Kubeconfig 文件。默認(rèn)情況下生成的 Kubeconfig 只能在集群網(wǎng)絡(luò)的內(nèi)部使用。不過(guò)我們只需調(diào)整這幾行內(nèi)容就可以消除這一限制:
yaml
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTi…
insecure-skip-tls-verify: false
server: https://karmada-apiserver.karmada-system.svc.cluster.local:5443 # <- this works only in the cluster
name: karmada-apiserver
# truncated
請(qǐng)將之前獲取的節(jié)點(diǎn) IP 地址替換進(jìn)去:
yaml
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTi…
insecure-skip-tls-verify: false
server: https://<node's IP address>:32443 # <- this works from the public internet
name: karmada-apiserver
# truncated
接下來(lái)就可以開(kāi)始測(cè)試 Karmada 了。
安裝 Karmada 代理程序
運(yùn)行下列命令檢索所有部署和所有集群:
bash
$ kubectl get clusters,deployments --kubecnotallow=karmada-config
No resources found
可想而知,目前沒(méi)有任何部署,也沒(méi)有任何額外的集群。我們可以添加幾個(gè)集群并將其連接到 Karmada 控制平面。
請(qǐng)重復(fù)執(zhí)行下列命令三次:
bash
linode-cli lke cluster-create \
--label <insert-cluster-name> \
--region <insert-region> \
--k8s_version 1.23
linode-cli lke kubeconfig-view "insert cluster id here" --text | tail +2 | base64 -d > kubeconfig-<insert-cluster-name>
執(zhí)行時(shí)請(qǐng)分別使用如下的值:
- Cluster name eu, region eu-west 以及 kubeconfig file kubeconfig-eu
- Cluster name ap, region ap-south 以及 kubeconfig file kubeconfig-ap
- Cluster name us, region us-west 以及 kubeconfig file kubeconfig-us
隨后通過(guò)下列命令確認(rèn)集群已經(jīng)成功創(chuàng)建:
bash
$ kubectl get pods -A --kubecnotallow=kubeconfig-eu
$ kubectl get pods -A --kubecnotallow=kubeconfig-ap
$ kubectl get pods -A --kubecnotallow=kubeconfig-us
接下來(lái)要將這些集群加入 Karmada 集群。Karmada 需要在其他每個(gè)集群中使用代理程序來(lái)協(xié)調(diào)控制平面的部署。
我們可以使用 Helm 安裝 Karmada 代理程序并將其鏈接至集群管理器:
bash
$ helm install karmada karmada-charts/karmada \
--kubecnotallow=kubeconfig-<insert-cluster-name> \
--create-namespace --namespace karmada-system \
--versinotallow=1.2.0 \
--set installMode=agent \
--set agent.clusterName=<insert-cluster-name> \
--set agent.kubeconfig.caCrt=<karmada kubeconfig certificate authority> \
--set agent.kubeconfig.crt=<karmada kubeconfig client certificate data> \
--set agent.kubeconfig.key=<karmada kubeconfig client key data> \
--set agent.kubeconfig.server=https://<insert node's IP address>:32443 \
上述命令同樣需要重復(fù)三次,每次分別插入下列變量:
- 集群名稱:分別為 eu、ap 和 us。
- 集群管理器的證書(shū)授權(quán)機(jī)構(gòu)。我們可以在 karmada-config 文件的 clusters [0].cluster ['certificate-authority-data'] 中找到該值,這些值可以通過(guò) base64 進(jìn)行解碼。
- 用戶的客戶端證書(shū)數(shù)據(jù)。我們可以在 karmada-config 文件的 users [0].user ['client-certificate-data'] 中找到該值,這些值可以通過(guò) base64 進(jìn)行解碼。
- 用戶的客戶端密鑰數(shù)據(jù)。我們可以在 karmada-config 文件的 users [0].user ['client-key-data'] 中找到該值,這些值可以通過(guò) base64 進(jìn)行解碼。
- 承載 Karmada 控制平面的節(jié)點(diǎn)的 IP 地址。
隨后可以運(yùn)行下列命令來(lái)驗(yàn)證安裝是否成功完成:
bash
$ kubectl get clusters --kubecnotallow=karmada-config
NAME VERSION MODE READY
eu v1.23.8 Pull True
ap v1.23.8 Pull True
us v1.23.8 Pull True
借助 Karmada Policies 編排多集群部署
只要配置正確無(wú)誤,我們即可將工作負(fù)載提交給 Karmada,由它將任務(wù)分發(fā)給其他集群。
為了進(jìn)行測(cè)試,我們首先需要?jiǎng)?chuàng)建一個(gè)部署:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
replicas: 3
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- image: stefanprodan/podinfo
name: hello
---
apiVersion: v1
kind: Service
metadata:
name: hello
spec:
ports:
- port: 5000
targetPort: 9898
selector:
app: hello
隨后通過(guò)下列命令將該部署提交至 Karmada API 服務(wù)器:
bash
$ kubectl apply -f deployment.yaml --kubecnotallow=karmada-config
該部署包含三個(gè)副本,那么是否可以平均分發(fā)給這三個(gè)集群?一起來(lái)驗(yàn)證一下:
bash
$ kubectl get deployments --kubecnotallow=karmada-config
NAME READY UP-TO-DATE AVAILABLE
hello 0/3 0 0
Karmada 為何沒(méi)有創(chuàng)建 Pod?先來(lái)看看這個(gè)部署:
bash
$ kubectl describe deployment hello --kubecnotallow=karmada-config
Name: hello
Namespace: default
Selector: app=hello
Replicas: 3 desired | 0 updated | 0 total | 0 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Events:
Type Reason From Message
---- ------ ---- -------
Warning ApplyPolicyFailed resource-detector No policy match for resource
Karmada 并不知道該如何處理這個(gè)部署,因?yàn)槲覀兩形粗付ú呗浴?/span>
Karmada 調(diào)度器會(huì)使用策略將工作負(fù)載分配給集群。那么我們就定義一個(gè)簡(jiǎn)單的策略,為每個(gè)集群分配一個(gè)副本:
yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: hello-propagation
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: hello
- apiVersion: v1
kind: Service
name: hello
placement:
clusterAffinity:
clusterNames:
- eu
- ap
- us
replicaScheduling:
replicaDivisionPreference: Weighted
replicaSchedulingType: Divided
weightPreference:
staticWeightList:
- targetCluster:
clusterNames:
- us
weight: 1
- targetCluster:
clusterNames:
- ap
weight: 1
- targetCluster:
clusterNames:
- eu
weight: 1
并用下列命令將該策略提交給集群:
bash
$ kubectl apply -f policy.yaml --kubecnotallow=karmada-config
然后再來(lái)看看部署和 Pod:
bash
$ kubectl get deployments --kubecnotallow=karmada-config
NAME READY UP-TO-DATE AVAILABLE
hello 3/3 3 3
$ kubectl get pods --kubecnotallow=kubeconfig-eu
NAME READY STATUS RESTARTS
hello-5d857996f-hjfqq 1/1 Running 0
$ kubectl get pods --kubecnotallow=kubeconfig-ap
NAME READY STATUS RESTARTS
hello-5d857996f-xr6hr 1/1 Running 0
$ kubectl get pods --kubecnotallow=kubeconfig-us
NAME READY STATUS RESTARTS
hello-5d857996f-nbz48 1/1 Running 0
Karmada 會(huì)為每個(gè)集群分配一個(gè) Pod,因?yàn)椴呗灾袨槊總€(gè)集群定義了相等的權(quán)重。
我們用下列命令將該部署擴(kuò)展為 10 個(gè)副本:
bash
$ kubectl scale deployment/hello --replicas=10 --kubecnotallow=karmada-config
隨后查看 Pod 會(huì)看到如下的結(jié)果:
bash
$ kubectl get deployments --kubecnotallow=karmada-config
NAME READY UP-TO-DATE AVAILABLE
hello 10/10 10 10
$ kubectl get pods --kubecnotallow=kubeconfig-eu
NAME READY STATUS RESTARTS
hello-5d857996f-dzfzm 1/1 Running 0
hello-5d857996f-hjfqq 1/1 Running 0
hello-5d857996f-kw2rt 1/1 Running 0
hello-5d857996f-nz7qz 1/1 Running 0
$ kubectl get pods --kubecnotallow=kubeconfig-ap
NAME READY STATUS RESTARTS
hello-5d857996f-pd9t6 1/1 Running 0
hello-5d857996f-r7bmp 1/1 Running 0
hello-5d857996f-xr6hr 1/1 Running 0
$ kubectl get pods --kubecnotallow=kubeconfig-us
NAME READY STATUS RESTARTS
hello-5d857996f-nbz48 1/1 Running 0
hello-5d857996f-nzgpn 1/1 Running 0
hello-5d857996f-rsp7k 1/1 Running 0
隨后修改策略,讓 EU 和 US 集群各承載 40% 的 Pod,讓 AP 集群只承載 20%。
yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: hello-propagation
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: hello
- apiVersion: v1
kind: Service
name: hello
placement:
clusterAffinity:
clusterNames:
- eu
- ap
- us
replicaScheduling:
replicaDivisionPreference: Weighted
replicaSchedulingType: Divided
weightPreference:
staticWeightList:
- targetCluster:
clusterNames:
- us
weight: 2
- targetCluster:
clusterNames:
- ap
weight: 1
- targetCluster:
clusterNames:
- eu
weight: 2
并通過(guò)下列命令提交策略:
bash
$ kubectl apply -f policy.yaml --kubecnotallow=karmada-config
接著可以看到,Pod 的分配情況也酌情產(chǎn)生了變化:
bash
$ kubectl get pods --kubecnotallow=kubeconfig-eu
NAME READY STATUS RESTARTS AGE
hello-5d857996f-hjfqq 1/1 Running 0 6m5s
hello-5d857996f-kw2rt 1/1 Running 0 2m27s
$ kubectl get pods --kubecnotallow=kubeconfig-ap
hello-5d857996f-k9hsm 1/1 Running 0 51s
hello-5d857996f-pd9t6 1/1 Running 0 2m41s
hello-5d857996f-r7bmp 1/1 Running 0 2m41s
hello-5d857996f-xr6hr 1/1 Running 0 6m19s
$ kubectl get pods --kubecnotallow=kubeconfig-us
hello-5d857996f-nbz48 1/1 Running 0 6m29s
hello-5d857996f-nzgpn 1/1 Running 0 2m51s
hello-5d857996f-rgj9t 1/1 Running 0 61s
hello-5d857996f-rsp7k 1/1 Running 0 2m51s
Karmada 支持通過(guò)多種策略分配工作負(fù)載,更多高級(jí)用例可以參考文檔。
Pod 在三個(gè)集群中運(yùn)行,但我們?cè)撊绾卧L問(wèn)?
先來(lái)看看 Karmada 中的服務(wù):
bash
$ kubectl describe service hello --kubecnotallow=karmada-config
Name: hello
Namespace: default
Labels: propagationpolicy.karmada.io/name=hello-propagation
propagationpolicy.karmada.io/namespace=default
Selector: app=hello
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.105.24.193
IPs: 10.105.24.193
Port: <unset> 5000/TCP
TargetPort: 9898/TCP
Events:
Type Reason Message
---- ------ -------
Normal SyncSucceed Successfully applied resource(default/hello) to cluster ap
Normal SyncSucceed Successfully applied resource(default/hello) to cluster us
Normal SyncSucceed Successfully applied resource(default/hello) to cluster eu
Normal AggregateStatusSucceed Update resourceBinding(default/hello-service) with AggregatedStatus successfully.
Normal ScheduleBindingSucceed Binding has been scheduled
Normal SyncWorkSucceed Sync work of resourceBinding(default/hello-service) successful.
這些服務(wù)被部署在全部的三個(gè)集群中,但彼此之間并未連接。
盡管 Karmada 可以管理多個(gè)集群,但它并未提供任何網(wǎng)絡(luò)機(jī)制將這三個(gè)集群連接在一起。換句話說(shuō),Karmada 是一種跨越多個(gè)集群編排部署的好工具,但我們需要通過(guò)其他機(jī)制讓這些集群相互通信。
使用 Istio 連接多個(gè)集群
Istio 通常被用于控制同一個(gè)集群中應(yīng)用程序之間的網(wǎng)絡(luò)流量,它可以檢查所有傳入和傳出的請(qǐng)求,并通過(guò) Envoy 以代理的方式發(fā)送這些請(qǐng)求。
Istio 控制平面負(fù)責(zé)更新并收集來(lái)自這些代理的指標(biāo),還可以發(fā)出指令借此轉(zhuǎn)移流量。
因此我們可以用 Istio 攔截到特定服務(wù)的所有流量,并將其重定向至三個(gè)集群之一。這就是所謂的 Istio 多集群配置。
理論知識(shí)這就夠了,接下來(lái)親自試試吧。首先需要在三個(gè)集群中安裝 Istio。雖然安裝方法很多,但 Helm 最方便:
bash
$ helm repo add istio https://istio-release.storage.googleapis.com/charts
$ helm repo list
NAME URL
istio https://istio-release.storage.googleapis.com/charts
我們可以用下列命令將 Istio 安裝給三個(gè)集群:
bash
$ helm install istio-base istio/base \
--kubecnotallow=kubeconfig-<insert-cluster-name> \
--create-namespace --namespace istio-system \
--versinotallow=1.14.1
請(qǐng)將 cluster-name 分別替換為 ap、eu 和 us,并將該命令同樣執(zhí)行三遍。
Base chart 將只安裝通用資源,例如 Roles 和 RoleBindings。實(shí)際的安裝會(huì)被打包到 istiod chart 中。但在執(zhí)行該操作前,我們首先需要配置 Istio Certificate Authority (CA),以確保這些集群可以相互連接和信任。
請(qǐng)?jiān)谝粋€(gè)新目錄中使用下列命令克隆 Istio 代碼庫(kù):
bash
$ git clone https://github.com/istio/istio
創(chuàng)建一個(gè) certs 文件夾并進(jìn)入該目錄:
bash
$ mkdir certs
$ cd certs
使用下列命令創(chuàng)建根證書(shū):
bash
$ make -f ../istio/tools/certs/Makefile.selfsigned.mk root-ca
該命令將生成下列文件:
- root-cert.pem:生成的根證書(shū)
- root-key.pem:生成的根密鑰
- root-ca.conf:供 OpenSSL 生成根證書(shū)的配置
- root-cert.csr:為根證書(shū)生成的 CSR
對(duì)于每個(gè)集群,還需要為 Istio Certificate Authority 生成一個(gè)中間證書(shū)和密鑰:
bash
$ make -f ../istio/tools/certs/Makefile.selfsigned.mk cluster1-cacerts
$ make -f ../istio/tools/certs/Makefile.selfsigned.mk cluster2-cacerts
$ make -f ../istio/tools/certs/Makefile.selfsigned.mk cluster3-cacerts
上述命令會(huì)在名為 cluster1、cluster2 和 cluster3 的目錄下生成下列文件:
bash
$ kubectl create secret generic cacerts -n istio-system \
--kubecnotallow=kubeconfig-<cluster-name>
--from-file=<cluster-folder>/ca-cert.pem \
--from-file=<cluster-folder>/ca-key.pem \
--from-file=<cluster-folder>/root-cert.pem \
--from-file=<cluster-folder>/cert-chain.pem
我們需要使用下列變量執(zhí)行這些命令:
| cluster name | folder name |
| :----------: | :---------: |
| ap | cluster1 |
| us | cluster2 |
| eu | cluster3 |
上述操作完成后,可以安裝 istiod 了:
bash
$ helm install istiod istio/istiod \
--kubecnotallow=kubeconfig-<insert-cluster-name> \
--namespace istio-system \
--versinotallow=1.14.1 \
--set global.meshID=mesh1 \
--set global.multiCluster.clusterName=<insert-cluster-name> \
--set global.network=<insert-network-name>
請(qǐng)使用下列變量將上述命令重復(fù)執(zhí)行三遍:
| cluster name | network name |
| :----------: | :----------: |
| ap | network1 |
| us | network2 |
| eu | network3 |
我們還可以使用拓?fù)渥⑨寔?lái)標(biāo)記 Istio 的命名空間:
bash
$ kubectl label namespace istio-system topology.istio.io/network=network1 --kubecnotallow=kubeconfig-ap
$ kubectl label namespace istio-system topology.istio.io/network=network2 --kubecnotallow=kubeconfig-us
$ kubectl label namespace istio-system topology.istio.io/network=network3 --kubecnotallow=kubeconfig-eu
至此幾乎就快完成了。
通過(guò)東西網(wǎng)關(guān)為流量創(chuàng)建隧道
接下來(lái)我們還需要:
- 一個(gè)網(wǎng)關(guān),借此通過(guò)隧道將流量從一個(gè)集群發(fā)送到另一個(gè)
- 一種機(jī)制,借此發(fā)現(xiàn)其他集群中的 IP 地址
我們可以使用 Helm 安裝網(wǎng)關(guān):
bash
$ helm install eastwest-gateway istio/gateway \
--kubecnotallow=kubeconfig-<insert-cluster-name> \
--namespace istio-system \
--versinotallow=1.14.1 \
--set labels.istio=eastwestgateway \
--set labels.app=istio-eastwestgateway \
--set labels.topology.istio.io/network=istio-eastwestgateway \
--set labels.topology.istio.io/network=istio-eastwestgateway \
--set networkGateway=<insert-network-name> \
--set service.ports[0].name=status-port \
--set service.ports[0].port=15021 \
--set service.ports[0].targetPort=15021 \
--set service.ports[1].name=tls \
--set service.ports[1].port=15443 \
--set service.ports[1].targetPort=15443 \
--set service.ports[2].name=tls-istiod \
--set service.ports[2].port=15012 \
--set service.ports[2].targetPort=15012 \
--set service.ports[3].name=tls-webhook \
--set service.ports[3].port=15017 \
--set service.ports[3].targetPort=15017 \
請(qǐng)使用下列變量將上述命令執(zhí)行三遍:
| cluster name | network name |
| :----------: | :----------: |
| ap | network1 |
| us | network2 |
| eu | network3 |
隨后對(duì)于每個(gè)集群,請(qǐng)使用下列資源暴露一個(gè)網(wǎng)關(guān):
yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: cross-network-gateway
spec:
selector:
istio: eastwestgateway
servers:
- port:
number: 15443
name: tls
protocol: TLS
tls:
mode: AUTO_PASSTHROUGH
hosts:
- "*.local"
并使用下列命令將文件提交至集群:
bash
$ kubectl apply -f expose.yaml --kubecnotallow=kubeconfig-eu
$ kubectl apply -f expose.yaml --kubecnotallow=kubeconfig-ap
$ kubectl apply -f expose.yaml --kubecnotallow=kubeconfig-us
對(duì)于發(fā)現(xiàn)機(jī)制,我們需要共享每個(gè)集群的憑據(jù)。這是因?yàn)榧翰⒉恢辣舜说拇嬖凇?/span>
為了發(fā)現(xiàn)其他 IP 地址,集群必須能彼此訪問(wèn),并將這些集群注冊(cè)為流量的可能目的地。為此我們必須使用其他集群的 kubeconfig 文件創(chuàng)建一個(gè) Kubernetes secret。Istio 可以借此連接其他集群,發(fā)現(xiàn)端點(diǎn),并指示 Envoy 代理轉(zhuǎn)發(fā)流量。
我們需要三個(gè) Secret:
yaml
apiVersion: v1
kind: Secret
metadata:
labels:
istio/multiCluster: true
annotations:
networking.istio.io/cluster: <insert cluster name>
name: "istio-remote-secret-<insert cluster name>"
type: Opaque
data:
<insert cluster name>: <insert cluster kubeconfig as base64>
請(qǐng)使用下列變量創(chuàng)建這三個(gè) Secret:
| cluster name | secret filename | kubeconfig |
| :----------: | :-------------: | :-----------: |
| ap | secret1.yaml | kubeconfig-ap |
| us | secret2.yaml | kubeconfig-us |
| eu | secret3.yaml | kubeconfig-eu |
接下來(lái)需要向集群提交 Secret,但是請(qǐng)注意,不要將 AP 的 Secret 提交給 AP 集群。
為此需要執(zhí)行下列命令:
bash
$ kubectl apply -f secret2.yaml -n istio-system --kubecnotallow=kubeconfig-ap
$ kubectl apply -f secret3.yaml -n istio-system --kubecnotallow=kubeconfig-ap
$ kubectl apply -f secret1.yaml -n istio-system --kubecnotallow=kubeconfig-us
$ kubectl apply -f secret3.yaml -n istio-system --kubecnotallow=kubeconfig-us
$ kubectl apply -f secret1.yaml -n istio-system --kubecnotallow=kubeconfig-eu
$ kubectl apply -f secret2.yaml -n istio-system --kubecnotallow=kubeconfig-eu
至此,大部分操作已經(jīng)完成,我們可以開(kāi)始測(cè)試整個(gè)配置了。
測(cè)試多集群網(wǎng)絡(luò)連接
首先為一個(gè)睡眠中的 Pod 創(chuàng)建一個(gè)部署。我們可以使用該 Pod 向剛才創(chuàng)建的 Hello 部署發(fā)出請(qǐng)求:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sleep
spec:
selector:
matchLabels:
app: sleep
template:
metadata:
labels:
app: sleep
spec:
terminationGracePeriodSeconds: 0
containers:
- name: sleep
image: curlimages/curl
command: ["/bin/sleep", "3650d"]
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /etc/sleep/tls
name: secret-volume
volumes:
- name: secret-volume
secret:
secretName: sleep-secret
optional: true
請(qǐng)用下列命令創(chuàng)建部署:
bash
$ kubectl apply -f sleep.yaml --kubecnotallow=karmada-config
因?yàn)樵摬渴鹕形粗付ú呗裕琄armada 將不處理該部署,使其處于 “未決” 狀態(tài)。我們可以修改策略以包含該部署:
yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: hello-propagation
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: hello
- apiVersion: v1
kind: Service
name: hello
- apiVersion: apps/v1
kind: Deployment
name: sleep
placement:
clusterAffinity:
clusterNames:
- eu
- ap
- us
replicaScheduling:
replicaDivisionPreference: Weighted
replicaSchedulingType: Divided
weightPreference:
staticWeightList:
- targetCluster:
clusterNames:
- us
weight: 2
- targetCluster:
clusterNames:
- ap
weight: 2
- targetCluster:
clusterNames:
- eu
weight: 1
使用下列命令應(yīng)用該策略:
bash
$ kubectl apply -f policy.yaml --kubecnotallow=karmada-config
要了解該 Pod 被部署到哪里,可以使用下列命令:
bash
$ kubectl get pods --kubecnotallow=kubeconfig-eu
$ kubectl get pods --kubecnotallow=kubeconfig-ap
$ kubectl get pods --kubecnotallow=kubeconfig-us
接下來(lái),假設(shè)該 Pod 被部署到 US 集群,請(qǐng)執(zhí)行下列命令:
bash
for i in {1..10}
do
kubectl exec --kubecnotallow=kubeconfig-us -c sleep \
"$(kubectl get pod --kubecnotallow=kubeconfig-us -l \
app=sleep -o jsnotallow='{.items[0].metadata.name}')" \
-- curl -sS hello:5000 | grep REGION
done
我們將會(huì)發(fā)現(xiàn),響應(yīng)會(huì)來(lái)自不同地域的不同 Pod!搞定!
總結(jié)
該配置其實(shí)非?;A(chǔ),缺乏真實(shí)環(huán)境中可能需要的其他很多功能:
- 我們可以從每個(gè)集群暴露出一個(gè) Istio 入口以攝入流量
- 我們可以使用 Istio 進(jìn)行流量塑型,這樣就會(huì)優(yōu)先進(jìn)行本地處理
- 還可以使用 Istio 策略強(qiáng)制規(guī)則定義流量如何在不同集群之間流動(dòng)
這篇文章的內(nèi)容感覺(jué)還行吧?有沒(méi)有想要立即在 Linode 平臺(tái)上親自嘗試一下?別忘了,現(xiàn)在注冊(cè)可以免費(fèi)獲得價(jià)值 100 美元的使用額度,快點(diǎn)自己動(dòng)手體驗(yàn)本文介紹的功能和服務(wù)吧↓↓↓
出海云服務(wù),Akamai 是您的不二之選!
歡迎關(guān)注Akamai,第一時(shí)間了解高可用的 MySQL/MariaDB 參考架構(gòu),以及豐富的應(yīng)用程序示例。