概要
現在、ローカルにvue+djangoの開発環境をkubernetesで構築しようとしているのですが、
mysqlのコンテナを立てる際にハマったことがあったので、情報を共有します。
MySQL8をPythonで使う場合について
MySQLをPythonで使う場合、パッケージにmysqlclient
を選択することがあると思います。
ここでMySQL8でmysqlclient
を使う場合に注意する点があります。
MySQL8.0.4以降、デフォルトの認証方式が変更され、mysql_native_password
からcaching_sha2_password
になりました。しかし、mysqlclient
はこのcaching_sha2_password
に対応していません。
そのため、以下のように、my.cnfを変更するか、もしくはmysqld
の実行時に--default-authentication-plugin=mysql_native_password
オプションをつけて、認証方式をmysql_native_password
に戻す必要があります。
[mysqld]
default-authentication-plugin = mysql_native_password
mysqld --default-authentication-plugin=mysql_native_password
kubernetesでMySQLをデプロイ
私は、docker-composeにてMySQL8系のコンテナを利用していたこともあり、その際にdocker-compose.ymlからコマンドを上書きして、後者のコマンドにオプションをつけて実行する方法で実行していたため、kubernetesでの実行時も同様の方法を選択しました。
一部抜粋した設定定義ファイルでは以下のように指定していました。
注:ここではローカル環境用の設定定義のため、パスワード等をConfigMapで設定していますが、実際の運用ではSecretを推奨です
...
spec:
containers:
- name: mysql
image: mysql:8.0.15
# この部分
command:
- mysqld
- --user=root --default-authentication-plugin=mysql_native_password
env:
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
name: mysql-cm
key: MYSQL_USER
- name: MYSQL_PASSWORD
valueFrom:
configMapKeyRef:
name: mysql-cm
key: MYSQL_PASSWORD
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: mysql-cm
key: MYSQL_DATABASE
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
...
しかし、これを用いてリソースを作成するとなぜか初期化の段階でうまくいきません。
これはkubernetesのcommandの仕様が、少し特殊だったことが原因でした。
kubernetesのcommandとENTRYPOINT
結論から言いますと、kubernetesのcommandはCMD
だけではなく、ENTRYPOINT
も上書きしてしまうことが問題点となっていました。
kubernetes学習番外編 コンテナ起動時のコマンド実行 - そんな今日この頃の技術ネタ
このリソースでは公式のMySQLイメージを利用していますが、公式イメージはイメージ内でENTRYPOINTを利用して初期化をするスクリプトが走っています。
そのため、上記のようにkubernetesのcommandを利用してしまうと、ENTRYPOINT
が上書きされてしまい、公式イメージによって自動化されていた初期化のプロセスを実行しなくてはいけないんですが、それをうまく実行できていなかったために、エラーとなっていたようです。
そのため、以下のようにmy.cnfを変更する方法で、認証方式をmysql_native_password
に戻すことで、エラーを回避することができました。
apiVersion: v1
kind: ConfigMap
metadata:
name: django-mysql-cm
labels:
project: django-vue
app: mysql
data:
MYSQL_USER: timer
MYSQL_PASSWORD: timer
MYSQL_DATABASE: timer
MYSQL_HOST: django-mysql-svc
my.cnf: |-
[mysqld]
default-authentication-plugin = mysql_native_password
---
...
containers:
- name: mysql
image: mysql:8.0.15
env:
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
name: django-mysql-cm
key: MYSQL_USER
- name: MYSQL_PASSWORD
valueFrom:
configMapKeyRef:
name: django-mysql-cm
key: MYSQL_PASSWORD
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: django-mysql-cm
key: MYSQL_DATABASE
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: my-cnf
mountPath: /etc/my.cnf
subPath: my.cnf
readOnly: true
- name: data
mountPath: /var/lib/mysql
subPath: mysql
volumes:
- name: my-cnf
configMap:
name: django-mysql-cm
items:
- key: my.cnf
path: my.cnf
...
あとがき
今回は思ってもみなかったkubernetesの仕様でかなりの時間対応させられることになってしまいました。
初期化で失敗している時点で、公式イメージの初期化処理が通ってないと気づくのが、もう少し早かったならばと悔やまれます。
現在まだ環境を構築中ですが、開発環境が完成したら、後日公開したいなと思っています。