跨多个 Kubernetes 集群部署 TiDB 集群

    需要配置 Kubernetes 的网络和 DNS,使得 Kubernetes 集群满足以下条件:

    • 各 Kubernetes 集群上的 TiDB 组件有能力访问集群内和集群间所有 TiDB 组件的 Pod IP。
    • 各 Kubernetes 集群上的 TiDB 组件有能力解析集群内和集群间所有 TiDB 组件的 Pod FQDN。

    多个 EKS 或者 GKE 集群网络互通可以参考 构建多个网络互通的 AWS EKS 集群 与 。

    支持场景

    目前支持场景:

    • 新部署跨多个 Kubernetes 集群的 TiDB 集群。
    • 在其他 Kubernetes 集群上部署开启此功能的新集群加入同样开启此功能的集群。

    实验性支持场景:

    • 对已有数据的集群从未开启此功能状态变为开启此功能状态,如需在生产环境中使用,建议通过数据迁移完成此需求。

    不支持场景:

    • 两个已有数据集群互相连通,对于这一场景应通过数据迁移完成。

    部署跨多个 Kubernetes 集群的 TiDB 集群,默认你已部署好此场景所需要的 Kubernetes 集群,在此基础上进行下面的部署工作。

    下面以跨两个 Kubernetes 部署 TiDB 集群为例进行介绍,将在每个 Kubernetes 集群部署一个 TidbCluster。

    后文中,、${tc_name_2} 分别代表将部署到各个 Kubernetes 集群的 TidbCluster 的名字,${namespace_1}${namespace_2} 分别代表各 TidbCluster 将部署到的命名空间,${cluster_domain_1}${cluster_domain_2} 分别代表各个 Kubernetes 集群的 。

    创建并部署初始 TidbCluster。

    相关字段含义如下:

    • spec.acrossK8s:表示该 TiDB 集群是否要跨 Kubernetes 集群部署,本例中必须设置为 true

    • spec.clusterDomain:设置后,会使用包含 Cluster Domain 的 Pod FQDN 作为组件间相互访问的地址。

      以 Pod ${tc_name}-pd-0 举例,其他 Kubernetes 集群的 Pod 会使用地址 ${tc_name}-pd-0.${tc_name}-pd-peer.${ns}.svc.${cluster_domain} 来访问该 Pod。

      如果 Pod 访问其他 Kubernetes 集群的 Pod FQDN 时需要 Cluster Domain,那么必须设置该字段。

    第 2 步:部署新的 TidbCluster 加入 TiDB 集群

    等待初始集群部署完成后,部署新的 TidbCluster 加入 TiDB 集群。在实际使用中,新部署的 TidbCluster 可以加入任意的已经部署的 TidbCluster。

    1. cat << EOF | kubectl apply -n ${namespace_2} -f -
    2. apiVersion: pingcap.com/v1alpha1
    3. kind: TidbCluster
    4. metadata:
    5. name: "${tc_name_2}"
    6. spec:
    7. version: v5.4.0
    8. timezone: UTC
    9. pvReclaimPolicy: Delete
    10. enableDynamicConfiguration: true
    11. configUpdateStrategy: RollingUpdate
    12. clusterDomain: "${cluster_domain_2}"
    13. acrossK8s: true
    14. cluster:
    15. name: "${tc_name_1}"
    16. namespace: "${namespace_1}"
    17. clusterDomain: "${cluster_domain_1}"
    18. discovery: {}
    19. pd:
    20. baseImage: pingcap/pd
    21. maxFailoverCount: 0
    22. replicas: 1
    23. requests:
    24. storage: "10Gi"
    25. config: {}
    26. tikv:
    27. baseImage: pingcap/tikv
    28. maxFailoverCount: 0
    29. replicas: 1
    30. requests:
    31. storage: "10Gi"
    32. config: {}
    33. tidb:
    34. baseImage: pingcap/tidb
    35. maxFailoverCount: 0
    36. replicas: 1
    37. service:
    38. type: ClusterIP
    39. config: {}
    40. EOF

    跨多个 Kubernetes 集群部署开启组件间 TLS 的 TiDB 集群

    可以按照以下步骤为跨多个 Kubernetes 集群部署的 TiDB 集群开启组件间 TLS。

    下面以跨两个 Kubernetes 部署 TiDB 集群为例进行介绍,将在每个 Kubernetes 集群部署一个 TidbCluster。

    后文中,${tc_name_1}${tc_name_2} 分别代表将部署到各个 Kubernetes 集群的 TidbCluster 的名字,${namespace_1}${namespace_2} 分别代表各 TidbCluster 将部署到的命名空间,${cluster_domain_1}${cluster_domain_2} 分别代表各个 Kubernetes 集群的 Cluster Domain

    使用 cfssl 系统签发根证书

    如果你使用 cfssl,签发 CA 证书的过程与一般签发过程没有差别,需要保存好第一次创建的 CA 证书,并且在后面为 TiDB 组件签发证书时都使用这个 CA 证书,即在为其他集群创建组件证书时,不需要再次创建 CA 证书,你只需要完成一次为 TiDB 组件间开启 TLS 文档中 1 ~ 4 步操作,完成 CA 证书签发,为其他集群组件间证书签发操作从第 5 步开始即可。

    使用 cert-manager 系统签发根证书

    如果你使用 cert-manager,只需要在初始 Kubernetes 集群创建 CA Issuer 和创建 CA Certificate,并导出 CA Secret 给其他的 Kubernetes 集群,其他集群只需要创建组件证书签发 Issuer(在 TLS 文档中指名字为 ${cluster_name}-tidb-issuerIssuer),配置 Issuer 使用该 CA,具体过程如下:

    1. 在初始 Kubernetes 集群上创建 CA Issuer 和创建 CA Certificate

      执行以下指令:

      1. cat <<EOF | kubectl apply -f -
      2. apiVersion: cert-manager.io/v1
      3. kind: Issuer
      4. metadata:
      5. name: ${tc_name_1}-selfsigned-ca-issuer
      6. namespace: ${namespace}
      7. spec:
      8. selfSigned: {}
      9. ---
      10. apiVersion: cert-manager.io/v1
      11. kind: Certificate
      12. metadata:
      13. name: ${tc_name_1}-ca
      14. namespace: ${namespace_1}
      15. spec:
      16. secretName: ${tc_name_1}-ca-secret
      17. commonName: "TiDB"
      18. isCA: true
      19. duration: 87600h # 10yrs
      20. renewBefore: 720h # 30d
      21. issuerRef:
      22. name: ${tc_name_1}-selfsigned-ca-issuer
      23. kind: Issuer
      24. EOF
    2. 导出 CA 并删除无关信息。

      首先需要导出存放 CA 的 SecretSecret 的名字可以由第一步 Certificate.spec.secretName 得到。

      1. kubectl get secret ${tc_name_1}-ca-secret -n ${namespace_1} -o yaml > ca.yaml
      1. apiVersion: v1
      2. data:
      3. ca.crt: LS0...LQo=
      4. tls.crt: LS0t....LQo=
      5. tls.key: LS0t...tCg==
      6. kind: Secret
      7. metadata:
      8. name: ${tc_name_2}-ca-secret
      9. type: kubernetes.io/tls
    3. 将导出的 CA 导入到其他 Kubernetes 集群。

      你需要配置这里的 namespace 使得相关组件可以访问到 CA 证书:

      1. kubectl apply -f ca.yaml -n ${namespace_2}
    4. 在所有 Kubernetes 集群创建组件证书签发 Issuer,使用该 CA。

      1. 在初始 Kubernetes 集群上,创建组件间证书签发 Issuer

        执行以下指令:

        1. cat << EOF | kubectl apply -f -
        2. kind: Issuer
        3. metadata:
        4. name: ${tc_name_1}-tidb-issuer
        5. spec:
        6. ca:
        7. secretName: ${tc_name_1}-ca-secret
        8. EOF
      2. 在其他 Kubernetes 集群上,创建组件间证书签发 Issuer

        执行以下指令:

    第 2 步:为各个 Kubernetes 集群的 TiDB 组件签发证书

    你需要为每个 Kubernetes 集群上的 TiDB 组件都签发组件证书。在签发组件证书时,需要在 hosts 中加上以 .${cluster_domain} 结尾的授权记录。例如,初始 TidbCluster 的配置为 ${tc_name_1}-pd.${namespace_1}.svc.${cluster_domain_1}

    使用 cfssl 系统为 TiDB 组件签发证书

    如果使用 cfssl,以创建 PD 组件所使用的证书为例,可以通过如下指令创建初始 TidbCluster 的 pd-server.json 文件:

    1. cat << EOF > pd-server.json
    2. {
    3. "CN": "TiDB",
    4. "hosts": [
    5. "127.0.0.1",
    6. "::1",
    7. "${tc_name_1}-pd",
    8. "${tc_name_1}-pd.${namespace_1}",
    9. "${tc_name_1}-pd.${namespace_1}.svc",
    10. "${tc_name_1}-pd.${namespace_1}.svc.${cluster_domain_1}",
    11. "${tc_name_1}-pd-peer",
    12. "${tc_name_1}-pd-peer.${namespace_1}",
    13. "${tc_name_1}-pd-peer.${namespace_1}.svc",
    14. "${tc_name_1}-pd-peer.${namespace_1}.svc.${cluster_domain_1}",
    15. "*.${tc_name_1}-pd-peer",
    16. "*.${tc_name_1}-pd-peer.${namespace_1}",
    17. "*.${tc_name_1}-pd-peer.${namespace_1}.svc",
    18. "*.${tc_name_1}-pd-peer.${namespace_1}.svc.${cluster_domain_1}"
    19. ],
    20. "key": {
    21. "algo": "ecdsa",
    22. "size": 256
    23. },
    24. "names": [
    25. {
    26. "C": "US",
    27. "L": "CA",
    28. "ST": "San Francisco"
    29. }
    30. ]
    31. }
    32. EOF

    使用 cert-manager 系统为 TiDB 组件签发证书

    如果使用 cert-manager,以创建初始 TidbCluster 的 PD 组件所使用的证书为例,Certifcates 如下所示。

    1. cat << EOF | kubectl apply -f -
    2. apiVersion: cert-manager.io/v1
    3. kind: Certificate
    4. metadata:
    5. name: ${tc_name_1}-pd-cluster-secret
    6. namespace: ${namespace_1}
    7. spec:
    8. secretName: ${tc_name_1}-pd-cluster-secret
    9. duration: 8760h # 365d
    10. renewBefore: 360h # 15d
    11. subject:
    12. organizations:
    13. - PingCAP
    14. commonName: "TiDB"
    15. usages:
    16. - server auth
    17. - client auth
    18. dnsNames:
    19. - "${tc_name_1}-pd"
    20. - "${tc_name_1}-pd.${namespace_1}"
    21. - "${tc_name_1}-pd.${namespace_1}.svc"
    22. - "${tc_name_1}-pd.${namespace_1}.svc.${cluster_domain_1}"
    23. - "${tc_name_1}-pd-peer"
    24. - "${tc_name_1}-pd-peer.${namespace_1}"
    25. - "${tc_name_1}-pd-peer.${namespace_1}.svc"
    26. - "${tc_name_1}-pd-peer.${namespace_1}.svc.${cluster_domain_1}"
    27. - "*.${tc_name_1}-pd-peer"
    28. - "*.${tc_name_1}-pd-peer.${namespace_1}"
    29. - "*.${tc_name_1}-pd-peer.${namespace_1}.svc"
    30. - "*.${tc_name_1}-pd-peer.${namespace_1}.svc.${cluster_domain_1}"
    31. ipAddresses:
    32. - 127.0.0.1
    33. - ::1
    34. issuerRef:
    35. name: ${tc_name_1}-tidb-issuer
    36. kind: Issuer
    37. group: cert-manager.io
    38. EOF

    需要参考 TLS 相关文档,为组件签发对应的证书,并在相应 Kubernetes 集群中创建 Secret。

    其他 TLS 相关信息,可参考以下文档:

    通过如下命令部署初始 TidbCluster。下面的 YAML 文件已经开启了 TLS 功能,并通过配置 cert-allowed-cn,使得各个组件开始验证由 CNTiDBCA 所签发的证书。

    1. cat << EOF | kubectl apply -n ${namespace_1} -f -
    2. apiVersion: pingcap.com/v1alpha1
    3. kind: TidbCluster
    4. metadata:
    5. name: "${tc_name_1}"
    6. spec:
    7. version: v5.4.0
    8. timezone: UTC
    9. tlsCluster:
    10. enabled: true
    11. pvReclaimPolicy: Delete
    12. enableDynamicConfiguration: true
    13. configUpdateStrategy: RollingUpdate
    14. clusterDomain: "${cluster_domain_1}"
    15. acrossK8s: true
    16. discovery: {}
    17. pd:
    18. baseImage: pingcap/pd
    19. maxFailoverCount: 0
    20. replicas: 1
    21. requests:
    22. storage: "10Gi"
    23. config:
    24. security:
    25. cert-allowed-cn:
    26. - TiDB
    27. baseImage: pingcap/tikv
    28. maxFailoverCount: 0
    29. replicas: 1
    30. storage: "10Gi"
    31. config:
    32. security:
    33. cert-allowed-cn:
    34. - TiDB
    35. tidb:
    36. baseImage: pingcap/tidb
    37. maxFailoverCount: 0
    38. replicas: 1
    39. service:
    40. type: ClusterIP
    41. tlsClient:
    42. enabled: true
    43. config:
    44. security:
    45. cert-allowed-cn:
    46. - TiDB
    47. EOF

    第 4 步:部署新的 TidbCluster 加入 TiDB 集群

    等待初始集群部署完成部署后,创建新的 TidbCluster 加入集群。在实际使用中,新部署的 TidbCluster 可以加入任意的已经部署的 TidbCluster。

    1. cat << EOF | kubectl apply -n ${namespace_2} -f -
    2. apiVersion: pingcap.com/v1alpha1
    3. kind: TidbCluster
    4. metadata:
    5. name: "${tc_name_2}"
    6. spec:
    7. version: v5.4.0
    8. timezone: UTC
    9. tlsCluster:
    10. enabled: true
    11. pvReclaimPolicy: Delete
    12. enableDynamicConfiguration: true
    13. configUpdateStrategy: RollingUpdate
    14. clusterDomain: "${cluster_domain_2}"
    15. acrossK8s: true
    16. cluster:
    17. name: "${tc_name_1}"
    18. namespace: "${namespace_1}"
    19. clusterDomain: "${cluster_domain_1}"
    20. discovery: {}
    21. pd:
    22. baseImage: pingcap/pd
    23. maxFailoverCount: 0
    24. replicas: 1
    25. requests:
    26. storage: "10Gi"
    27. config:
    28. security:
    29. cert-allowed-cn:
    30. - TiDB
    31. tikv:
    32. baseImage: pingcap/tikv
    33. maxFailoverCount: 0
    34. replicas: 1
    35. requests:
    36. storage: "10Gi"
    37. config:
    38. security:
    39. cert-allowed-cn:
    40. - TiDB
    41. tidb:
    42. baseImage: pingcap/tidb
    43. maxFailoverCount: 0
    44. replicas: 1
    45. service:
    46. type: ClusterIP
    47. tlsClient:
    48. enabled: true
    49. config:
    50. security:
    51. cert-allowed-cn:
    52. - TiDB
    53. EOF

    当跨 Kubernetes 集群部署一个 TiDB 集群时,如果要对 TiDB 集群的各组件 Pod 进行滚动升级,请按照本文中的步骤依次修改各 Kubernetes 集群的 TidbCluster 定义中各组件的 version 配置。

    1. 升级所有 Kubernetes 集群的 PD 版本。

      1. 修改初始 TidbCluster 定义中的 spec.pd.version 字段。

        1. apiVersion: pingcap.com/v1alpha1
        2. kind: TidbCluster
        3. # ...
        4. spec:
        5. pd:
        6. version: ${version}
      2. 查看 PD Pods 状态,等待初始 TidbCluster 对应的 PD Pod 都重建完毕进入 Running 状态。

      3. 按照前两步,升级其他 TidbCluster 的 PD 版本。

    2. 以步骤 1 为例,按顺序进行如下升级操作:

      1. 如果集群中部署了 TiFlash,为所有部署了 TiFlash 的 Kubernetes 集群升级 TiFlash 版本。
      2. 升级所有 Kubernetes 集群的 TiKV 版本。
      3. 如果集群中部署了 Pump,为所有部署了 Pump 的 Kubernetes 集群升级 Pump 版本。
      4. 升级所有 Kubernetes 集群的 TiDB 版本。
      5. 如果集群中部署了 TiCDC,为所有部署了 TiCDC 的 Kubernetes 集群升级 TiCDC 版本。

    退出和回收已加入的 TidbCluster

    当你需要让一个集群从所加入的跨 Kubernetes 部署的 TiDB 集群退出并回收资源时,可以通过缩容流程来实现上述需求。在此场景下,需要满足缩容的一些限制,限制如下:

    • 缩容后,集群中 TiKV 副本数应大于 PD 中设置的 max-replicas 数量,默认情况下 TiKV 副本数量需要大于 3。

    以上面文档创建的第二个 TidbCluster 为例,先将 PD、TiKV、TiDB 的副本数设置为 0,如果开启了 TiFlash、TiCDC、Pump 等其他组件,也请一并将其副本数设为 0:

    1. kubectl patch tc ${tc_name_2} -n ${namespace_2} --type merge -p '{"spec":{"pd":{"replicas":0},"tikv":{"replicas":0},"tidb":{"replicas":0}}}'

    等待第二个 TidbCluster 状态变为 Ready,相关组件此时应被缩容到 0 副本:

    Pod 列表显示为 No resources found.,此时 Pod 已经被全部缩容,TidbCluster 对应组件已经退出 TiDB 集群,查看状态:

    1. kubectl get tc ${tc_name_2} -n ${namespace_2}
    1. kubectl delete tc ${tc_name_2} -n ${namespace_2}

    通过上述步骤完成已加入集群的退出和资源回收。

    警告

    目前此场景属于实验性支持,可能会造成数据丢失,请谨慎使用。

    已有数据集群指的是已部署的 TiDB 集群,且在部署时已设置 spec.acrossK8s: false

    根据构建的多个 Kubernetes 集群之间的网络情况不同,有不同的方法。

    如果所有 Kubernetes 集群有着相同的 Cluster Domain,那么只需要更新 TidbCluster 的 spec.acrossK8s 配置。执行以下命令:

    1. kubectl patch tidbcluster cluster1 --type merge -p '{"spec":{"acrossK8s": true}}'

    修改完成后,TiDB 集群进入滚动更新状态,等待滚动更新结束。

    如果各个 Kubernetes 集群有着不同的 Cluster Domain,那么需要更新 TidbCluster 的 spec.clusterDomainspec.acrossK8s 配置。具体步骤如下:

    1. 更新 spec.clusterDomainspec.acrossK8s 配置:

      根据你的 Kubernetes 集群信息中的 clusterDomain 配置下面的参数:

      跨多个 Kubernetes 集群部署 TiDB 集群 - 图2警告

      目前需要你使用正确的信息配置 clusterDomain,配置修改后无法再次修改。

      1. kubectl patch tidbcluster cluster1 --type merge -p '{"spec":{"clusterDomain":"cluster1.com", "acrossK8s": true}}'

      修改完成后,TiDB 集群进入滚动更新状态,等待滚动更新结束。

    2. 更新 PD 的 PeerURL 信息:

      滚动更新结束后,需要使用 port-forward 暴露 PD 的 API 接口,使用 PD 的 API 接口更新 PD 的 PeerURL

      1. 使用 port-forward 暴露 PD 的 API 接口:

        1. kubectl port-forward pods/cluster1-pd-0 2380:2380 2379:2379 -n pingcap
      2. 访问 PD API,获取 members 信息,注意使用 port-forward 后,终端会被占用,需要在另一个终端执行下列操作:

        1. curl http://127.0.0.1:2379/v2/members

        注意

        如果集群开启了 TLS,使用 curl 命令时需要配置证书。例如:

        curl --cacert /var/lib/pd-tls/ca.crt --cert /var/lib/pd-tls/tls.crt --key /var/lib/pd-tls/tls.key https://127.0.0.1:2379/v2/members

        执行后输出如下结果:

      3. 记录各个 PD 实例的 id,使用 id 依次更新每个成员的 peerURL

        1. member_ID="6ed0312dc663b885"
        2. member_peer_url="http://cluster1-pd-0.cluster1-pd-peer.pingcap.svc.cluster1.com:2380"
        3. -H "Content-Type: application/json" -d '{"peerURLs":["${member_peer_url}"]}'

    完成上述步骤后,该 TidbCluster 可以作为跨 Kubernetes 集群部署 TiDB 集群的初始 TidbCluster。可以参考部署新的 TidbCluster 加入 TiDB 集群一节部署其他的 TidbCluster。

    更多示例信息以及开发信息,请参阅 。

    跨多个 Kubernetes 集群部署的 TiDB 集群监控