1. cluster1_name="cluster1"
  2. cluster1_cluster_domain="cluster1.com"
  3. cluster1_namespace="pingcap"

执行以下指令:

  1. cat << EOF | kubectl apply -n ${cluster1_namespace} -f -
  2. apiVersion: pingcap.com/v1alpha1
  3. kind: TidbCluster
  4. metadata:
  5. name: "${cluster1_name}"
  6. spec:
  7. version: v5.2.1
  8. timezone: UTC
  9. pvReclaimPolicy: Delete
  10. enableDynamicConfiguration: true
  11. configUpdateStrategy: RollingUpdate
  12. clusterDomain: "${cluster1_cluster_domain}"
  13. discovery: {}
  14. pd:
  15. baseImage: pingcap/pd
  16. replicas: 1
  17. requests:
  18. storage: "10Gi"
  19. config: {}
  20. tikv:
  21. baseImage: pingcap/tikv
  22. replicas: 1
  23. requests:
  24. storage: "10Gi"
  25. config: {}
  26. tidb:
  27. baseImage: pingcap/tidb
  28. replicas: 1
  29. service:
  30. type: ClusterIP
  31. config: {}
  32. EOF

部署新集群加入初始集群

等待集群 1 完成部署后,创建集群 2。在实际使用中,新创建的集群 2 可以加入多集群内的任意一个已有集群。

可以参考下面的范例,根据实际情况设置填入集群 1 和集群 2 的 NameCluster DomainNamespace 等相关信息:

  1. cluster1_name="cluster1"
  2. cluster1_cluster_domain="cluster1.com"
  3. cluster1_namespace="pingcap"
  4. cluster2_name="cluster2"
  5. cluster2_cluster_domain="cluster2.com"
  6. cluster2_namespace="pingcap"

执行以下指令:

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

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

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

签发根证书

使用 cfssl 系统签发根证书

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

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

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

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

    根据实际情况设置以下环境变量:

    1. cluster_name="cluster1"
    2. namespace="pingcap"

    执行以下指令:

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

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

    1. kubectl get secret cluster1-ca-secret -n ${namespace} -o yaml > ca.yaml

    删除 Secret YAML 文件中无关信息,删除后 YAML 文件如下所示,其中 data 内信息已省略:

    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: cluster1-ca-secret
    9. type: kubernetes.io/tls
  3. 将导出的 CA 导入到其他集群。

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

    1. kubectl apply -f ca.yaml -n ${namespace}
  4. 在初始集群和新集群创建组件证书签发 Issuer,使用该 CA。

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

      根据实际情况设置以下环境变量:

      1. cluster_name="cluster1"
      2. namespace="pingcap"
      3. ca_secret_name="cluster1-ca-secret"

      执行以下指令:

      1. cat << EOF | kubectl apply -f -
      2. apiVersion: cert-manager.io/v1alpha2
      3. kind: Issuer
      4. metadata:
      5. name: ${cluster_name}-tidb-issuer
      6. namespace: ${namespace}
      7. spec:
      8. ca:
      9. secretName: ${ca_secret_name}
      10. EOF
    2. 在新集群上,创建组件间证书签发 Issuer

      根据实际情况设置以下环境变量,其中 ca_secret_name 需要指向你刚才导入的存放 CASecretcluster_namenamespace 在下面的操作中需要用到:

      1. cluster_name="cluster2"
      2. namespace="pingcap"
      3. ca_secret_name="cluster1-ca-secret"

      执行以下指令:

      1. cat << EOF | kubectl apply -f -
      2. apiVersion: cert-manager.io/v1alpha2
      3. kind: Issuer
      4. metadata:
      5. name: ${cluster_name}-tidb-issuer
      6. namespace: ${namespace}
      7. spec:
      8. ca:
      9. secretName: ${ca_secret_name}
      10. EOF

为各个 Kubernetes 集群的 TiDB 组件签发证书

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

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

如果使用 cfssl,以创建 PD 组件所使用的证书为例,pd-server.json 文件如下所示。

根据实际情况设置以下环境变量:

  1. cluster_name=cluster2
  2. cluster_domain=cluster2.com
  3. namespace=pingcap

