VMware Tanzu SQL with MySQL for Kubernetes を構築してみた

# 概要
VMware Tanzu SQL の MySQL版を構築してみましたので、まとめてみます。
基本的にはMySQL Opearatorと似たようなものかなと思いつつ今後比較したりしてみようと思い、構築をしてみた次第です。

## 本記事の対象
- Tanzu SQLを触ってみたい方
- Kubernetes上にMySQLを用意してみたい方
- MySQL を複数台冗長構成で立ててみたい方

## VMware Tanzu SQL with MySQL for Kubernetesについて
Kubernetesのオペレーターを利用してDB操作の半自動化を実現しているものとなります。
また、InnoDB Clusterの仕組みを構成に利用しており、可用性の高いMySQLを実現しています。

最終的に展開されるMySQLインスタンスでは以下計5つのPodが用意されます。
- MySQL database × 3（プライマリ1, セカンダリ2）
- MySQL Router（プロキシ） × 2

## Tanzu SQL アーキテクチャ図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/2b29db2d-40fb-c946-1928-a5559798cb76.png)
[画像引用元](https://docs.vmware.com/en/VMware-Tanzu-SQL-with-MySQL-for-Kubernetes/1.6/tanzu-mysql-k8s/GUID-architecture.html)

# 構築手順
以下の順番で進めていきます。
- 事前準備
- Tanzu SQL Operator デプロイ
- MySQLインスタンスデプロイ


## 事前準備
Tanzu SQLを構築するにあたり以下の準備が必要となるため、あらかじめ実施しておきます。
- Tanzu Networkのアカウント
- Kubernetes環境の準備
    - Cert Managerのインストール
    - Helmのインストール
    - ストレージクラスの作成

### Tanzu Networkのアカウント
後程Operatorを展開する中でTanzu Networkの認証情報が必要となりますので、事前に作成をしておきます。

https://network.pivotal.io/

### Kubernetes環境の準備
今回は以下のようなKubernets環境で実施します。
この環境に必要な準備を進めていきます。

一応以下記事に同じ構成を作成する手順をまとめております。
[よく使っているkubeadmを使ったKubernetes検証環境の構築](https://qiita.com/strawberryjam/items/f0ff7bef425f6a711b10)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/8b5614d5-9001-bfe4-c61f-43260678cc48.png)



**Cert Managerのインストール**
インストール要件にCert Managerが必要なため用意しておきます。
```shell
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.10.1/cert-manager.yaml
```
インストールされていることを確認
```shell
kubectl api-resources --api-group=cert-manager.io

# 出力
NAME                  SHORTNAMES   APIVERSION           NAMESPACED   KIND
certificaterequests   cr,crs       cert-manager.io/v1   true         CertificateRequest
certificates          cert,certs   cert-manager.io/v1   true         Certificate
clusterissuers                     cert-manager.io/v1   false        ClusterIssuer
issuers                            cert-manager.io/v1   true         Issuer
```

**Helmのインストール**
後程の作業で利用するため、Helmのインストールをしておきます。
以下はUbuntu環境想定の作業になります。
※他の環境は公式ドキュメントを参照してください
[公式ドキュメント](https://helm.sh/docs/intro/install/)

```shell
# リポジトリを追加
curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list

# インストール
sudo apt-get update
sudo apt-get install helm
```

HelmクライアントでOCI サポートを有効にするため、環境変数を設定しておきます。
```shell
export HELM_EXPERIMENTAL_OCI=1
```

**ストレージクラスの作成**
MySQLのインスタンスで利用するPVに使うストレージクラスの作成をしておきます。
利用するストレージ等に合わせて任意で作業を実施してください。
今回私はNFSのストレージを使う予定のため、NFSの外部プロビジョナーを使ってみます。
[NFS Subdir External Provisioner](https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner)

```shell
# helmリポジトリの追加
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

# インストール実施
helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set nfs.server={任意のNFSサーバーIP} --set nfs.path=/ --set storageClass.name={任意のストレージクラス名}
```
ストレージクラスが自動で作成されるため、確認しておきます。
問題なく作成されていることが確認できました。
```shell
kubectl get sc

# 出力
NAME       PROVISIONER                                     RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
tanzusql   cluster.local/nfs-subdir-external-provisioner   Delete          Immediate           true                   37h
```

以上で以前事前準備は完了となります。

## Tanzu SQL Operator デプロイ
Tanzu SQL のOperatorのデプロイを進めていきます。

**Tanzu Network Registryにログイン**
Tanzu Network Registryのアカウントでログインをしておきます。
ログイン情報は各々で作成されたアカウント情報を入力ください。
※Tanzu Networkのアカウントと同じになります
```shell
helm registry login registry.tanzu.vmware.com
```

**Helm Chartのダウンロード**
Tanzu レジストリからHelm Chartをダウンロードします。
以下コマンドでは/tmpにダウンロードしています。
```shell
helm pull oci://registry.tanzu.vmware.com/tanzu-mysql-for-kubernetes/tanzu-mysql-operator-chart --version 1.6.2 --untar --untardir /tmp
```
※本手順にて一度以下エラーが出力されましたが、調べてもよくわからずもう一度実行したらうまくいきました。
```shell
Error: pulling from host registry.tanzu.vmware.com failed with status code [manifests 1.6.2]: 403 Forbidden
```

Operator群を展開するnamespaceを作成しておきます。
```shell
kubectl create namespace tanzu-mysql-for-kubernetes-system
```

secretを作成しておきます。
UERNAMEやPASSWORDは前手順同様にTanzu Networkのアカウントをご利用ください。
```shell
kubectl create secret docker-registry tanzu-image-registry \
--docker-server=https://registry.tanzu.vmware.com/ \
--docker-username="${USERNAME}" \
--docker-password="${PASSWORD}" \
--namespace tanzu-mysql-for-kubernetes-system
```

デプロイを実行します。
```shell
helm install --wait my-mysql-operator /tmp/tanzu-sql-with-mysql-operator/ \
  --values=operator-values-overrides.yaml \
  --namespace=tanzu-mysql-for-kubernetes-system
```

問題なくデプロイがされていることを確認します。
```shell
kubectl get all --namespace=tanzu-mysql-for-kubernetes-system

# 出力
NAME                                     READY   STATUS    RESTARTS   AGE
pod/my-mysql-operator-6f9fcd469b-kh5v9   1/1     Running   0          56m

NAME                                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/tanzu-mysql-webhook-service   ClusterIP   10.108.241.73   <none>        443/TCP   56m

NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-mysql-operator   1/1     1            1           56m

NAME                                           DESIRED   CURRENT   READY   AGE
replicaset.apps/my-mysql-operator-6f9fcd469b   1         1         1       56m
```

以上でOperatorのデプロイが完了となります。

## MySQLインスタンスデプロイ
ここからMySQLインスタンスのデプロイを行っていきます。

**展開先の名前空間作成**
任意の名称でMySQLインスタンスを展開する名前空間を作成してください。
```shell
kubectl create namespace testmysql
```
secretを作成しておきます。
USERNAME等はTanzu Networkの情報を入力ください。
```shell
kubectl create secret --namespace=testmysql \
    docker-registry tanzu-image-registry \
    --docker-server=https://registry.tanzu.vmware.com/ \
    --docker-username="${USERNAME}" \
    --docker-password="${PASSWORD}"
```


**インスタンス展開用マニフェスト作成**
Tanzu SQLのOperatorを展開しますと、kindでMySQLを指定できるようになります。
kind MySQLの仕様は以下公式ドキュメントに記載があります。
[Tanzu MySQL CRD Property Reference](https://docs.vmware.com/en/VMware-Tanzu-SQL-with-MySQL-for-Kubernetes/1.6/tanzu-mysql-k8s/GUID-property-reference-mysql.html)

今回は以下のような最低限の記載で進めていきます。
StorageClassNameはご自身の作成されたものを指定ください
```mysqlinstance.yaml
apiVersion: with.sql.tanzu.vmware.com/v1
kind: MySQL
metadata:
  name: mysql-sample-ha
spec:
  storageClassName: tanzusql
  storageSize: 40Gi
  imagePullSecretName: tanzu-image-registry
  highAvailability:
    enabled: true
```

デプロイを実施しておきます。
```
kubectl apply -f mysqlinstance.yaml
```

MySQLのインスタンスデプロイ時にPVCも合わせて展開されるため、紐づけできるPVの作成もしておきます。
```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0000
  annotations:
    volume.beta.kubernetes.io/storage-class: "tanzusql"
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  claimRef:
    namespace: testmysql
    name: mysql-data-mysql-sample-ha-0
  #ご自身の環境に合わせて記載ください
  nfs:
    server: XX.XX.XX.XX
    path: /export/nfs/XX
```

ここまでで必要なもののデプロイが全て完了となります。
Podを見てみるとMySQLのpodが3つとproxyが2つデプロイされていることがわかります。
```shell
kubectl get pods

# 出力
NAME                                              READY   STATUS    RESTARTS      AGE
mysql-sample-ha-0                                 3/3     Running   0             39h
mysql-sample-ha-1                                 3/3     Running   1 (39h ago)   39h
mysql-sample-ha-2                                 3/3     Running   1 (39h ago)   39h
mysql-sample-ha-proxy-0                           1/1     Running   0             39h
mysql-sample-ha-proxy-1                           1/1     Running   0             39h
```

## 動作確認
MySQLインスタンスの展開を実施するとユーザー名とパスワードが自動生成されています。
そちらでログインができるところまで確認していきます。
```
# ユーザー名確認
kubectl get secret mysql-sample-ha-app-user-db-secret -o jsonpath='{.data.username}' | base64 -d ;

# パスワード確認
kubectl get secret mysql-sample-ha-app-user-db-secret -o jsonpath='{.data.password}' | base64 -d ;
```

確認したユーザー名パスワードでMySQLにログインできることを確認していきます。
```shell
kubectl exec -ti pod/mysql-sample-ha-0 -- bash -c "mysql -u {ユーザー名} -p"
```
無事ログインもできることが確認でき、MySQLが利用できる状態にあることがわかりました。

# 最後に
今回はTanzu SQLのMySQL版を構築してみました。
ドキュメントが公式以外がまだ少ないため、エラーなどが出ず無事に進めることができて良かったです。
一旦構築までした段階では記事にまとめたMySQL Operatorと似たようなものだなという感触止まりです。
構築自体はできるようになったため、あとは実際に使ったりしながら、MySQL Operatorとの違いは探っていければと思います。