GKE上にWordPress環境を作ったときの備忘録

# はじめに
Kubernetesの学習のためにGKE上にWordPress環境を作った時の備忘録です。
間よくばこのままGKE上に残しておきたいと思ったのですが、ランニング費用が高くなってしまうため、現在GCPアカウントのアップグレードはしていません。

## クラスターの作成
少しでも費用を抑えられればと思い、machine-typeとdisk-sizeのスペックをデフォルトより下げて作成しました。
machine-type=e2-small
disk-size=30
```
$ gcloud container clusters create --zone=us-central1-c --machine-type=e2-small --disk-size=30 --num-nodes=3 cluster-g01
Default change: VPC-native is the default mode during cluster creation for versions greater than 1.21.0-gke.1500. To create advanced routes based clusters, please pass the `--no-enable-ip-alias` flag
Default change: During creation of nodepools or autoscaling configuration changes for cluster versions greater than 1.24.1-gke.800 a default location policy is applied. For Spot and PVM it defaults to ANY, and for all other VM kinds a BALANCED policy is used. To change the default values use the `--location-policy` flag.
Note: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s).
Creating cluster cluster-g01 in us-central1-c... Cluster is being configured...
working                                                                        
Creating cluster cluster-g01 in us-central1-c... Cluster is being deployed...wo
rking..                                                                        
Creating cluster cluster-g01 in us-central1-c... Cluster is being health-checke
d (master is healthy)...done.                                                  
Created [https://container.googleapis.com/v1/projects/pro-ghidorah-web01-gce/zones/us-central1-c/clusters/cluster-g01].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-c/cluster-g01?project=pro-ghidorah-web01-gce
kubeconfig entry generated for cluster-g01.
NAME: cluster-g01
LOCATION: us-central1-c
MASTER_VERSION: 1.27.2-gke.1200
MASTER_IP: 34.118.203.189
MACHINE_TYPE: e2-small
NODE_VERSION: 1.27.2-gke.1200
NUM_NODES: 3
STATUS: RUNNING
$ gcloud config set project pro-ghidorah-web01-gce
Updated property [core/project].
$ gcloud container clusters list
NAME: cluster-g01
LOCATION: us-central1-c
MASTER_VERSION: 1.27.2-gke.1200
MASTER_IP: 34.118.203.189
MACHINE_TYPE: e2-small
NODE_VERSION: 1.27.2-gke.1200
NUM_NODES: 3
STATUS: RUNNING
```
起動したクラスターに接続して、Podを確認します。
```
$ gcloud container clusters get-credentials cluster-g01 --region us-central1-c
Fetching cluster endpoint and auth data.
kubeconfig entry generated for cluster-g01.
$ kubectl get pod --all-namespaces
NAMESPACE     NAME                                                    READY   STATUS    RESTARTS        AGE
gmp-system    alertmanager-0                                          2/2     Running   0               5m19s
gmp-system    collector-5dm2w                                         2/2     Running   0               3m59s
gmp-system    collector-htxk4                                         2/2     Running   0               4m
gmp-system    collector-plzzr                                         2/2     Running   0               4m
gmp-system    gmp-operator-66bfbfc769-sxwzx                           1/1     Running   0               5m22s
gmp-system    rule-evaluator-85fff98f4d-2mpwv                         2/2     Running   2 (3m59s ago)   4m7s
kube-system   event-exporter-gke-7bf6c99dcb-tbst5                     2/2     Running   0               5m40s
kube-system   fluentbit-gke-8t797                                     2/2     Running   0               4m36s
kube-system   fluentbit-gke-cmx4t                                     2/2     Running   0               4m35s
kube-system   fluentbit-gke-h87zg                                     2/2     Running   0               4m34s
kube-system   gke-metrics-agent-9chn6                                 2/2     Running   0               4m34s
kube-system   gke-metrics-agent-khtmx                                 2/2     Running   0               4m36s
kube-system   gke-metrics-agent-kr74d                                 2/2     Running   0               4m35s
kube-system   konnectivity-agent-6f6945cd8c-mp46p                     1/1     Running   0               5m30s
kube-system   konnectivity-agent-6f6945cd8c-twpnc                     1/1     Running   0               4m12s
kube-system   konnectivity-agent-6f6945cd8c-vpbt6                     1/1     Running   0               4m12s
kube-system   konnectivity-agent-autoscaler-5d9dbcc6d8-bnpq4          1/1     Running   0               5m29s
kube-system   kube-dns-865c4fb86d-nbc6b                               4/4     Running   0               5m44s
kube-system   kube-dns-865c4fb86d-xfkcn                               4/4     Running   0               4m12s
kube-system   kube-dns-autoscaler-84b8db4dc7-2ksnt                    1/1     Running   0               5m44s
kube-system   kube-proxy-gke-cluster-g01-default-pool-e0dae0bf-9w41   1/1     Running   0               4m10s
kube-system   kube-proxy-gke-cluster-g01-default-pool-e0dae0bf-p404   1/1     Running   0               4m27s
kube-system   kube-proxy-gke-cluster-g01-default-pool-e0dae0bf-qpzv   1/1     Running   0               3m46s
kube-system   l7-default-backend-f77b65cbd-zn79d                      1/1     Running   0               5m27s
kube-system   metrics-server-v0.5.2-6bf74b5d5f-zlbmq                  2/2     Running   0               4m2s
kube-system   pdcsi-node-f7rfx                                        2/2     Running   0               4m33s
kube-system   pdcsi-node-mvbnq                                        2/2     Running   0               4m35s
kube-system   pdcsi-node-tkfbw                                        2/2     Running   0               4m35s
```
kubectlが実行できるようになったことを確認します。
```
$ kubectl get node
NAME                                         STATUS   ROLES    AGE     VERSION
gke-cluster-g01-default-pool-e0dae0bf-9w41   Ready    <none>   5m44s   v1.27.2-gke.1200
gke-cluster-g01-default-pool-e0dae0bf-p404   Ready    <none>   5m44s   v1.27.2-gke.1200
gke-cluster-g01-default-pool-e0dae0bf-qpzv   Ready    <none>   5m44s   v1.27.2-gke.1200
```
## 永続化のためのボリュームを作成
こちら↓のサイトを参考に作成します。

