こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。
今回はWordpress+MySQL環境を構築するにあたり、PV/PVCを用意してMySQLのデータをpod外に退避し、podが消えてもデータ自体は消えないようにしたいと思います。
過去の構築ログは以下になります。
構築する環境
以下が、今までに構築した環境です。
ConfigMapとSecretを用いて、環境変数をpodに設定しデプロイしておりました。
今回はPV/PVCを作成し、それをMySQLのpodにアタッチし、データをpod外に保存するようにします。GKEだけでは構築出来ない為、GCE(Google Compute Engine)においてストレージを用意して、そこにPV/PVCをデプロイしていきます。構築イメージは以下です。
PV/PVCを用いないとどうなるか?
使用するyamlファイル等は以下とします。
yamlファイルをデプロイした後のpodとserviceの状態は以下となりました。
LoadBalancerのEXTERNAL-IPとポートを使ってWebブラウザにアクセスします。
$ kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/mysql-pod 1/1 Running 0 4m57s
pod/wordpress-pod 1/1 Running 0 4m19s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.62.0.1 <none> 443/TCP 15m
service/mysql-clusterip ClusterIP 10.62.2.95 <none> 3306/TCP 5m5s
service/wordpress-loadbalancer LoadBalancer 10.62.0.71 34.30.162.91 60000:31028/TCP 4m7s
用意したサーバは"not PV/PVC"というタイトルのWebサイトになります。
このデータの一部がMySQLのpodに存在しています。
この状態でMySQLのpodを削除して再度MySQL podをデプロイします。
MySQL podという点では同じですが中身は全く異なります。
$ kubectl delete pod mysql-pod
pod "mysql-pod" deleted
$ kubectl apply -f mysql-pod.yaml
Warning: Autopilot set default resource requests for Pod default/mysql-pod, as resource requests were not specified. See http://g.co/gke/autopilot-defaults
pod/mysql-pod created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-pod 1/1 Running 0 19s
wordpress-pod 1/1 Running 0 8m52s
この状態で再度EXTERNAL-IPとポートでアクセスすると再度初期画面が表示されてしまいます。
MySQLのpodが消えてしまったことでデータも消えてしまったことになります。
黄色枠内にデータが存在し、podが消えるのと同時にデータも消えてしまうのです。
用意したファイル一覧
今回、PV/PVCを用いた環境を構築するにあたり用意したyamlファイルは以下となります。
まずvol.3から新規作成・変更点のあるyamlファイルになります。
mysql-pv.yaml
PVをデプロイする為のyamlファイルとなります。
GKE独自の設定としては"gcePersistentDisk"となるかと思います。
pdNameのところにPVをデプロイするディスクを指定します。gke-mysql-mydiskとしておりますが、これは後程GUI上で作成します。fsTypeのところはFileSystemのタイプを指定します。今回はext4とします。
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-vol-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: mysql-storage
gcePersistentDisk:
pdName: gke-mysql-mydisk
fsType: ext4
mysql-pvc.yaml
vol.3から新規作成したものになります。PVとは異なり、GKE特異のものはないかと思います。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-vol-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: mysql-storage
resources:
requests:
storage: 100Gi
mysql-pod.yaml
podにvolumeをアタッチし、デプロイする為の設定を追加しています。
mountPathを"/var/lib/mysql"としているのはMySQLのデータはデフォルトでここに格納されるためです。
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
以下はvol.3から変更していないyamlファイルとなります。
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
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
wordpress-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: wp-sec
data:
WORDPRESS_DB_PASSWORD : cGFzc3dvcmQK
wordpress-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
name: wordpress-loadbalancer
spec:
type: LoadBalancer
selector:
app: wordpress
ports:
- protocol: TCP
port: 60000
targetPort: 80
mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-cm
data:
MYSQL_DATABASE : gke-wordpress-database
MYSQL_USER : devuser
MYSQL_ROOT_PASSWORD : password
mysql-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysql-sec
data:
MYSQL_PASSWORD : cGFzc3dvcmQK
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
構築
まずGCEでPV/PVC用のディスクを用意します。
なお、以下のWebサイトを参考にしております。
まず、GCEを開くと以下のような画面が表示されるため、ストレージという項目の"ディスク"を押下します。
遷移し、以下のような画面が表示されます。
上部に表示されている"ディスクを作成"を押下します。
ディスクの名前やどのリージョン・ゾーンに作成するか、容量などを決定していきます。
この状態でPV/PVCをyamlをベースにデプロイしていきます。
実行後、PVCのステータスがBoundになっていれば問題ないと思います。
Pendingになっているようであれば、おそらくyamlに記載ミスなどがあるかと思います。
$ kubectl apply -f mysql-pv.yaml
persistentvolume/mysql-vol-pv created
$ kubectl apply -f mysql-pvc.yaml
persistentvolumeclaim/mysql-vol-pvc created
$ kubectl get pv,pvc -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/mysql-vol-pv 100Gi RWO Retain Bound default/mysql-vol-pvc mysql-storage 28s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/mysql-vol-pvc Bound mysql-vol-pv 100Gi RWO mysql-storage 18s Filesystem
この状態でpod,service,ConfigMap,Secretをyamlファイルでデプロイしていきます。
デプロイ結果が以下となります。
$ 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 6m12s 10.112.0.132 gk3-my-pool-1-d33c8819-85t9 <none> <none>
pod/wordpress-pod 1/1 Running 0 3m12s 10.112.0.133 gk3-my-pool-1-d33c8819-85t9 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.112.128.1 <none> 443/TCP 64m <none>
service/mysql-clusterip ClusterIP 10.112.128.253 <none> 3306/TCP 54m app=mysql
service/wordpress-loadbalancer LoadBalancer 10.112.130.188 34.30.162.91 60000:30188/TCP 54m app=wordpress
NAME DATA AGE
configmap/kube-root-ca.crt 1 64m
configmap/mysql-cm 3 55m
configmap/wp-cm 3 55m
NAME TYPE DATA AGE
secret/mysql-sec Opaque 1 55m
secret/wp-sec Opaque 1 55m
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/mysql-vol-pv 100Gi RWO Retain Bound default/mysql-vol-pvc mysql-storage 11m Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/mysql-vol-pvc Bound mysql-vol-pv 100Gi RWO mysql-storage 11m Filesystem
今回LoadBalancerのEXTERNAL-IPが34.30.162.91となっているので、このIPアドレス+ポート番号60000で接続します。
用意したサーバは"PV/PVC on GKE"というタイトルのWebサイトになります。
この状態でmysqlのpodを削除し、再度デプロイします。
$ kubectl delete pod mysql-pod
pod "mysql-pod" deleted
$ kubectl apply -f mysql-pod.yaml
Warning: Autopilot set default resource requests for Pod default/mysql-pod, as resource requests were not specified. See http://g.co/gke/autopilot-defaults
pod/mysql-pod created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-pod 1/1 Running 0 93s
wordpress-pod 1/1 Running 0 9m13s
再度アクセスします。
PV/PVCを作らない状態と異なり、データが残っていることが確認できますね。
データが黄色枠に保存されており、MySQLのpodはここを参照しているためデータが残る状態になっているということですね。