pd-server.json可以通过如下指令创建:

  1. cat << EOF > pd-server.json
  2. {
  3. "CN": "TiDB",
  4. "hosts": [
  5. "127.0.0.1",
  6. "::1",
  7. "${cluster_name}-pd",
  8. "${cluster_name}-pd.${namespace}",
  9. "${cluster_name}-pd.${namespace}.svc",
  10. "${cluster_name}-pd.${namespace}.svc.${cluster_domain}",
  11. "${cluster_name}-pd-peer",
  12. "${cluster_name}-pd-peer.${namespace}",
  13. "${cluster_name}-pd-peer.${namespace}.svc",
  14. "${cluster_name}-pd-peer.${namespace}.svc.${cluster_domain}",
  15. "*.${cluster_name}-pd-peer",
  16. "*.${cluster_name}-pd-peer.${namespace}",
  17. "*.${cluster_name}-pd-peer.${namespace}.svc",
  18. "*.${cluster_name}-pd-peer.${namespace}.svc.${cluster_domain}"
  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,以创建 PD 组件所使用的证书为例,Certifcates 如下所示。

通过以下指令设置环境变量:

  1. cluster_name="cluster2"
  2. namespace="pingcap"
  3. cluster_domain="cluster2.com"

执行以下指令:

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

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

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

部署初始集群

通过如下命令部署初始化集群,实际使用中需要根据你的实际情况设置 cluster1_namecluster1_cluster_domain 变量的内容,其中 cluster1_name 为集群 1 的集群名称,cluster1_cluster_domain 为集群 1 的 Cluster Domaincluster1_namespace 为集群 1 的命名空间。下面的 YAML 文件已经开启了 TLS 功能,并通过配置 cert-allowed-cn,使得各个组件开始验证由 CNTiDBCA 所签发的证书。

根据实际情况设置以下环境变量:

  1. cluster1_name="cluster1"
  2. cluster1_cluster_domain="cluster1.com"
  3. cluster1_namespace="pingcap"

执行以下指令:

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

部署新集群加入初始集群

等待集群 1 完成部署,完成部署后,创建集群 2,相关命令如下。在实际使用中,集群 1 并不一定是初始集群,可以指定多集群内的任一集群加入。

根据实际情况设置以下环境变量:

  1. cluster1_name="cluster1"
  2. cluster1_cluster_domain="cluster1.com"
  3. cluster1_namespace="pingcap"
  4. cluster2_name="cluster2"
  5. cluster2_cluster_domain="cluster2.com"
  6. cluster2_namespace="pingcap"

执行以下指令:

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

退出和回收已加入集群

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

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

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

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

等待集群 2 状态变为 Ready,相关组件此时应被缩容到 0 副本:

  1. kubectl get pods -l app.kubernetes.io/instance=cluster2 -n pingcap

Pod 列表显示为 No resources found.,此时 Pod 已经被全部缩容,集群 2 已经退出集群,查看集群 2 的集群状态:

  1. kubectl get tc cluster2

结果显示集群 2 为 Ready 状态,此时可以删除该对象,对相关资源进行回收。

  1. kubectl delete tc cluster2

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

已有数据集群开启跨多个 Kubernetes 集群功能并作为 TiDB 集群的初始集群

警告:

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

  1. 更新 .spec.clusterDomain 配置:

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

    警告:

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

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

    修改完成后,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

      执行后输出如下结果:

      1. {"members":[{"id":"6ed0312dc663b885","name":"cluster1-pd-0.cluster1-pd-peer.pingcap.svc.cluster1.com","peerURLs":["http://cluster1-pd-0.cluster1-pd-peer.pingcap.svc:2380"],"clientURLs":["http://cluster1-pd-0.cluster1-pd-peer.pingcap.svc.cluster1.com:2379"]},{"id":"bd9acd3d57e24a32","name":"cluster1-pd-1.cluster1-pd-peer.pingcap.svc.cluster1.com","peerURLs":["http://cluster1-pd-1.cluster1-pd-peer.pingcap.svc:2380"],"clientURLs":["http://cluster1-pd-1.cluster1-pd-peer.pingcap.svc.cluster1.com:2379"]},{"id":"e04e42cccef60246","name":"cluster1-pd-2.cluster1-pd-peer.pingcap.svc.cluster1.com","peerURLs":["http://cluster1-pd-2.cluster1-pd-peer.pingcap.svc:2380"],"clientURLs":["http://cluster1-pd-2.cluster1-pd-peer.pingcap.svc.cluster1.com:2379"]}]}
    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. curl http://127.0.0.1:2379/v2/members/${member_ID} -XPUT \
      4. -H "Content-Type: application/json" -d '{"peerURLs":["${member_peer_url}"]}'

更多示例信息以及开发信息,请参阅 multi-cluster