Help us understand the problem. What is going on with this article?

Kubernetes: MySQL Operatorの動作検証

More than 1 year has passed since last update.

概要

 Operatorは、CoreOS社(2018年現在はRedHat社)が、2016年に管理者のもつアプリケーションのナレッジを、Kubernetesの拡張機能を活用しソフトウェアとしてプログラムするものとして、発表されました。Kubernetesでは、セルフヒーリングなどインフラストラクチャーの運用を自律化させるフレームワークが備わっています。このフレームワークを使ったOperatorを開発することでアプリケーションの運用を支援します。
 今回は、2018/7にv0.2.0が公開されたOracle社が提供するMySQL-Operatorの動作検証を行います。

検証環境

  • Kubernetes v1.10.0
  • minikube v0.28.2
  • Helm v2.9.1

事前準備

 MySQL-Operator はHelmをつかってデプロイするため、Helmのセットアップを行います。

$ helm init
...

$ kubectl get pod -n kube-system
NAME                                        READY     STATUS              RESTARTS   AGE
...
tiller-deploy-f9b8476d-79g5k                1/1       Running             0          6m

これにより、Kubernetesのkube-systemネームスペースにTaillerのPodがデプロイされます。

Operatorのデプロイ

 初めに公式のGitHubレポジトリからMySQL-Operatorをダウンロードします。

$ git clone https://github.com/oracle/mysql-operator.git
Cloning into 'mysql-operator'...
...

$ cd mysql-operator

次に、MySQL-Operatorをデプロイします。デプロイ先のデフォルトはmysql-operatorネームスペースになります。

$ kubectl create namespace mysql-operator
namespace "mysql-operator" created

$ helm install --name mysql-operator mysql-operator
NAME:   mysql-operator
LAST DEPLOYED: Sun Aug 12 19:40:33 2018
NAMESPACE: kube-system
STATUS: DEPLOYED

RESOURCES:
==> v1/ServiceAccount
NAME            SECRETS  AGE
mysql-operator  1        0s
mysql-agent     1        0s

==> v1beta1/CustomResourceDefinition
NAME                                   AGE
mysqlclusters.mysql.oracle.com         0s
mysqlbackups.mysql.oracle.com          0s
mysqlrestores.mysql.oracle.com         0s
mysqlbackupschedules.mysql.oracle.com  0s

==> v1beta1/ClusterRole
mysql-operator  0s
mysql-agent     0s

==> v1beta1/ClusterRoleBinding
NAME            AGE
mysql-agent     0s
mysql-operator  0s

==> v1beta1/Deployment
NAME            DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
mysql-operator  1        1        1           0          0s

==> v1/Pod(related)
NAME                             READY  STATUS   RESTARTS  AGE
mysql-operator-56cb675b7f-jr56r  0/1    Pending  0         0s


NOTES:
Thanks for installing the MySQL Operator.

Check if the operator is running with

kubectl -n mysql-operator get po

$ kubectl get pod -n mysql-operator
NAME                              READY     STATUS    RESTARTS   AGE
mysql-operator-56cb675b7f-jr56r   1/1       Running   0          3m

mysql-operator-XXXXXというPodがデプロイされていればデプロイ成功です。
MySQL-Operatorでは、次の4つのCRD(CustomResourceDefinition)がデプロイされます。

  • mysqlclusters.mysql.oracle.com
    MySQLのクラスタをコントロール (kind: Cluster)
  • mysqlbackups.mysql.oracle.com
    データのバックアップをコントロール (kind:Backup )
  • mysqlrestores.mysql.oracle.com
    データのリストアをコントロール (kind: Restore)
  • mysqlbackupschedules.mysql.oracle.com
    定期実行のバックアップスケジュールをコントロール (kind: BackupSchedule)

Operatorでは、こららのCRDを使いMySQLを操作していきます。

シンプルな構成のMySQLのデプロイ

 今回の検証では、defaultネームスペースにMySQLをデプロイします。
まずは、defaultネームスペースにServiceAccountとRoleBindingを設定します。以下のようなserviceaccount.yamlファイルを作成します。

serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mysql-agent
  namespace: default
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: mysql-agent
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: mysql-agent
subjects:
- kind: ServiceAccount
  name: mysql-agent
  namespace: default

