MinikubeでWordPressを構築してみた

[前回](https://qiita.com/moritalous/items/578ba63a5de18841f80d)構築したRaspberry Pi上のKubernetesで、WordPressを構築してみました。

ポイント

* Dockerイメージはオフィシャルのものを使用
* DBはMariaDB
* MariaDBの`/var/lib/mysql`とWordPressの`/var/www/html`はホスト(Raspberry Pi)上のディスクに永続化

# 構築

Yamlの構成はこんな感じです。

```console
./
├── mariadb
│   ├── mariadb-persistentvolume.yaml
│   ├── mariadb-service.yaml
│   └── mariadb-statefulset.yaml
└── wordpress
    ├── wordpress-persistentvolume.yaml
    ├── wordpress-service.yaml
    └── wordpress-statefulset.yaml

2 directories, 6 files
```

## ディスク

Minikubeは以下のホスト上のディレクトで永続ができるように設定済みのようです。
https://minikube.sigs.k8s.io/docs/handbook/persistent_volumes/

* /data
* /var/lib/minikube
* /var/lib/docker
* /tmp/hostpath_pv
* /tmp/hostpath-provisioner

`/data`ディレクトリを使用しようと思いますので、作成します。

```console
mkdir -p /data
```

## MariaDBの構築

使用したリソースは以下のものです。パスワードが平文で書かれていますので、`Secret`リソースを使うべきかと思います。

| リソース | 説明 |
| --- | --- |
| StatefulSet | データの永続化が必要なのでDeployment(ReplicaSet)ではなくStatefulSetを使いました |
| Service | Pod間での通信を行うため、ClusterIP ServiceでMariaDBのポート`3306`を公開します |
| PersistentVolume | Raspberry Pi上の`/data/mariadb`をPersistentVolumeとして定義します。 |

```yaml:mariadb-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mariadb-statefulset
spec:
  selector:
    matchLabels:
      app: mariadb-app
  serviceName: mariadb-service
  replicas: 1
  template:
    metadata:
      labels:
        app: mariadb-app
    spec:
      containers:
      - name: mariadb
        image: mariadb:latest
        ports:
        - containerPort: 3306
        env:
          - name: MYSQL_ROOT_PASSWORD
            value: somewordpress
          - name: MYSQL_DATABASE
            value: wordpress
          - name: MYSQL_USER
            value: wordpress
          - name: MYSQL_PASSWORD
            value: wordpress
        volumeMounts:
          - name: mariadb-pvc
            mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: mariadb-pvc
      spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: manual
          selector:
            matchLabels:
              app: mariadb
          resources:
            requests:
              storage: 1Gi
```

```yaml:mariadb-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mariadb-service
spec:
  type: ClusterIP
  selector:
    app: mariadb-app
  ports:
  - port: 3306
```

```yaml:mariadb-persistentvolume.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mariadb-pv-volume
  labels:
    type: local
    app: mariadb
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/data/mariadb"
```

## WordPressの構築

WordPressもMariaDBとほぼ同じです。違うのはこれぐらいです。

* Serviceの種別がNodePortで、外部に公開
* DB接続先をMariaDBのClusterIPで指定

| リソース | 説明 |
| --- | --- |
| StatefulSet | MariaDB同様、データの永続化をするため、StatefulSetを使いました |
| Service | 外部から接続するため、NodePortを使用してコンテナ内の80番ポートを30080番として外部公開します。|
| PersistentVolume | Raspberry Pi上の`/data/wordpress`をPersistentVolumeとして定義します。 |

```yaml:wordpress-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: wordpress-statefulset
spec:
  selector:
    matchLabels:
      app: wordpress-app
  serviceName: wordpress-service
  replicas: 1
  template:
    metadata:
      labels:
        app: wordpress-app
    spec:
      containers:
      - name: wordpress
        image: wordpress:latest
        ports:
        - containerPort: 80
        env:
          - name: WORDPRESS_DB_HOST
            value: mariadb-service:3306
          - name: WORDPRESS_DB_USER
            value: wordpress
          - name: WORDPRESS_DB_PASSWORD
            value: wordpress
        volumeMounts:
          - name: wordpress-pvc
            mountPath: /var/www/html
  volumeClaimTemplates:
    - metadata:
        name: wordpress-pvc
      spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: manual
          selector:
            matchLabels:
              app: wordpress
          resources:
            requests:
              storage: 1Gi
```

```yaml:wordpress-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress-nodepod
spec:
  type: NodePort
  selector:
    app: wordpress-app
  ports:
  - port: 80
    nodePort: 30080
```

```yaml:wordpress-persistentvolume.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: wordpress-pv-volume
  labels:
    type: local
    app: wordpress
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/data/wordpress"
```

# 起動

サブディレクトリ含めて全Yamlを適用します

```console
$ kubectl apply -f ./ -R
persistentvolume/mariadb-pv-volume created
service/mariadb-service created
statefulset.apps/mariadb-statefulset created
persistentvolume/wordpress-pv-volume created
service/wordpress-nodepod created
statefulset.apps/wordpress-statefulset created
$ 
```

起動したか確認

```console
$ kubectl get svc,po,pv,pvc
NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/kubernetes          ClusterIP   10.96.0.1       <none>        443/TCP        24h
service/mariadb-service     ClusterIP   10.105.29.150   <none>        3306/TCP       36s
service/wordpress-nodepod   NodePort    10.100.194.70   <none>        80:30080/TCP   36s

NAME                          READY   STATUS    RESTARTS   AGE
pod/mariadb-statefulset-0     1/1     Running   0          36s
pod/wordpress-statefulset-0   1/1     Running   0          36s

NAME                                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                           STORAGECLASS   REASON   AGE
persistentvolume/mariadb-pv-volume     1Gi        RWO            Retain           Bound    default/mariadb-pvc-mariadb-statefulset-0       manual                  36s
persistentvolume/wordpress-pv-volume   1Gi        RWO            Retain           Bound    default/wordpress-pvc-wordpress-statefulset-0   manual                  36s

NAME                                                          STATUS   VOLUME                CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/mariadb-pvc-mariadb-statefulset-0       Bound    mariadb-pv-volume     1Gi        RWO            manual         36s
persistentvolumeclaim/wordpress-pvc-wordpress-statefulset-0   Bound    wordpress-pv-volume   1Gi        RWO            manual         36s
$ 
```

Raspberry Pi上の`/data`ディレクトリ配下にファイルが作成されていることを確認できます。

```console
$ ls /data/mariadb/
aria_log.00000001  ib_buffer_pool  ib_logfile0  multi-master.info  performance_schema
aria_log_control   ibdata1         ibtmp1       mysql              wordpress
$ ls /data/wordpress/
index.php    wp-activate.php     wp-comments-post.php  wp-content   wp-links-opml.php  wp-mail.php      wp-trackback.php
license.txt  wp-admin            wp-config.php         wp-cron.php  wp-load.php        wp-settings.php  xmlrpc.php
readme.html  wp-blog-header.php  wp-config-sample.php  wp-includes  wp-login.php       wp-signup.php
$ 
```

ブラウザでも確認

Raspberry Piの外部から`http://raspberrypi.local:30080/`へアクセス

![raspberrypi.local_30080_wp-admin_install.php(iPad).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/59463b5c-2446-96fc-bc8d-9ffa44e2f323.png)

無事疎通ができました。
1件画像つきで投稿してみました。

![raspberrypi.local_30080__p=5(iPad).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/95119f83-a15c-8677-a669-f322a7872887.png)


この状態で、MariaDBのPodを強制的に削除してみます。

```console
$ kubectl delete po mariadb-statefulset-0 
pod "mariadb-statefulset-0" deleted
$ kubectl get po
NAME                      READY   STATUS              RESTARTS   AGE
mariadb-statefulset-0     0/1     ContainerCreating   0          3s       ←自動的にPodが再作成される
wordpress-statefulset-0   1/1     Running             0          9m29s
$ kubectl get po
NAME                      READY   STATUS    RESTARTS   AGE
mariadb-statefulset-0     1/1     Running   0          9s
wordpress-statefulset-0   1/1     Running   0          9m35s
pi@raspberrypi:~/k8s/minikube-wordpress $ 
```

データは`/data/mariadb`で永続化されているのでMariaDBのPodが再作成された後は、問題なく画面表示ができます。同様に、WordPressのPodを削除しても、問題ありませんでした。



# 参考

https://minikube.sigs.k8s.io/docs/handbook/persistent_volumes/
https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/
https://docs.docker.jp/compose/wordpress.html