はじめに
Kubernetesの普及に伴い、クラウドネイティブなデータベース運用も重要な課題となっています。そこで今回は「mariadb-operator」について検証しました。
Kubernetes Operators for MariaDB – MariaDB Knowledge Base
mariadb-operator は、クラウド ネイティブな方法で MariaDB を実行および操作できる Kubernetes オペレーターです。命令型コマンドの代わりに Kubernetes CRD を使用して MariaDB インスタンスを宣言的に管理することを目的としています。
mariadb-operatorは、Kubernetes上でデプロイやスケーリング、バックアップを自動化し、運用の手間を大幅に軽減します。
また、HAオプションとして、MaxScaleによるデータベースプロキシや、MariaDB Galera Cluster、レプリケーションがサポートされています。
他にも、S3へのバックアップやPrometheus監視など、以下の機能をサポートしています。(一部抜粋)
mariadb-operator/mariadb-operator: 🦭 Run and operate MariaDB in a cloud native way
- 複数のバックアップ ストレージ タイプ: S3 互換、PVC、Kubernetes ボリューム。
- mysqld-exporterおよび maxscale-exporter 経由のPrometheus メトリック。
ライセンスについて
MariaDB部分については基本的にオープンソースとなりますが、例外的に、MaxScaleにはBSL(Business Source License)ライセンスが指定されていますので、商用利用についてはライセンス料が発生する場合があります。
mariadb-operator/docs/MAXSCALE.md at main · mariadb-operator/mariadb-operator
MaxScale 23.08 is licensed under Business Source License. Make sure you understand the implications before using it!
BSLライセンスの基本的な考え方については、以下のMariaDB公式ブログをご参照ください。
BSL(Business Source License) | MariaDB
MariaDB Server, MariaDB ColumnStore インスタンス数が3未満の場合はいかなる目的にも利用可能
環境構築
前提となるソフトウェア類をインストールします。
詳細説明は公式リファレンスに譲り、ここでは割愛させていただきます。
1 2 3 4 5 |
sudo dnf -y install dnf-plugins-core sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl enable --now docker sudo usermod -aG docker $USER && newgrp docker |
Install and Set Up kubectl on Linux | Kubernetes
1 2 3 4 5 |
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl # SELinuxをpermissiveモードに設定する(効果的に無効化する) sudo setenforce 0 sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config |
1 2 3 4 5 6 |
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.26.0/kind-linux-amd64 sudo install -o root -g root -m 0755 kind /usr/local/bin/kind curl -LO https://raw.githubusercontent.com/kubernetes-sigs/kind/main/site/content/docs/user/kind-example-config.yaml kind create cluster --config kind-example-config.yaml |
mariadb-operatorのインストール
今回の検証用に新しくmariadb-operator
というNamespaceを作成します。
1 2 |
kubectl create namespace mariadb-operator kubectl config set-context --current --namespace mariadb-operator |
1 2 3 |
$ kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * kind-kind kind-kind kind-kind mariadb-operator |
早速、mariadb-operatorのインストールをしていきます。Custom Resource Definitions(CRDs)と、Operatorの以下の二つが必要です。
- mariadb-operator-crds
- mariadb-operator
helm、OLM、または直接マニフェストを使用してインストールができます。
今回はhelmを利用するので、以下のようにリポジトリを登録しインストールを実行します。
1 2 3 4 |
helm repo add mariadb-operator https://helm.mariadb.com/mariadb-operator helm repo update mariadb-operator helm install mariadb-operator-crds mariadb-operator/mariadb-operator-crds helm install mariadb-operator mariadb-operator/mariadb-operator |
検証時でのmariadb-operatorバージョンは0.37.1です。
また、CRDsおよびOperatorの作成が確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
$ helm ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION mariadb-operator mariadb-operator 1 2025-03-27 07:54:32.711409162 +0000 UTC deployed mariadb-operator-0.37.1 0.37.1 mariadb-operator-crds mariadb-operator 1 2025-03-27 07:54:24.321924196 +0000 UTC deployed mariadb-operator-crds-0.37.1 0.0.0 $ kubectl get customresourcedefinitions NAME CREATED AT backups.k8s.mariadb.com 2025-03-27T07:54:28Z connections.k8s.mariadb.com 2025-03-27T07:54:28Z databases.k8s.mariadb.com 2025-03-27T07:54:28Z grants.k8s.mariadb.com 2025-03-27T07:54:28Z mariadbs.k8s.mariadb.com 2025-03-27T07:54:28Z maxscales.k8s.mariadb.com 2025-03-27T07:54:28Z restores.k8s.mariadb.com 2025-03-27T07:54:28Z sqljobs.k8s.mariadb.com 2025-03-27T07:54:28Z users.k8s.mariadb.com 2025-03-27T07:54:28Z $ kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE mariadb-operator 1/1 1 1 77s mariadb-operator-cert-controller 1/1 1 1 77s mariadb-operator-webhook 1/1 1 1 77s |
MariaDBシングルインスタンス環境の作成
マニフェストを使って、各リソースを作成していきます。
サンプルマニフェストは、Gitリポジトリのexamples/manifests
配下にあり、指定可能なパラメータはAPI_REFERENCEで説明されています。
まずは、サンプルマニフェストをGitHubリポジトリから取得してしまいましょう。
1 2 |
sudo dnf install -y git git clone --depth=1 https://github.com/mariadb-operator/mariadb-operator.git |
Quickstartでも紹介されている、基本形のMariaDBシングルインスタンス環境を作成していきます。
rootパスワード用にmariadb-secret.yaml
テンプレートと、MariaDBをmariadb.yaml
テンプレートを使用して作成します。
1 2 3 |
cd ~/mariadb-operator/examples/manifests/ kubectl apply -f config/mariadb-secret.yaml kubectl apply -f mariadb.yaml |
作成されたリソースを確認します。
完了までに時間がかかるので、--watch
オプションで経過を観察するのが良いでしょう。
MariaDBリソースの「READYがTrue、STATUSがRunning」となったのを確認したら無事に起動完了です。
途中でエラーが出ていますが、最終的にRunningなのでここでは無視でOKとします。
1 2 3 4 5 6 |
$ kubectl get mariadbs --watch NAME READY STATUS PRIMARY UPDATES AGE mariadb False Not ready mariadb-0 ReplicasFirstPrimaryLast 0s mariadb True Running mariadb-0 ReplicasFirstPrimaryLast 20s mariadb False Error reconciling SQL: error getting mariadb.sys Grant: Grant.k8s.mariadb.com "mariadb-mariadb-sys-global-priv" not found mariadb-0 ReplicasFirstPrimaryLast 20s mariadb True Running mariadb-0 ReplicasFirstPrimaryLast 20s |
MariaDBリソースを作成すると以下の付随するリソースが作成されます。
- StatefulSet: mariadbd
- Secret : mariadb認証用
- ConfigMap : mariadb設定ファイル
- Service : mariadbへの接続
(一部出力を省略)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
$ kubectl get statefulsets/mariadb NAME READY AGE mariadb 1/1 47s $ kubectl get pods/mariadb-0 NAME READY STATUS RESTARTS AGE mariadb-0 1/1 Running 0 61s $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mariadb LoadBalancer 10.96.22.5 <pending> 3306:31339/TCP 69s mariadb-internal ClusterIP None <none> 3306/TCP 69s ... $ kubectl get configmaps NAME DATA AGE ... mariadb-config 1 95s mariadb-config-default 1 95s mariadb-config-tls 1 95s ... $ kubectl get secrets NAME TYPE DATA AGE mariadb Opaque 2 112s mariadb-ca Opaque 2 109s mariadb-ca-bundle Opaque 1 109s mariadb-client-cert kubernetes.io/tls 2 109s ... mariadb-password Opaque 1 109s mariadb-server-cert kubernetes.io/tls 2 109s ... |
今回作成に使用したマニフェストは以下の通りです。
-
2つのDBパスワードを管理するSecretリソースを作成します。
Secretに平文やbase64 encodeされた値を記載するのはセキュリティ上望ましくないため、本番で利用する場合はkubesecの利用をご検討ください。123456789apiVersion: v1kind: Secretmetadata:name: mariadblabels:k8s.mariadb.com/watch: ""stringData:password: MariaDB11!root-password: MariaDB11! -
次に、基本的なMariaDBリソースのマニフェストとなります。
rootPasswordSecretKeyRef
セクションに上記で作成するSecretを指定しています。1234567891011121314151617181920212223242526272829303132333435363738394041424344apiVersion: k8s.mariadb.com/v1alpha1kind: MariaDBmetadata:name: mariadbspec:rootPasswordSecretKeyRef:name: mariadbkey: passwordusername: mariadbpasswordSecretKeyRef:name: mariadb-passwordkey: passwordgenerate: truedatabase: mariadbport: 3306storage:size: 1Giservice:type: LoadBalancermetadata:annotations:metallb.universe.tf/loadBalancerIPs: 172.18.0.20myCnf: |[mariadb]bind-address=*default_storage_engine=InnoDBbinlog_format=rowinnodb_autoinc_lock_mode=2innodb_buffer_pool_size=1024Mmax_allowed_packet=256Mresources:requests:cpu: 100mmemory: 128Milimits:memory: 1Gimetrics:
テストデータの作成
データベース作成、ユーザー作成、権限付与には、
Database、User、Grantリソースを作成していきます。
1 2 3 |
kubectl apply -f sqljobs/0_user.yaml kubectl apply -f sqljobs/1_database.yaml kubectl apply -f sqljobs/2_grant.yaml |
それぞれのリソースが作成されています。
1 2 3 4 5 6 7 8 9 |
$ kubectl get databases,users,grants sqljob NAME READY STATUS CHARSET COLLATE MARIADB AGE NAME database.k8s.mariadb.com/sqljob True Created utf8 utf8_general_ci mariadb 49s NAME READY STATUS MAXCONNS MARIADB AGE user.k8s.mariadb.com/sqljob True Created 10 mariadb 49s NAME READY STATUS DATABASE TABLE USERNAME GRANTOPT MARIADB AGE grant.k8s.mariadb.com/sqljob True Created sqljob * sqljob true mariadb 49s |
今回作成に使用したマニフェストは以下の通りです。
-
sqljobという名前のユーザーを作成します。
sqljobs/0_user.yaml
1234567891011121314apiVersion: k8s.mariadb.com/v1alpha1kind: Usermetadata:name: sqljobspec:mariaDbRef:name: mariadbpasswordSecretKeyRef:name: mariadbkey: passwordrequire:issuer: "/CN=mariadb-ca"subject: "/CN=mariadb-client"host: "%" -
sqljobという名前のデータベースを作成します。
sqljobs/1_database.yaml
123456789apiVersion: k8s.mariadb.com/v1alpha1kind: Databasemetadata:name: sqljobspec:mariaDbRef:name: mariadbcharacterSet: utf8collate: utf8_general_ci -
sqljobユーザーに、sqljobデータベースに対するALL PRIVILEGES権限を付与します。
sqljobs/2_grant.yaml
1234567891011121314apiVersion: k8s.mariadb.com/v1alpha1kind: Grantmetadata:name: sqljobspec:mariaDbRef:name: mariadbprivileges:- "ALL PRIVILEGES"database: "sqljob"table: "*"username: sqljobgrantOption: truehost: "%"
SQLジョブ
SQL文を実行するにはSQLジョブを作成します。
1 2 3 |
kubectl apply -f sqljobs/sqljob_01-users_tls.yaml kubectl apply -f sqljobs/sqljob_02-repos.yaml kubectl apply -f sqljobs/sqljob_03-stars.yaml |
それぞれのリソースが作成されます。
完了までに時間がかかるので、--watch
オプションで経過を観察するのが良いでしょう。
03-starsの1回目のSuccessが表示されたらwatchを止めてOKです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ kubectl get sqljobs --watch NAME COMPLETE STATUS MARIADB AGE 01-users True Success mariadb 3s 02-repos False Dependency '01-users' not ready mariadb 3s 03-stars False Dependency '01-users' not ready mariadb 3s 02-repos False Dependency '01-users' not ready mariadb 5s 02-repos False Running mariadb 5s 03-stars False Dependency '02-repos' not ready mariadb 5s 02-repos True Success mariadb 8s 03-stars False Dependency '02-repos' not ready mariadb 10s 03-stars False Scheduled mariadb 10s 03-stars True Success mariadb 23s |
今回作成に使用したマニフェストは以下の通りです。
-
usersテーブルを作成し、テストデータをINSERTするSQL文を実行します。
sqljobs/sqljob_01-users_tls.yaml
123456789101112131415161718192021222324252627282930313233343536373839404142apiVersion: k8s.mariadb.com/v1alpha1kind: SqlJobmetadata:name: 01-usersspec:mariaDbRef:name: mariadbinheritMetadata:annotations:database.myorg.io: mariadbpodMetadata:labels:sidecar.istio.io/inject: "false"serviceAccountName: sqljobusername: sqljobpasswordSecretKeyRef:name: mariadbkey: passwordtlsCASecretRef:name: mariadb-ca-bundletlsClientCertSecretRef:name: mariadb-client-certdatabase: sqljobsql: |CREATE TABLE IF NOT EXISTS users (id bigint PRIMARY KEY AUTO_INCREMENT,username varchar(255) NOT NULL,UNIQUE KEY name__unique_idx (username));INSERT INTO users(username) VALUES('mmontes11')ON DUPLICATE KEY UPDATE id=id;INSERT INTO users(username) VALUES('Vidalee')ON DUPLICATE KEY UPDATE id=id;INSERT INTO users(username) VALUES('macno')ON DUPLICATE KEY UPDATE id=id;INSERT INTO users(username) VALUES('eloylp')ON DUPLICATE KEY UPDATE id=id;INSERT INTO users(username) VALUES('ksankeerth')ON DUPLICATE KEY UPDATE id=id;INSERT INTO users(username) VALUES('stefan-bergstein')ON DUPLICATE KEY UPDATE id=id;--To be continued, contribute to mariadb-operator! 🦭 -
01とほぼ同じなので省略します。
sqljobs/sqljob_02-repos.yaml
12345apiVersion: k8s.mariadb.com/v1alpha1kind: SqlJobmetadata:name: 02-repos...以下省略 -
上記2つは一度きり実行のJobリソースであるのに対し、こちらは1分ごとにJob作成を繰り返すCronJobリソースとなっています。
sqljobs/sqljob_03-stars.yaml
12345678910111213141516apiVersion: k8s.mariadb.com/v1alpha1kind: SqlJobmetadata:name: 03-starsspec:dependsOn:- name: 01-users- name: 02-reposmariaDbRef:name: mariadbschedule:cron: "*/1 * * * *"suspend: falsetimeZone: "UTC"...以下省略...
01と02のJobはそれぞれ1個、03のCronJobは1分ごとに1個作成されていることが確認できます。
1 2 3 4 5 6 7 8 9 10 11 |
$ kubectl get cronjobs NAME SCHEDULE TIMEZONE SUSPEND ACTIVE LAST SCHEDULE AGE 03-stars */1 * * * * UTC False 0 55s 50m $ kubectl get jobs NAME STATUS COMPLETIONS DURATION AGE 01-users Complete 1/1 3s 49m 02-repos Complete 1/1 3s 49m 03-stars-29051086 Complete 1/1 3s 2m37s 03-stars-29051087 Complete 1/1 3s 97s 03-stars-29051088 Complete 1/1 3s 37s |
接続確認
Kubernetesクラスタ内部から各MariaDBコンテナへは、ServiceによるFQDNでアクセス可能です。
(一部出力を省略)
1 2 3 4 5 6 7 8 9 10 |
$ kubectl get services,endpoints NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/mariadb LoadBalancer 10.96.37.80 <pending> 3306:31477/TCP 7m42s service/mariadb-internal ClusterIP None <none> 3306/TCP 7m42s ... NAME ENDPOINTS AGE endpoints/mariadb 10.244.2.3:3306 7m42s endpoints/mariadb-internal 10.244.2.3:3306 7m42s ... |
Serviceリソースが2つあります。
mariadb-internal
はクラスタ内部専用の3306ポートを利用してアクセス可能なサービスです。ただし、Headlessのため、CLUSTER-IPはNoneとなっており、DNS経由でPodのIP(エンドポイント)に直接アクセス可能です。mariadb
はNodePort(例:31477ポート)を利用して外部からアクセス可能なサービスです。
サービス経由では、mariadb-internal.mariadb-operator.svc.cluster.local
のようなFQDNでアクセスします。
個別のコンテナへの接続は、mariadb-0.mariadb-internal.mariadb-operator.svc.cluster.local
と先頭にPod名を付けてあげる形になります。
接続確認してみましょう。
1 2 3 4 5 6 7 8 9 10 |
$ kubectl run conn --image=mariadb:11.4.4 --rm -it --restart=Never -- sh -c "mariadb -u root -pMariaDB11! -P3306 -h mariadb-internal.mariadb-operator.svc.cluster.local" If you don't see a command prompt, try pressing enter. MariaDB [(none)]> SELECT @@hostname; +------------+ | @@hostname | +------------+ | mariadb-0 | +------------+ 1 row in set (0.000 sec) |
SQLジョブで投入したユーザー権限およびデータも確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
MariaDB [(none)]> SELECT user,host FROM mysql.user; +-------------+-----------+ | User | Host | +-------------+-----------+ | mariadb | % | | root | % | | sqljob | % | | healthcheck | 127.0.0.1 | | healthcheck | ::1 | | healthcheck | localhost | | mariadb.sys | localhost | | root | localhost | +-------------+-----------+ 8 rows in set (0.001 sec) MariaDB [(none)]> SHOW GRANTS FOR sqljob@'%'; +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Grants for sqljob@% | +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO <code>sqljob</code>@<code>%</code> IDENTIFIED BY PASSWORD '*57685B4F0FF9D049082E296E2C39354B7A98774E' REQUIRE ISSUER '/CN=mariadb-ca' SUBJECT '/CN=mariadb-client' WITH MAX_USER_CONNECTIONS 10 | | GRANT ALL PRIVILEGES ON <code>sqljob</code>.* TO <code>sqljob</code>@<code>%</code> WITH GRANT OPTION | +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.000 sec) MariaDB [(none)]> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mariadb | | mysql | | performance_schema | | sqljob | | sys | +--------------------+ 6 rows in set (0.000 sec) MariaDB [(none)]> USE sqljob Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed MariaDB [sqljob]> SHOW TABLES; +------------------+ | Tables_in_sqljob | +------------------+ | repos | | stars | | users | +------------------+ 3 rows in set (0.000 sec) MariaDB [sqljob]> SELECT * FROM stars; +-----+---------+---------+ | id | user_id | repo_id | +-----+---------+---------+ | 30 | 1 | 1 | | 46 | 1 | 2 | | 3 | 1 | 3 | | 9 | 2 | 1 | | 31 | 2 | 2 | | 21 | 2 | 3 | | 29 | 3 | 1 | | 1 | 3 | 2 | | 7 | 3 | 3 | | 11 | 4 | 1 | | 110 | 4 | 2 | | 56 | 4 | 3 | | 24 | 5 | 1 | | 8 | 5 | 2 | | 51 | 5 | 3 | | 19 | 6 | 1 | | 15 | 6 | 2 | | 4 | 6 | 3 | +-----+---------+---------+ 18 rows in set (0.000 sec) |
補足:MariaDBバージョン指定方法
MariaDBリソースのコンテナはDockerレジストリのMariaDB公式イメージを使用しています。
1 2 |
$ kubectl get po/mariadb-0 -ojson | jq -r .spec.containers[].image docker-registry1.mariadb.com/library/mariadb:11.4.4 |
現在、デフォルトでmariadb:11.4.4バージョンが使用されていますが、これは.spec.image
で指定が可能です。
ただし、MariaDB公式イメージのバージョン10.5以上のみがサポートされています。
mariadb-operator/README.md at main · mariadb-operator/mariadb-operator
MariaDB compatibility
MariaDB Community >= 10.5
まとめ
今回は構築編ということで、Operatorのインストール、MariaDBコンテナの作成、SQL実行を試してみました。
どれも、マニフェストを適用するだけで簡単に作れてしまいます。
スケーラビリティと自動化を両立させた MariaDB Operatorで、クラウドネイティブなデータベース管理を体験してみませんか?