2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MySQL Operator for Kubernetes の構築をさっくりと試してみた

Last updated at Posted at 2022-12-19

概要

MySQL Operator for Kubernetes(以下MySQL Operator)というKubernetes上にMySQLの環境を手軽に用意できるOperatorを試してみましたのでまとめてみます。
(普段はインメモリのDBやSQLiteのようなファイルベースを使いがち)

本記事の対象

  • Kubernetesを触り始めた方
  • 簡単にMySQLを構築してみたい方
  • MySQL Operatorを使ってみたい方

※本記事ではKubernetesの環境はご自身で準備いただくことを前提としております

MySQL Operatorについて

OperatorというKubernetesの運用自動化に使われる拡張機能を利用して、Oracle社のMySQL開発チームにて開発がされたものとなります。
MySQL OperatorはMySQL InnoDB Clusterの管理に重点を置いております。
参考リンク:KubernetesのOperatorについて
開発元Github:MySQL Operator for Kubernetes

MySQL InnoDB Clusterについて

複数台のMySQLServerでの高可用性やスケーリングなどの機能を提供するものになります。
最低3台のMySQL Serverと、アプリケーションとMySQL Server間のルーティングを提供するMySQL Routerで構成がされます。
引用元

MySQL Operatorのアーキテクチャ図

image.png
画像引用元

構築手順

それではここからMySQL Operatorの構築した手順について記載いたします。
基本的には公式ドキュメントを参考にしながら進めております。
公式ドキュメント

今回展開先に使用したKubernetes環境

Kubeadmで構築した1台のMasterと2台のWorkerで成る以下のようなKubernetesクラスタに対して展開を行いました。
一応以下記事に同じ構成を作成する手順をまとめております。
よく使っているkubeadmを使ったKubernetes検証環境の構築
image.png

MySQL Operatorデプロイ

CRDのインストール

MySQL Operatorで使用されるカスタム リソース定義 (CRD) をインストールします

kubectl apply -f https://raw.githubusercontent.com/mysql/mysql-operator/trunk/deploy/deploy-crds.yaml

#出力
customresourcedefinition.apiextensions.k8s.io/innodbclusters.mysql.oracle.com created
customresourcedefinition.apiextensions.k8s.io/mysqlbackups.mysql.oracle.com created
customresourcedefinition.apiextensions.k8s.io/clusterkopfpeerings.zalando.org created
customresourcedefinition.apiextensions.k8s.io/kopfpeerings.zalando.org created

MySQL Operator デプロイ

以下コマンドでMySQL Operatorのデプロイを実施します。

kubectl apply -f https://raw.githubusercontent.com/mysql/mysql-operator/trunk/deploy/deploy-operator.yaml

#出力
clusterrole.rbac.authorization.k8s.io/mysql-operator created
clusterrole.rbac.authorization.k8s.io/mysql-sidecar created
clusterrolebinding.rbac.authorization.k8s.io/mysql-operator-rolebinding created
clusterkopfpeering.zalando.org/mysql-operator created
namespace/mysql-operator created
serviceaccount/mysql-operator-sa created
deployment.apps/mysql-operator created

名前空間[mysql-operator]が自動で作成されデプロイが行われたため、実行に問題がないか確認。

kubectl get deployment mysql-operator --namespace mysql-operator

#出力
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
mysql-operator   1/1     1            1           25h

以上でMySQL Operatorの準備が完了となります。
ここから先はMySQL Operatorで管理するMySQL InnoDB Clusterを展開していきます。

MySQL InnoDB Clusterデプロイ

Secret作成

MySQLのrootユーザー用のSecretを作成しておきます。
※mysqlpwdとtestは任意の値に変更してください

kubectl create secret generic mysqlpwd \
        --from-literal=rootUser=root \
        --from-literal=rootHost=% \
        --from-literal=rootPassword="test"
#出力
secret/mysqlpwd created

MySQL InnoDB Cluster yaml作成

MySQL InnoDB Clusterをデプロイするためのyamlを準備します。
以下ではMySQL Serverインスタンス3台とMySQL Routerインスタンス1台を定義しています。
※sercretNameは前述の手順で作成したSercretをご記載ください

