头图

对Kubernetes来说,跨越多个地域(Region)部署工作负载,这是个有趣的挑战。虽然从技术上来说,我们可以用分布在多个地域的节点创建集群,但因为会造成额外的延迟,通常并不建议这样做。

一种比较流行的替代方法是在每个地域部署一个集群,然后设法对多个集群进行必要的编排。

图片
我们可以让一个集群中的节点分布在不同地域,或者在每个地域部署一个集群

本文将介绍如何:

  1. 分别在北美、欧洲和东南亚各自创建一个集群。
  2. 创建第四个集群,将其作为上述三个集群的编排器。
  3. 设置一个将三个集群连接在一起的网络,从而实现跨集群的无缝通信。

本文涉及的操作均可通过脚本实现,只需最少量人工介入即可适用于Terraform。相关代码请访问LearnK8s GitHub。

创建集群管理器

首先创建用于管理其余集群的集群。我们可以通过下列命令创建该集群并保存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

随后可通过下列命令验证安装过程已成功完成:

bash
$ kubectl get pods -A --kubeconfig=kubeconfig-cluster-manager

我们还需要在集群管理器中安装Karmada,这个管理系统可以帮助我们跨越多个Kubernetes集群或多个云平台运行自己的云原生应用程序。Karmada是一种安装在集群管理器中的控制平面,其他集群中需要安装代理程序。

该控制平面包含三个组件:

  1. 一个API服务器(API Server)
  2. 一个控制器管理器(Controller Manager)
  3. 一个调度器(Scheduler)

图片
Karmada的控制平面

是否看起来觉得很熟悉?这是因为它与Kubernetes控制平面功能其实是相同组件,只不过Karmada能适用于多种集群。

理论部分说的差不多了,接下来开始看看具体要用的代码。我们可以使用Helm安装Karmada API服务器。为此可使用下列命令添加Helm仓库:

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服务器必须能被所有其他集群访问,因此我们必须:

  • 从节点上将其暴露出来;并且
  • 确保连接是可信任的。

因此首先需要通过下列命令获取承载了控制平面的节点的IP地址:

bash
kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type==\"ExternalIP\")].address}' \
 --kubeconfig=kubeconfig-cluster-manager

随后即可用下列命令安装Karmada控制平面:

bash
$ helm install karmada karmada-charts/karmada \
 --kubeconfig=kubeconfig-cluster-manager \
 --create-namespace --namespace karmada-system \
 --version=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>"

安装完成后,即可通过下列命令获得Kubeconfig并连接到Karmada API:

bash
kubectl get secret karmada-kubeconfig \
 --kubeconfig=kubeconfig-cluster-manager \
 -n karmada-system \
 -o jsonpath={.data.kubeconfig} | base64 -d > karmada-config

不过为什么这里要用另一个Kubeconfig文件?

按照设计,Karmada API是为了取代标准的Kubernetes API,同时依然提供了用户需要的全部功能。换句话说,我们可以借助kubectl创建横跨多个集群的部署。

在测试Karmada API和kubectl之前,还需要调整Kubeconfig文件。默认情况下生成的Kubeconfig只能在集群网络的内部使用。不过我们只需调整这几行内容就可以消除这一限制:

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

请将之前获取的节点IP地址替换进去:

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

接下来就可以开始测试Karmada了。

安装Karmada代理程序

运行下列命令检索所有部署和所有集群:

bash
$ kubectl get clusters,deployments --kubeconfig=karmada-config
No resources found

可想而知,目前没有任何部署,也没有任何额外的集群。我们可以添加几个集群并将其连接到Karmada控制平面。

请重复执行下列命令三次:

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>

执行时请分别使用如下的值:

  • 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

随后通过下列命令确认集群已经成功创建:

bash
$ kubectl get pods -A --kubeconfig=kubeconfig-eu
$ kubectl get pods -A --kubeconfig=kubeconfig-ap
$ kubectl get pods -A --kubeconfig=kubeconfig-us

