1
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をOpenShiftで使ってみた

Last updated at Posted at 2022-06-22

はじめに

MySQL Operator for Kubernetesは、MySQLをKubernetes上で稼働させるために各種存在するOperatorの1つで、Oracleにより開発されています。MySQL 8.0.29のリリースと共に、MySQL Operator for KubernetesがGAとなったことが発表されました。

MySQL Operator for Kubernetesを使用すると、InnoDBコンテナを複数個起動しInnoDBクラスターを構成すると共に、アプリケーションとInnoDBクラスタを接続するMySQL Routerもコンテナとして稼働させて、全体で高可用性環境を実現します。この環境をKubernetesのコンテナ管理とOperatorの機能を用いることで、環境の自動的なプロビジョニングが可能となります。

MySQL Operatorのインストール方法は、MySQL Operator GitHub Project PageのREADME.mdで説明されていますが、この公式ガイドそのままではOpenShiftでPodとして起動できないため、ここではOpenShiftにMySQL Operatorをインストールする追加の手順を含めて説明します。

前提

OpenShiftは、CodeReady Containersの2.4.1(Linux版)を使用します。これはOpenShift4.10.14に相当しますが、MySQL Operatorには前提とするKubernetesバージョンやOpenShiftバージョンは指定されていないので、より古いバージョンでも手順は同じかと思います。

$ crc version
CRC version: 2.4.1+b877358
OpenShift version: 4.10.14
Podman version: 4.0.2
$ oc get clusterversion
NAME      VERSION   AVAILABLE   PROGRESSING   SINCE   STATUS
version   4.10.14   True        False         20d     Cluster version is 4.10.14

インストール

MySQL Operatorのインストールは、Operator自身のインストールとInnoDBクラスターのインストールの2段階で行います。

また公式ガイドでは、インストール方法としてHelmを使用する方法と、kubectlコマンドを使用する方法それぞれ説明されていますが、ここではkubectl(正確にはoc)コマンドを使用した方法に沿って説明します。

MySQL OperatorとInnoDBクラスターは、それぞれ異なるProjectにインストールすることとします。MySQL Operator用にmysql-operator、InnoDBクラスター用にmysqlProjectを使用します。インストール手順の中で使用するdeploy-operator.yamlファイルには、MySQL Operatorが使用するnamespaceとしてmysql-operatorが直書きされているので、そのまま使用します。

Operatorインストール

CRDインストール

最初にMySQL Operatorが使用するCRD(Custom Resource Definition)をインストールします。公式ガイドのコマンドパラメータをそのまま使用します。

$ oc 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用Projectの作成

公式ガイドが提供するdeploy-operator.yamlには、Operatorの使用するClusterRoleとServiceAccountおよびそのロールへのClusterRoleBinding、そしてDeploymentとNamespaceが定義されています。Projectは作成してくれないので、このyamlをapplyする前にmysql-operator Projectを作成します。

$ oc new-project mysql-operator
Now using project "mysql-operator" on server "https://api.crc.testing:6443".

You can add applications to this project with the 'new-app' command. For example, try:

    oc new-app rails-postgresql-example

to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:

    kubectl create deployment hello-node --image=k8s.gcr.io/e2e-test-images/agnhost:2.33 -- /agnhost serve-hostname

MySQL Operatorインストール

この後、手順の通りdeploy-operator.yamlをapplyします。

$ oc 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
Warning: resource namespaces/mysql-operator is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by oc apply. oc apply should only be used on resources created declaratively by either oc create --save-config or oc apply. The missing annotation will be patched automatically.
namespace/mysql-operator configured
serviceaccount/mysql-operator-sa created
deployment.apps/mysql-operator created

先にProjectを作成済みであるため、NamespaceのところでWarningが出ていますが、気にせず進みます。これで、mysql-operator Deploymentが作成されたので、operator podが立ち上がるはずですが、いつまでたってもPodが起動する気配がありません。何が起きているかを知るためにEventを見てみましょう。

$ oc get event
LAST SEEN   TYPE      REASON              OBJECT                                 MESSAGE
7s          Warning   FailedCreate        replicaset/mysql-operator-586f9f5d5b   Error creating: pods "mysql-operator-586f9f5d5b-" is forbidden: unable to validate against any security context constraint: [provider "anyuid": Forbidden: not usable by user or serviceaccount, spec.containers[0].securityContext.runAsUser: Invalid value: 2: must be in the ranges: [1000640000, 1000649999], provider "nonroot": Forbidden: not usable by user or serviceaccount, provider "hostmount-anyuid": Forbidden: not usable by user or serviceaccount, provider "machine-api-termination-handler": Forbidden: not usable by user or serviceaccount, provider "hostnetwork": Forbidden: not usable by user or serviceaccount, provider "hostaccess": Forbidden: not usable by user or serviceaccount, provider "privileged": Forbidden: not usable by user or serviceaccount]
2m50s       Normal    ScalingReplicaSet   deployment/mysql-operator              Scaled up replica set mysql-operator-586f9f5d5b to 1

