天天看點

為 MySQL 用戶端開啟 TLS

本文主要描述了在 Kubernetes 上如何為 TiDB 叢集的 MySQL 用戶端開啟 TLS。TiDB Operator 從 v1.1 開始已經支援為 Kubernetes 上 TiDB 叢集開啟 MySQL 用戶端 TLS。開啟步驟為:

為 TiDB Server 頒發一套 Server 端證書,為 MySQL Client 頒發一套 Client 端證書。并建立兩個 Secret 對象,Secret 名字分别為:${cluster_name}-tidb-server-secret 和 ${cluster_name}-tidb-client-secret,分别包含前面建立的兩套證書;

部署叢集,設定 .spec.tidb.tlsClient.enabled 屬性為 true;

配置 MySQL 用戶端使用加密連接配接。

其中,頒發證書的方式有多種,本文檔提供兩種方式,使用者也可以根據需要為 TiDB 叢集頒發證書,這兩種方式分别為:

使用 cfssl 系統頒發證書;

使用 cert-manager 系統頒發證書;

第一步:為 TiDB 叢集頒發兩套證書

使用 cfssl 系統頒發證書

首先下載下傳 cfssl 軟體并初始化證書頒發機構:

mkdir -p ~/bin

curl -s -L -o ~/bin/cfssl

https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 curl -s -L -o ~/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64

chmod +x ~/bin/{cfssl,cfssljson}

export PATH=$PATH:~/bin

mkdir -p cfssl

cd cfssl

cfssl print-defaults config > ca-config.json

cfssl print-defaults csr > ca-csr.json

在 ca-config.json 配置檔案中配置 CA 選項:

{

"signing": {
    "default": {
        "expiry": "8760h"
    },
    "profiles": {
        "server": {
            "expiry": "8760h",
            "usages": [
                "signing",
                "key encipherment",
                "server auth"
            ]
        },
        "client": {
            "expiry": "8760h",
            "usages": [
                "signing",
                "key encipherment",
                "client auth"
            ]
        }
    }
}           

}

您還可以修改 ca-csr.json 證書簽名請求 (CSR):

"CN": "TiDB Server",
"key": {
    "algo": "rsa",
    "size": 2048
},
"names": [
    {
        "C": "US",
        "L": "CA",
        "O": "PingCAP",
        "ST": "Beijing",
        "OU": "TiDB"
    }
]           

使用定義的選項生成 CA:

cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

生成 Server 端證書。

首先生成預設的 server.json 檔案:

cfssl print-defaults csr > server.json

然後編輯這個檔案,修改 CN,hosts 屬性:

...

"CN": "TiDB Server",
"hosts": [
  "127.0.0.1",
  "::1",
  "${cluster_name}-tidb",
  "${cluster_name}-tidb.${namespace}",
  "${cluster_name}-tidb.${namespace}.svc",
  "*.${cluster_name}-tidb",
  "*.${cluster_name}-tidb.${namespace}",
  "*.${cluster_name}-tidb.${namespace}.svc",
  "*.${cluster_name}-tidb-peer",
  "*.${cluster_name}-tidb-peer.${namespace}",
  "*.${cluster_name}-tidb-peer.${namespace}.svc"
],           

其中 ${cluster_name} 為叢集的名字,${namespace} 為 TiDB 叢集部署的命名空間,使用者也可以添加自定義 hosts。

最後生成 Server 端證書:

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server server.json | cfssljson -bare server

生成 Client 端證書。

首先生成預設的 client.json 檔案:

cfssl print-defaults csr > client.json

然後編輯這個檔案,修改 CN,hosts 屬性,hosts 可以留白:

"CN": "TiDB Client",
"hosts": [],           

最後生成 Client 端證書:

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client

建立 Kubernetes Secret 對象。

到這裡假設你已經按照上述文檔把兩套證書都建立好了。通過下面的指令為 TiDB 叢集建立 Secret 對象:

kubectl create secret generic ${cluster_name}-tidb-server-secret --namespace=${namespace} --from-file=tls.crt=server.pem --from-file=tls.key=server-key.pem --from-file=ca.crt=ca.pem

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

這樣就給 Server/Client 端證書分别建立了:

一個 Secret 供 TiDB Server 啟動時加載使用;

另一個 Secret 供 MySQL 用戶端連接配接 TiDB 叢集時候使用。

使用者可以生成多套 Client 端證書,并且至少要生成一套 Client 證書供 TiDB Operator 内部元件通路 TiDB Server(目前有 TidbInitializer 會通路 TiDB Server 來設定密碼或者一些初始化操作)。

使用 cert-manager 頒發證書

安裝 cert-manager。

請參考官網安裝:cert-manager installation in Kubernetes。

建立一個 Issuer 用于給 TiDB 叢集頒發證書。

為了配置 cert-manager 頒發證書,必須先建立 Issuer 資源。

首先建立一個目錄儲存 cert-manager 建立證書所需檔案:

mkdir -p cert-manager

cd cert-manager

然後建立一個 tidb-server-issuer.yaml 檔案,輸入以下内容:

apiVersion: cert-manager.io/v1alpha2

kind: Issuer

metadata:

name: ${cluster_name}-selfsigned-ca-issuer

namespace: ${namespace}

spec:

selfSigned: {}

kind: Certificate

name: ${cluster_name}-ca

secretName: ${cluster_name}-ca-secret

commonName: "TiDB CA"

isCA: true

issuerRef:

name: ${cluster_name}-selfsigned-ca-issuer
kind: Issuer           

name: ${cluster_name}-tidb-issuer

ca:

secretName: ${cluster_name}-ca-secret           

上面的檔案建立三個對象:

一個 SelfSigned 類型的 Isser 對象(用于生成 CA 類型 Issuer 所需要的 CA 證書);

一個 Certificate 對象,isCa 屬性設定為 true;

一個可以用于頒發 TiDB Server TLS 證書的 Issuer。

最後執行下面的指令進行建立:

kubectl apply -f tidb-server-issuer.yaml

建立 Server 端證書。

在 cert-manager 中,Certificate 資源表示證書接口,該證書将由上面建立的 Issuer 頒發并保持更新。

首先來建立 Server 端證書,建立一個 tidb-server-cert.yaml 檔案,并輸入以下内容:

name: ${cluster_name}-tidb-server-secret

secretName: ${cluster_name}-tidb-server-secret

duration: 8760h # 365d

renewBefore: 360h # 15d

organization:

- PingCAP           

commonName: "TiDB Server"

usages:

- server auth           

dnsNames:

- "${cluster_name}-tidb"
- "${cluster_name}-tidb.${namespace}"
- "${cluster_name}-tidb.${namespace}.svc"
- "*.${cluster_name}-tidb"
- "*.${cluster_name}-tidb.${namespace}"
- "*.${cluster_name}-tidb.${namespace}.svc"
- "*.${cluster_name}-tidb-peer"
- "*.${cluster_name}-tidb-peer.${namespace}"
- "*.${cluster_name}-tidb-peer.${namespace}.svc"           

ipAddresses:

- 127.0.0.1
- ::1           

issuerRef:

name: ${cluster_name}-tidb-issuer
kind: Issuer
group: cert-manager.io           

其中 ${cluster_name} 為叢集的名字:

spec.secretName 請設定為 ${cluster_name}-tidb-server-secret;

usages 請添加上 server auth;

dnsNames 需要填寫這 6 個 DNS,根據需要可以填寫其他 DNS:

${cluster_name}-tidb

${cluster_name}-tidb.${namespace}

${cluster_name}-tidb.${namespace}.svc

*.${cluster_name}-tidb

*.${cluster_name}-tidb.${namespace}

*.${cluster_name}-tidb.${namespace}.svc

*.${cluster_name}-tidb-peer

