构建多个网络互通的 Google Cloud GKE 集群

本文介绍了如何构建多个 Google Kubernetes Engine (GKE) 集群,并配置集群之间的网络互通,为跨 Kubernetes 集群部署 TiDB 集群作准备。

如果仅需要部署一个 TiDB 集群到一个 GKE 集群,请参考在 Google Cloud GKE 上部署 TiDB 集群文档。

环境准备

部署前,请确认已完成以下环境准备:

  • Helm 3:用于安装 TiDB Operator
  • gcloud:用于创建和管理 GCP 服务的命令行工具
  • 完成 GKE 快速入门 中的准备工作 (Before you begin)

配置 Google Cloud 服务

使用以下命令,设置好你的 Google Cloud 项目:

gcloud config set core/project <google-cloud-project>

第 1 步:创建网络

  1. 创建一个自定义子网的 VPC 网络。

    gcloud compute networks create ${network_name} --subnet-mode=custom
  2. 在新创建的 VPC 网络下创建三个属于不同 Region 的子网,子网的 CIDR block 相互不重叠。

    gcloud compute networks subnets create ${subnet_1} \ --region=${region_1} \ --network=${network_name} \ --range=10.0.0.0/16 \ --secondary-range pods=10.10.0.0/16,services=10.100.0.0/16
    gcloud compute networks subnets create ${subnet_2} \ --region=${region_2} \ --network=${network_name} \ --range=10.1.0.0/16 \ --secondary-range pods=10.11.0.0/16,services=10.101.0.0/16
    gcloud compute networks subnets create ${subnet_3} \ --region=${region_3} \ --network=${network_name} \ --range=10.2.0.0/16 \ --secondary-range pods=10.12.0.0/16,services=10.102.0.0/16

    ${subnet_1}${subnet_2}${subnet_3} 为三个不同子网的名字。

    参数 --range=10.0.0.0/16 指定集群的子网的 CIRD 块,所有集群的子网的 CIDR block 必须不相互重叠。

    参数 --secondary-range pods=10.11.0.0/16,services=10.101.0.0/16 中指定了 Kubernetes 的 Pod 与 Service 使用的 CIRD block,将会在后面使用到。

第 2 步:启动 Kubernetes 集群

创建三个 GKE 集群,每个集群使用上述创建的子网。

  1. 创建三个 GKE 集群,每个集群有一个默认的节点池:

    gcloud beta container clusters create ${cluster_1} \ --region ${region_1} --num-nodes 1 \ --network ${network_name} --subnetwork ${subnet_1} \ --cluster-dns clouddns --cluster-dns-scope vpc \ --cluster-dns-domain ${cluster_domain_1} --enable-ip-alias \ --cluster-secondary-range-name=pods --services-secondary-range-name=services
    gcloud beta container clusters create ${cluster_2} \ --region ${region_2} --num-nodes 1 \ --network ${network_name} --subnetwork ${subnet_2} \ --cluster-dns clouddns --cluster-dns-scope vpc \ --cluster-dns-domain ${cluster_domain_2} --enable-ip-alias \ --cluster-secondary-range-name=pods --services-secondary-range-name=services
    gcloud beta container clusters create ${cluster_3} \ --region ${region_3} --num-nodes 1 \ --network ${network_name} --subnetwork ${subnet_3} \ --cluster-dns clouddns --cluster-dns-scope vpc \ --cluster-dns-domain ${cluster_domain_3} --enable-ip-alias \ --cluster-secondary-range-name=pods --services-secondary-range-name=services

    上述命令中,${cluster_domain_n} 表示第 n 个集群的 cluster domain。在后续部署 TiDB 集群时,需要配置部署的 TidbCluster CR 中的 spec.clusterDomain

    使用 VPC 范围的 Cloud DNS 服务,使得集群可以解析其他集群的 Pod 和 Service 地址。

  2. 为每个集群创建 PD、TiKV 和 TiDB 使用的独立的节点池。

    以集群 1 为例:

    gcloud container node-pools create pd --cluster ${cluster_1} --machine-type n1-standard-4 --num-nodes=1 \ --node-labels=dedicated=pd --node-taints=dedicated=pd:NoSchedule gcloud container node-pools create tikv --cluster ${cluster_1} --machine-type n1-highmem-8 --num-nodes=1 \ --node-labels=dedicated=tikv --node-taints=dedicated=tikv:NoSchedule gcloud container node-pools create tidb --cluster ${cluster_1} --machine-type n1-standard-8 --num-nodes=1 \ --node-labels=dedicated=tidb --node-taints=dedicated=tidb:NoSchedule
  3. 获取每个集群的 Kubernetes context,后续当你使用 kubectl 命令操作特定的集群时,需要指定对应的 context。

    kubectl config get-contexts

    输出类似如下,其中的 NAME 项就是你后续需要使用的 context。

    CURRENT NAME CLUSTER AUTHINFO NAMESPACE * gke_pingcap_us-west1_tidb-1 gke_pingcap_us-west1_tidb-1 gke_pingcap_us-west1_tidb-1 gke_pingcap_us-west2_tidb-2 gke_pingcap_us-west2_tidb-2 gke_pingcap_us-west2_tidb-2 gke_pingcap_us-west3_tidb-3 gke_pingcap_us-west3_tidb-3 gke_pingcap_us-west3_tidb-3

    后文中,使用 ${context_1}${context_2}${context_3} 分别代表各个集群的 context。

