为 DM 开启 TLS

    TiDB Operator 从 v1.2 开始已经支持为 Kubernetes 上 DM 集群组件间开启 TLS。开启步骤为:

    1. 为即将被创建的 DM 集群的每个组件生成证书:

      • 为 DM-master/DM-worker 组件分别创建一套 Server 端证书,保存为 Kubernetes Secret 对象:${cluster_name}-${component_name}-cluster-secret
      • 为它们的各种客户端创建一套共用的 Client 端证书,保存为 Kubernetes Secret 对象:${cluster_name}-dm-client-secret

      注意

      创建的 Secret 对象必须符合上述命名规范,否则将导致 DM 集群部署失败。

    2. 部署集群,设置 .spec.tlsCluster.enabled 属性为 true

      为 DM 组件开启 TLS - 图2注意

      在集群创建后,不能修改此字段,否则将导致集群升级失败,此时需要删除已有集群,并重新创建。

    3. 配置 dmctl 连接集群。

    其中,颁发证书的方式有多种,本文档提供两种方式,用户也可以根据需要为 DM 集群颁发证书,这两种方式分别为:

    当需要更新已有 TLS 证书时,可参考更新和替换 TLS 证书

    使用 cfssl 系统颁发证书

    1. 首先下载 cfssl 软件并初始化证书颁发机构:

    2. 生成 ca-config.json 配置文件:

      1. cat << EOF > ca-config.json
      2. {
      3. "signing": {
      4. "default": {
      5. "expiry": "8760h"
      6. },
      7. "profiles": {
      8. "internal": {
      9. "expiry": "8760h",
      10. "usages": [
      11. "signing",
      12. "key encipherment",
      13. "server auth",
      14. "client auth"
      15. ]
      16. },
      17. "client": {
      18. "expiry": "8760h",
      19. "usages": [
      20. "signing",
      21. "key encipherment",
      22. "client auth"
      23. ]
      24. }
      25. }
      26. }
      27. }
      28. EOF
    3. 生成 ca-csr.json 配置文件:

      1. cat << EOF > ca-csr.json
      2. {
      3. "CN": "TiDB",
      4. "CA": {
      5. "expiry": "87600h"
      6. },
      7. "key": {
      8. "algo": "rsa",
      9. "size": 2048
      10. },
      11. "names": [
      12. {
      13. "C": "US",
      14. "L": "CA",
      15. "O": "PingCAP",
      16. "ST": "Beijing",
      17. "OU": "TiDB"
      18. }
      19. ]
      20. }
      21. EOF
    4. 使用定义的选项生成 CA:

      1. cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
    5. 生成 Server 端证书。

      这里需要为每个 DM 集群的组件生成一套 Server 端证书。

      • DM-master Server 端证书

        首先生成默认的 dm-master-server.json 文件:

        1. cfssl print-defaults csr > dm-master-server.json

        然后编辑这个文件,修改 CNhosts 属性:

        1. ...
        2. "CN": "TiDB",
        3. "hosts": [
        4. "127.0.0.1",
        5. "::1",
        6. "${cluster_name}-dm-master",
        7. "${cluster_name}-dm-master.${namespace}",
        8. "${cluster_name}-dm-master.${namespace}.svc",
        9. "${cluster_name}-dm-master-peer",
        10. "${cluster_name}-dm-master-peer.${namespace}",
        11. "${cluster_name}-dm-master-peer.${namespace}.svc",
        12. "*.${cluster_name}-dm-master-peer",
        13. "*.${cluster_name}-dm-master-peer.${namespace}",
        14. "*.${cluster_name}-dm-master-peer.${namespace}.svc"
        15. ],
        16. ...

        其中 ${cluster_name} 为 DM 集群的名字,${namespace} 为 DM 集群部署的命名空间,用户也可以添加自定义 hosts

        最后生成 DM-master Server 端证书:

        1. cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=internal dm-master-server.json | cfssljson -bare dm-master-server
      • DM-worker Server 端证书

        1. cfssl print-defaults csr > dm-worker-server.json

        然后编辑这个文件,修改 CNhosts 属性:

        1. ...
        2. "CN": "TiDB",
        3. "hosts": [
        4. "127.0.0.1",
        5. "::1",
        6. "${cluster_name}-dm-worker",
        7. "${cluster_name}-dm-worker.${namespace}",
        8. "${cluster_name}-dm-worker.${namespace}.svc",
        9. "${cluster_name}-dm-worker-peer",
        10. "${cluster_name}-dm-worker-peer.${namespace}",
        11. "${cluster_name}-dm-worker-peer.${namespace}.svc",
        12. "*.${cluster_name}-dm-worker-peer",
        13. "*.${cluster_name}-dm-worker-peer.${namespace}",
        14. "*.${cluster_name}-dm-worker-peer.${namespace}.svc"
        15. ],
        16. ...

        其中 ${cluster_name} 为集群的名字,${namespace} 为 DM 集群部署的命名空间,用户也可以添加自定义 hosts

        最后生成 DM-worker Server 端证书:

    6. 生成 Client 端证书。

      首先生成默认的 client.json 文件:

      1. cfssl print-defaults csr > client.json

      然后编辑这个文件,修改 CNhosts 属性,hosts 可以留空:

      1. ...
      2. "hosts": [],
      3. ...

      最后生成 Client 端证书:

      1. cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client
    7. 创建 Kubernetes Secret 对象。

      假设你已经按照上述文档为每个组件创建了一套 Server 端证书,并为各个客户端创建了一套 Client 端证书。通过下面的命令为 DM 集群创建这些 Secret 对象:

      • DM-master 集群证书 Secret:

        1. kubectl create secret generic ${cluster_name}-dm-master-cluster-secret --namespace=${namespace} --from-file=tls.crt=dm-master-server.pem --from-file=tls.key=dm-master-server-key.pem --from-file=ca.crt=ca.pem
      • DM-worker 集群证书 Secret:

        1. kubectl create secret generic ${cluster_name}-dm-worker-cluster-secret --namespace=${namespace} --from-file=tls.crt=dm-worker-server.pem --from-file=tls.key=dm-worker-server-key.pem --from-file=ca.crt=ca.pem
      • Client 证书 Secret:

        1. kubectl create secret generic ${cluster_name}-dm-client-secret --namespace=${namespace} --from-file=tls.crt=client.pem --from-file=tls.key=client-key.pem --from-file=ca.crt=ca.pem

      这里给 DM-master/DM-worker 的 Server 端证书分别创建了一个 Secret 供他们启动时加载使用,另外一套 Client 端证书供他们的客户端连接使用。

    使用 系统颁发证书

    1. 安装 cert-manager。

      请参考官网安装:。

    2. 创建一个 Issuer 用于给 DM 集群颁发证书。

      为了配置 cert-manager 颁发证书,必须先创建 Issuer 资源。

      首先创建一个目录保存 cert-manager 创建证书所需文件:

      1. mkdir -p cert-manager
      2. cd cert-manager

      然后创建一个 dm-cluster-issuer.yaml 文件,输入以下内容:

      1. apiVersion: cert-manager.io/v1
      2. kind: Issuer
      3. metadata:
      4. name: ${cluster_name}-selfsigned-ca-issuer
      5. namespace: ${namespace}
      6. spec:
      7. selfSigned: {}
      8. ---
      9. apiVersion: cert-manager.io/v1
      10. kind: Certificate
      11. metadata:
      12. name: ${cluster_name}-ca
      13. namespace: ${namespace}
      14. spec:
      15. secretName: ${cluster_name}-ca-secret
      16. commonName: "TiDB"
      17. isCA: true
      18. duration: 87600h # 10yrs
      19. renewBefore: 720h # 30d
      20. issuerRef:
      21. name: ${cluster_name}-selfsigned-ca-issuer
      22. kind: Issuer
      23. ---
      24. apiVersion: cert-manager.io/v1
      25. kind: Issuer
      26. metadata:
      27. name: ${cluster_name}-dm-issuer
      28. namespace: ${namespace}
      29. spec:
      30. ca:
      31. secretName: ${cluster_name}-ca-secret

      其中 ${cluster_name} 为集群的名字,上面的文件创建三个对象:

      • 一个 SelfSigned 类型的 Isser 对象(用于生成 CA 类型 Issuer 所需要的 CA 证书);
      • 一个 Certificate 对象,isCa 属性设置为 true
      • 一个可以用于颁发 DM 组件间 TLS 证书的 Issuer。

      最后执行下面的命令进行创建:

    3. 创建 Server 端证书。

      我们需要为每个组件创建一个 Server 端证书,并且为它们的 Client 创建一套公用的 Client 端证书。

      • DM-master 组件的 Server 端证书。

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

        其中 ${cluster_name} 为集群的名字:

        • spec.secretName 请设置为 ${cluster_name}-dm-master-cluster-secret
        • usages 请添加上 server authclient auth
        • dnsNames 需要填写上面 yaml 中的 DNS,根据需要可以填写其他 DNS;
        • ipAddresses 需要填写这两个 IP ,根据需要可以填写其他 IP:
          • 127.0.0.1
          • ::1
        • issuerRef 请填写上面创建的 Issuer;
        • 其他属性请参考 cert-manager API

        创建这个对象以后,cert-manager 会生成一个名字为 ${cluster_name}-dm-master-cluster-secret 的 Secret 对象供 DM 集群的 DM-master 组件使用。

      • DM-worker 组件的 Server 端证书。

        1. apiVersion: cert-manager.io/v1
        2. kind: Certificate
        3. metadata:
        4. name: ${cluster_name}-dm-worker-cluster-secret
        5. namespace: ${namespace}
        6. spec:
        7. secretName: ${cluster_name}-dm-worker-cluster-secret
        8. duration: 8760h # 365d
        9. renewBefore: 360h # 15d
        10. subject:
        11. organizations:
        12. - PingCAP
        13. commonName: "TiDB"
        14. usages:
        15. - server auth
        16. - client auth
        17. dnsNames:
        18. - "${cluster_name}-dm-worker"
        19. - "${cluster_name}-dm-worker.${namespace}"
        20. - "${cluster_name}-dm-worker.${namespace}.svc"
        21. - "${cluster_name}-dm-worker-peer"
        22. - "${cluster_name}-dm-worker-peer.${namespace}.svc"
        23. - "*.${cluster_name}-dm-worker-peer"
        24. - "*.${cluster_name}-dm-worker-peer.${namespace}"
        25. - "*.${cluster_name}-dm-worker-peer.${namespace}.svc"
        26. ipAddresses:
        27. - 127.0.0.1
        28. - ::1
        29. issuerRef:
        30. name: ${cluster_name}-dm-issuer
        31. kind: Issuer
        32. group: cert-manager.io

        其中 ${cluster_name} 为集群的名字:

        • spec.secretName 请设置为 ;
        • usages 请添加上 server authclient auth
        • dnsNames 需要填写上面 yaml 中的 DNS,根据需要可以填写其他 DNS;
        • ipAddresses 需要填写这两个 IP ,根据需要可以填写其他 IP:
          • 127.0.0.1
          • ::1
        • issuerRef 请填写上面创建的 Issuer;
        • 其他属性请参考 。

        创建这个对象以后,cert-manager 会生成一个名字为 ${cluster_name}-dm-cluster-secret 的 Secret 对象供 DM 集群的 DM-worker 组件使用。

      • 一套 DM 集群组件的 Client 端证书。

        1. apiVersion: cert-manager.io/v1
        2. kind: Certificate
        3. metadata:
        4. name: ${cluster_name}-dm-client-secret
        5. namespace: ${namespace}
        6. spec:
        7. secretName: ${cluster_name}-dm-client-secret
        8. duration: 8760h # 365d
        9. renewBefore: 360h # 15d
        10. subject:
        11. organizations:
        12. - PingCAP
        13. commonName: "TiDB"
        14. usages:
        15. - client auth
        16. issuerRef:
        17. name: ${cluster_name}-dm-issuer
        18. kind: Issuer
        19. group: cert-manager.io

        其中 ${cluster_name} 为集群的名字:

        • spec.secretName 请设置为 ${cluster_name}-dm-client-secret
        • usages 请添加上 client auth
        • dnsNamesipAddresses 不需要填写;
        • issuerRef 请填写上面创建的 Issuer;
        • 其他属性请参考 cert-manager API

        创建这个对象以后,cert-manager 会生成一个名字为 ${cluster_name}-cluster-client-secret 的 Secret 对象供 DM 组件的 Client 使用。

    第二步:部署 DM 集群

    在部署 DM 集群时,可以开启集群间的 TLS,同时可以设置 cert-allowed-cn 配置项,用来验证集群间各组件证书的 CN (Common Name)。

    注意

    目前 DM-master 的 cert-allowed-cn 配置项只能设置一个值。因此所有 Certificate 对象的 commonName 都要设置成同样一个值。

    创建 dm-cluster.yaml 文件:

    1. apiVersion: pingcap.com/v1alpha1
    2. kind: DMCluster
    3. metadata:
    4. name: ${cluster_name}
    5. namespace: ${namespace}
    6. spec:
    7. tlsCluster:
    8. enabled: true
    9. version: v5.4.0
    10. pvReclaimPolicy: Retain
    11. discovery: {}
    12. master:
    13. baseImage: pingcap/dm
    14. maxFailoverCount: 0
    15. replicas: 1
    16. storageSize: "1Gi"
    17. config:
    18. cert-allowed-cn:
    19. - TiDB
    20. worker:
    21. baseImage: pingcap/dm
    22. maxFailoverCount: 0
    23. replicas: 1
    24. storageSize: "1Gi"
    25. config:
    26. cert-allowed-cn:
    27. - TiDB

    然后使用 kubectl apply -f dm-cluster.yaml 来创建 DM 集群。

    进入 DM-master Pod:

    1. kubectl exec -it ${cluster_name}-dm-master-0 -n ${namespace} sh

    使用 dmctl

    1. cd /var/lib/dm-master-tls
    2. /dmctl --ssl-ca=ca.crt --ssl-cert=tls.crt --ssl-key=tls.key --master-addr 127.0.0.1:8261 list-member

    用 DM 集群同步开启了 MySQL 客户端 TLS 验证的 MySQL/TiDB 数据库

    下面部分主要介绍如何配置 DM 同步开启了 MySQL 客户端 TLS 验证的 MySQL/TiDB 数据库。如需了解如何为 TiDB 的 MySQL 客户端开启 TLS,可以参考

    第一步:创建各 MySQL 客户端 TLS 的 Kubernetes Secret 对象

    到这里假设你已经部署了开启 MySQL 客户端 TLS 的 MySQL/TiDB 数据库。通过下面的命令为 TiDB 集群创建 Secret 对象:

    1. kubectl create secret generic ${mysql_secret_name1} --namespace=${namespace} --from-file=tls.crt=client.pem --from-file=tls.key=client-key.pem --from-file=ca.crt=ca.pem
    2. kubectl create secret generic ${tidb_secret_name} --namespace=${namespace} --from-file=tls.crt=client.pem --from-file=tls.key=client-key.pem --from-file=ca.crt=ca.pem

    创建好上下游数据库的 Kubernetes Secret 对象后,我们需要设置 spec.tlsClientSecretNames 使得 Secret 对象被挂载到 DM-master/DM-worker 的 Pod。

    1. apiVersion: pingcap.com/v1alpha1
    2. kind: DMCluster
    3. metadata:
    4. name: ${cluster_name}
    5. namespace: ${namespace}
    6. spec:
    7. version: v5.4.0
    8. pvReclaimPolicy: Retain
    9. discovery: {}
    10. tlsClientSecretNames:
    11. - ${mysql_secret_name1}
    12. - ${tidb_secret_name}
    13. master:
    14. ...

    第三步:修改数据源配置与同步任务配置

    设置 spec.tlsClientSecretNames 选项后,TiDB Operator 会将 Secret 对象 ${secret_name} 挂载到 /var/lib/source-tls/${secret_name} 路径。

    1. 填写数据源配置 source1.yamlfrom.security 选项:

      1. name: test
      2. task-mode: all
      3. is-sharding: false
      4. target-database:
      5. host: ${tidb_host}
      6. port: 4000
      7. user: "root"
      8. password: ""
      9. security:
      10. ssl-ca: /var/lib/source-tls/${tidb_secret_name}/ca.crt
      11. ssl-cert: /var/lib/source-tls/${tidb_secret_name}/tls.crt
      12. ssl-key: /var/lib/source-tls/${tidb_secret_name}/tls.key
      13. mysql-instances:
      14. - source-id: "replica-01"
      15. loader-config-name: "global"
      16. loaders:
      17. global:
      18. dir: "/var/lib/dm-worker/dumped_data"

    参考。