Operator Podが使用するServiceAccountに適切なSCCが設定されていないため、Podの作成でFailedCreateになっていました。これを解消するために、Podが使用するServiceAccountにSCCを付与します。各種SCCについてのエラーが出ていますが、ここではanyuidのみ設定すれば問題は解消します。

$ oc get serviceaccount
NAME                SECRETS   AGE
builder             2         9m30s
default             2         9m30s
deployer            2         9m30s
mysql-operator-sa   2         8m7s
$ oc get deployment mysql-operator -o custom-columns=NAME:metadata.name,ACCOUNT:spec.template.spec.serviceAccountName
NAME             ACCOUNT
mysql-operator   mysql-operator-sa
$ oc adm policy add-scc-to-user anyuid -z mysql-operator-sa
clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid added: "mysql-operator-sa"

しばらく待っていると、Podの作成が成功して、Operator Podが起動します。

$ oc get event
LAST SEEN   TYPE      REASON              OBJECT                                 MESSAGE
21s         Normal    Scheduled           pod/mysql-operator-586f9f5d5b-hsqck    Successfully assigned mysql-operator/mysql-operator-586f9f5d5b-hsqck to crc-m5qn9-master-0
19s         Normal    AddedInterface      pod/mysql-operator-586f9f5d5b-hsqck    Add eth0 [10.217.0.131/23] from openshift-sdn
19s         Normal    Pulling             pod/mysql-operator-586f9f5d5b-hsqck    Pulling image "mysql/mysql-operator:8.0.29-2.0.4"
7m57s       Warning   FailedCreate        replicaset/mysql-operator-586f9f5d5b   Error creating: pods "mysql-operator-586f9f5d5b-" is forbidden: unable to validate against any security context constraint: [provider "anyuid": Forbidden: not usable by user or serviceaccount, spec.containers[0].securityContext.runAsUser: Invalid value: 2: must be in the ranges: [1000640000, 1000649999], provider "nonroot": Forbidden: not usable by user or serviceaccount, provider "hostmount-anyuid": Forbidden: not usable by user or serviceaccount, provider "machine-api-termination-handler": Forbidden: not usable by user or serviceaccount, provider "hostnetwork": Forbidden: not usable by user or serviceaccount, provider "hostaccess": Forbidden: not usable by user or serviceaccount, provider "privileged": Forbidden: not usable by user or serviceaccount]
21s         Normal    SuccessfulCreate    replicaset/mysql-operator-586f9f5d5b   Created pod: mysql-operator-586f9f5d5b-hsqck
13m         Normal    ScalingReplicaSet   deployment/mysql-operator              Scaled up replica set mysql-operator-586f9f5d5b to 1
$ oc get pod
NAME                              READY   STATUS    RESTARTS   AGE
mysql-operator-586f9f5d5b-hsqck   1/1     Running   0          82s

InnoDBクラスターインストール

Operatorが立ち上がったので、続いてInnoDBクラスターをインストールします。ここでは公式ガイドに従い、3個のInnoDB Podと1個のMySQL Router Podを起動します。

クラスター用Projectの作成

InnoDBクラスターは、mysql Projectに作成することにしたので、ここでそのProjectを作成します。この後、管理者パスワード用のSecretや、InnoDBClusterリソースをこのProjectに作成します。

$ oc new-project mysql
Now using project "mysql" on server "https://api.crc.testing:6443".

You can add applications to this project with the 'new-app' command. For example, try:

    oc new-app rails-postgresql-example

to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:

    kubectl create deployment hello-node --image=k8s.gcr.io/e2e-test-images/agnhost:2.33 -- /agnhost serve-hostname

Secretの作成

まず、管理者用のパスワードをSecretに指定します。ガイドの通り管理ユーザをroot、パスワードをsakilaとしていますが、少なくともパスワードは変更すべきです。

$ oc create secret generic mypwds --from-literal=rootUser=root --from-literal=rootHost=% --from-literal=rootPassword="sakila"
secret/mypwds created

クラスターPodとrouter Podのインストール