配置防火墙规则

  1. 更新集群 1 的防火墙规则。

    1. 找到用于 GKE Pod 间通信的防火墙规则的名字,防火墙规则命名规则类似于:gke-${cluster_1}-${hash}-all

      gcloud compute firewall-rules list --filter='name~gke-${cluster_1}-.*-all'

      输出类似如下,其 NAME 项为规则的名字。

      NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED gke-${cluster_1}-b8b48366-all ${network} INGRESS 1000 tcp,udp,icmp,esp,ah,sctp False
    2. 更新该防火墙规则的 source range,加上另外两个集群的 Pod 网络的 CIDR block。

      gcloud compute firewall-rules update ${firewall_rule_name} --source-ranges 10.10.0.0/16,10.11.0.0/16,10.12.0.0/16

      你可以通过以下命令检查防火墙规则是否成功更新。

      gcloud compute firewall-rules describe ${firewall_rule_name}
  2. 按照步骤 1,更新集群 2 与集群 3 的防火墙规则。

第 3 步:验证网络连通性

在部署 TiDB 集群之前,你需要先验证多个集群之间的网络连通性。

  1. 将下面定义保存到 sample-nginx.yaml 文件。

    apiVersion: v1 kind: Pod metadata: name: sample-nginx labels: app: sample-nginx spec: hostname: sample-nginx subdomain: sample-nginx-peer containers: - image: nginx:1.21.5 imagePullPolicy: IfNotPresent name: nginx ports: - name: http containerPort: 80 restartPolicy: Always --- apiVersion: v1 kind: Service metadata: name: sample-nginx-peer spec: ports: - port: 80 selector: app: sample-nginx clusterIP: None
  2. 在三个集群对应的命名空间下部署 NGINX 服务。

    kubectl --context ${context_1} -n default apply -f sample-nginx.yaml kubectl --context ${context_2} -n default apply -f sample-nginx.yaml kubectl --context ${context_3} -n default apply -f sample-nginx.yaml
  3. 通过访问其他集群的 NGINX 服务,来验证网络是否连通。

    以验证集群 1 到集群 2 的网络连通性为例,执行以下命令。

    kubectl --context ${context_1} exec sample-nginx -- curl http://sample-nginx.sample-nginx-peer.default.svc.${cluster_domain_2}:80

    如果输出为 NGINX 的欢迎页面,那么就表明网络是正常连通的。

  4. 验证完成后,执行以下命令删除 NGINX 服务。

    kubectl --context ${context_1} -n default delete -f sample-nginx.yaml kubectl --context ${context_2} -n default delete -f sample-nginx.yaml kubectl --context ${context_3} -n default delete -f sample-nginx.yaml

第 4 步:部署 TiDB Operator

每个集群的 TidbCluster CR 由当前集群的 TiDB Operator 管理,因此每个集群都需要部署 TiDB Operator。

参考在 Kubernetes 上部署 TiDB Operator 部署 TiDB Operator 到每个 GKE 集群。区别在于,需要通过命令 kubectl --context ${context}helm --kube-context ${context} 为每个 GKE 集群部署 TiDB Operator。

第 5 步:部署 TiDB 集群

参考跨多个 Kubernetes 集群部署 TiDB 集群为每个集群部署一个 TidbCluster CR。需要注意的是:

例如,部署初始集群 TidbCluster CR 到集群 1 时,将 spec.clusterDomain 指定为 ${cluster_domain_1}:

apiVersion: pingcap.com/v1alpha1 kind: TidbCluster # ... spec: #.. clusterDomain: "${cluster_domain_1}" acrossK8s: true

探索更多

文档内容是否有帮助?