KubernetesでWordpressアプリケーションをデプロイする。

# 概要
Kubernetesの理解を深めるために、以下のKubernetes公式チュートリアルに取り組みました。
https://kubernetes.io/ja/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/

ただ実施するのでは味気ないので、理解が曖昧な箇所は深堀りしながら進めました。

# 環境
Windows 11
Rancher Desktop：1.8.1

# 準備
以下の3ファイルを準備します。
1. mysql-deployment.yaml
2. wordpress-deployment.yaml
3. kustomization.yaml

### 1.mysql-deployment.yaml

```bash:yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels: #「labels」という項目は色々な場所に出てくるので注意が必要。ここではKey=app,value=wordpressというラベルをServiceに付与している。
    app: wordpress
spec:
  ports:
    - port: 3306 #Serviceの3306ポートへのアクセスをPodの3306ポートに紐づける。
  selector:  #ServiceをどのPodと紐づけるかを指定するのがselector。ここではapp: wordpress/tier: mysqlラベルが付与されたPodを紐づけている。
    app: wordpress
    tier: mysql
  clusterIP: None #"None"を指定することで、"Headless"とよばれるServiceになる。Headless Serviceではクラスタ内DNSからPodのIPを取得し、Podに負荷分散する(DNSラウンドロビン)。
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress 
spec:
  accessModes:
    - ReadWriteOnce #単一ノードからRead/Writeが可能。
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-mysql
  labels: #Deploymentに付与するラベル。
    app: wordpress
spec:
  selector:
    matchLabels: #どのPodをDeploymentの対象とするかを指定する。今回はapp: wordpressとtier: mysqlの2つのラベルを持つPodをDeploymentの対象にしている。
      app: wordpress 
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels: #Podに付与するラベル。spec.selector.matchLabelsと一致している必要がある。
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:8.0
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef: 
              name: mysql-pass 
              key: password #mysql-passというsecretリソースの、passwordというkeyに対応するvalueを取得する
        - name: MYSQL_DATABASE
          value: wordpress #ここではsecretリソースから取得せず、そのままPWをべた書きしている。
        - name: MYSQL_USER
          value: wordpress
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql #マウント先
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

```

#### PVCのマニフェストはあるが、PVが無いのはなぜ？
PVCのマニフェストの中でStorageClassを指定していないため、デフォルトのStorageClassが使われます。
```bash:command
$ kubectl get sc -A
NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path (default)   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  81d
```
local-pathというStorageClassです。クラスター作成時から存在していました。
PROVISIONERがrancher.io/local-pathとなっていて、このProvisionerがPVを自動的にプロビジョニングするので、PVを明示的に作成しなくてもOKのようです。

また、DeploymentのマニフェストにReplicaset数の指定がありませんでした。
この場合、Replicaset数とPod数はどうなるのか、後ほど確認してみます。

### 2.wordpress-deployment.yaml
```bash:yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer #LoadBalancerでは外部疎通性のある仮想IPが払い出されますが、利用できる環境がクラウド環境などに限られるので今回はIPが払い出されません。
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:6.2.1-apache
        name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: wordpress-mysql
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        - name: WORDPRESS_DB_USER
          value: wordpress
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim

```

### 3.kustomization.yaml
Kustomizeとは、Kubernetesのマニフェスト管理ツールです。
kustomization.yamlという名前のファイルで管理するようです。他の名前は不可。
```bash:yaml
secretGenerator:
- name: mysql-pass
  literals:
  - password=<お好きなパスワードを指定>
resources:
  - mysql-deployment.yaml
  - wordpress-deployment.yaml
```

# リソース作成
用意した3ファイルが存在するディレクトリで実行
```bash:commnad
$ kubectl apply -k ./
secret/mysql-pass-m9tcmtc8h7 created
service/wordpress created
service/wordpress-mysql created
persistentvolumeclaim/mysql-pv-claim created
persistentvolumeclaim/wp-pv-claim created
deployment.apps/wordpress created
deployment.apps/wordpress-mysql created
```
リソースが作成されていることを確認していきます。

### Secret
```bash:commnad
$ kubectl get secret
NAME                    TYPE     DATA   AGE
mysql-pass-m9tcmtc8h7   Opaque   1      2m15s
```
### PVC
```bash:commnad
$ kubectl get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE					
wp-pv-claim      Bound    pvc-4334b6cd-9ace-4938-bbdb-064be1e95f6e   20Gi       RWO            local-path     5m33s					
mysql-pv-claim   Bound    pvc-f9f14a60-603c-4d67-8f38-17abd603fc0c   20Gi       RWO            local-path     5m33s					
```
### PV
先に述べた通り、PVが自動作成されています。
なお、PVC経由で作成されたPVの名前は「pvc-」から始まります。
```bash:command
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE
pvc-4334b6cd-9ace-4938-bbdb-064be1e95f6e   20Gi       RWO            Delete           Bound    default/wp-pv-claim      local-path              5m45s
pvc-f9f14a60-603c-4d67-8f38-17abd603fc0c   20Gi       RWO            Delete           Bound    default/mysql-pv-claim   local-path              5m45s
```
### Replicaset
Replicaset数はそれぞれ1つずつになっています。
```bash:commnad
$ kubectl get rs
NAME                         DESIRED   CURRENT   READY   AGE
wordpress-77f4df4cbc         1         1         1       7m42s
wordpress-mysql-6745f5dc49   1         1         1       7m42s
```

### Pod
Pod数もそれぞれ1つずつになっています。
```bash:commnad
$ kubectl get pod
NAMESPACE     NAME                                     READY   STATUS      RESTARTS        AGE
default       wordpress-77f4df4cbc-zkh8p               1/1     Running     0               8m1s
default       wordpress-mysql-6745f5dc49-m778z         1/1     Running     0               8m1s
```

最後にアクセスできるかを確認します。

```bash:commnad
$ kubectl get svc
NAME              TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes        ClusterIP      10.43.0.1       <none>        443/TCP        74d
wordpress         LoadBalancer   10.43.129.204   <pending>     80:30652/TCP   10m
wordpress-mysql   ClusterIP      None            <none>        3306/TCP       10m
```

wordpress ServiceのPORT(S)が80:30652となっています。
80がLoadBalancerのポートで、30652がノードのポートです。
今回LoadBalancerにはEXTERNAL-IPが割り当てられていない(pending)ため、直接ノードにアクセスすることになります。
ノードのIPは172.27.28.244だったので、URLはhttp://172.27.28.244:30652です。

無事アクセスできました！
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3510470/5c9043da-2c70-f2f9-ec41-9e603273bab5.png)

# 参考
https://kubernetes.io/ja/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/

https://www.fadhil-blog.dev/blog/rancher-local-path-provisioner/