接下来要将这些集群加入Karmada集群。Karmada需要在其他每个集群中使用代理程序来协调控制平面的部署。

图片
Karmada代理程序

我们可以使用Helm安装Karmada代理程序并将其链接至集群管理器:

bash
$ helm install karmada karmada-charts/karmada \
 --kubeconfig=kubeconfig-<insert-cluster-name> \
 --create-namespace --namespace karmada-system \
 --version=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 \

上述命令同样需要重复三次,每次分别插入下列变量:

  • 集群名称:分别为eu、ap和us。
  • 集群管理器的证书授权机构。我们可以在karmada-config文件的clusters[0].cluster['certificate-authority-data']中找到该值,这些值可以通过base64进行解码。
  • 用户的客户端证书数据。我们可以在karmada-config文件的users[0].user['client-certificate-data']中找到该值,这些值可以通过base64进行解码。
  • 用户的客户端密钥数据。我们可以在karmada-config文件的users[0].user['client-key-data']中找到该值,这些值可以通过base64进行解码。
  • 承载Karmada控制平面的节点的IP地址。

随后可以运行下列命令来验证安装是否成功完成:

bash
$ kubectl get clusters --kubeconfig=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编排多集群部署

只要配置正确无误,我们即可将工作负载提交给Karmada,由它将任务分发给其他集群。

为了进行测试,我们首先需要创建一个部署:

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

随后通过下列命令将该部署提交至Karmada API服务器:

bash
$ kubectl apply -f deployment.yaml --kubeconfig=karmada-config

该部署包含三个副本,那么是否可以平均分发给这三个集群?一起来验证一下:

bash
$ kubectl get deployments --kubeconfig=karmada-config
NAME    READY   UP-TO-DATE   AVAILABLE
hello   0/3     0            0

Karmada为何没有创建Pod?先来看看这个部署:

bash
$ kubectl describe deployment hello --kubeconfig=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并不知道该如何处理这个部署,因为我们尚未指定策略。

Karmada调度器会使用策略将工作负载分配给集群。那么我们就定义一个简单的策略,为每个集群分配一个副本:

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 --kubeconfig=karmada-config

然后再来看看部署和Pod:

bash
$ kubectl get deployments --kubeconfig=karmada-config
NAME    READY   UP-TO-DATE   AVAILABLE
hello   3/3     3            3
$ kubectl get pods --kubeconfig=kubeconfig-eu
NAME                    READY   STATUS    RESTARTS
hello-5d857996f-hjfqq   1/1     Running   0
$ kubectl get pods --kubeconfig=kubeconfig-ap
NAME                    READY   STATUS    RESTARTS
hello-5d857996f-xr6hr   1/1     Running   0
$ kubectl get pods --kubeconfig=kubeconfig-us
NAME                    READY   STATUS    RESTARTS
hello-5d857996f-nbz48   1/1     Running   0

图片
Karmada为每个集群分配一个Pod

Karmada会为每个集群分配一个Pod,因为策略中为每个集群定义了相等的权重。

我们用下列命令将该部署扩展为10个副本:

bash
$ kubectl scale deployment/hello --replicas=10 --kubeconfig=karmada-config

随后查看Pod会看到如下的结果:

bash
$ kubectl get deployments --kubeconfig=karmada-config
NAME    READY   UP-TO-DATE   AVAILABLE
hello   10/10   10           10
$ kubectl get pods --kubeconfig=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 --kubeconfig=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 --kubeconfig=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

并通过下列命令提交策略:

bash
$ kubectl apply -f policy.yaml --kubeconfig=karmada-config

接着可以看到,Pod的分配情况也酌情产生了变化:

bash
$ kubectl get pods --kubeconfig=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 --kubeconfig=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 --kubeconfig=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

图片
Pod会根据策略的指定进行分配

Karmada支持通过多种策略分配工作负载,更多高级用例可以参考文档。

Pod在三个集群中运行,但我们该如何访问?

先来看看Karmada中的服务:

bash
$ kubectl describe service hello --kubeconfig=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.