InnoDBクラスターPodは、InnoDBClusterリソースの作成によりインストールできます。yaml定義は公式ガイドで提供されているものをそのまま使用し、InnoDB Pod3個、MySQL Router Pod1個含み、管理ユーザを先ほど作成したSecretの内容としたmyclusterクラスターが作成されます。

ガイドでは一旦ファイルmycluster.yamlに保存した後、そのファイルをoc applyコマンドに渡していますが、ここでは標準入力を使います。-fオプションのパラメータとしてハイフン '-'を指定することで、入力は標準入力となります。ガイドのyamlをコピー&ペーストして、Ctrl-Dで入力を終了します。

$ oc apply -f -
apiVersion: mysql.oracle.com/v2
kind: InnoDBCluster
metadata:
  name: mycluster
spec:
  secretName: mypwds
  tlsUseSelfSigned: true
  instances: 3
  router:
    instances: 1
^D
innodbcluster.mysql.oracle.com/mycluster created

これで、InnoDB PodのStatefulSet。MySQL RouterのDeploymentとReplicaSetおよびそれらのServiceが作成されますが、ここでもPodが立ち上がる気配はありません。MySQL Operatorのインストールと同様にEventを確認します。

$ oc get events --field-selector "type!=Normal"
LAST SEEN   TYPE      REASON         OBJECT                  MESSAGE
1s          Warning   FailedCreate   statefulset/mycluster   create Pod mycluster-0 in StatefulSet mycluster failed error: pods "mycluster-0" is forbidden: unable to validate against any security context constraint: [spec.initContainers[2].securityContext.capabilities.add: Invalid value: "DAC_OVERRIDE": capability may not be added, spec.initContainers[2].securityContext.capabilities.add: Invalid value: "SETGID": capability may not be added, spec.initContainers[2].securityContext.capabilities.add: Invalid value: "SETUID": capability may not be added, spec.initContainers[2].securityContext.capabilities.add: Invalid value: "SYS_NICE": capability may not be added, spec.initContainers[2].securityContext.capabilities.add: Invalid value: "SYS_RESOURCE": capability may not be added, spec.containers[1].securityContext.capabilities.add: Invalid value: "DAC_OVERRIDE": capability may not be added, spec.containers[1].securityContext.capabilities.add: Invalid value: "SETGID": capability may not be added, spec.containers[1].securityContext.capabilities.add: Invalid value: "SETUID": capability may not be added, spec.containers[1].securityContext.capabilities.add: Invalid value: "SYS_NICE": capability may not be added, spec.containers[1].securityContext.capabilities.add: Invalid value: "SYS_RESOURCE": capability may not be added, provider restricted: .spec.securityContext.fsGroup: Invalid value: []int64{27}: 27 is not an allowed group, spec.initContainers[0].securityContext.runAsUser: Invalid value: 0: must be in the ranges: [1000680000, 1000689999], spec.initContainers[1].securityContext.runAsUser: Invalid value: 27: must be in the ranges: [1000680000, 1000689999], spec.initContainers[2].securityContext.runAsUser: Invalid value: 27: must be in the ranges: [1000680000, 1000689999], spec.containers[0].securityContext.runAsUser: Invalid value: 27: must be in the ranges: [1000680000, 1000689999], spec.containers[1].securityContext.runAsUser: Invalid value: 27: must be in the ranges: [1000680000, 1000689999], provider "nonroot": Forbidden: not usable by user or serviceaccount, provider "hostmount-anyuid": Forbidden: not usable by user or serviceaccount, provider "machine-api-termination-handler": Forbidden: not usable by user or serviceaccount, provider "hostnetwork": Forbidden: not usable by user or serviceaccount, provider "hostaccess": Forbidden: not usable by user or serviceaccount, provider "privileged": Forbidden: not usable by user or serviceaccount]

Operatorと同様にSCCの問題がStatefulSet myclusterにあることがわかります。使用されているServiceAccountが存在することを確認し、SCCを付与します。ここでは、privileged SCCが必要となります。

$ oc get serviceaccount
NAME                   SECRETS   AGE
builder                2         25m
default                2         25m
deployer               2         25m
mycluster-sidecar-sa   2         21m
$ oc get statefulset mycluster -o custom-columns=NAME:metadata.name,ACCOUNT:spec.template.spec.serviceAccountName
NAME        ACCOUNT
mycluster   mycluster-sidecar-sa
$ oc adm policy add-scc-to-user privileged -z mycluster-sidecar-sa
clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid added: "mycluster-sidecar-sa"

これで、Podが起動します。

