2022/12/06
[小〜中規模向け]GKEにTiDBをデプロイする
概要
MySQL互換のNewSQLであるTiDBをGKEにデプロイしてみました。
今回は、そのデプロイ方法を備忘録として記載します。
注意
弊社のサービスはまだまだ規模が小さいため、省コスト(開発環境や小規模向けアプリのため)の設定です。具体的にはtidbの構成要素である、pd
/ tikv
/ tidb
などのプロセスを同一のノードにホストするような設定にしています。
GKEのclusterはregionalなクラスターを作成して、アプリとDBは同一ノードにデプロイするようにしています。
これによって、各zoneに1台、計3台のノードにごっちゃにデプロイするようにしています。
大規模の場合は、公式サイトでやっているようにtidbの pd
/ tikv
/ tidb
専用にノードプールを作成する方が良いでしょう。
※ノードの1台を強制削除しても問題ないかはまだ未確認です。 時間ができたら試してみようと思います。(あとバックアップスケジュールとかも時間ができたら・・)
参考
基本的には公式サイトのGKE向けのドキュメントを参考にしています。
デプロイ手順
node poolの設定
# まずは各ノードにtagを付与します。
# pd=true/tikv=true/tidb=true というタグを付与します。後で、pd=trueとなっているノードにpdのpodをデプロイする設定に使います。
% gcloud container node-pools update "your-node-pool-name" \
--project="your-project-id" \
--region="your-region" \
--cluster="your-cluster-name" \
--node-labels=pd=true,tikv=true,tidb=true
# node-taintsは削除しておきます。全てのpodがノードにデプロイできるようにするためです。
% gcloud container node-pools update "your-node-pool-name" \
--project="your-project-id" \
--region="your-region" \
--cluster="your-cluster-name" \
--node-taints=""
# 設定が終わったら、以下のコマンドで、ちゃんとtagやtaintsが設定されていることを確認します。
% kubectl get node
% kubectl describe node <node-name-here>
storageclass
次に、clusterで利用するdiskの種類を定義します。 SSDを利用します。
nodelalloc
とnoatime
のmountOptions
を指定する必要があるようなので、そのようにしました。
# 定義ファイルを作成
% cat <<'EOF' > storageclass.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: pd-custom
provisioner: kubernetes.io/gce-pd
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
type: pd-ssd
mountOptions:
- nodelalloc,noatime
EOF
# デプロイ
$ kubectl apply -f storageclass.yaml
# 確認(pd-customという名前のレコードが出てくればOK / そのほかにもデフォルトで作成されているpremium-rwoやstandard-rwoなども一緒に出てきます。)
$ kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
pd-custom kubernetes.io/gce-pd Delete WaitForFirstConsumer true XX
premium-rwo pd.csi.storage.gke.io Delete WaitForFirstConsumer true XX
standard kubernetes.io/gce-pd Delete Immediate true XX
standard-rwo (default) pd.csi.storage.gke.io Delete WaitForFirstConsumer true XX
operator
CRDs
次に、tidb operatorのためのCustom Resource Definitionsをデプロイします。
% wget https://raw.githubusercontent.com/pingcap/tidb-operator/v1.3.9/manifests/crd.yaml -O crd.yaml
% kubectl create -f crd.yaml
customresourcedefinition.apiextensions.k8s.io/backupschedules.pingcap.com created
customresourcedefinition.apiextensions.k8s.io/backups.pingcap.com created
customresourcedefinition.apiextensions.k8s.io/dmclusters.pingcap.com created
customresourcedefinition.apiextensions.k8s.io/restores.pingcap.com created
customresourcedefinition.apiextensions.k8s.io/tidbclusterautoscalers.pingcap.com created
customresourcedefinition.apiextensions.k8s.io/tidbclusters.pingcap.com created
customresourcedefinition.apiextensions.k8s.io/tidbinitializers.pingcap.com created
customresourcedefinition.apiextensions.k8s.io/tidbmonitors.pingcap.com created
customresourcedefinition.apiextensions.k8s.io/tidbngmonitorings.pingcap.com created
helm3 add pingcap repo
# confirm helm version
% helm version
version.BuildInfo{Version:"v3.10.2", GitCommit:"50f003e5ee8704ec937a756c646870227d7c8b58", GitTreeState:"clean", GoVersion:"go1.19.3"}
# add pingcap repo for helm3
% helm repo add pingcap https://charts.pingcap.org/
namespace
tidb-operator用のnamespaceを作成します。
# 定義ファイルを作成
% cat <<'EOF' > namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: tidb-admin
EOF
# デプロイ
% kubectl create -f namespace.yaml
namespace/tidb-admin created
tidb-operator
helm3
を使って、tidb-operatorをデプロイします。
# install tidb-operator with helm3
# for more version information, check [github releases](https://github.com/pingcap/tidb-operator/releases) in advance.
% helm install --namespace tidb-admin tidb-operator pingcap/tidb-operator --version v1.3.9
NAME: tidb-operator
LAST DEPLOYED: Thu Dec 1 15:56:21 2022
NAMESPACE: tidb-admin
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Make sure tidb-operator components are running:
kubectl get pods --namespace tidb-admin -l app.kubernetes.io/instance=tidb-operator
# check the operator pods are running
% kubectl get pods --namespace tidb-admin -l app.kubernetes.io/instance=tidb-operator
NAME READY STATUS RESTARTS AGE
tidb-controller-manager-xxxxxxxxxx-xxxxx 1/1 Running 0 XX
tidb-scheduler-xxxxxxxxxx-xxxxx 2/2 Running 0 XX
tidb cluster
namespace
tidb-cluster用のnamespaceを作成します。
# 定義ファイルを作成
% cat <<'EOF' > namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: tidb-cluster
EOF
# デプロイ
% kubectl create -f namespace.yaml
namespace/tidb-cluster created
tidb cluster
tidb-clusterをデプロイします。
# 定義ファイルの作成
# https://raw.githubusercontent.com/pingcap/tidb-operator/master/examples/gcp/tidb-cluster.yaml -O tidb-cluster.yaml を参考にしました。
% cat <<'EOF' > tidb-cluster.yaml
apiVersion: pingcap.com/v1alpha1
kind: TidbCluster
metadata:
name: tidb
namespace: tidb-cluster
spec:
version: v6.1.0
timezone: UTC
configUpdateStrategy: RollingUpdate
pvReclaimPolicy: Retain
enableDynamicConfiguration: true
schedulerName: default-scheduler
topologySpreadConstraints:
- topologyKey: topology.kubernetes.io/zone
helper:
image: alpine:3.16.0
pd:
baseImage: pingcap/pd
maxFailoverCount: 0
replicas: 3
requests:
storage: "2Gi"
config: |
[dashboard]
internal-proxy = true
[replication]
location-labels = ["topology.kubernetes.io/zone", "kubernetes.io/hostname"]
max-replicas = 3
nodeSelector:
pd: "true" # `pd=true`タグがついたnodeにデプロイされます。
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- pd
topologyKey: kubernetes.io/hostname # レプリカが同一node内にデプロイされないようにしています。
tikv:
baseImage: pingcap/tikv
maxFailoverCount: 0
replicas: 3
requests:
storage: "10Gi"
annotations:
tidb.pingcap.com/sysctl-init: "true"
podSecurityContext:
sysctls:
- name: net.core.somaxconn
value: "32768"
config: {}
nodeSelector:
tikv: "true" # `tikv=true`タグがついたnodeにデプロイされます。
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- tikv
topologyKey: kubernetes.io/hostname # レプリカが同一node内にデプロイされないようにしています。
tidb:
baseImage: pingcap/tidb
maxFailoverCount: 0
replicas: 2
service:
type: NodePort
config: |
[performance]
tcp-keep-alive = true
annotations:
tidb.pingcap.com/sysctl-init: "true"
podSecurityContext:
sysctls:
- name: net.ipv4.tcp_keepalive_time
value: "300"
- name: net.ipv4.tcp_keepalive_intvl
value: "75"
- name: net.core.somaxconn
value: "32768"
separateSlowLog: true
nodeSelector:
tidb: "true" # `tidb=true`タグがついたnodeにデプロイされます。
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- tidb
topologyKey: kubernetes.io/hostname # レプリカが同一node内にデプロイされないようにしています。
EOF
# デプロイ
% kubectl apply -f tidb-cluster.yaml
# 確認(pod)
% kubectl get pods -n tidb-cluster
NAME READY STATUS RESTARTS AGE
tidb-discovery-xxxxxxxxxx-xxxxx 1/1 Running 0 5m18s
tidb-pd-0 1/1 Running 0 5m18s
tidb-pd-1 1/1 Running 0 2m44s
tidb-pd-2 1/1 Running 0 2m44s
tidb-tidb-0 2/2 Running 0 48s
tidb-tidb-1 2/2 Running 0 47s
tidb-tikv-0 1/1 Running 0 108s
tidb-tikv-1 1/1 Running 0 108s
tidb-tikv-2 1/1 Running 0 108s
# 確認(service)
% kubectl get svc -n tidb-cluster
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tidb-discovery ClusterIP XXX.XX.XXX.XXX <none> 10261/TCP,10262/TCP 12m
tidb-pd ClusterIP XXX.XX.XXX.XX <none> 2379/TCP 12m
tidb-pd-peer ClusterIP None <none> 2380/TCP,2379/TCP 12m
tidb-tidb NodePort XXX.XX.XXX.XX <none> 4000:30225/TCP,10080:30395/TCP 7m54s
tidb-tidb-peer ClusterIP None <none> 10080/TCP 7m54s
tidb-tikv-peer ClusterIP None <none> 20160/TCP 8m54s
動作確認
最後に、kubectl port-forward
を使ってローカルのmysqlクライアントを使ってアクセスできるか確認しました。
# tidb serviceにport-forwardします。
% kubectl port-forward svc/tidb-tidb 4000:4000 -n tidb-cluster
# 別プロセスのターミナルを開いて、アクセスできることを確認しました。
$ mysql -h 127.0.0.1 -P 4000 -u root
mysql> /* you can run any query now! */
mysql>
以上になります。