这些服务被部署在全部的三个集群中,但彼此之间并未连接。

尽管Karmada可以管理多个集群,但它并未提供任何网络机制将这三个集群连接在一起。换句话说,Karmada是一种跨越多个集群编排部署的好工具,但我们需要通过其他机制让这些集群相互通信。

使用Istio连接多个集群

Istio通常被用于控制同一个集群中应用程序之间的网络流量,它可以检查所有传入和传出的请求,并通过Envoy以代理的方式发送这些请求。

图片
Envoy能够充当所有流量的代理

Istio控制平面负责更新并收集来自这些代理的指标,还可以发出指令借此转移流量。

图片
借助Istio,我们可以定义策略来管理集群中的流量

因此我们可以用Istio拦截到特定服务的所有流量,并将其重定向至三个集群之一。这就是所谓的Istio多集群配置。

理论知识这就够了,接下来亲自试试吧。首先需要在三个集群中安装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安装给三个集群:

bash
$ helm install istio-base istio/base \
 --kubeconfig=kubeconfig-<insert-cluster-name> \
 --create-namespace --namespace istio-system \
 --version=1.14.1

请将cluster-name分别替换为ap、eu和us,并将该命令同样执行三遍。

Base chart将只安装通用资源,例如Roles和RoleBindings。实际的安装会被打包到istiod chart中。但在执行该操作前,我们首先需要配置Istio Certificate Authority (CA),以确保这些集群可以相互连接和信任。

请在一个新目录中使用下列命令克隆Istio代码库:

bash
$ git clone https://github.com/istio/istio

创建一个certs文件夹并进入该目录:

bash
$ mkdir certs
$ cd certs

使用下列命令创建根证书:

bash
$ make -f ../istio/tools/certs/Makefile.selfsigned.mk root-ca

该命令将生成下列文件:

  • root-cert.pem:生成的根证书
  • root-key.pem:生成的根密钥
  • root-ca.conf:供OpenSSL生成根证书的配置
  • root-cert.csr:为根证书生成的CSR

对于每个集群,还需要为Istio Certificate Authority生成一个中间证书和密钥:

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

上述命令会在名为cluster1、cluster2和cluster3的目录下生成下列文件:

bash
$ kubectl create secret generic cacerts -n istio-system \
 --kubeconfig=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

我们需要使用下列变量执行这些命令:

| cluster name | folder name |
| :----------: | :---------: |
|      ap      |  cluster1   |
|      us      |  cluster2   |
|      eu      |  cluster3   |

上述操作完成后,可以安装istiod了:

bash
$ helm install istiod istio/istiod \
 --kubeconfig=kubeconfig-<insert-cluster-name> \
 --namespace istio-system \
 --version=1.14.1 \
 --set global.meshID=mesh1 \
 --set global.multiCluster.clusterName=<insert-cluster-name> \
 --set global.network=<insert-network-name>

请使用下列变量将上述命令重复执行三遍:

| cluster name | network name |
| :----------: | :----------: |
|      ap      |   network1   |
|      us      |   network2   |
|      eu      |   network3   |

我们还可以使用拓扑注释来标记Istio的命名空间:

bash
$ kubectl label namespace istio-system topology.istio.io/network=network1 --kubeconfig=kubeconfig-ap
$ kubectl label namespace istio-system topology.istio.io/network=network2 --kubeconfig=kubeconfig-us
$ kubectl label namespace istio-system topology.istio.io/network=network3 --kubeconfig=kubeconfig-eu

至此几乎就快完成了。

通过东西网关为流量创建隧道

接下来我们还需要:

  • 一个网关,借此通过隧道将流量从一个集群发送到另一个
  • 一种机制,借此发现其他集群中的IP地址

图片
Istio多集群:发现端点并安装东西网关

我们可以使用Helm安装网关:

bash
$ helm install eastwest-gateway istio/gateway \
 --kubeconfig=kubeconfig-<insert-cluster-name> \
 --namespace istio-system \
 --version=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 \

