GKE上にMySQL/Redisを乗せて永続化させる
GKE上にMySQLとかRedisをわざわざ乗っけるならCloud SQLとかMemoryStoreとか使っといた方が耐障害性たけーよなとか思うんですが料金がお手軽じゃないです。
なので試しにGKEにのせてみることにします。
replicaは1台です。
Secret / ConfigMap の登録
--- apiVersion: v1 kind: Secret metadata: name: mysql-secret data: MYSQL_ROOT_PASSWORD: <BASE64_ENCODED_ROOT_PASSWORD> MYSQL_DATABASE: <BASE64_ENCODED_DATABASE> MYSQL_USER: <BASE64_ENCODED_USER> MYSQL_PASSWORD: <BASE64_ENCODED_PASSWORD> --- apiVersion: v1 kind: ConfigMap metadata: name: mysql-config-file data: custom.cnf: | [mysqld] default_authentication_plugin=mysql_native_password character-set-server=utf8mb4 [client] default-character-set=utf8mb4
$ kubectl apply -f mysql-config.yml
まずMySQLの設定に必要なConfigMapとSecretをapplyしておきます。
Secretの値にはbase64エンコードされた値を入れておく必要があります。
(一応エンコードが必要ないstringDataなるフィールドもある)
$ echo -n "<TEXT>" | openssl enc -e -base64
これでエンコードできる。
Mysql Serviceの登録
--- apiVersion: v1 kind: Service metadata: name: mysql spec: ports: - port: 3306 selector: app: mysql clusterIP: None --- apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: StatefulSet metadata: name: mysql spec: selector: matchLabels: app: mysql replicas: 1 serviceName: mysql template: metadata: labels: app: mysql spec: containers: - image: mysql:8.0.15 name: mysql ports: - containerPort: 3306 name: mysql envFrom: - configMapRef: name: mysql-config-file - secretRef: name: mysql-config volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql subPath: mysql - name: mysql-config-volume mountPath: /etc/mysql/conf.d/custom.cnf subPath: custom.cnf volumes: - name: mysql-config-volume configMap: name: mysql-config-file volumeClaimTemplates: - metadata: name: mysql-persistent-storage spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 20Gi
$ kubectl apply -f mysql.yml
volumeClaimTemplatesにClaimの情報を書き込んだ上で、そのClaimをvolumeMountsで指定してやります。 これで自動的にPersistentVolumeが立つようになります。
GKEではPersistent Volumeのデフォルトとして GCEPersistentDisk が作成されます。 デフォルトではHDDなので、SSDで作成したい場合はStorageClassを追加してspec.storageClassNameを指定する必要があります。
MySQLのデプロイでちょっとハマったんですが、マウントするストレージのディレクトリにはいくつかファイル(ディレクトリ)があるようで、MySQLは初回起動時にデータを保管するディレクトリが空でない場合にエラーを吐くため、Podが立ちませんでした。
対策として、subPath: mysql
を指定することでPersistentVolumeに mysql/
ディレクトリを作成して、そのディレクトリを /var/lib/mysql
にマウントするようにしています。
Redis Serviceのデプロイ
apiVersion: v1 kind: Service metadata: name: redis spec: ports: - port: 6379 clusterIP: None selector: app: redis --- apiVersion: apps/v1 kind: StatefulSet metadata: name: redis spec: selector: matchLabels: app: redis serviceName: redis replicas: 1 template: metadata: labels: app: redis spec: containers: - name: master image: redis:alpine ports: - containerPort: 6379 volumeMounts: - name: redis-persistent-storage mountPath: /data subPath: redis volumeClaimTemplates: - metadata: name: redis-persistent-storage spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi
$ kubectl apply -f redis.yml
MySQLとあんまり変わらないです。 確認してみます。
# keyをセットする $ kubectl exec -it redis-0 redis-cli 127.0.0.1:6379> set key redis OK 127.0.0.1:6379> exit # podを落として再度作成されるまで待つ $ kubectl delete pod redis-0 pod "redis-0" deleted # 新しくできたpodに入ってkeyをgetしてみる $ kubectl exec -it redis-0 redis-cli 127.0.0.1:6379> get key "redis"
大丈夫そうです。
このままだとスケールしませんが節約にはなります。
でも節約考えるならGKE使わなくてもいいんだよなぁ…