https://qiita.com/ohtsuka-shota/items/7075d8f4d3307711c8b9

PVCをyamlからデプロイすると、PVCに関連付けられたStorageClassが反応しGCE上にストレージを作成します。

## StorageClassとPVCのyamlファイルをviで作成
GCE上にストレージを作成する為のyamlファイル。
metadataの名前の部分がPVCのstorageClassNameと一致すると、キックされてストレージを作成しに行きます。
```mysql-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: mysql-storage-class
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
  fstype: ext4
  replication-type: none
```
```mysql-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-vol-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: mysql-storage-class
  resources:
    requests:
      storage: 30Gi
```
## StorageClassとPVCをデプロイ
```
$ kubectl apply -f mysql-storageclass.yaml
storageclass.storage.k8s.io/mysql-storage-class created
$ kubectl apply -f mysql-pvc.yaml
persistentvolumeclaim/mysql-vol-pvc created
$ kubectl get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS          REASON   AGE
persistentvolume/pvc-657c571e-4415-4e33-ae9a-c29657d0c95c   30Gi       RWO            Delete           Bound    default/mysql-vol-pvc   mysql-storage-class            11s

NAME                                  STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
persistentvolumeclaim/mysql-vol-pvc   Bound    pvc-657c571e-4415-4e33-ae9a-c29657d0c95c   30Gi       RWO            mysql-storage-class   15s
```
GCE及びGKE上で作成されたストレージ、PVCが確認出来ます。

## ConfigMapとSecretに環境変数をセット
次は、こちら↓のサイトを参考にConfigMapとSecretに環境変数をセットして、Podを起ち上げます。

https://qiita.com/ohtsuka-shota/items/12a7f7a51e572f3da656

### ConfigMapのyamlファイル作成
```mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-cm
data:
  MYSQL_DATABASE: gke-wordpress-database
  MYSQL_USER: devuser
  MYSQL_ROOT_PASSWORD: xxxxxxxx
```
```wordpress-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: wp-cm
data:
  WORDPRESS_DB_HOST: mysql-clusterip
  WORDPRESS_DB_NAME : gke-wordpress-database
  WORDPRESS_DB_USER: devuser
```
### Secretのyamlファイル作成
```mysql-secret.yaml
apiVersion: v1 
kind: Secret 
metadata: 
  name: mysql-sec 
data: 
  MYSQL_PASSWORD: xxxxxxxx 
```
```wordpress-secret.yaml
apiVersion: v1 
kind: Secret 
metadata: 
  name: wp-sec 
data: 
  WORDPRESS_DB_PASSWORD : xxxxxxxx
```
## Podのyamlファイル作成
以下もこちら↓のサイトを参考にyamlファイルを作成しました。

https://qiita.com/ohtsuka-shota/items/12a7f7a51e572f3da656