请使用下列变量将上述命令执行三遍:

| cluster name | network name |
| :----------: | :----------: |
|      ap      |   network1   |
|      us      |   network2   |
|      eu      |   network3   |

随后对于每个集群,请使用下列资源暴露一个网关:

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 --kubeconfig=kubeconfig-eu
$ kubectl apply -f expose.yaml --kubeconfig=kubeconfig-ap
$ kubectl apply -f expose.yaml --kubeconfig=kubeconfig-us

对于发现机制,我们需要共享每个集群的凭据。这是因为集群并不知道彼此的存在。

为了发现其他IP地址,集群必须能彼此访问,并将这些集群注册为流量的可能目的地。为此我们必须使用其他集群的kubeconfig文件创建一个Kubernetes secret。Istio可以借此连接其他集群,发现端点,并指示Envoy代理转发流量。

我们需要三个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>

请使用下列变量创建这三个Secret:

| cluster name | secret filename |  kubeconfig   |
| :----------: | :-------------: | :-----------: |
|      ap      |  secret1.yaml   | kubeconfig-ap |
|      us      |  secret2.yaml   | kubeconfig-us |
|      eu      |  secret3.yaml   | kubeconfig-eu |

接下来需要向集群提交Secret,但是请注意,不要将AP的Secret提交给AP集群。

为此需要执行下列命令:

bash
$ kubectl apply -f secret2.yaml -n istio-system --kubeconfig=kubeconfig-ap
$ kubectl apply -f secret3.yaml -n istio-system --kubeconfig=kubeconfig-ap
$ kubectl apply -f secret1.yaml -n istio-system --kubeconfig=kubeconfig-us
$ kubectl apply -f secret3.yaml -n istio-system --kubeconfig=kubeconfig-us
$ kubectl apply -f secret1.yaml -n istio-system --kubeconfig=kubeconfig-eu
$ kubectl apply -f secret2.yaml -n istio-system --kubeconfig=kubeconfig-eu

至此,大部分操作已经完成,我们可以开始测试整个配置了。

测试多集群网络连接

首先为一个睡眠中的Pod创建一个部署。我们可以使用该Pod向刚才创建的Hello部署发出请求:

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

请用下列命令创建部署:

bash
$ kubectl apply -f sleep.yaml --kubeconfig=karmada-config

因为该部署尚未指定策略,Karmada将不处理该部署,使其处于“未决”状态。我们可以修改策略以包含该部署:

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

使用下列命令应用该策略:

bash
$ kubectl apply -f policy.yaml --kubeconfig=karmada-config

要了解该Pod被部署到哪里,可以使用下列命令:

bash
$ kubectl get pods --kubeconfig=kubeconfig-eu
$ kubectl get pods --kubeconfig=kubeconfig-ap
$ kubectl get pods --kubeconfig=kubeconfig-us

接下来,假设该Pod被部署到US集群,请执行下列命令:

bash
for i in {1..10}
do
 kubectl exec --kubeconfig=kubeconfig-us -c sleep \
   "$(kubectl get pod --kubeconfig=kubeconfig-us -l \
   app=sleep -o jsonpath='{.items[0].metadata.name}')" \
   -- curl -sS hello:5000 | grep REGION
done

我们将会发现,响应会来自不同地域的不同Pod!搞定!

总结

该配置其实非常基础,缺乏真实环境中可能需要的其他很多功能:

  1. 我们可以从每个集群暴露出一个Istio入口以摄入流量
  2. 我们可以使用Istio进行流量塑型,这样就会优先进行本地处理
  3. 还可以使用Istio策略强制规则定义流量如何在不同集群之间流动

Akamai
1 声望1 粉丝

Akamai 支持并保护网络生活。全球各大优秀公司纷纷选择 Akamai 来打造并提供安全的数字化体验,为数十亿人每天的生活、工作和娱乐提供助力。 我们横跨云端和边缘的计算平台在全球广泛分布,不仅能让客户轻松开发...