kubernetesでMysqlを動かしてみる

k8sの勉強としてMySQLを動かしてみました。
単に動かすだけならk8sのtasksに載ってる通り↓やればできたのですが、

> Run a Single-Instance Stateful Application
> https://kubernetes.io/docs/tasks/run-application/run-single-instance-stateful-application/

これだけだと何をやってるのかよくわからなかったので、自分なりに補足してみました。

# Run a Single-Instance Stateful Applicationでやっていること

- MySQLの**pod**が使用する**persistentvolume**を作成
- ↑の永続ボリュームをpodが見つけられるよう、podに持たせる**persistentVolumeClaim**を作成
- **deployment**を介してMySQLのpodを立てる
- podに外部から接続するための**service**を作成

上記ではやっていませんが、Secretを使う書き方にも挑戦してみます

#PersistentVolume(PV)とPersistentVolumeClaim(PVC)の作成

PVはホストが持っているストレージをpodに割り当てたいときに使う。
PVを介することで容量を必要な分だけ、任意のディレクトリで割り当てることができる

```yaml:mysql_pv.yaml
application/mysql/mysql-pv.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
  name: mysql-pv-volume # PVの名前
  labels:
    type: local
spec:
  storageClassName: manual # PVCと一致させる必要がある
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce # 一つのノードからread/writeでマウントできるモード
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  # storageClassName=manualのPVを探してマウントする
  storageClassName: manual 
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi # PVが持っている容量のうち20GBを使用する
```

#mysqlのpodとservice作成

```yaml:mysql_deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  # deploymentが管理するpodを定義
  # labelsにapp=mysqlと設定されたpodを管理する
  selector:
    app: mysql 
  clusterIP: None
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
　# podをアップデートする時の動作を定義
  # Recreateのときはpodは一つしか存在できず、更新すると
  # 古いものが消え新しいものが再度作成される
  strategy:
    type: Recreate
  template: # podの定義
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password # 本番ではsecretを使ってねとある
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:# コンテナ内のどのディレクトリにpersistentVolumeをマウントするか
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes: #
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim
          # name=mysql-pv-claimを使って、マウントできるPVを探す
```

せっかくなのでSecretを使う場合のやりかたにも挑戦してみます

SecretはdeploymentやServiceのようなk8sのリソースの一つで、名前の通りパスワード等の機密情報を管理するものです。
deploymentのマニフェストにパスワードのベタ書きを避けるために使用します。

Secretに書くパスワードはbase64形式でデコードする必要があります。

```bash
echo "password" | base64
vi secret.yaml
kubectl create -f secret.yaml
```
Secretのマニフェストはこんな感じ↓

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
data:
  password: cGFzc3dvcmQK
```

deploymentのマニフェストのパスワード部分をこんなふうに書き換えます

```yaml
 env:
   - name: MYSQL_ROOT_PASSWORD
     valueFrom:
       secretKeyRef:
         name: mysql-secret
         key: password
```

# 動作確認
ドキュメントの通りにコマンドを実行してみます

```bash
# リソースを作成
$ kubectl create -f mysql_pv.yaml
$ kubectl create -f mysql_deployment.yaml

# コンテナに入ってみる
# mysqlが起動すれば成功
kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword
```