mycluster.yaml
apiVersion: mysql.oracle.com/v2
kind: InnoDBCluster
metadata:
  name: mycluster
spec:
  secretName: mysqlpwd
  tlsUseSelfSigned: true
  instances: 3
  router:
    instances: 1

MySQL InnoDB Cluster デプロイ

作成したyamlでInnoDB Clusterのデプロイを行います。

kubectl apply -f mycluster.yaml

#出力
innodbcluster.mysql.oracle.com/mycluster created

以下コマンドでプロセスがすべてONLINEになるまで待機をします。
(少し時間がかかると聞いたため、ご飯でも食べてきます)

kubectl get innodbcluster --watch

#出力
NAME        STATUS    ONLINE   INSTANCES   ROUTERS   AGE
mycluster   PENDING   0        3           1         15s

MySQL InnoDB Cluster デプロイ失敗

ここでしばらく待つ(ご飯から帰ってくる)とONLINEになっているはずが、、一向にならない。。
そこで生成されているPodのログをのぞいてみます。

kubectl describe pod mycluster-0

#出力抜粋
Warning  FailedScheduling  11s    default-scheduler  0/3 nodes are available: 3 pod has unbound immediate PersistentVolumeClaims. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling.

Error    Logging           22s    kopf               Handler 'on_pod_create' failed temporarily: Sidecar of mycluster-0 is not yet configured
  Normal   Logging           22s    kopf               POD CREATED: pod=mycluster-0 ContainersReady=None Ready=None gate[configured]=None

中身を見るとWarningの中にPersistentVolumeClaimsがバインドされていない旨の記載があります。
ここでPersistentVolumeを作成していなかったことに気づきます。

PersistentVolume の作成

MySQL Serverの展開にPersistentVolume(以下PV)が必要になるため、準備を進めます。
今回INSTANCEは3つあるため、小分けに3つのPVを用意していきます。

PV作成用のyaml作成

今回はNFSのサーバーがありましたため、そちらを使用していきます。
※NFS等の外部ストレージの用意が急遽難しい場合はhostPathの指定でローカルのディレクトリで取り合えず試すことはできます。
※hostPathの指定は以下yaml内のコメントアウト部分です。nfsの記載と入れ替えでご利用ください。

pv0001.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    server: ××.××.××.××
    path: /export/nfs/pv0001
  #hostPath:
  #  path: /data/pv0001

PV作成

作成したyamlでPVを作成します。

kubectl apply -f pv0001.yaml

#出力
persistentvolume/pv0001 created

今回はPVを3つ用意してSTATUSがAvailableになっていることを確認します。

kubectl get pv

#出力
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv0001   50Gi       RWX            Recycle          Available                                   115m
pv0002   50Gi       RWX            Recycle          Available                                   115m
pv0003   50Gi       RWX            Recycle          Available                                   115m

これでPVの準備は完了となります。

補足

今回私はNFSを利用しましたが、それにあたりKubernetes Clusterに参加しているMaster及びWorkerに、
nfs-commonのインストールが必要になります。
同じ手順を追っていただきNFSを使ってみた方は各Kubernetes Nodeに以下のような形でインストールが必要な旨ご注意ください。

sudo apt-get install nfs-common

MySQL InnoDB Clusterデプロイ リベンジ

それではPVの準備が出来たため、気を取り直してMySQL InnoDB Clusterのデプロイを行います。

MySQL InnoDB Cluster yaml修正

今回PVの作成の際にaccessModesをReadWriteManyにしています。
そのため、前述で作成したmycluster.yamlでもReadWriteManyを指定する形に修正しておきます。
※datadirVolumeClaimTemplate以下を追記しております。

mycluster.yaml
apiVersion: mysql.oracle.com/v2
kind: InnoDBCluster
metadata:
  name: mycluster
spec:
  secretName: mysqlpwd
  tlsUseSelfSigned: true
  instances: 3
  router:
    instances: 1
  datadirVolumeClaimTemplate:
    accessModes:
      - ReadWriteMany

MySQL InnoDB Cluster 再デプロイ

修正したyamlにて再度デプロイを実施して、ONLINEになるまで待機します。

kubectl apply -f mycluster.yaml
kubectl get innodbcluster --watch