```mysql-pod.yaml
apiVersion: v1 
kind: Pod 
metadata: 
  name: mysql-pod  
  labels: 
    app: mysql  
spec: 
  containers: 
    - name:  mysql-con  
      image: mysql:8.0-debian 
      ports: 
      - containerPort: 3306
      envFrom: 
      - configMapRef:
          name: mysql-cm
      - secretRef:
          name: mysql-sec
      volumeMounts:
      - mountPath: /var/lib/mysql
        name: mysql-vol-pvc
  volumes:
    - name: mysql-vol-pvc
      persistentVolumeClaim:
        claimName: mysql-vol-pvc 
```
```wordpress-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: wordpress-pod
  labels: 
    app: wordpress  
spec: 
  containers: 
    - name:  wordpress-con 
      image: wordpress:php8.1-apache 
      ports: 
      - containerPort: 80
      envFrom:
      - configMapRef: 
          name: wp-cm 
      - secretRef:
          name: wp-sec
```
## ClusterIPのyamlファイル作成
```mysql-clusterip.yaml
apiVersion: v1
kind: Service 
metadata: 
  name: mysql-clusterip 
spec:  
  selector:  
    app: mysql  
  type: ClusterIP 
  ports: 
  - name: mysql  
    port: 3306
    protocol: TCP  
    targetPort: 3306
```
## 静的IPアドレスの予約
静的IPアドレスを予約して、wordpress-loadbalancer.yamlのloadBalancerIPの値を予約したIPアドレス「xx.xxx.xxx.xxx」にしておく。
## LoadBalancerのyamlファイル作成
```wordpress-loadbalancer.yaml
apiVersion: v1 
kind: Service 
metadata: 
  name: wordpress-loadbalancer
spec: 
  type: LoadBalancer 
  loadBalancerIP: xx.xxx.xxx.xxx
  selector:
    app: wordpress
  ports: 
  - protocol: TCP 
    port: 60000
    targetPort: 80
```
ConfigMap,Secret,pod,Serviceをyamlファイルでデプロイ
```
$ kubectl apply -f mysql-configmap.yaml
configmap/mysql-cm created
$ kubectl apply -f wordpress-configmap.yaml
configmap/wp-cm created
$ kubectl apply -f mysql-secret.yaml 
secret/mysql-sec created
$ kubectl apply -f wordpress-secret.yaml
secret/wp-sec created
$ kubectl apply -f mysql-pod.yaml
pod/mysql-pod created
$ kubectl apply -f wordpress-pod.yaml
pod/wordpress-pod created
$ kubectl apply -f mysql-clusterip.yaml
service/mysql-clusterip created
$ kubectl apply -f wordpress-loadbalancer.yaml
service/wordpress-loadbalancer created
```
それぞれのステイタスを確認
```
$ kubectl get pod,svc,cm,secret,pv,pvc -o wide
NAME                READY   STATUS    RESTARTS   AGE     IP           NODE                                         NOMINATED NODE   READINESS GATES
pod/mysql-pod       1/1     Running   0          2m15s   10.44.0.10   gke-cluster-g01-default-pool-b2ea2262-82rb   <none>           <none>
pod/wordpress-pod   1/1     Running   0          101s    10.44.0.11   gke-cluster-g01-default-pool-b2ea2262-82rb   <none>           <none>

NAME                             TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)           AGE   SELECTOR
service/kubernetes               ClusterIP      10.48.0.1     <none>           443/TCP           22m   <none>
service/mysql-clusterip          ClusterIP      10.48.5.69    <none>           3306/TCP          66s   app=mysql
service/wordpress-loadbalancer   LoadBalancer   10.48.10.32   xx.xxx.xxx.xxx   60000:30982/TCP   51s   app=wordpress

NAME                         DATA   AGE
configmap/kube-root-ca.crt   1      22m
configmap/mysql-cm           3      3m21s
configmap/wp-cm              3      3m7s

NAME               TYPE     DATA   AGE
secret/mysql-sec   Opaque   1      2m53s
secret/wp-sec      Opaque   1      2m39s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS          REASON   AGE     VOLUMEMODE
persistentvolume/pvc-657c571e-4415-4e33-ae9a-c29657d0c95c   30Gi       RWO            Delete           Bound    default/mysql-vol-pvc   mysql-storage-class            9m19s   Filesystem

NAME                                  STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE     VOLUMEMODE
persistentvolumeclaim/mysql-vol-pvc   Bound    pvc-657c571e-4415-4e33-ae9a-c29657d0c95c   30Gi       RWO            mysql-storage-class   9m23s   Filesystem
```
## Webブラウザーでアクセス
ロードバランサーの外部IPアドレス(xx.xxx.xxx.xxx:60000)にブラウザーでアクセス。WordPressのインストール画面が表示されていることを確認します。

## 構築した環境の図解

![kubernetes230716.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236301/61af6a6b-633c-36cb-6bb7-ee139c507443.jpeg)
※正しいかどうか分かりませんが、自分の理解ではこうなっています。

## pod,svc,cm,secretのクリーンアップ
クリーンアップは、"kubectl delete"で行います。例えばsvcの場合は、次のように削除します。

```
$ kubectl delete service wordpress-loadbalancer
service "wordpress-loadbalancer" deleted
$ kubectl delete service mysql-clusterip
service "mysql-clusterip" deleted
```
$ kubectl delete [pod/service/configmap/secret] [name]

## ディスクを削除
GCEのディスクはコンソールから削除しました。

## クラスターの削除
GKEのクラスターの削除もコンソールから行いました。

# まとめ
Kubernetes学習のためにGKEを始めたのですが、3ヶ月の無料期間ではここまでが精一杯でした。
今後はデプロイメントを使っての環境構築を学習したいと思っています。
この環境で3日間動かして、1日平均303円でした。1ヶ月(30日)稼働させると、9,090円になります。