*.${cluster_name}-tidb-peer.${namespace}

*.${cluster_name}-tidb-peer.${namespace}.svc

ipAddresses 需要填寫這兩個 IP ,根據需要可以填寫其他 IP:

127.0.0.1

::1

issuerRef 請填寫上面建立的 Issuer;

其他屬性請參考 cert-manager API。

通過執行下面的指令來建立證書:

kubectl apply -f tidb-server-cert.yaml

建立這個對象以後,cert-manager 會生成一個名字為 ${cluster_name}-tidb-server-secret 的 Secret 對象供 TiDB Server 使用。

建立 Client 端證書。

建立一個 tidb-client-cert.yaml 檔案,并輸入以下内容:

name: ${cluster_name}-tidb-client-secret

secretName: ${cluster_name}-tidb-client-secret

- PingCAP           

commonName: "TiDB Client"

- client auth           
name: ${cluster_name}-tidb-issuer
kind: Issuer
group: cert-manager.io           

spec.secretName 請設定為 ${cluster_name}-tidb-client-secret;

usages 請添加上 client auth;

dnsNames 和 ipAddresses 不需要填寫;

kubectl apply -f tidb-client-cert.yaml

建立這個對象以後,cert-manager 會生成一個名字為 ${cluster_name}-tidb-client-secret 的 Secret 對象供 TiDB Client 使用。

注意:

TiDB Server 的 TLS 相容 MySQL 協定。當

QQ靓号買賣

證書内容發生改變後,需要管理者手動執行 SQL 語句 alter instance reload tls 進行重新整理。

第二步:部署 TiDB 叢集

接下來将會通過兩個 CR 對象來建立一個 TiDB 叢集,并且執行以下步驟:

開啟 MySQL 用戶端 TLS;

對叢集進行初始化(這裡建立了一個資料庫 app)。

apiVersion: pingcap.com/v1alpha1

kind: TidbCluster

name: ${cluster_name}

namespace: ${namespace}

version: v3.1.0

timezone: UTC

pvReclaimPolicy: Retain

pd:

baseImage: pingcap/pd

replicas: 1

requests:

storage: "1Gi"           

config: {}

tikv:

baseImage: pingcap/tikv

storage: "1Gi"           

tidb:

baseImage: pingcap/tidb

service:

type: ClusterIP           

tlsClient:

enabled: true           

kind: TidbInitializer

name: ${cluster_name}-init

image: tnir/mysqlclient

cluster:

namespace: ${namespace}

name: ${cluster_name}

initSql: |-

create database app;

其中 ${cluster_name} 為叢集的名字,${namespace} 為 TiDB 叢集部署的命名空間。通過設定 spec.tidb.tlsClient.enabled 屬性為 true 來開啟 MySQL 用戶端 TLS。

将上面檔案儲存為 cr.yaml,然後使用 kubectl apply -f cr.yaml 來建立 TiDB 叢集。

第三步:配置 MySQL 用戶端使用加密連接配接

可以根據官網文檔提示,使用上面建立的 Client 證書,通過下面的方法連接配接 TiDB 叢集:

擷取 Client 證書的方式并連接配接 TiDB Server 的方法是:

kubectl get secret -n ${namespace} ${cluster_name}-tidb-client-secret -ojsonpath='{.data.tls.crt}' | base64 --decode > client-tls.crt

kubectl get secret -n ${namespace} ${cluster_name}-tidb-client-secret -ojsonpath='{.data.tls.key}' | base64 --decode > client-tls.key

kubectl get secret -n ${namespace} ${cluster_name}-tidb-client-secret -ojsonpath='{.data.ca.crt}' | base64 --decode > client-ca.crt

mysql -uroot -p -P 4000 -h ${tidb_host} --ssl-cert=client-tls.crt --ssl-key=client-tls.key --ssl-ca=client-ca.crt

最後請參考 官網文檔 來驗證是否正确開啟了 TLS。