【k8s】mysqlから学ぶConfigMap&Secret

# はじめに
kubernetes(以下k8s)でmysqlのdeploymentを作成するしていく中でk8sのConfigMp,Secretについて学べるなと考えました。
そこで本記事では、k8sでmysqlのdeploymentを作成する手順を記載と共にconfigmapやsecretの使用方法についてd記載していきます。

# この記事で学べること
- k8s deployment
- k8s ConfigMap
- k8s Secret
- kubectlコマンドの基礎

# 全体図
構築する実行環境は以下の通りになります。
![k8s-sql.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/2fb8f073-54e7-3aa9-a2cb-1dc8bb72ad7e.png)

### deployment
podの拡張概念。
図の通り、deploymentがrs(replicaset)を生成し、rsがpodを生成してくれます。
podは一つ以上のコンテナからできています。


![k8s-deploy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/984e077b-ec1c-0745-825e-4ab0839a33f1.png)

今回の場合は、mysqlコンテナが一つ入ったpodが生成されます。


### configMap
k8s Config＆Storageリソースの一つ。
configMapはその名の通り、(configuration mapping)以下のような設定情報をコンテナにマッピングすることができます。

- 環境変数
- ファイル(volume)

configmapとして切り分けておくことで、設定ファイルを複数のコンテナに即座に反映させることができます。
今回はmysqlコンテナに初期化時にdatabaseを生成するための設定ファイルをマッピングします。

### secret
k8s Config＆Storageリソースの一つ。
secretはconfigmapと異なりパスワードなどの以下のような機密情報をコンテナにマッピングするために使用します。

- 環境変数
- ファイル(volume)

今回は、環境変数にmysqlのパスワード情報をマッピングします。

# 環境構築手順
## リソースの作成

### deploymentの作成
```yaml:deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        # コンテナのどの場所にマッピングするかを記述する。
        volumeMounts:
        - name: sql-init-config
          # docker-entrypoint-initdb.dディレクトリ下にスクリプトファイルを入れておくと初期化時データベースを作成してくれる。
          mountPath: /docker-entrypoint-initdb.d
        env:
          - name: MYSQL_ROOT_PASSWORD
            # secretを使用して環境変数を設定する。
            valueFrom:
                secretKeyRef:
                  name: sql-secret
                  key: password
        ports:
        - containerPort: 800
      # podに提供するvolumeを指定する。
      volumes:
        # volumeMounts.nameと一致させる必要がある。
        - name: sql-init-config
        # volumeとしてconfigMapを使う。
          configMap:
              name: db-init-configmap
              items:
                - key: init.sql
                  path: init.sql

```
ここで、着目すべき部分は以下の通りです。

```yaml:deploy.yaml
apiVersion: apps/v1
# ・・・・・・・・・・・・・・・・・・・・
    spec:
#　=============コンテナについて書く。================
      containers:
      - name: mysql
        image: mysql:5.7
        # コンテナのどの場所にマッピングするかを記述する。
        volumeMounts:
        - name: sql-init-config
          # docker-entrypoint-initdb.dディレクトリ下にスクリプトファイルを入れておくと初期化時データベースを作成してくれる。
          mountPath: /docker-entrypoint-initdb.d
        env:
          - name: MYSQL_ROOT_PASSWORD
            # secretを使用して環境変数を設定する。
            valueFrom:
                secretKeyRef:
                  name: sql-secret
                  key: password
        ports:
        - containerPort: 800
#　=======================================

# --------podに提供するvolumeを指定する。---------
      volumes:
        # volumeMounts.nameと一致させる必要がある。
        - name: sql-init-config
        # volumeとしてconfigMapを使う。
          configMap:
              name: db-init-configmap
              items:
                - key: init.sql
                  path: init.sql
# -----------------------------------------
```
- コンテナのどの場所にマウントするか指定する
    - `spec.containers[*].volumeMounts`に記述する
- 環境変数として、secretをマッピングする
    - `spec.containers[*].env.valueFrom.secretKeyRef`に記述する。
- コンテナ(pod)に提供するvolumeを指定する。
    - `spec.volumes`に記述する。
    
### configmapを作成する。

```yaml:configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: db-init-configmap
data:
  # init.sqlファイルをしてコンテナ内にマッピングされる。
  init.sql: |
    CREATE DATABASE IF NOT EXISTS app;

```

### secretを作成

```yaml:secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: sql-secret
type: Opaque
data:
  # パスワードをbase64でエンコードした値
  password: cGFzc3dvcmQ=

```
エンコードのやり方は

```
$ encode -n [sqlのパスワード] | base64
```

ファイルを作成が終わったら、kubectlコマンドでそれぞれのリソースを作成します。

```
$ kubectl apply -f deploy.yaml  
 
deployment.apps/mysql created
```

```
$ kubectl apply -f configmap.yaml 

configmap/db-init-configmap created
```

```
$ kubectl apply -f secret.yaml
secret/sql-secret created
```
## ちゃんと設定できているか確認する

そのためmysqlのコンテナにログインしてみます。

まずは、deploymentから作成されたmysqlのpodを確認します。

```
$ kubectl get po
NAME                    READY   STATUS    RESTARTS   AGE
mysql-b6cff87cf-9dfbx   1/1     Running   0          3m54s
```
mysqlのpodが起動していることが確認できます。このpod名を利用してコンテナ内にログインしまう。

コマンドは以下の通りです。

```
$ kubectl exec -it mysql-b6cff87cf-9dfbx bash
```

### 環境変数を確認

```
root@mysql-b6cff87cf-9dfbx:/# env | grep MYSQL_ROOT     
MYSQL_ROOT_PASSWORD=password

```
すると、MYSQL_ROOT_PASSWORDが環境変数として設定されていることがわかります。

### configmapの確認
実際にマウント先に指定したdocker-entrypoint-initdb.ディレクトリの中身を見てみます。

```
root@mysql-b6cff87cf-9dfbx:/# ls docker-entrypoint-initdb.d/
init.sql
```
ちゃんとinit.sqlファイルがマウントされていることがわかります。
また、ファイルの中身を見てみると。。

```
root@mysql-b6cff87cf-9dfbx:/# cat docker-entrypoint-initdb.d/init.sql 
CREATE DATABASE IF NOT EXISTS app;
```
configmapで指定した中身と一緒になっています。

### mysqlにappデータベースが生成されているか確認

まずは、mysqlにログインしてみます。

```
root@mysql-b6cff87cf-9dfbx:/# mysql -u root -p
Enter password: (passwordと入力してください。)
///
mysql> 
```
これでログインできました。

次にデータベースの一覧をみてみます。

```sql
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| app                |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)
```

appデータベースが生成されていることが確認できました。

# まとめ
- configMap
    - 設定ファイルなどをコンテナにマッピングすることができる。
    - コンテナのどこにマッピングするか（`spec.container[].volumeMounts`）などを記載する

- secret
    - パスワードの機密情報をコンテナにマッピングすることができる。
    - 環境変数にマッピングする場合は、`spec.container[].env.valuefrom`に記述する
    
- configmapやsecretを使用するときは、コンテナにどの種類のvolumeを使用するか（`spec.volumes`）などを記述する必要がある。

- kubectl 
    - リソース(deployment,configmapなど)を作成する
        - `kubectl apply -f [リソースのファイルパス]`
    - podの一覧を表示する
        - `kubectl get po`
    - pod内にログインする
        - `kubectl exec -it [pod名] bash`