定義したServiceAccountとRoleBindingをkubectlを使ってデプロイします。

$ kubectl create -f serviceaccount.yaml
serviceaccount "mysql-agent" created
rolebinding "mysql-agent" created

続いて、シンプルなMySQLのクラスタ構成を作るための定義を、以下のcluster.yamlファイルに作成します。

cluster.yaml
apiVersion: mysql.oracle.com/v1alpha1
kind: Cluster
metadata:
  name: my-app-db
  namespace: default

定義したClusterをkubectlを使ってデプロイします。

$ kubectl create -f cluster.yaml
mysqlcluster "my-app-db" created

$ kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
my-app-db-0   2/2       Running   0          17m
my-app-db-1   2/2       Running   0          2m
my-app-db-2   2/2       Running   0          1m

$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
my-app-db    ClusterIP   None         <none>        3306/TCP   19m
...

デプロイが成功すると、StatefulSetにて3つのPodが生成されます。また、Service(svc)には、各Podの名前をDNSへ登録するためのヘッドレスサービスmy-app-dが登録されています。

続いて、デプロイしたMySQLへアクセスしてみます。
MySQL Operatorのデフォルトでは、Rootパスワードは自動生成されているため、MySQLのRootパスワードを取得します。

$ kubectl get secret my-app-db-root-password -o jsonpath="{.data.password}" | base64 --decode
<Password>

取得したRootパスワードを使って、MySQLのテーブルにアクセスします。
アクセスには、mysqlコマンドを利用します。

$ kubectl run mysql-client --image=mysql:5.7 -it --rm --restart=Never -- mysql -h my-app-db -uroot -p<Password> -e 'SELECT 1'
mysql: [Warning] Using a password on the command line interface can be insecure.
+---+
| 1 |
+---+
| 1 |
+---+

デプロイしたMySQLを削除します。

$ kubectl delete -f cluster.yaml
mysqlcluster "my-app-db" deleted

Rootパスワード変更+PersistentVolume構成のMySQLのデプロイ

 次に、MySQLの以下の点をカスタマイズしデプロイします。

  • MySQLのRootパスワードを任意に変更
  • MySQLのデプロイ数を2つに変更
  • Multi-MasterモードのMySQLに変更
  • MySQLのデータ格納ディレクトリをPersistentVolumeを使用

まず、MySQLのRootパスワードを格納するSecretを作成します。

$ kubectl create secret generic mysql-root-user-secret --from-literal=password=hogehoge
secret "mysql-root-user-secret" created

次に、MySQLのYAMLをcluster-pv.yamlに作成します。

cluster-pv.yaml
apiVersion: mysql.oracle.com/v1alpha1
kind: Cluster
metadata:
  name: my-app-db
spec:
  rootPasswordSecret:
    name: mysql-root-user-secret
  members: 2
  multiMaster: true
  volumeClaimTemplate:
    metadata:
      name: data
    spec:
      storageClassName: standard
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi

spec. rootPasswordSecretに、先ほど作成したSecretを指定します。この指定により、MySQLのRootパスワードが任意に指定できます。
spec. membersには、MySQLのデプロイ数を指定します。ここではデプロイ数を2を設定しています。
spec.multiMasterにTrueを指定することで、Multi-MasterモードのMySQLとなります。
spec.volumeClaimTemplateには、MySQLのデータ格納ディレクトリの格納先となるPersistentVolumeを指定します。このvolumeClaimTemplateは、StatefulSetでPodが生成される際に、自動でPersistentVolumeClaimとPersistentVolumeを作成します。今回の検証では、minikubeを利用しているため、あらかじめminikubeに設定されているStorageClassのstandardをstorageClassNameに指定します。

作成したcluster-pv.yamlをデプロイします。

$ kubectl create -f cluster-pv.yaml
mysqlcluster "my-app-db" created

デプロイしたMySQLを確認します。

$ kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
my-app-db-0   2/2       Running   0          1m
my-app-db-1   1/2       Running   0          44s

$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
...
my-app-db    ClusterIP   None         <none>        3306/TCP   1m