少し待つとONLINEが3になり全プロセスがONLINEになったことが確認できました。

NAME        STATUS   ONLINE   INSTANCES   ROUTERS   AGE
mycluster   ONLINE   3        3           1         112s

pvcも試しに見てみると無事にBoundになっており、それぞれバインドされていることが確認できます。

NAME                  STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
datadir-mycluster-0   Bound    pv0001   50Gi       RWX                           8m30s
datadir-mycluster-1   Bound    pv0002   50Gi       RWX                           8m30s
datadir-mycluster-2   Bound    pv0003   50Gi       RWX                           8m30s

構築した環境でMySQLを試してみる

せっかくなので構築した環境でMySQLを少し試してみます。

MySQLへログイン

まずは作成したMySQL Serverへログインをしてみます。

接続先のIPアドレスを確認

MySQLにログインするにあたり、接続先のIPアドレスを確認していきます。
Kubernetesクラスタ内から接続できる入り口としてServiceが展開されているので、そのCLUSTER-IPを確認します。

kubectl get service mycluster

#出力
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                  AGE
mycluster   ClusterIP   10.102.215.34   <none>        3306/TCP,33060/TCP,6446/TCP,6448/TCP,6447/TCP,6449/TCP   13m

ログイン実行

前述で確認したCLUSTER-IPを用いてログインを行います。
※mysqlコマンドでログインを試すため、Masterに一旦mysqlクライアントをインストールしております

mysql -h 10.102.215.34 -u root -p

上記コマンド実行後パスワードが求められるので、Sercret作成の際に使ったパスワードを入力すると、
無事にログインが完了してSQLコマンドを実行できるようになります。

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1159
Server version: 8.0.31 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

お試しで色々SQLを実行

とりあえずINSERTしたデータをSELECTできるところまで実行してみます。

-- DBの作成と指定
create database test_db;
use test_db;

-- テーブルの作成とデータの挿入
create table test_table(test_id int auto_increment not null primary key, test_text text not null);
insert into test_table (test_text) values('Hello MySQL Operator');

-- 挿入したデータの取得
select * from test_table;

-- 出力
+---------+----------------------+
| test_id | test_text            |
+---------+----------------------+
|       1 | Hello MySQL Operator |
+---------+----------------------+
1 row in set (0.00 sec)

無事にSQLコマンドが動作していることが確認できました。
以上で、MySQL Serverとして問題なく利用できることが確認できたかと思います。

おまけ:現在のSQL Serverのhostnameについて

最後にhostnameの取得を行ってみます。
MySQLでは以下コマンドでhostnameを取得することができます。

select @@hostname;

-- 出力
+-------------+
| @@hostname  |
+-------------+
| mycluster-0 |
+-------------+
1 row in set (0.00 sec)

mycluster-0というhostnameが取得できました。
このhostnameをkubectl get podsの結果と照らし合わせると、現在Workerのubuntu-kube02上のSQL Serverに入っているんだなと確認ができました。

kubectl get pods -o wide

# 出力
NAME                                READY   STATUS      RESTARTS      AGE   IP            NODE            NOMINATED NODE   READINESS GATES
mycluster-0                         2/2     Running     0             36m   10.244.2.49   ubuntu-kube02   <none>           2/2
mycluster-1                         2/2     Running     0             36m   10.244.1.39   ubuntu-kube03   <none>           2/2
mycluster-2                         2/2     Running     0             36m   10.244.2.48   ubuntu-kube02   <none>           2/2

最後に

今回構築していて気になったこと

途中でPVを作ってPVCとバインドをしているのですが、その際にストレージクラスの指定をしていませんでした。
なにかデフォルトのなにかが勝手に使用されるのかなと思いましたが、「kubectl get sc」をうっても特に出力はされませんでした。
問題なく動きはしたものの、ストレージクラスはなくても動くもの?なのかというところが疑問のままになりました。
(他パターン等で試したり、色々調べてみます)

感想

今回はMySQL Operatorについて構築をしてみた内容についてまとめました。
Kubernetesは触り始めて間もないため、実際は記事に書いてあるよりも苦労したところもありました。
Kubernetesは今後も使う機会がありそうなため、もう少し土台はしっかり学んでおければと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?