跨多个 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。
cat << EOF | kubectl apply -n ${namespace_2} -f -
apiVersion: pingcap.com/v1alpha1
kind: TidbCluster
metadata:
name: "${tc_name_2}"
spec:
version: v5.4.0
timezone: UTC
pvReclaimPolicy: Delete
enableDynamicConfiguration: true
configUpdateStrategy: RollingUpdate
clusterDomain: "${cluster_domain_2}"
acrossK8s: true
cluster:
name: "${tc_name_1}"
namespace: "${namespace_1}"
clusterDomain: "${cluster_domain_1}"
discovery: {}
pd:
baseImage: pingcap/pd
maxFailoverCount: 0
replicas: 1
requests:
storage: "10Gi"
config: {}
tikv:
baseImage: pingcap/tikv
maxFailoverCount: 0
replicas: 1
requests:
storage: "10Gi"
config: {}
tidb:
baseImage: pingcap/tidb
maxFailoverCount: 0
replicas: 1
service:
type: ClusterIP
config: {}
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-issuer
的 Issuer
),配置 Issuer
使用该 CA,具体过程如下:
在初始 Kubernetes 集群上创建
CA Issuer
和创建CA Certificate
。执行以下指令:
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: ${tc_name_1}-selfsigned-ca-issuer
namespace: ${namespace}
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ${tc_name_1}-ca
namespace: ${namespace_1}
spec:
secretName: ${tc_name_1}-ca-secret
commonName: "TiDB"
isCA: true
duration: 87600h # 10yrs
renewBefore: 720h # 30d
issuerRef:
name: ${tc_name_1}-selfsigned-ca-issuer
kind: Issuer
EOF
导出 CA 并删除无关信息。
首先需要导出存放 CA 的
Secret
,Secret
的名字可以由第一步Certificate
的.spec.secretName
得到。kubectl get secret ${tc_name_1}-ca-secret -n ${namespace_1} -o yaml > ca.yaml
apiVersion: v1
data:
ca.crt: LS0...LQo=
tls.crt: LS0t....LQo=
tls.key: LS0t...tCg==
kind: Secret
metadata:
name: ${tc_name_2}-ca-secret
type: kubernetes.io/tls
将导出的 CA 导入到其他 Kubernetes 集群。
你需要配置这里的
namespace
使得相关组件可以访问到 CA 证书:kubectl apply -f ca.yaml -n ${namespace_2}
在所有 Kubernetes 集群创建组件证书签发
Issuer
,使用该 CA。在初始 Kubernetes 集群上,创建组件间证书签发
Issuer
。执行以下指令:
cat << EOF | kubectl apply -f -
kind: Issuer
metadata:
name: ${tc_name_1}-tidb-issuer
spec:
ca:
secretName: ${tc_name_1}-ca-secret
EOF
在其他 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
文件:
cat << EOF > pd-server.json
{
"CN": "TiDB",
"hosts": [
"127.0.0.1",
"::1",
"${tc_name_1}-pd",
"${tc_name_1}-pd.${namespace_1}",
"${tc_name_1}-pd.${namespace_1}.svc",
"${tc_name_1}-pd.${namespace_1}.svc.${cluster_domain_1}",
"${tc_name_1}-pd-peer",
"${tc_name_1}-pd-peer.${namespace_1}",
"${tc_name_1}-pd-peer.${namespace_1}.svc",
"${tc_name_1}-pd-peer.${namespace_1}.svc.${cluster_domain_1}",
"*.${tc_name_1}-pd-peer",
"*.${tc_name_1}-pd-peer.${namespace_1}",
"*.${tc_name_1}-pd-peer.${namespace_1}.svc",
"*.${tc_name_1}-pd-peer.${namespace_1}.svc.${cluster_domain_1}"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"L": "CA",
"ST": "San Francisco"
}
]
}
EOF
使用 cert-manager 系统为 TiDB 组件签发证书
如果使用 cert-manager
,以创建初始 TidbCluster 的 PD 组件所使用的证书为例,Certifcates
如下所示。
cat << EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ${tc_name_1}-pd-cluster-secret
namespace: ${namespace_1}
spec:
secretName: ${tc_name_1}-pd-cluster-secret
duration: 8760h # 365d
renewBefore: 360h # 15d
subject:
organizations:
- PingCAP
commonName: "TiDB"
usages:
- server auth
- client auth
dnsNames:
- "${tc_name_1}-pd"
- "${tc_name_1}-pd.${namespace_1}"
- "${tc_name_1}-pd.${namespace_1}.svc"
- "${tc_name_1}-pd.${namespace_1}.svc.${cluster_domain_1}"
- "${tc_name_1}-pd-peer"
- "${tc_name_1}-pd-peer.${namespace_1}"
- "${tc_name_1}-pd-peer.${namespace_1}.svc"
- "${tc_name_1}-pd-peer.${namespace_1}.svc.${cluster_domain_1}"
- "*.${tc_name_1}-pd-peer"
- "*.${tc_name_1}-pd-peer.${namespace_1}"
- "*.${tc_name_1}-pd-peer.${namespace_1}.svc"
- "*.${tc_name_1}-pd-peer.${namespace_1}.svc.${cluster_domain_1}"
ipAddresses:
- 127.0.0.1
- ::1
issuerRef:
name: ${tc_name_1}-tidb-issuer
kind: Issuer
group: cert-manager.io
EOF
需要参考 TLS 相关文档,为组件签发对应的证书,并在相应 Kubernetes 集群中创建 Secret。
其他 TLS 相关信息,可参考以下文档:
通过如下命令部署初始 TidbCluster。下面的 YAML 文件已经开启了 TLS 功能,并通过配置 cert-allowed-cn
,使得各个组件开始验证由 CN
为 TiDB
的 CA
所签发的证书。
cat << EOF | kubectl apply -n ${namespace_1} -f -
apiVersion: pingcap.com/v1alpha1
kind: TidbCluster
metadata:
name: "${tc_name_1}"
spec:
version: v5.4.0
timezone: UTC
tlsCluster:
enabled: true
pvReclaimPolicy: Delete
enableDynamicConfiguration: true
configUpdateStrategy: RollingUpdate
clusterDomain: "${cluster_domain_1}"
acrossK8s: true
discovery: {}
pd:
baseImage: pingcap/pd
maxFailoverCount: 0
replicas: 1
requests:
storage: "10Gi"
config:
security:
cert-allowed-cn:
- TiDB
baseImage: pingcap/tikv
maxFailoverCount: 0
replicas: 1
storage: "10Gi"
config:
security:
cert-allowed-cn:
- TiDB
tidb:
baseImage: pingcap/tidb
maxFailoverCount: 0
replicas: 1
service:
type: ClusterIP
tlsClient:
enabled: true
config:
security:
cert-allowed-cn:
- TiDB
EOF
第 4 步:部署新的 TidbCluster 加入 TiDB 集群
等待初始集群部署完成部署后,创建新的 TidbCluster 加入集群。在实际使用中,新部署的 TidbCluster 可以加入任意的已经部署的 TidbCluster。
cat << EOF | kubectl apply -n ${namespace_2} -f -
apiVersion: pingcap.com/v1alpha1
kind: TidbCluster
metadata:
name: "${tc_name_2}"
spec:
version: v5.4.0
timezone: UTC
tlsCluster:
enabled: true
pvReclaimPolicy: Delete
enableDynamicConfiguration: true
configUpdateStrategy: RollingUpdate
clusterDomain: "${cluster_domain_2}"
acrossK8s: true
cluster:
name: "${tc_name_1}"
namespace: "${namespace_1}"
clusterDomain: "${cluster_domain_1}"
discovery: {}
pd:
baseImage: pingcap/pd
maxFailoverCount: 0
replicas: 1
requests:
storage: "10Gi"
config:
security:
cert-allowed-cn:
- TiDB
tikv:
baseImage: pingcap/tikv
maxFailoverCount: 0
replicas: 1
requests:
storage: "10Gi"
config:
security:
cert-allowed-cn:
- TiDB
tidb:
baseImage: pingcap/tidb
maxFailoverCount: 0
replicas: 1
service:
type: ClusterIP
tlsClient:
enabled: true
config:
security:
cert-allowed-cn:
- TiDB
EOF
当跨 Kubernetes 集群部署一个 TiDB 集群时,如果要对 TiDB 集群的各组件 Pod 进行滚动升级,请按照本文中的步骤依次修改各 Kubernetes 集群的 TidbCluster 定义中各组件的 version
配置。
升级所有 Kubernetes 集群的 PD 版本。
修改初始 TidbCluster 定义中的
spec.pd.version
字段。apiVersion: pingcap.com/v1alpha1
kind: TidbCluster
# ...
spec:
pd:
version: ${version}
查看 PD Pods 状态,等待初始 TidbCluster 对应的 PD Pod 都重建完毕进入
Running
状态。按照前两步,升级其他 TidbCluster 的 PD 版本。
以步骤 1 为例,按顺序进行如下升级操作:
- 如果集群中部署了 TiFlash,为所有部署了 TiFlash 的 Kubernetes 集群升级 TiFlash 版本。
- 升级所有 Kubernetes 集群的 TiKV 版本。
- 如果集群中部署了 Pump,为所有部署了 Pump 的 Kubernetes 集群升级 Pump 版本。
- 升级所有 Kubernetes 集群的 TiDB 版本。
- 如果集群中部署了 TiCDC,为所有部署了 TiCDC 的 Kubernetes 集群升级 TiCDC 版本。
退出和回收已加入的 TidbCluster
当你需要让一个集群从所加入的跨 Kubernetes 部署的 TiDB 集群退出并回收资源时,可以通过缩容流程来实现上述需求。在此场景下,需要满足缩容的一些限制,限制如下:
- 缩容后,集群中 TiKV 副本数应大于 PD 中设置的
max-replicas
数量,默认情况下 TiKV 副本数量需要大于 3。
以上面文档创建的第二个 TidbCluster 为例,先将 PD、TiKV、TiDB 的副本数设置为 0,如果开启了 TiFlash、TiCDC、Pump 等其他组件,也请一并将其副本数设为 0:
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 集群,查看状态:
kubectl get tc ${tc_name_2} -n ${namespace_2}
kubectl delete tc ${tc_name_2} -n ${namespace_2}
通过上述步骤完成已加入集群的退出和资源回收。
警告
目前此场景属于实验性支持,可能会造成数据丢失,请谨慎使用。
已有数据集群指的是已部署的 TiDB 集群,且在部署时已设置 spec.acrossK8s: false
。
根据构建的多个 Kubernetes 集群之间的网络情况不同,有不同的方法。
如果所有 Kubernetes 集群有着相同的 Cluster Domain,那么只需要更新 TidbCluster 的 spec.acrossK8s
配置。执行以下命令:
kubectl patch tidbcluster cluster1 --type merge -p '{"spec":{"acrossK8s": true}}'
修改完成后,TiDB 集群进入滚动更新状态,等待滚动更新结束。
如果各个 Kubernetes 集群有着不同的 Cluster Domain,那么需要更新 TidbCluster 的 spec.clusterDomain
和 spec.acrossK8s
配置。具体步骤如下:
更新
spec.clusterDomain
与spec.acrossK8s
配置:根据你的 Kubernetes 集群信息中的
clusterDomain
配置下面的参数:警告
目前需要你使用正确的信息配置
clusterDomain
,配置修改后无法再次修改。kubectl patch tidbcluster cluster1 --type merge -p '{"spec":{"clusterDomain":"cluster1.com", "acrossK8s": true}}'
修改完成后,TiDB 集群进入滚动更新状态,等待滚动更新结束。
更新 PD 的
PeerURL
信息:滚动更新结束后,需要使用
port-forward
暴露 PD 的 API 接口,使用 PD 的 API 接口更新 PD 的PeerURL
。使用
port-forward
暴露 PD 的 API 接口:kubectl port-forward pods/cluster1-pd-0 2380:2380 2379:2379 -n pingcap
访问
PD API
,获取members
信息,注意使用port-forward
后,终端会被占用,需要在另一个终端执行下列操作: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
执行后输出如下结果:
记录各个 PD 实例的
id
,使用id
依次更新每个成员的peerURL
:member_ID="6ed0312dc663b885"
member_peer_url="http://cluster1-pd-0.cluster1-pd-peer.pingcap.svc.cluster1.com:2380"
-H "Content-Type: application/json" -d '{"peerURLs":["${member_peer_url}"]}'
完成上述步骤后,该 TidbCluster 可以作为跨 Kubernetes 集群部署 TiDB 集群的初始 TidbCluster。可以参考部署新的 TidbCluster 加入 TiDB 集群一节部署其他的 TidbCluster。
更多示例信息以及开发信息,请参阅 。