こんにちは。SREの徳田です。
今回、Kubernetes上でMySQLを動かしたい、という要望があったので、mysql-operatorについて調査してみました。
Operatorとは
Operatorは2016年にCoreOSが公開した手法・概念で、端的に言うとKubernetesを基盤としたアプリケーションのパッケージング・展開・管理を行う方法です。また、このOperatorの開発を手助けしてくれるものがOperator Frameworkです。
Operatorで管理する対象のアプリケーションはなんでもいいのですが、大抵の場合は管理が難しいとされているStatefulなアプリケーションのものがほとんどです。
また、公開されているOperatorを共有できるOperatorHub.ioというサイトも有ります。まだ種類は少ないですが、こちらでどのようなOperatorがあるかも確認することが出来ます。
mysql-operator
このOperatorでMySQLを管理しようと実装されたのがmysql-operatorです。
現在開発が行われているmysql-operatorは、oracleが開発しているものとpresslabsが開発しているものがあるようです。
この2つのmysql-operatorについて詳しく見ていきましょう。
oracle mysql-operator
oracleが開発しているmysql-operatorでは以下の機能があります。
- 高可用性なMySQLクラスタの作成・削除
- 自動化されたデータベースのバックアップ、障害検知、復旧
- クラスタ毎に定義された自動バックアップをスケジュール
- オンデマンドなバックアップの作成
- バックアップを使ったデータベースのリストア
一通りのオペレーションはできそうですね。
クラスタ作成
クラスタの作成は以下のようなManifestを適用します。
apiVersion: mysql.oracle.com/v1alpha1
kind: Cluster
metadata:
name: mysql-test-cluster
spec:
members: 3
exampleなどはこちらにまとまっています。
https://github.com/oracle/mysql-operator/blob/master/docs/user/clusters.md
適用するとGroup Replicationで構成されたクラスタが作成されます。
クラスタへの接続方法
MySQL Routerを使った接続を推奨しているようです。exampleでは以下のManifestがありました。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: wordpress-router
labels:
app: wordpress-router
spec:
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress-router
spec:
containers:
- name: mysqlrouter
image: mysql/mysql-router:8.0.12
env:
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: wordpress-mysql-root-password
key: password
- name: MYSQL_USER
value: root
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_HOST
value: mysql-wordpress-0.mysql-wordpress
- name: MYSQL_INNODB_NUM_MEMBERS
value: "3"
command:
- "/bin/bash"
- "-cx"
- "exec /run.sh mysqlrouter"
- name: wordpress
image: wordpress:4.9-php7.2-apache
env:
- name: WORDPRESS_DB_HOST
value: 127.0.0.1:6446
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: wordpress-mysql-root-password
key: password
ports:
- containerPort: 80
wordpressのPodにSidecarとしてmysql-routerを起動させ、クラスタとの疎通性を確保しています。
バックアップ作成方法
スケジュールされたバックアップの設定は以下のようなManifestを適用します。
apiVersion: mysql.oracle.com/v1alpha1
kind: BackupSchedule
metadata:
name: mysql-backup-schedule
spec:
schedule: '*/30 * * * *'
backupTemplate:
executor:
provider: mysqldump
databases:
- test
storageProvider:
s3:
endpoint: ocitenancy.compat.objectstorage.ociregion.oraclecloud.com
region: ociregion
bucket: mybucket
credentialsSecret:
name: s3-credentials
cluster:
name: mysql-cluster
バックアップ先にはOracle Cloud、AWS、Google Cloudに対応しています。
presslabs mysql-operator
presslabsが開発しているoperatorは以下をゴールとして置いています。
- MySQLクラスタを簡単にデプロイする
- DevOpsにフレンドリー(監視、可用性、スケール、バックアップなど)
- すぐに使えるバックアップ とPoint-In-Timeリカバリ
- クラスタ内とクラスタ間の複製をサポート
また、このOperatorではMySQLではなくPercona MySQLを使用しています。将来的にMariaDBで互換性のある実装ができそうであればMariaDBのサポートもしていくそうです。
クラスタ作成
クラスタを作成するには例として以下のManifestを適用します。
apiVersion: mysql.presslabs.org/v1alpha1
kind: MysqlCluster
metadata:
name: my-cluster
spec:
replicas: 2
secretName: my-secret
my-secretにはrootのパスワードなどを設定しておきます。
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
# root password is required to be specified
ROOT_PASSWORD: bm90LXNvLXNlY3VyZQ==
上記2つのManifestを適用すると、レプリケーションが設定されたMySQLクラスタが作成されます。
クラスタへの接続方法
クラスタを作成した際に以下3つのServiceも作成されています。
- my-cluster-mysql: MySQLインスタンスに接続できるService。Read用
- my-cluster-mysql-master: MySQLのMasterとして可動しているインスタンスに接続できるService。Write用
- my-cluster-nodes: Headless Service。特定のインスタンスへ接続可
これらのServiceを使用してアプリケーションから接続を行います。
バックアップ作成方法
クラスタのバックアップを取るにはクラスタのManifestに設定を追加します。
apiVersion: mysql.presslabs.org/v1alpha1
kind: MysqlCluster
metadata:
name: my-cluster
spec:
replicas: 2
secretName: my-secret
backupSecretName: my-cluster-backup-secret
backupURL: gs://pl-test-mysql-operator/
バックアップ先は、S3・GCS・Azureがあります。backupSecretNameには適切なクラウドのCredentialを格納したSecretの名前を指定します。
また、backupScheduleを設定することでバックアップのスケジュールを行うことが出来ます。
2つのOperatorを調べてみて
まず大きな違いはこちら。
比較項目 | oracle製 | presslabs製 |
レプリ手段 | Group Replication | Master-Slave |
アプリからの疎通性 | MySQL Router | Kubernetes Service |
障害検知など | MySQL自身 | orchestrator |
レプリ手段はどちらのOperatorも現状選択できないようです。oracle製の方は障害の検知などはGroup Replicationの機能に頼っているため、Master-Slaveの設定は構成したところで障害の際必要な機能が提供できないですね。また、presslabsは現状Group Replicationに対応していない、という感じでした。
アプリからの疎通性について、presslabsはProxy SQLのインテグレーションを機能として提供予定とのことです。Kubernetes Serviceを使うと、DNSキャッシュをしているときなど面倒なので、Ambassadorパターンのコンテナの役割をしてくれるProxy SQLの機能追加が待ち遠しいところです。
最後の「障害検知など」ですが、実はpresslabs製のmysql-operatorはGitHubで開発されているorchestratorというツールを利用しています。障害検知やフェールオーバー処理などはこのorchestratorにまかせています。
これ以外に簡単に触ってみて、
- presslabs製はClusterのManifestに直接mysqlの設定を書く必要がある。ConfigMapに切り出したい・・。
- presslabs製はMySQLクラスタに対するPodDisruptionBadgetも作成してくれる。oracle製は自分で作成する必要あり。
- oracle製はBackupにS3のCredentialにしか対応していない。GCPを利用している場合にアクセス制御がかけづらい。
という感想でした。また、presslabs製のほうがKubernetesやHelmのパッケージで色々調整できたり、ある程度MySQLの設定のチューニングがされていたりと、作り込み具合が良かったイメージです。開発もpresslabsのmysql-operatorほうが活発でした。
まとめ
mysql-operatorの紹介と簡単な比較をしてみました。
個人的にはpresslabs製のmysql-operator推しです。(しかし、MySQL Router+Group Replicationも素晴らしいかったです。が、Operatorの話ではないので・・。)
今回実際導入した手順や作成は省いたので、次回の記事のときにでも紹介できれば・・・と思っております。
それでは!