InnoDB Podは、デフォルトで100GBのRWO PVを使用します。つまり100GBのPVが合計3個必要となります。ここで使用しているCodeReady Containersでは、開発用途のPVがあらかじめ用意されているため特に手当は必要ありませんが、実際の環境では別途ストレージが必要となります。Podが使用するPVCがPVとbindできないとPodはPendingのままとなります。

$ oc get pvc
NAME                  STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
datadir-mycluster-0   Bound    pv0019   100Gi      RWO,ROX,RWX                   22m
datadir-mycluster-1   Bound    pv0012   100Gi      RWO,ROX,RWX                   21m
datadir-mycluster-2   Bound    pv0010   100Gi      RWO,ROX,RWX                   21m

最初は、InnoDB Podが3個。これが正常に起動した後、MySQL RouterのPodが1個上がります。InnoDB Podは、READINESS GATEを持っているので、これが2/2になると正常に稼働していることがわかります。その確認のためには、oc get podコマンドに-o wideオプションが必要です。

$ oc get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE                 NOMINATED NODE   READINESS GATES
mycluster-0                         2/2     Running   0          99m   10.217.0.165   crc-m5qn9-master-0   <none>           2/2
mycluster-1                         2/2     Running   0          99m   10.217.0.166   crc-m5qn9-master-0   <none>           2/2
mycluster-2                         2/2     Running   0          99m   10.217.0.167   crc-m5qn9-master-0   <none>           2/2
mycluster-router-8498dd4468-6lx6m   1/1     Running   0          97m   10.217.0.169   crc-m5qn9-master-0   <none>           <none>
$ oc get statefulset mycluster -o wide
NAME        READY   AGE    CONTAINERS      IMAGES
mycluster   3/3     100m   sidecar,mysql   mysql/mysql-operator:8.0.29-2.0.4,mysql/mysql-server:8.0.29

これで、MySQL OperatorおよびOperatorが制御するInnoDBクラスターがインストールできました。

稼働確認

クラスターが立ち上がったので、MySQLが機能していることを確認しましょう。

クラスターの状態

インストールの中で、InnoDB Podが3個RUNNINGであり、READY=2/2かつREADINESS GATE=2/2となりました。Podとしての正常性はこれで確認できるので、MySQL内部の状態を調べます。

クラスターの状態確認は、mysqlshコマンドを使用します。公式のガイドでは、mysqlsh用のPodを個別に立ち上げています。ガイドの中にも記載されている通りMySQLコンテナの中にもmysqlshはインストールされているので、ここではそれを使用しましょう。

InnoDB Podでmysqlshを実行して、クラスターのstatus()出力を確認します。InnoDB Podには、MySQLのコンテナとsidecarコンテナが稼働しているため、MySQLコンテナを指定する必要がある点に注意してください。まず、mycluster-0 Podのmysqlコンテナでmysqlshを実行します。

$ oc get pod
NAME                                READY   STATUS    RESTARTS   AGE
mycluster-0                         2/2     Running   0          32m
mycluster-1                         2/2     Running   0          32m
mycluster-2                         2/2     Running   0          32m
mycluster-router-8498dd4468-6lx6m   1/1     Running   0          29m
$ oc exec -it mycluster-0 -c mysql -- mysqlsh
Cannot set LC_ALL to locale en_US.UTF-8: No such file or directory
MySQL Shell 8.0.29

Copyright (c) 2016, 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 '\?' for help; '\quit' to exit.
 MySQL  JS >

クラスターに管理者IDで接続し、dba.getCluster().status()を実行します。ユーザrootのパスワードは、InnoDBクラスターのインストールで作成したSecretに記載したものを使用します。

 MySQL  JS > \c root@mycluster
