3.2. MySQL
3.2.1. 概要
OpenShift Online には、MySQL の実行用のコンテナーイメージがあります。このイメージでは、設定で指定されるユーザー名、パスワード、データベース名を基にデータベースサービスが提供されます。
3.2.2. バージョン
3.2.3. イメージ
RHEL 7 イメージは、Red Hat レジストリーから入手できます。
$ docker pull registry.access.redhat.com/rhscl/mysql-56-rhel7 $ docker pull registry.access.redhat.com/rhscl/mysql-57-rhel7
これらのイメージは、mysql
イメージストリームで使用することができます。
3.2.4. 設定および用途
3.2.4.1. データベースの初期化
共有ボリュームを初めて使用する場合には、データベース、データベースの管理ユーザー、MySQL root ユーザー (MYSQL_ROOT_PASSWORD
環境変数を指定した場合) が作成され、次に MySQL デーモンが起動します。その後、MySQL デーモンが起動します。別のコンテナーにボリュームを再アタッチする場合には、データベース、データベースユーザー、管理者ユーザーは作成されず、MySQL デーモンが開始されます。
以下のコマンドは、新しいデータベースの Pod を作成し、さらにコンテナー内で MySQL を実行します。
$ oc new-app \ -e MYSQL_USER=<username> \ -e MYSQL_PASSWORD=<password> \ -e MYSQL_DATABASE=<database_name> \ mysql:5.6
3.2.4.2. コンテナーでの MySQL コマンドの実行
OpenShift Online は Software Collections (SCL) を使用して、MySQL をインストールし、起動します。(デバッグ用に) 実行中のコンテナー内で MySQL コマンドを実行する場合には bash を使用して呼び出す必要があります。
これを実行するには、まず Pod 名を特定します。たとえば、現在のプロジェクトで Pod の一覧を表示できます。
$ oc get pods
次に、Pod に対してリモートシェルセッションを開始します。
$ oc rsh <pod>
コンテナーに入ると、必要な SCL が自動的に有効になります。
Bash シェルから mysql コマンドを実行し、MySQL の対話セッションを開始して通常の MySQL 操作が実行できるようになりました。たとえば、データベースユーザーとして認証するには、以下を実行します。
bash-4.2$ mysql -u $MYSQL_USER -p$MYSQL_PASSWORD -h $HOSTNAME $MYSQL_DATABASE Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 4 Server version: 5.6.37 MySQL Community Server (GPL) ... mysql>
完了したら、quit または exit を入力して MySQL セッションを終了します。
3.2.4.3. 環境変数
MySQL ユーザー名、パスワード、データベース名は、以下の環境変数で設定する必要があります。
変数名 | 説明 |
---|---|
| アプリケーションで使用するために作成されたデータベースユーザーのユーザー名を指定します。 |
|
|
|
|
| root ユーザーの任意のパスワード。これが設定されていない場合には、root アカウントにリモートログインできません。コンテナーからはいつでも、パスワードなしにローカル接続が可能です。 |
| Kubernetes が自動作成したサービスホストの変数 |
| Kubernetes が自動作成したサービスポートの変数 |
ユーザー名、パスワード、データベース名を指定する必要があります。この 3 つすべてを指定しない場合には、Pod は起動に失敗し、OpenShift Online は Pod の再起動を継続的に試行します。
MySQL 設定は、以下の環境変数で設定できます。
変数名 | 説明 | デフォルト |
---|---|---|
| テーブル名の保存および比較方法を設定します。 | 0 |
| クライアントが同時に接続可能な最大数 | 151 |
| 生成された文字列/中間文字列または 1 つのパケットの最大サイズ | 200M |
| FULLTEXT インデックスに含める文字の最小長 | 4 |
| FULLTEXT インデックスに含める文字の最大長 | 20 |
| ネイティブの AIO が壊れている場合に innodb_use_native_aio の設定値を制御します。 | 1 |
| 全スレッド用に開くテーブル数 | 400 |
| インデックスブロックに使用するバッファーサイズ | 利用可能メモリーの 10% |
| 分類に使用するバッファーサイズ | 256K |
| シーケンススキャンに使用するバッファーサイズ | 利用可能メモリーの 5% |
| InnoDB がテーブルやインデックスデータをキャッシュするバッファープールのサイズ | 利用可能メモリーの 50% |
| ロググループにある各ログファイルのサイズ | 利用可能メモリーの 15% |
| InnoDB がディスクのログファイルへの書き込みに使用するバッファーサイズ | 利用可能メモリーの 15% |
メモリー関連のパラメーターの一部には、デフォルトとしてパーセンテージがあります。これらの値は、メモリー制限 に基づいてコンテナーの起動中に動的に計算されます。
3.2.4.4. ボリュームのマウントポイント
MySQL イメージは、マウントしたボリュームで実行して、データベース用に永続ストレージを有効化できます。
- /var/lib/mysql/data: これは、MySQL がデータベースのファイルを保存するデータディレクトリーです。
3.2.4.5. パスワードの変更
パスワードはイメージ設定の一部であるため、データベースユーザー (MYSQL_USER
) と root ユーザーのパスワードを変更する唯一のサポートされている方法として、環境変数 MYSQL_PASSWORD
と MYSQL_ROOT_PASSWORD
をそれぞれ変更することができます。
現在のパスワードは、Pod またはデプロイメント設定を Web コンソールで表示するか、CLI で環境変数を表示して、確認できます。
$ oc set env pod <pod_name> --list
MYSQL_ROOT_PASSWORD
が設定されている場合は常に、root ユーザーに特定のパスワードを指定してリモートアクセスを有効にできます。また、この設定が解除されている場合は常に、root ユーザーのリモートアクセスが無効になります。これは、常にリモートアクセスのある通常ユーザー MYSQL_USER
には影響がありません。これは、root ユーザーのローカルアクセスに影響を与えず、このユーザーは localhost でパスワードなしにいつでもログインできます。
SQL ステートメントや、前述した環境変数以外の方法でデータベースのパスワードを変更すると、変数に保存されている値と、実際のパスワードが一致しなくなる可能性があります。データベースコンテナーが起動するたびに、パスワードは環境変数に保存されている値にリセットされます。
これらのパスワードを変更するには、oc set env
コマンドを使用して、関連するデプロイメント設定の任意の環境変数 1 つまたは両方を更新します。たとえば、テンプレートからアプリケーションを作成する場合など、複数のデプロイメント設定がこれらの環境変数を使用する場合には、デプロイメント設定ごとに変数を更新し、パスワードがどこでも同期されるようにします。これは、すべて同じコマンドで実行できます。
$ oc set env dc <dc_name> [<dc_name_2> ...] \ MYSQL_PASSWORD=<new_password> \ MYSQL_ROOT_PASSWORD=<new_root_password>
アプリケーションによっては、アプリケーションの他の場所にあるパスワードの他の環境変数を更新して一致させる必要があるものもあります。たとえば、フロントエンド Pod のより一般的な DATABASE_USER
変数などは、データベースユーザーのパスワードと一致する必要がある場合があります。必要とされる環境変数すべてにおいて、パスワードがアプリケーションごとに一致しているようにしてください。 一致しない場合には、トリガーされた時点で、Pod の再デプロイメントが失敗する場合があります。
設定変更トリガーが設定されている場合には、環境変数を更新すると、データベースサーバーの再デプロイメントがトリガーされます。設定されていない場合には、新しいデプロイメントを手動で起動して、パスワードの変更を適用する必要があります。
新規パスワードが有効になっていることを確認するには、まず実行中の MySQL Pod に対してリモートシェルセッションを開きます。
$ oc rsh <pod>
Bash シェルから、データベースユーザーの新規パスワードを確認します。
bash-4.2$ mysql -u $MYSQL_USER -p<new_password> -h $HOSTNAME $MYSQL_DATABASE -te "SELECT * FROM (SELECT database()) db CROSS JOIN (SELECT user()) u"
パスワードが正しく変更された場合には、以下のような表が表示されるはずです。
+------------+---------------------+ | database() | user() | +------------+---------------------+ | sampledb | user0PG@172.17.42.1 | +------------+---------------------+
root ユーザーの新規パスワードを確認するには、以下を実行します。
bash-4.2$ mysql -u root -p<new_root_password> -h $HOSTNAME $MYSQL_DATABASE -te "SELECT * FROM (SELECT database()) db CROSS JOIN (SELECT user()) u"
パスワードが正しく変更された場合には、以下のような表が表示されるはずです。
+------------+------------------+ | database() | user() | +------------+------------------+ | sampledb | root@172.17.42.1 | +------------+------------------+
3.2.5. テンプレートからのデータベースサービスの作成
OpenShift Online には テンプレートが含まれており、新規データベースサービスの作成を簡素化します。テンプレートには、必須の環境変数をすべて定義するパラメーターフィールドがあり (ユーザー、パスワード、データベース名など)、自動生成されたパスワード値など、事前定義済みのデフォルト値が設定されます。また、テンプレートは デプロイメント設定 および サービス の両方を定義します。
MySQL テンプレートは、クラスターの初期設定時にクラスター管理者により、デフォルトの openshift プロジェクトに登録しておく必要があります。
以下のテンプレートを使用できます。
-
mysql-persistent
は、データベースのデータ用に永続ボリュームストアを使用するので、データは Pod が再起動されても残ります。
この説明に従い、テンプレートをインスタンス化できます。
サービスをインスタンス化したら、データベースにアクセスする予定のある別のコンポーネントのデプロイメント設定に、ユーザー名、パスワード、データベース名の環境変数をコピーできます。このコンポーネントは、定義したサービスを使用してこのデータベースにアクセスできます。
3.2.5.1. MySQL マスターのデプロイメント設定の作成
MySQL レプリケーションを設定するには、デプロイメント設定 を、レプリケーションコントローラー を定義するテンプレート例に定義します。MySQL のマスターとスレーブレプリケーションには、デプロイメント設定が 2 つ必要です。1 つ目のデプロイメント設定では、MySQL マスター サーバーを、2 つ目で MySQL スレーブ サーバーを定義します。
MySQL サーバーに対してマスターとして機能するように指示するには、デプロイメント設定のコンテナー定義にある command
フィールドに、run-mysqld-master を設定する必要があります。このスクリプトは、MySQL イメージの別のエントリーポイントとして機能し、MySQL サーバーがレプリケーションのマスターとして実行するように設定します。
MySQL レプリケーションでは、マスターとスレーブ間のデータをリレーする特別ユーザーが必要です。この目的で使用できるように、以下の環境変数をテンプレートに定義します。
変数名 | 説明 | デフォルト |
---|---|---|
| レプリケーションユーザーのユーザー名 | master |
| レプリケーションユーザーのパスワード | generated |
例3.1 サンプルテンプレートでの MySQL マスターデプロイメント設定のオブジェクト定義
kind: "DeploymentConfig" apiVersion: "v1" metadata: name: "mysql-master" spec: strategy: type: "Recreate" triggers: - type: "ConfigChange" replicas: 1 selector: name: "mysql-master" template: metadata: labels: name: "mysql-master" spec: volumes: - name: "mysql-master-data" persistentVolumeClaim: claimName: "mysql-master" containers: - name: "server" image: "openshift/mysql-56-centos7" command: - "run-mysqld-master" ports: - containerPort: 3306 protocol: "TCP" env: - name: "MYSQL_MASTER_USER" value: "${MYSQL_MASTER_USER}" - name: "MYSQL_MASTER_PASSWORD" value: "${MYSQL_MASTER_PASSWORD}" - name: "MYSQL_USER" value: "${MYSQL_USER}" - name: "MYSQL_PASSWORD" value: "${MYSQL_PASSWORD}" - name: "MYSQL_DATABASE" value: "${MYSQL_DATABASE}" - name: "MYSQL_ROOT_PASSWORD" value: "${MYSQL_ROOT_PASSWORD}" volumeMounts: - name: "mysql-master-data" mountPath: "/var/lib/mysql/data" resources: {} terminationMessagePath: "/dev/termination-log" imagePullPolicy: "IfNotPresent" securityContext: capabilities: {} privileged: false restartPolicy: "Always" dnsPolicy: "ClusterFirst"
デプロイメント設定を作成し、MySQL マスターサーバーが指定された Pod を起動した後には、MYSQL_DATABASE
で定義されたデータベースが作成され、このデータベースをスレーブに複製するようにサーバーが設定されます。
提供されているサンプルでは、MySQL マスターサーバーのレプリカ 1 つのみが定義されています。これにより、OpenShift Online はサーバーの 1 つのインスタンスのみを起動します。複数のインスタンス (multi-master) はサポートされません。そのため、このレプリケーションコントローラーをスケーリングすることはできません。
テンプレートにデプロイメント設定を定義して、MySQL マスターで作成したデータベースを複製します。このデプロイメント設定は、command
フィールドが run-mysqld-slave に設定されている、MySQL イメージを起動するレプリケーションコントローラーを作成します。このもう 1 つのエントリーポイントでは、データベースの初期化をスキップし、MySQL サーバーが mysql-master サービスに接続するように設定します。 これについても、サンプルのテンプレートに定義されています。
例3.2 サンプルテンプレートでの MySQL スレーブデプロイメント設定のオブジェクト定義
kind: "DeploymentConfig" apiVersion: "v1" metadata: name: "mysql-slave" spec: strategy: type: "Recreate" triggers: - type: "ConfigChange" replicas: 1 selector: name: "mysql-slave" template: metadata: labels: name: "mysql-slave" spec: containers: - name: "server" image: "openshift/mysql-56-centos7" command: - "run-mysqld-slave" ports: - containerPort: 3306 protocol: "TCP" env: - name: "MYSQL_MASTER_USER" value: "${MYSQL_MASTER_USER}" - name: "MYSQL_MASTER_PASSWORD" value: "${MYSQL_MASTER_PASSWORD}" - name: "MYSQL_DATABASE" value: "${MYSQL_DATABASE}" resources: {} terminationMessagePath: "/dev/termination-log" imagePullPolicy: "IfNotPresent" securityContext: capabilities: {} privileged: false restartPolicy: "Always" dnsPolicy: "ClusterFirst"
このデプロイメント設定のサンプルでは、最初のレプリカ数を 1 に設定して、レプリケーションコントローラーを開始します。アカウントのリソース容量に達するまで、両方向にこのレプリケーションコントローラーをスケーリングできます。
3.2.5.2. ヘッドレスサービスの作成
MySQL スレーブのレプリケーションコントローラーで作成した Pod は、レプリケーションを登録するために、MySQL マスターサーバーに到達する必要があります。この目的のために、サンプルテンプレートでは、mysql-master と呼ばれるヘッドレスサービスを定義します。このサービスは、レプリケーションだけに使用するのではなく、クライアントは MySQL ホストとして mysql-master:3306 にクエリーも送信します。
ヘッドレスサービスを含めるには、サービス定義の clusterIP
パラメーターを None に設定します。このように設定すると、DNS クエリーを使用して、このサービスの現在のエンドポイントを表す Pod の IP アドレス一覧を取得できるようになります。
例3.3 サンプルテンプレートでのヘッドレスサービスのオブジェクト定義
kind: "Service" apiVersion: "v1" metadata: name: "mysql-master" labels: name: "mysql-master" spec: ports: - protocol: "TCP" port: 3306 targetPort: 3306 nodePort: 0 selector: name: "mysql-master" clusterIP: "None" type: "ClusterIP" sessionAffinity: "None" status: loadBalancer: {}
3.2.5.3. MySQL スレーブのスケーリング
クラスターのメンバー数を増やすには、以下を実行します。
$ oc scale rc mysql-slave-1 --replicas=<number>
このコマンドは、レプリケーションコントローラーに対して、新しい MySQL スレーブ Pod を作成するように指示します。新しいスレーブが作成されると、スレーブのエントリーポイントが最初に mysql-master サービスに問い合わせして、レプリケーションセットに登録しようとします。これが完了すると、MySQL マスターサーバーはスレーブに複製されたデータベースを送信します。
スケールダウン時には、MySQL スレーブがシャットダウンされ、スレーブに永続ストレージが定義されていないので、スレーブ上の全データが失われます。MySQL マスターサーバーは、スレーブに到達できないことを検出し、自動的にレプリケーションからそのスレーブを取り除きます。
3.2.6. トラブルシューティング
以下のセクションでは、発生する可能性のある問題と、考えられる解決策を説明します。
3.2.6.1. Linux ネイティブの AIO の障害
現象
MySQL コンテナーが起動に失敗し、以下のようなログを出力します。
151113 5:06:56 InnoDB: Using Linux native AIO 151113 5:06:56 InnoDB: Warning: io_setup() failed with EAGAIN. Will make 5 attempts before giving up. InnoDB: Warning: io_setup() attempt 1 failed. InnoDB: Warning: io_setup() attempt 2 failed. Waiting for MySQL to start ... InnoDB: Warning: io_setup() attempt 3 failed. InnoDB: Warning: io_setup() attempt 4 failed. Waiting for MySQL to start ... InnoDB: Warning: io_setup() attempt 5 failed. 151113 5:06:59 InnoDB: Error: io_setup() failed with EAGAIN after 5 attempts. InnoDB: You can disable Linux Native AIO by setting innodb_use_native_aio = 0 in my.cnf 151113 5:06:59 InnoDB: Fatal error: cannot initialize AIO sub-system 151113 5:06:59 [ERROR] Plugin 'InnoDB' init function returned error. 151113 5:06:59 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed. 151113 5:06:59 [ERROR] Unknown/unsupported storage engine: InnoDB 151113 5:06:59 [ERROR] Aborting
説明
MySQL のストレージエンジンは、リソース制限が原因で、カーネルの AIO (非同期 I/O) 機能を使用できませんでした。
解決策
環境変数 MYSQL_AIO
の値を 0
に設定して、AIO の使用を完全に停止します。今後のデプロイメントでは、この設定により MySQL の設定変数 innodb_use_native_aio
の値が 0
に指定されます。