$ kubectl get pvc
NAME               STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-my-app-db-0   Bound     pvc-d536b611-a04c-11e8-9566-080027ae26d3   1Gi        RWO            standard       2m
data-my-app-db-1   Bound     pvc-f115036f-a04c-11e8-9566-080027ae26d3   1Gi        RWO            standard       1m

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                      STORAGECLASS   REASON    AGE
pvc-d536b611-a04c-11e8-9566-080027ae26d3   1Gi        RWO            Delete           Bound     default/data-my-app-db-0   standard                 2m
pvc-f115036f-a04c-11e8-9566-080027ae26d3   1Gi        RWO            Delete           Bound     default/data-my-app-db-1   standard                 1m

MySQLのPodが2つと、データ格納のPersistentVolumeClaimとPersistentVolumeがデプロイされているのが確認できます。
さらに、kubectl describeコマンドでPodを確認してみます。

$ kubectl describe pod my-app-db-0
Name:           my-app-db-0
Namespace:      default
...
    Mounts:
      /var/lib/mysql from data (rw)
      /var/lib/mysql-agent from mysqlbackupvolume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from mysql-agent-token-9ztcv (ro)
...
Volumes:
  data:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  data-my-app-db-0
    ReadOnly:   false
  mysqlbackupvolume:
    Type:    EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:  
  mysql-agent-token-9ztcv:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  mysql-agent-token-9ztcv
    Optional:    false

my-app-db-0のPod内の/var/lib/mysqlが、自動生成されたPersistentVolumeClaimのdata-my-app-db-0を使ってPersistentVolumeをマウントしているのがわかります。
 以上で。Rootパスワード変更+PersistentVolume構成のMySQLがデプロイされました。

クリーンアップ

最初に、デプロイしたMySQLと自動生成されたPersistentVolumeClaim、PersistentVolumeを削除します。

$ kubectl delete -f cluster-pv.yaml
$ kubectl delete pvc --all
$ kubectl delete pv --all

次に、ServiceAccountとRoleBindingを削除します。

$ kubectl delete -f serviceaccount.yaml

最後に、MySQL Operatorとmysql-operatorネームスペースを削除します。

$ helm delete mysql-operator
$ kubectl delete ns mysql-operator

感想

 今回の動作検証では、MySQLのデプロイメントを行いました。MySQL Operatorにより、複雑なYAMLを作成しなくても容易にMySQLのクラスタ構成をデプロイすることが可能です。Operatorを使わず、クラスタ構成のMySQLのYAMLを作成しようとすると、インフラストラクチャーのナレッジとMySQLのナレッジの両方を身につける必要があります。しかし、MySQLが今すぐ欲しい、MySQLを利用するアプリケーションの開発に専念したい等、これらのナレッジをもった管理者が側にいれば良いのになぁと思うケースもあるでしょう。このような場合に、MySQL Operatorを使うと有効かと思います。
 このように、Operatorは管理者のナレッジを実現し、アプリケーションの運用を支援するソフトウェアになります。またOperatorのユーザや開発者が多くなりあらゆる運用のナレッジがOperatorに実装されるようになれば、これまで組織や管理者ごとにバラバラであった運用ナレッジを、世界中で共有することができるかも知れません。
 残念な点としては、MySQL Operatorはv0.2.0(2018/8現在)と開発がスタートしたばかりのため、以下の制限があるようです。今後の開発に期待します。

  • Maser-Slave構成が不完全
    MySQLのPodのデプロイは行われますが、Slaveの設定ができておらず、Master-Slave間のデータ同期が出来ません。
  • Backup/Restoreで指定できるバックアップ先のストレージはAmazon S3のみ
    今回検証で作成したcluster-pv.yamlspec. backupVolumeClaimTemplateを追加することで、Backup/Restoreで利用するためのPersistentVolume, PersistentVolumeClaimは自動生成できます(参照)。しかし、CRDのBackup/Restoreではサポートされていません。

参考情報

ysakashita
サーバ/ストレージからVM/Containerまでのインフラの管理技術を研究開発しています.SNIA-J( http://www.snia-j.org ) でも活動中.博士(情報科学),情報処理学会会員.
zlab
技術で新しい世界へシフトする。
https://zlab.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした