KubernetesでMySQL Serverを立ててみた

今回は完全に個人メモで〜す。本来はGCPのCloud Loggingを使うんですが、直近で使えるデータベースが１つしかないので、機能テスト(Jobの機能テスト)の自動実行向けにKubernetes上にMySQLを立ててみた。自動テスト向けのDBなので、Pod再作成などによってテーブルやデータが消えても問題ない（→テーブル作成やテストデータ登録は自動テスト実施のタイミングで行うため）。

#　マニフェストファイルを作る

用意したマニフェストファイルは以下の通り。

```yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql-server
spec:
  type: ClusterIP
  ports:
    - name: mysql
      port: 3306
      targetPort: 3306
      protocol: TCP
  selector:
    app: mysql-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-server
spec:
  selector:
    matchLabels:
      app: mysql-server
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql-server
    spec:
      containers:
        - image: mysql:5.7
          name: mysql
          resources:
          env:
            - name: MYSQL_USER
              value: devuser
            - name: MYSQL_PASSWORD
              value: devuser
            - name: MYSQL_ROOT_PASSWORD
              value: password
            - name: LANG
              value: C.UTF-8
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-server-initdb
              mountPath: /docker-entrypoint-initdb.d
            - name: mysql-server-conf
              mountPath: /etc/mysql/conf.d
      volumes:
        - name: mysql-server-initdb
          configMap:
            name: mysql-server-initdb-config
        - name: mysql-server-conf
          configMap:
            name: mysql-server-conf-config
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-server-initdb-config
data:
  createdb.sql: |
    CREATE DATABASE job1;
    CREATE DATABASE job2;
    GRANT ALL ON job1.* TO devuser;
    GRANT ALL ON job2.* TO devuser;
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-server-conf-config
data:
  custom.cnf: |
    [mysqld]
    character-set-server=utf8
```

# 軽く説明を残しておく

## Deployment

PodでMySQLを起動する。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-server
spec:
  selector:
    matchLabels:
      app: mysql-server
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql-server
    spec:
      containers:
        - image: mysql:5.7
          name: mysql
          resources:
          env:
            - name: MYSQL_USER
              value: devuser
            - name: MYSQL_PASSWORD
              value: devuser
            - name: MYSQL_ROOT_PASSWORD
              value: password
            - name: LANG
              value: C.UTF-8
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-server-initdb
              mountPath: /docker-entrypoint-initdb.d
            - name: mysql-server-conf
              mountPath: /etc/mysql/conf.d
      volumes:
        - name: mysql-server-initdb
          configMap:
            name: mysql-server-initdb-config
        - name: mysql-server-conf
          configMap:
            name: mysql-server-conf-config
```

## ConfigMap

### データベースを初期化するためのSQLを用意

以下で指定したSQLは`/docker-entrypoint-initdb.d/createdb.sql`に保存され、データベース初期化時に実行される。

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-server-initdb-config
data:
  createdb.sql: |
    CREATE DATABASE job1;
    CREATE DATABASE job2;
    GRANT ALL ON job1.* TO devuser;
    GRANT ALL ON job2.* TO devuser;
```

### MySQLの動作をカスタマイズする設定ファイルを用意

`/etc/mysql/conf.d/custom.cnf`に保存され、データベース起動時に読み込まれる。

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-server-conf-config
data:
  custom.cnf: |
    [mysqld]
    character-set-server=utf8
```


## Service

他のPodからアクセスできるようにするためにServiceを作っておく。

```yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql-server
spec:
  type: ClusterIP
  ports:
    - name: mysql
      port: 3306
      targetPort: 3306
      protocol: TCP
  selector:
    app: mysql-server
```

# 適用してみる

用意したマニフェストファイルを適用する。

```
$ kubectl apply -f mysql-server.yaml 
service/mysql-server created
deployment.apps/mysql-server created
configmap/mysql-server-initdb-config created
configmap/mysql-server-conf-config created
```

起動確認してみる。

```
$ kubectl get pod,svc
NAME                                READY   STATUS    RESTARTS   AGE
pod/mysql-server-76f4b79f55-f2rqp   1/1     Running   0          55s

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP    4d5h
service/mysql-server   ClusterIP   10.104.183.144   <none>        3306/TCP   55s
```

# データベースにログインしてみる(Podの中から)

```
$ kubectl exec -it $(kubectl get pod | grep mysql | cut -d " " -f 1) -c mysql -- mysql --user=devuser --password=devuser
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.35 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

DBが作られているか確認してみる。

```
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| job1               |
| job2               |
+--------------------+
3 rows in set (0.01 sec)
```

設定内容が取り込まれているか確認してみる。

```
mysql> show variables like "chara%";
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
```

# データベースにログインしてみる(クラスタの外部から)

いったんport-forwardを使ってクラスタの外からアクセスしてみる。

```
$ kubectl port-forward service/mysql-server 3306:3306
Forwarding from 127.0.0.1:3306 -> 3306
Forwarding from [::1]:3306 -> 3306
```

別ターミナルを上げてクラスタの外からmysqlコマンドを使ってアクセスしてみる。

```
$ mysql --host=127.0.0.1 --user=devuser --password=devuser
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.7.35 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| job1               |
| job2               |
+--------------------+
3 rows in set (0.00 sec)

MySQL [(none)]>
```