Creating a session to 'root@mycluster'
Please provide the password for 'root@mycluster': ******
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 4555 (X protocol)
Server version: 8.0.29 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.
 MySQL  mycluster:33060+ ssl  JS > dba.getCluster().status()
{
    "clusterName": "mycluster", 
    "defaultReplicaSet": {
        "name": "default", 
        "primary": "mycluster-0.mycluster-instances.mysql.svc.cluster.local:3306", 
        "ssl": "REQUIRED", 
        "status": "OK", 
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", 
        "topology": {
            "mycluster-0.mycluster-instances.mysql.svc.cluster.local:3306": {
                "address": "mycluster-0.mycluster-instances.mysql.svc.cluster.local:3306", 
                "memberRole": "PRIMARY", 
                "mode": "R/W", 
                "readReplicas": {}, 
                "replicationLag": null, 
                "role": "HA", 
                "status": "ONLINE", 
                "version": "8.0.29"
            }, 
            "mycluster-1.mycluster-instances.mysql.svc.cluster.local:3306": {
                "address": "mycluster-1.mycluster-instances.mysql.svc.cluster.local:3306", 
                "memberRole": "SECONDARY", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "replicationLag": null, 
                "role": "HA", 
                "status": "ONLINE", 
                "version": "8.0.29"
            }, 
            "mycluster-2.mycluster-instances.mysql.svc.cluster.local:3306": {
                "address": "mycluster-2.mycluster-instances.mysql.svc.cluster.local:3306", 
                "memberRole": "SECONDARY", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "replicationLag": null, 
                "role": "HA", 
                "status": "ONLINE", 
                "version": "8.0.29"
            }
        }, 
        "topologyMode": "Single-Primary"
    }, 
    "groupInformationSourceMember": "mycluster-0.mycluster-instances.mysql.svc.cluster.local:3306"
}
 MySQL  mycluster:33060+ ssl  JS > \q
Bye!
bash-4.4$ exit
exit

クラスターの中では、各InnoDB Podはインスタンスと認識されています。StatefulSetであるPodは、pod DNSを介して<pod名>.<headless service名>.<namespace名>.svc.cluster.localとして識別されます。

この出力から、

  • クラスター全体のstatusがOKであること
  • クラスターには3つのインスタンスが登録され、それぞれONLINEであること
  • mycluster-0 PodがPRIMARYロールを持ちR/Wモードで稼働していること
  • それ以外のPodはSECONDARYロールを持ちR/Oモードで稼働していること

などがわかります。

MySQL DBへのアクセス

Podの状態とmysqlshを使用した確認では、外形的にMySQLが正常動作しているように見えました。ここでは実際にDBへのアクセスを行い、DBとしての機能が正常であることを確認しましょう。

ガイドでは、3306ポートをforwardして、OpenShiftの外部からDBにアクセスする方法が紹介されていましたが、ここではMySQL Router Podのmysqlコマンドを使用します。

$ oc get pod
NAME                                READY   STATUS    RESTARTS   AGE
mycluster-0                         2/2     Running   0          52m
mycluster-1                         2/2     Running   0          52m
mycluster-2                         2/2     Running   0          52m
mycluster-router-8498dd4468-6lx6m   1/1     Running   0          49m
$ oc exec -it mycluster-router-8498dd4468-6lx6m -- /bin/bash
bash-4.4$ mysql -uroot -p
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 15077
Server version: 8.0.29 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>

performance_schema DBでは、InnoDBクラスター関連のデータを管理しているので、そこからインスタンスメンバーについて調べてみましょう。

mysql> show databases;
+-------------------------------+
| Database                      |
+-------------------------------+
| information_schema            |
| mysql                         |
| mysql_innodb_cluster_metadata |
| performance_schema            |
| sys                           |
+-------------------------------+
5 rows in set (0.00 sec)

mysql> use performance_schema;  
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
mysql> select MEMBER_HOST,MEMBER_STATE,MEMBER_ROLE from replication_group_members;
+---------------------------------------------------------+--------------+-------------+
| MEMBER_HOST                                             | MEMBER_STATE | MEMBER_ROLE |
+---------------------------------------------------------+--------------+-------------+
| mycluster-1.mycluster-instances.mysql.svc.cluster.local | ONLINE       | SECONDARY   |
| mycluster-0.mycluster-instances.mysql.svc.cluster.local | ONLINE       | PRIMARY     |
| mycluster-2.mycluster-instances.mysql.svc.cluster.local | ONLINE       | SECONDARY   |
+---------------------------------------------------------+--------------+-------------+
3 rows in set (0.00 sec)

mysql> quit
Bye

DBの内容が表示され、DBが正常に機能していることがわかりました。

おわりに

MySQLの高可用性オプションとして提供されているInnoDBクラスターをOpenShift上に構築し、健全性の確認まで行いました。コンテナを使用することで、複数のInnoDBインスタンスの作成が一度に完了し、Operatorで自動管理されます。ここでは取り上げませんでしたが、InnoDB Podの配置を適切にノード上に分散させれば、仮想サーバで組んだInnoDBクラスターと同等の耐障害性も得られます。

Kubernetes上では主にstatelessなアプリケーションを中心に稼働が進んでいますが、こうしたコンテナ稼働を意識したDatabaseが普及して、statefulなアプリケーションでも利用が広がることを期待しています。

1
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
1
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?