このチュートリアルでは、Distributed Replicated Block Device(DRBD)と Compute Engine を使用して、MySQL 5.6 データベースを Google Cloud にデプロイする手順について説明します。DRBD は、Linux プラットフォームで使用される、レプリケーション対応の分散ストレージ システムです。
このチュートリアルは、システム管理者、デベロッパー、エンジニア、データベース管理者、または DevOps エンジニアの方を対象としています。以下のような理由から、マネージド サービスを使用する代わりに自分で MySQL インスタンスを管理することが必要になる場合があります。
- MySQL のクロスリージョン インスタンスを使用している。
- MySQL のマネージド バージョンでは利用できないパラメータを設定する必要がある。
- マネージド バージョンでは設定できない方法でパフォーマンスを最適化する必要がある。
DRBD のレプリケーションは、ブロック デバイスレベルで行われます。つまり、MySQL 自体でレプリケーションを構成しなくても、読み取りのロード バランシング サポートやセキュアな接続といった DRBD がもたらすメリットをすぐに得ることができます。
このチュートリアルでは以下の対象を使用します。
本書では、MySQL クラスタリング、DRBD 構成、Linux リソース管理などの高度な機能を参照しますが、上記のリソースを使用するにあたり高度な知識は必要ありません。
アーキテクチャ
Pacemaker はクラスタ リソース マネージャーです。Pacemaker は、Corosync というクラスタ通信および参加パッケージを使用します。このチュートリアルでは、DRBD を使用してプライマリ インスタンスの MySQL ディスクをスタンバイ インスタンスにレプリケートします。また、クライアントを MySQL クラスタに接続するために、内部ロードバランサもデプロイします。
このチュートリアルでデプロイする、Pacemaker で管理されるクラスタは、3 つのインスタンスからなります。そのうち、プライマリとスタンバイとして機能する 2 つのインスタンスに MySQL をインストールします。3 つ目のインスタンスはクォーラム デバイスとして機能します。
クラスタ内のアクティブ ノード(MySQL を実行するノード)は、各ノードによる投票で決定されます。2 ノードクラスタの場合、わずか 1 票の獲得でアクティブ ノードが決まります。この場合、クラスタの動作がスプリット ブレインの問題やダウンタイムにつながる可能性があります。スプリット ブレインの問題は、両方のノードが制御権を取得した場合に発生します。これは 2 ノードクラスタのシナリオでは、わずか 1 票の獲得で制御権が得られるためです。また、接続が失われた場合に常にプライマリとなるように構成されているノードがシャットダウンすると、ダウンタイムが発生します。2 つのノード間の接続が失われると、複数のクラスタノードが自身をアクティブ ノードとみなすリスクがあります。
こうした状況は、クォーラム デバイスを追加すると回避できます。クォーラム デバイスは、投票する役割だけを果たすアービターとして機能します。database1
インスタンスと database2
インスタンスが通信できない場合は、この役割のクォーラム デバイスノードが 2 つのノードのいずれかと通信できるため、過半数のノードとの通信が維持されます。
次の図は、ここで説明するシステムのアーキテクチャを示しています。
目標
- クラスタ インスタンスを作成する。
- MySQL と DRBD を 2 つのインスタンスにインストールする。
- DRBD レプリケーションを構成する。
- Pacemaker をインスタンスにインストールする。
- インスタンス上で Pacemaker クラスタリングを構成する。
- インスタンスを作成してクォーラム デバイスとして構成する。
- フェイルオーバーをテストする。
費用
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。
始める前に
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine API.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine API.
このチュートリアルでは、特に記載がない限り、Cloud Shell を使用してコマンドを入力します。
このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。
設定
このセクションでは、サービス アカウントの設定、環境変数の作成、IP アドレスの予約を行います。
クラスタ インスタンス用のサービス アカウントを設定する
Cloud Shell を開きます。
サービス アカウントを作成します。
gcloud iam service-accounts create mysql-instance \ --display-name "mysql-instance"
サービス アカウントに、このチュートリアルに必要なロールを付与します。
gcloud projects add-iam-policy-binding ${DEVSHELL_PROJECT_ID} \ --member=serviceAccount:mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --role=roles/compute.instanceAdmin.v1 gcloud projects add-iam-policy-binding ${DEVSHELL_PROJECT_ID} \ --member=serviceAccount:mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --role=roles/compute.viewer gcloud projects add-iam-policy-binding ${DEVSHELL_PROJECT_ID} \ --member=serviceAccount:mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --role=roles/iam.serviceAccountUser
Cloud Shell 環境変数を作成する
このチュートリアルに必要な環境変数を設定したファイルを作成します。
cat <<EOF > ~/.mysqldrbdrc # Cluster instance names DATABASE1_INSTANCE_NAME=database1 DATABASE2_INSTANCE_NAME=database2 QUORUM_INSTANCE_NAME=qdevice CLIENT_INSTANCE_NAME=mysql-client # Cluster IP addresses DATABASE1_INSTANCE_IP="10.140.0.2" DATABASE2_INSTANCE_IP="10.140.0.3" QUORUM_INSTANCE_IP="10.140.0.4" ILB_IP="10.140.0.6" # Cluster zones and region DATABASE1_INSTANCE_ZONE="asia-east1-a" DATABASE2_INSTANCE_ZONE="asia-east1-b" QUORUM_INSTANCE_ZONE="asia-east1-c" CLIENT_INSTANCE_ZONE="asia-east1-c" CLUSTER_REGION="asia-east1" EOF
現在のセッションで環境変数を読み込み、今後ログインするときに自動的に変数を読み込むように Cloud Shell を設定します。
source ~/.mysqldrbdrc grep -q -F "source ~/.mysqldrbdrc" ~/.bashrc || echo "source ~/.mysqldrbdrc" >> ~/.bashrc
IP アドレスを予約する
Cloud Shell で、3 つの各クラスタノード用に内部 IP アドレスを予約します。
gcloud compute addresses create ${DATABASE1_INSTANCE_NAME} ${DATABASE2_INSTANCE_NAME} ${QUORUM_INSTANCE_NAME} \ --region=${CLUSTER_REGION} \ --addresses "${DATABASE1_INSTANCE_IP},${DATABASE2_INSTANCE_IP},${QUORUM_INSTANCE_IP}" \ --subnet=default
Compute Engine インスタンスを作成する
次の手順では、クラスタ インスタンスは Debian 9 を使用し、クライアント インスタンスは Ubuntu 16 を使用します。
Cloud Shell で、
asia-east1-a
ゾーン内にdatabase1
という名前の MySQL インスタンスを作成します。gcloud compute instances create ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --machine-type=n1-standard-2 \ --network-tier=PREMIUM \ --maintenance-policy=MIGRATE \ --image-family=debian-9 \ --image-project=debian-cloud \ --boot-disk-size=50GB \ --boot-disk-type=pd-standard \ --boot-disk-device-name=${DATABASE1_INSTANCE_NAME} \ --create-disk=mode=rw,size=300,type=pd-standard,name=disk-1 \ --private-network-ip=${DATABASE1_INSTANCE_NAME} \ --tags=mysql --service-account=mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --scopes="https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly" \ --metadata="DATABASE1_INSTANCE_IP=${DATABASE1_INSTANCE_IP},DATABASE2_INSTANCE_IP=${DATABASE2_INSTANCE_IP},DATABASE1_INSTANCE_NAME=${DATABASE1_INSTANCE_NAME},DATABASE2_INSTANCE_NAME=${DATABASE2_INSTANCE_NAME},QUORUM_INSTANCE_NAME=${QUORUM_INSTANCE_NAME},DATABASE1_INSTANCE_ZONE=${DATABASE1_INSTANCE_ZONE},DATABASE2_INSTANCE_ZONE=${DATABASE2_INSTANCE_ZONE}"
asia-east1-b
ゾーン内にdatabase2
という名前の MySQL インスタンスを作成します。gcloud compute instances create ${DATABASE2_INSTANCE_NAME} \ --zone=${DATABASE2_INSTANCE_ZONE} \ --machine-type=n1-standard-2 \ --network-tier=PREMIUM \ --maintenance-policy=MIGRATE \ --image-family=debian-9 \ --image-project=debian-cloud \ --boot-disk-size=50GB \ --boot-disk-type=pd-standard \ --boot-disk-device-name=${DATABASE2_INSTANCE_NAME} \ --create-disk=mode=rw,size=300,type=pd-standard,name=disk-2 \ --private-network-ip=${DATABASE2_INSTANCE_NAME} \ --tags=mysql \ --service-account=mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --scopes="https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly" \ --metadata="DATABASE1_INSTANCE_IP=${DATABASE1_INSTANCE_IP},DATABASE2_INSTANCE_IP=${DATABASE2_INSTANCE_IP},DATABASE1_INSTANCE_NAME=${DATABASE1_INSTANCE_NAME},DATABASE2_INSTANCE_NAME=${DATABASE2_INSTANCE_NAME},QUORUM_INSTANCE_NAME=${QUORUM_INSTANCE_NAME},DATABASE1_INSTANCE_ZONE=${DATABASE1_INSTANCE_ZONE},DATABASE2_INSTANCE_ZONE=${DATABASE2_INSTANCE_ZONE}"
asia-east1-c
ゾーン内に Pacemaker で使用するクォーラム ノードを作成します。gcloud compute instances create ${QUORUM_INSTANCE_NAME} \ --zone=${QUORUM_INSTANCE_ZONE} \ --machine-type=n1-standard-1 \ --network-tier=PREMIUM \ --maintenance-policy=MIGRATE \ --image-family=debian-9 \ --image-project=debian-cloud \ --boot-disk-size=10GB \ --boot-disk-type=pd-standard \ --boot-disk-device-name=${QUORUM_INSTANCE_NAME} \ --private-network-ip=${QUORUM_INSTANCE_NAME}
MySQL クライアント インスタンスを作成します。
gcloud compute instances create ${CLIENT_INSTANCE_NAME} \ --image-family=ubuntu-1604-lts \ --image-project=ubuntu-os-cloud \ --tags=mysql-client \ --zone=${CLIENT_INSTANCE_ZONE} \ --boot-disk-size=10GB \ --metadata="ILB_IP=${ILB_IP}"
DRBD のインストールと構成
このセクションでは、DRBD パッケージを database1
インスタンスと database2
インスタンスにインストールして構成した後、database1
から database2
への DRBD レプリケーションを開始します。
database1 上に DRBD を構成する
Google Cloud コンソールで、[VM インスタンス] ページに移動します。
database1
インスタンスの行で、[SSH] をクリックしてインスタンスに接続します。インスタンス メタデータを取得して環境変数に格納するためのファイルを作成します。
sudo bash -c cat <<EOF > ~/.varsrc DATABASE1_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_IP" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_IP" -H "Metadata-Flavor: Google") DATABASE1_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_NAME" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_NAME" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_ZONE" -H "Metadata-Flavor: Google") DATABASE1_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_ZONE" -H "Metadata-Flavor: Google") QUORUM_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/QUORUM_INSTANCE_NAME" -H "Metadata-Flavor: Google") EOF
ファイルからメタデータ変数を読み込みます。
source ~/.varsrc
データディスクをフォーマットします。
sudo bash -c "mkfs.ext4 -m 0 -F -E \ lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb"
mkfs.ext4
オプションについて詳しくは、mkfs.ext4 のマニュアル ページをご覧ください。DRBD をインストールします。
sudo apt -y install drbd8-utils
DRBD 構成ファイルを作成します。
sudo bash -c 'cat <<EOF > /etc/drbd.d/global_common.conf global { usage-count no; } common { protocol C; } EOF'
DRBD リソース ファイルを作成します。
sudo bash -c "cat <<EOF > /etc/drbd.d/r0.res resource r0 { meta-disk internal; device /dev/drbd0; net { allow-two-primaries no; after-sb-0pri discard-zero-changes; after-sb-1pri discard-secondary; after-sb-2pri disconnect; rr-conflict disconnect; } on database1 { disk /dev/sdb; address 10.140.0.2:7789; } on database2 { disk /dev/sdb; address 10.140.0.3:7789; } } EOF"
DRBD カーネル モジュールを読み込みます。
sudo modprobe drbd
/dev/sdb
ディスクの内容を消去します。sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
DRBD リソース
r0
を作成します。sudo drbdadm create-md r0
DRBD を起動します。
sudo drbdadm up r0
システム起動時に DRBD を無効化して、クラスタ リソース管理ソフトウェアが必要なすべてのリソースを順に起動できるようにします。
sudo update-rc.d drbd disable
database2 上に DRBD を構成する
DRBD パッケージを database2
インスタンスにインストールして構成します。
- SSH を使用して
database2
インスタンスに接続します。 インスタンス メタデータを取得して環境変数に格納するための
.varsrc
ファイルを作成します。sudo bash -c cat <<EOF > ~/.varsrc DATABASE1_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_IP" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_IP" -H "Metadata-Flavor: Google") DATABASE1_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_NAME" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_NAME" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_ZONE" -H "Metadata-Flavor: Google") DATABASE1_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_ZONE" -H "Metadata-Flavor: Google") QUORUM_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/QUORUM_INSTANCE_NAME" -H "Metadata-Flavor: Google") EOF
ファイルからメタデータ変数を読み込みます。
source ~/.varsrc
データディスクをフォーマットします。
sudo bash -c "mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb"
DRBD パッケージをインストールします。
sudo apt -y install drbd8-utils
DRBD 構成ファイルを作成します。
sudo bash -c 'cat <<EOF > /etc/drbd.d/global_common.conf global { usage-count no; } common { protocol C; } EOF'
DRBD リソース ファイルを作成します。
sudo bash -c "cat <<EOF > /etc/drbd.d/r0.res resource r0 { meta-disk internal; device /dev/drbd0; net { allow-two-primaries no; after-sb-0pri discard-zero-changes; after-sb-1pri discard-secondary; after-sb-2pri disconnect; rr-conflict disconnect; } on ${DATABASE1_INSTANCE_NAME} { disk /dev/sdb; address ${DATABASE1_INSTANCE_IP}:7789; } on ${DATABASE2_INSTANCE_NAME} { disk /dev/sdb; address ${DATABASE2_INSTANCE_IP}:7789; } } EOF"
DRBD カーネル モジュールを読み込みます。
sudo modprobe drbd
/dev/sdb
ディスクの内容を消去します。sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
DRBD リソース
r0
を作成します。sudo drbdadm create-md r0
DRBD を起動します。
sudo drbdadm up r0
システム起動時に DRBD を無効化して、クラスタ リソース管理ソフトウェアが必要なすべてのリソースを順に起動できるようにします。
sudo update-rc.d drbd disable
database1 から database2 への DRBD レプリケーションを開始する
- SSH を使用して
database1
インスタンスに接続します。 プライマリ ノード上のすべての
r0
リソースを上書きします。sudo drbdadm -- --overwrite-data-of-peer primary r0 sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/drbd0
DRBD のステータスを確認します。
sudo cat /proc/drbd | grep ============
出力は次のようになります。
[===================>] sync'ed:100.0% (208/307188)M
/dev/drbd
を/srv
にマウントするには:sudo mount -o discard,defaults /dev/drbd0 /srv
MySQL と Pacemaker をインストールする
このセクションでは、MySQL と Pacemaker を各インスタンスにインストールします。
MySQL を database1 にインストールする
- SSH を使用して
database1
インスタンスに接続します。 APT リポジトリを MySQL 5.6 パッケージ定義で更新します。
sudo bash -c 'cat <<EOF > /etc/apt/sources.list.d/mysql.list deb http://repo.mysql.com/apt/debian/ stretch mysql-5.6\ndeb-src http://repo.mysql.com/apt/debian/ stretch mysql-5.6 EOF'
GPG キーを APT
repository.srv
ファイルに追加します。wget -O /tmp/RPM-GPG-KEY-mysql https://repo.mysql.com/RPM-GPG-KEY-mysql sudo apt-key add /tmp/RPM-GPG-KEY-mysql
パッケージ リストを更新します。
sudo apt update
MySQL サーバーをインストールします。
sudo apt -y install mysql-server
パスワードの入力を求められたら、「
DRBDha2
」と入力します。MySQL サーバーを停止します。
sudo /etc/init.d/mysql stop
MySQL 構成ファイルを作成します。
sudo bash -c 'cat <<EOF > /etc/mysql/mysql.conf.d/my.cnf [mysqld] bind-address = 0.0.0.0 # You may want to listen at localhost at the beginning datadir = /var/lib/mysql tmpdir = /srv/tmp user = mysql EOF'
MySQL サーバー(
mysql.conf
内に構成されている)の一時ディレクトリを作成します。sudo mkdir /srv/tmp sudo chmod 1777 /srv/tmp
すべての MySQL データを DRBD ディレクトリ
/srv/mysql
に移動します。sudo mv /var/lib/mysql /srv/mysql
/var/lib/mysql
を、DRBD でレプリケートされたストレージ ボリューム内の/srv/mysql
にリンクします。sudo ln -s /srv/mysql /var/lib/mysql
/srv/mysql
のオーナーをmysql
プロセスに変更します。sudo chown -R mysql:mysql /srv/mysql
InnoDB
の初期データを削除して、ディスクを可能な限りクリーンな状態にします。sudo bash -c "cd /srv/mysql && rm ibdata1 && rm ib_logfile*"
InnoDB は、MySQL データベース管理システムのストレージ エンジンです。
MySQL を起動します。
sudo /etc/init.d/mysql start
後でデプロイをテストできるよう、root ユーザーにリモート接続の権限を付与します。
mysql -uroot -pDRBDha2 -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'DRBDha2' WITH GRANT OPTION;"
クラスタ リソース管理によって行われる MySQL の自動起動を無効化します。
sudo update-rc.d -f mysql disable
Pacemaker を database1 にインストールする
前に作成した
.varsrc
ファイルからメタデータ変数を読み込みます。source ~/.varsrc
MySQL サーバーを停止します。
sudo /etc/init.d/mysql stop
Pacemaker をインストールします。
sudo apt -y install pcs
システムの起動時にプライマリ インスタンス上で
pcsd
、corosync
、pacemaker
を有効化します。sudo update-rc.d -f pcsd enable sudo update-rc.d -f corosync enable sudo update-rc.d -f pacemaker enable
pacemaker
を起動する前に、corosync
を構成します。sudo update-rc.d corosync defaults 20 20 sudo update-rc.d pacemaker defaults 30 10
認証用のクラスタ ユーザー パスワード(
haCLUSTER3
)を設定します。sudo bash -c "echo hacluster:haCLUSTER3 | chpasswd"
corosync-keygen
スクリプトを実行します。これにより、128 ビットのクラスタ認証キーが生成されて/etc/corosync/authkey
に書き込まれます。sudo corosync-keygen -l
authkey
をdatabase2
インスタンスにコピーします。パスフレーズの入力を求められたら、Enter
キーを押します。sudo chmod 444 /etc/corosync/authkey gcloud beta compute scp /etc/corosync/authkey ${DATABASE2_INSTANCE_NAME}:~/authkey --zone=${DATABASE2_INSTANCE_ZONE} --internal-ip sudo chmod 400 /etc/corosync/authkey
Corosync クラスタ構成ファイルを作成します。
sudo bash -c "cat <<EOF > /etc/corosync/corosync.conf totem { version: 2 cluster_name: mysql_cluster transport: udpu interface { ringnumber: 0 Bindnetaddr: ${DATABASE1_INSTANCE_IP} broadcast: yes mcastport: 5405 } } quorum { provider: corosync_votequorum two_node: 1 } nodelist { node { ring0_addr: ${DATABASE1_INSTANCE_NAME} name: ${DATABASE1_INSTANCE_NAME} nodeid: 1 } node { ring0_addr: ${DATABASE2_INSTANCE_NAME} name: ${DATABASE2_INSTANCE_NAME} nodeid: 2 } } logging { to_logfile: yes logfile: /var/log/corosync/corosync.log timestamp: on } EOF"
totem
セクションでは、信頼性の高い通信を確保するために Totem プロトコルを構成しています。Corosync はこの通信を使用してクラスタ メンバーシップを制御し、クラスタ メンバー間の通信方法を指定します。このセットアップでの重要な設定は次のとおりです。
transport
: ユニキャスト モード(udpu)を指定します。Bindnetaddr
: Corosync のバインド先のネットワーク アドレスを指定します。nodelist
: クラスタ内の特定のノードへの通信方法を定義します。この例では、database1
ノードとdatabase2
ノードへの通信方法を定義しています。quorum
/two_node
: デフォルトでは、2 ノードクラスタ内のノードはどちらもクォーラムを獲得しません。これをオーバーライドするには、quorum
セクション内のtwo_node
に値「1」を指定します。
この設定により、クラスタを構成して、今後 3 つ目のノードをクォーラム デバイスとして追加するときに備えることができます。
corosync
用のサービス ディレクトリを作成します。sudo mkdir -p /etc/corosync/service.d
Pacemaker を認識するように
corosync
を構成します。sudo bash -c 'cat <<EOF > /etc/corosync/service.d/pcmk service { name: pacemaker ver: 1 } EOF'
デフォルトで
corosync
サービスを有効化します。sudo bash -c 'cat <<EOF > /etc/default/corosync # Path to corosync.conf COROSYNC_MAIN_CONFIG_FILE=/etc/corosync/corosync.conf # Path to authfile COROSYNC_TOTEM_AUTHKEY_FILE=/etc/corosync/authkey # Enable service by default START=yes EOF'
corosync
サービスとpacemaker
サービスを再起動します。sudo service corosync restart sudo service pacemaker restart
Corosync クォーラム デバイス パッケージをインストールします。
sudo apt -y install corosync-qdevice
DRBD の障害イベントを処理するシェル スクリプトをインストールします。
sudo bash -c 'cat << 'EOF' > /var/lib/pacemaker/drbd_cleanup.sh #!/bin/sh if [ -z \$CRM_alert_version ]; then echo "\$0 must be run by Pacemaker version 1.1.15 or later" exit 0 fi tstamp="\$CRM_alert_timestamp: " case \$CRM_alert_kind in resource) if [ \${CRM_alert_interval} = "0" ]; then CRM_alert_interval="" else CRM_alert_interval=" (\${CRM_alert_interval})" fi if [ \${CRM_alert_target_rc} = "0" ]; then CRM_alert_target_rc="" else CRM_alert_target_rc=" (target: \${CRM_alert_target_rc})" fi case \${CRM_alert_desc} in Cancelled) ;; *) echo "\${tstamp}Resource operation "\${CRM_alert_task}\${CRM_alert_interval}" for "\${CRM_alert_rsc}" on "\${CRM_alert_node}": \${CRM_alert_desc}\${CRM_alert_target_rc}" >> "\${CRM_alert_recipient}" if [ "\${CRM_alert_task}" = "stop" ] && [ "\${CRM_alert_desc}" = "Timed Out" ]; then echo "Executing recovering..." >> "\${CRM_alert_recipient}" pcs resource cleanup \${CRM_alert_rsc} fi ;; esac ;; *) echo "\${tstamp}Unhandled \$CRM_alert_kind alert" >> "\${CRM_alert_recipient}" env | grep CRM_alert >> "\${CRM_alert_recipient}" ;; esac EOF' sudo chmod 0755 /var/lib/pacemaker/drbd_cleanup.sh sudo touch /var/log/pacemaker_drbd_file.log sudo chown hacluster:haclient /var/log/pacemaker_drbd_file.log
MySQL を database2 にインストールする
- SSH を使用して
database2
インスタンスに接続します。 APT リポジトリを MySQL 5.6 パッケージで更新します。
sudo bash -c 'cat <<EOF > /etc/apt/sources.list.d/mysql.list deb http://repo.mysql.com/apt/debian/ stretch mysql-5.6\ndeb-src http://repo.mysql.com/apt/debian/ stretch mysql-5.6 EOF'
GPG キーを APT リポジトリに追加します。
wget -O /tmp/RPM-GPG-KEY-mysql https://repo.mysql.com/RPM-GPG-KEY-mysql sudo apt-key add /tmp/RPM-GPG-KEY-mysql
パッケージ リストを更新します。
sudo apt update
MySQL サーバーをインストールします。
sudo apt -y install mysql-server
パスワードの入力を求められたら、「
DRBDha2
」と入力します。MySQL サーバーを停止します。
sudo /etc/init.d/mysql stop
MySQL 構成ファイルを作成します。
sudo bash -c 'cat <<EOF > /etc/mysql/mysql.conf.d/my.cnf [mysqld] bind-address = 0.0.0.0 # You may want to listen at localhost at the beginning datadir = /var/lib/mysql tmpdir = /srv/tmp user = mysql EOF'
/var/lib/mysql
からデータを削除し、レプリケートされた DRBD ボリュームのマウント ポイント ターゲットへのシンボリック リンクを追加します。フェイルオーバーが発生した場合にのみ、DRBD ボリューム(/dev/drbd0
)が/srv
にマウントされます。sudo rm -rf /var/lib/mysql sudo ln -s /srv/mysql /var/lib/mysql
クラスタ リソース管理によって行われる MySQL の自動起動を無効化します。
sudo update-rc.d -f mysql disable
Pacemaker を database2 にインストールする
.varsrc
ファイルからメタデータ変数を読み込みます。source ~/.varsrc
Pacemaker をインストールします。
sudo apt -y install pcs
前にコピーした Corosync
authkey
ファイルを/etc/corosync/
に移動します。sudo mv ~/authkey /etc/corosync/ sudo chown root: /etc/corosync/authkey sudo chmod 400 /etc/corosync/authkey
システム起動時にスタンバイ インスタンス上で
pcsd
、corosync
、pacemaker
を有効化します。sudo update-rc.d -f pcsd enable sudo update-rc.d -f corosync enable sudo update-rc.d -f pacemaker enable
pacemaker
を起動する前に、corosync
を構成します。sudo update-rc.d corosync defaults 20 20 sudo update-rc.d pacemaker defaults 30 10
認証用のクラスタ ユーザー パスワードを設定します。このパスワードは、
database1
インスタンスに使用したもの(haCLUSTER3
)と同じです。sudo bash -c "echo hacluster:haCLUSTER3 | chpasswd"
corosync
構成ファイルを作成します。sudo bash -c "cat <<EOF > /etc/corosync/corosync.conf totem { version: 2 cluster_name: mysql_cluster transport: udpu interface { ringnumber: 0 Bindnetaddr: ${DATABASE2_INSTANCE_IP} broadcast: yes mcastport: 5405 } } quorum { provider: corosync_votequorum two_node: 1 } nodelist { node { ring0_addr: ${DATABASE1_INSTANCE_NAME} name: ${DATABASE1_INSTANCE_NAME} nodeid: 1 } node { ring0_addr: ${DATABASE2_INSTANCE_NAME} name: ${DATABASE2_INSTANCE_NAME} nodeid: 2 } } logging { to_logfile: yes logfile: /var/log/corosync/corosync.log timestamp: on } EOF"
Corosync サービス ディレクトリを作成します。
sudo mkdir /etc/corosync/service.d
Pacemaker を認識するように
corosync
を構成します。sudo bash -c 'cat <<EOF > /etc/corosync/service.d/pcmk service { name: pacemaker ver: 1 } EOF'
デフォルトで
corosync
サービスを有効化します。sudo bash -c 'cat <<EOF > /etc/default/corosync # Path to corosync.conf COROSYNC_MAIN_CONFIG_FILE=/etc/corosync/corosync.conf # Path to authfile COROSYNC_TOTEM_AUTHKEY_FILE=/etc/corosync/authkey # Enable service by default START=yes EOF'
corosync
サービスとpacemaker
サービスを再起動します。sudo service corosync restart sudo service pacemaker restart
Corosync クォーラム デバイス パッケージをインストールします。
sudo apt -y install corosync-qdevice
DRBD の障害イベントを処理するシェル スクリプトをインストールします。
sudo bash -c 'cat << 'EOF' > /var/lib/pacemaker/drbd_cleanup.sh #!/bin/sh if [ -z \$CRM_alert_version ]; then echo "\$0 must be run by Pacemaker version 1.1.15 or later" exit 0 fi tstamp="\$CRM_alert_timestamp: " case \$CRM_alert_kind in resource) if [ \${CRM_alert_interval} = "0" ]; then CRM_alert_interval="" else CRM_alert_interval=" (\${CRM_alert_interval})" fi if [ \${CRM_alert_target_rc} = "0" ]; then CRM_alert_target_rc="" else CRM_alert_target_rc=" (target: \${CRM_alert_target_rc})" fi case \${CRM_alert_desc} in Cancelled) ;; *) echo "\${tstamp}Resource operation "\${CRM_alert_task}\${CRM_alert_interval}" for "\${CRM_alert_rsc}" on "\${CRM_alert_node}": \${CRM_alert_desc}\${CRM_alert_target_rc}" >> "\${CRM_alert_recipient}" if [ "\${CRM_alert_task}" = "stop" ] && [ "\${CRM_alert_desc}" = "Timed Out" ]; then echo "Executing recovering..." >> "\${CRM_alert_recipient}" pcs resource cleanup \${CRM_alert_rsc} fi ;; esac ;; *) echo "\${tstamp}Unhandled \$CRM_alert_kind alert" >> "\${CRM_alert_recipient}" env | grep CRM_alert >> "\${CRM_alert_recipient}" ;; esac EOF' sudo chmod 0755 /var/lib/pacemaker/drbd_cleanup.sh sudo touch /var/log/pacemaker_drbd_file.log sudo chown hacluster:haclient /var/log/pacemaker_drbd_file.log
Corosync クラスタのステータスを確認します。
sudo corosync-cmapctl | grep "members...ip"
出力は次のようになります。
runtime.totem.pg.mrp.srp.members.1.ip (str) = r(0) ip(10.140.0.2) runtime.totem.pg.mrp.srp.members.2.ip (str) = r(0) ip(10.140.0.3)
クラスタを起動する
- SSH を使用して
database2
インスタンスに接続します。 .varsrc
ファイルからメタデータ変数を読み込みます。source ~/.varsrc
クラスタノードに対して認証を行います。
sudo pcs cluster auth --name mysql_cluster ${DATABASE1_INSTANCE_NAME} ${DATABASE2_INSTANCE_NAME} -u hacluster -p haCLUSTER3
クラスタを起動します。
sudo pcs cluster start --all
クラスタのステータスを確認します。
sudo pcs status
出力は次のようになります。
Cluster name: mysql_cluster WARNING: no stonith devices and stonith-enabled is not false Stack: corosync Current DC: database2 (version 1.1.16-94ff4df) - partition with quorum Last updated: Sat Nov 3 07:24:53 2018 Last change: Sat Nov 3 07:17:17 2018 by hacluster via crmd on database2 2 nodes configured 0 resources configured Online: [ database1 database2 ] No resources Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
クラスタ リソースを管理するように Pacemaker を構成する
次に、Pacemaker を構成して DRBD、ディスク、MySQL、クォーラム リソースを設定します。
- SSH を使用して
database1
インスタンスに接続します。 Pacemaker の
pcs
ユーティリティを使用して、いくつかの変更をファイルに入れて待機させます。これらの変更は、後で Cluster Information Base(CIB)にアトミックに push します。sudo pcs cluster cib clust_cfg
クォーラム デバイスは後でデプロイするため、STONITH を無効化します。
sudo pcs -f clust_cfg property set stonith-enabled=false
クォーラム関連の設定を無効化します。クォーラム デバイスノードは後で設定します。
sudo pcs -f clust_cfg property set no-quorum-policy=stop
復元後に Pacemaker からリソースが戻されないようにします。
sudo pcs -f clust_cfg resource defaults resource-stickiness=200
クラスタ内に DRBD リソースを作成します。
sudo pcs -f clust_cfg resource create mysql_drbd ocf:linbit:drbd \ drbd_resource=r0 \ op monitor role=Master interval=110 timeout=30 \ op monitor role=Slave interval=120 timeout=30 \ op start timeout=120 \ op stop timeout=60
DRBD リソースにプライマリの役割が 1 つだけ割り当てられていることを確認します。
sudo pcs -f clust_cfg resource master primary_mysql mysql_drbd \ master-max=1 master-node-max=1 \ clone-max=2 clone-node-max=1 \ notify=true
DRBD ディスクにマウントするファイル システム リソースを作成します。
sudo pcs -f clust_cfg resource create mystore_FS Filesystem \ device="/dev/drbd0" \ directory="/srv" \ fstype="ext4"
DRBD リソースがディスク リソースと同じ VM 上に配置されるようにクラスタを構成します。
sudo pcs -f clust_cfg constraint colocation add mystore_FS with primary_mysql INFINITY with-rsc-role=Master
DRBD プライマリが昇格された後にのみディスク リソースを起動するようにクラスタを構成します。
sudo pcs -f clust_cfg constraint order promote primary_mysql then start mystore_FS
MySQL サービスを作成します。
sudo pcs -f clust_cfg resource create mysql_service ocf:heartbeat:mysql \ binary="/usr/bin/mysqld_safe" \ config="/etc/mysql/my.cnf" \ datadir="/var/lib/mysql" \ pid="/var/run/mysqld/mysql.pid" \ socket="/var/run/mysqld/mysql.sock" \ additional_parameters="--bind-address=0.0.0.0" \ op start timeout=60s \ op stop timeout=60s \ op monitor interval=20s timeout=30s
MySQL リソースがディスク リソースと同じ VM 上に配置されるようにクラスタを構成します。
sudo pcs -f clust_cfg constraint colocation add mysql_service with mystore_FS INFINITY
DRBD ファイル システムが起動されてから MySQL サービスが起動されることを確認します。
sudo pcs -f clust_cfg constraint order mystore_FS then mysql_service
アラート エージェントを作成し、アラートを受信するようにログファイルにパッチを追加します。
sudo pcs -f clust_cfg alert create id=drbd_cleanup_file description="Monitor DRBD events and perform post cleanup" path=/var/lib/pacemaker/drbd_cleanup.sh sudo pcs -f clust_cfg alert recipient add drbd_cleanup_file id=logfile value=/var/log/pacemaker_drbd_file.log
変更をクラスタに commit します。
sudo pcs cluster cib-push clust_cfg
すべてのリソースがオンラインになっていることを確認します。
sudo pcs status
出力は次のようになります。
Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Slaves: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1
クォーラム デバイスを構成する
- SSH を使用して
qdevice
インスタンスに接続します。 pcs
とcorosync-qnetd
をインストールします。sudo apt update && sudo apt -y install pcs corosync-qnetd
Pacemaker / Corosync 構成システム デーモン(
pcsd
)サービスを起動し、システム起動時に有効化します。sudo service pcsd start sudo update-rc.d pcsd enable
認証用のクラスタ ユーザー パスワード(
haCLUSTER3
)を設定します。sudo bash -c "echo hacluster:haCLUSTER3 | chpasswd"
クォーラム デバイスのステータスを確認します。
sudo pcs qdevice status net --full
出力は次のようになります。
QNetd address: *:5403 TLS: Supported (client certificate required) Connected clients: 0 Connected clusters: 0 Maximum send/receive size: 32768/32768 bytes
database1 上でクォーラム デバイス設定を構成する
- SSH を使用して
database1
ノードに接続します。 .varsrc
ファイルからメタデータ変数を読み込みます。source ~/.varsrc
クラスタのクォーラム デバイスノードを認証します。
sudo pcs cluster auth --name mysql_cluster ${QUORUM_INSTANCE_NAME} -u hacluster -p haCLUSTER3
クォーラム デバイスをクラスタに追加します。
ffsplit
アルゴリズムを使用します。このアルゴリズムにより、50% 以上の得票に基づいてアクティブ ノードが決定されることが保証されます。sudo pcs quorum device add model net host=${QUORUM_INSTANCE_NAME} algorithm=ffsplit
クォーラム設定を
corosync.conf
に追加します。sudo bash -c "cat <<EOF > /etc/corosync/corosync.conf totem { version: 2 cluster_name: mysql_cluster transport: udpu interface { ringnumber: 0 Bindnetaddr: ${DATABASE1_INSTANCE_IP} broadcast: yes mcastport: 5405 } } quorum { provider: corosync_votequorum device { votes: 1 model: net net { tls: on host: ${QUORUM_INSTANCE_NAME} algorithm: ffsplit } } } nodelist { node { ring0_addr: ${DATABASE1_INSTANCE_NAME} name: ${DATABASE1_INSTANCE_NAME} nodeid: 1 } node { ring0_addr: ${DATABASE2_INSTANCE_NAME} name: ${DATABASE2_INSTANCE_NAME} nodeid: 2 } } logging { to_logfile: yes logfile: /var/log/corosync/corosync.log timestamp: on } EOF"
corosync
サービスを再起動して新しいクォーラム デバイス設定を再読み込みします。sudo service corosync restart
corosync
クォーラム デバイス デーモンを起動し、システム起動時に有効化します。sudo service corosync-qdevice start sudo update-rc.d corosync-qdevice defaults
database2 上でクォーラム デバイス設定を構成する
- SSH を使用して
database2
ノードに接続します。 .varsrc
ファイルからメタデータ変数を読み込みます。source ~/.varsrc
クォーラム設定を
corosync.conf
に追加します。sudo bash -c "cat <<EOF > /etc/corosync/corosync.conf totem { version: 2 cluster_name: mysql_cluster transport: udpu interface { ringnumber: 0 Bindnetaddr: ${DATABASE2_INSTANCE_IP} broadcast: yes mcastport: 5405 } } quorum { provider: corosync_votequorum device { votes: 1 model: net net { tls: on host: ${QUORUM_INSTANCE_NAME} algorithm: ffsplit } } } nodelist { node { ring0_addr: ${DATABASE1_INSTANCE_NAME} name: ${DATABASE1_INSTANCE_NAME} nodeid: 1 } node { ring0_addr: ${DATABASE2_INSTANCE_NAME} name: ${DATABASE2_INSTANCE_NAME} nodeid: 2 } } logging { to_logfile: yes logfile: /var/log/corosync/corosync.log timestamp: on } EOF"
corosync
サービスを再起動して新しいクォーラム デバイス設定を再読み込みします。sudo service corosync restart
Corosync クォーラム デバイス デーモンを起動し、システム起動時に有効化するように構成します。
sudo service corosync-qdevice start sudo update-rc.d corosync-qdevice defaults
クラスタのステータスを確認する
次のステップとして、クラスタ リソースがオンラインになっていることを確認します。
- SSH を使用して
database1
インスタンスに接続します。 クラスタのステータスを確認します。
sudo pcs status
出力は次のようになります。
Cluster name: mysql_cluster Stack: corosync Current DC: database1 (version 1.1.16-94ff4df) - partition with quorum Last updated: Sun Nov 4 01:49:18 2018 Last change: Sat Nov 3 15:48:21 2018 by root via cibadmin on database1 2 nodes configured 4 resources configured Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Slaves: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
クォーラムのステータスを表示します。
sudo pcs quorum status
出力は次のようになります。
Quorum information ------------------ Date: Sun Nov 4 01:48:25 2018 Quorum provider: corosync_votequorum Nodes: 2 Node ID: 1 Ring ID: 1/24 Quorate: Yes Votequorum information ---------------------- Expected votes: 3 Highest expected: 3 Total votes: 3 Quorum: 2 Flags: Quorate Qdevice Membership information ---------------------- Nodeid Votes Qdevice Name 1 1 A,V,NMW database1 (local) 2 1 A,V,NMW database2 0 1 Qdevice
クォーラム デバイスのステータスを表示します。
sudo pcs quorum device status
出力は次のようになります。
Qdevice information ------------------- Model: Net Node ID: 1 Configured node list: 0 Node ID = 1 1 Node ID = 2 Membership node list: 1, 2 Qdevice-net information ---------------------- Cluster name: mysql_cluster QNetd host: qdevice:5403 Algorithm: Fifty-Fifty split Tie-breaker: Node with lowest node ID State: Connected
クラスタ IP として内部ロードバランサを構成する
Cloud Shell を開きます。
非マネージド インスタンス グループを作成し、グループに
database1
インスタンスを追加します。gcloud compute instance-groups unmanaged create ${DATABASE1_INSTANCE_NAME}-instance-group \ --zone=${DATABASE1_INSTANCE_ZONE} \ --description="${DATABASE1_INSTANCE_NAME} unmanaged instance group" gcloud compute instance-groups unmanaged add-instances ${DATABASE1_INSTANCE_NAME}-instance-group \ --zone=${DATABASE1_INSTANCE_ZONE} \ --instances=${DATABASE1_INSTANCE_NAME}
非マネージド インスタンス グループを作成し、グループに
database2
インスタンスを追加します。gcloud compute instance-groups unmanaged create ${DATABASE2_INSTANCE_NAME}-instance-group \ --zone=${DATABASE2_INSTANCE_ZONE} \ --description="${DATABASE2_INSTANCE_NAME} unmanaged instance group" gcloud compute instance-groups unmanaged add-instances ${DATABASE2_INSTANCE_NAME}-instance-group \ --zone=${DATABASE2_INSTANCE_ZONE} \ --instances=${DATABASE2_INSTANCE_NAME}
port 3306
のヘルスチェックを作成します。gcloud compute health-checks create tcp mysql-backend-healthcheck \ --port 3306
リージョン内部のバックエンド サービスを作成します。
gcloud compute backend-services create mysql-ilb \ --load-balancing-scheme internal \ --region ${CLUSTER_REGION} \ --health-checks mysql-backend-healthcheck \ --protocol tcp
バックエンド サービスに、2 つのインスタンス グループをバックエンドとして追加します。
gcloud compute backend-services add-backend mysql-ilb \ --instance-group ${DATABASE1_INSTANCE_NAME}-instance-group \ --instance-group-zone ${DATABASE1_INSTANCE_ZONE} \ --region ${CLUSTER_REGION} gcloud compute backend-services add-backend mysql-ilb \ --instance-group ${DATABASE2_INSTANCE_NAME}-instance-group \ --instance-group-zone ${DATABASE2_INSTANCE_ZONE} \ --region ${CLUSTER_REGION}
ロードバランサの転送ルールを作成します。
gcloud compute forwarding-rules create mysql-ilb-forwarding-rule \ --load-balancing-scheme internal \ --ports 3306 \ --network default \ --subnet default \ --region ${CLUSTER_REGION} \ --address ${ILB_IP} \ --backend-service mysql-ilb
内部ロードバランサのヘルスチェックを許可するファイアウォール ルールを作成します。
gcloud compute firewall-rules create allow-ilb-healthcheck \ --direction=INGRESS --network=default \ --action=ALLOW --rules=tcp:3306 \ --source-ranges=130.211.0.0/22,35.191.0.0/16 --target-tags=mysql
ロードバランサのステータスを確認するには、Google Cloud コンソールの [ロード バランシング] ページに移動します。
[
mysql-ilb
] をクリックします。クラスタでは常に 1 つのインスタンスだけが MySQL を実行できるため、内部ロードバランサの観点から 1 つのインスタンスのみが正常な状態になります。
MySQL クライアントからクラスタに接続する
- SSH を使用して
mysql-client
インスタンスに接続します。 パッケージ定義を更新します。
sudo apt-get update
MySQL クライアントをインストールします。
sudo apt-get install -y mysql-client
テーブルを作成してサンプルデータを取り込むスクリプト ファイルを作成します。
cat <<EOF > db_creation.sql CREATE DATABASE source_db; use source_db; CREATE TABLE source_table ( id BIGINT NOT NULL AUTO_INCREMENT, timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, event_data float DEFAULT NULL, PRIMARY KEY (id) ); DELIMITER $$ CREATE PROCEDURE simulate_data() BEGIN DECLARE i INT DEFAULT 0; WHILE i < 100 DO INSERT INTO source_table (event_data) VALUES (ROUND(RAND()*15000,2)); SET i = i + 1; END WHILE; END$$ DELIMITER ; CALL simulate_data() EOF
テーブルを作成します。
ILB_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/ILB_IP" -H "Metadata-Flavor: Google") mysql -u root -pDRBDha2 "-h${ILB_IP}" < db_creation.sql
クラスタをテストする
デプロイ済みクラスタの HA 機能をテストするには、次のテストを実施できます。
database1
インスタンスをシャットダウンして、マスター データベースがdatabase2
インスタンスにフェイルオーバーするかどうかをテストします。database1
インスタンスを起動して、database1
がクラスタに正常に再参加できるかどうかを確認します。database2
インスタンスをシャットダウンして、マスター データベースがdatabase1
インスタンスにフェイルオーバーするかどうかをテストします。database2
インスタンスを起動して、database2
がクラスタに正常に再参加できるかどうか、database1
インスタンスが引き続きマスターのロールを保持するかどうかを確認します。database1
とdatabase2
の間にネットワーク パーティションを作成して、スプリット ブレインの問題をシミュレートします。
Cloud Shell を開きます。
database1
インスタンスを停止します。gcloud compute instances stop ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE}
クラスタのステータスを確認します。
gcloud compute ssh ${DATABASE2_INSTANCE_NAME} \ --zone=${DATABASE2_INSTANCE_ZONE} \ --command="sudo pcs status"
出力は次のようになります。構成に加えた変更が適用されていることを確認します。
2 nodes configured 4 resources configured Online: [ database2 ] OFFLINE: [ database1 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database2 ] Stopped: [ database1 ] mystore_FS (ocf::heartbeat:Filesystem): Started database2 mysql_service (ocf::heartbeat:mysql): Started database2 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
database1
インスタンスを起動します。gcloud compute instances start ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE}
クラスタのステータスを確認します。
gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
出力は次のようになります。
2 nodes configured 4 resources configured Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database2 ] Slaves: [ database1 ] mystore_FS (ocf::heartbeat:Filesystem): Started database2 mysql_service (ocf::heartbeat:mysql): Started database2 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
database2
インスタンスを停止します。gcloud compute instances stop ${DATABASE2_INSTANCE_NAME} \ --zone=${DATABASE2_INSTANCE_ZONE}
クラスタのステータスを確認します。
gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
出力は次のようになります。
2 nodes configured 4 resources configured Online: [ database1 ] OFFLINE: [ database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Stopped: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
database2
インスタンスを起動します。gcloud compute instances start ${DATABASE2_INSTANCE_NAME} \ --zone=${DATABASE2_INSTANCE_ZONE}
クラスタのステータスを確認します。
gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
出力は次のようになります。
2 nodes configured 4 resources configured Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Slaves: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
database1
とdatabase2
の間にネットワーク パーティションを作成します。gcloud compute firewall-rules create block-comms \ --description="no MySQL communications" \ --action=DENY \ --rules=all \ --source-tags=mysql \ --target-tags=mysql \ --priority=800
数分経ったら、クラスタのステータスを確認します。
database1
がプライマリの役割を保持する仕組みに注目してください。これは、ネットワークが分割されている場合、クォーラム ポリシーでは ID が最下位のノードが優先されるためです。その間、database2
MySQL サービスは停止されます。このクォーラム メカニズムにより、ネットワークが分割された場合でもスプリット ブレインの問題が回避されます。gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
出力は次のようになります。
2 nodes configured 4 resources configured Online: [ database1 ] OFFLINE: [ database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Stopped: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1
ネットワーク ファイアウォール ルールを削除してネットワーク パーティションを削除します(プロンプトが表示されたら、
Y
キーを押します)。gcloud compute firewall-rules delete block-comms
クラスタが正常な状態に戻ったことを確認します。
gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
出力は次のようになります。
2 nodes configured 4 resources configured Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Slaves: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1
SSH を使用して
mysql-client
インスタンスに接続します。シェルで、前に作成したテーブルのクエリを実行します。
ILB_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/ILB_IP" -H "Metadata-Flavor: Google") mysql -uroot "-h${ILB_IP}" -pDRBDha2 -e "select * from source_db.source_table LIMIT 10"
クラスタ内のデータ整合性が維持されていれば、10 件のレコードが次の形式で出力されます。
+----+---------------------+------------+ | id | timestamp | event_data | +----+---------------------+------------+ | 1 | 2018-11-27 21:00:09 | 1279.06 | | 2 | 2018-11-27 21:00:09 | 4292.64 | | 3 | 2018-11-27 21:00:09 | 2626.01 | | 4 | 2018-11-27 21:00:09 | 252.13 | | 5 | 2018-11-27 21:00:09 | 8382.64 | | 6 | 2018-11-27 21:00:09 | 11156.8 | | 7 | 2018-11-27 21:00:09 | 636.1 | | 8 | 2018-11-27 21:00:09 | 14710.1 | | 9 | 2018-11-27 21:00:09 | 11642.1 | | 10 | 2018-11-27 21:00:09 | 14080.3 | +----+---------------------+------------+
フェイルオーバー シーケンス
クラスタ内のプライマリ ノードが停止した場合、次のようにフェイルオーバーが行われます。
- クォーラム デバイスとスタンバイ ノードの両方が、プライマリ ノードとの接続を失います。
- クォーラム デバイスがスタンバイ ノードに投票します。スタンバイ ノードも自身に投票します。
- スタンバイ ノードがクォーラムを獲得します。
- スタンバイ ノードがプライマリに昇格されます。
- 新しいプライマリ ノードは次の処理を行います。
- DRBD をプライマリにプロモートする
- DRBD の MySQL データディスクをマウントする
- MySQL を起動する
- ロードバランサに対して正常な状態になる
- ロードバランサが新しいプライマリ ノードにトラフィックを送信し始めます。
クリーンアップ
プロジェクトを削除する
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
次のステップ
- DRBD の詳細を確認する。
- Pacemaker の詳細を確認する。
- Corosync Cluster Engine の詳細を確認する。
- MySQL サーバー 5.6 の高度な設定については、MySQL サーバー管理マニュアルをご覧ください。
- MySQL へのリモート アクセスを設定する場合は、Compute Engine 上で MySQL へのリモート アクセスをセットアップする方法をご覧ください。
- MySQL の詳細については、公式の MySQL ドキュメントをご覧ください。
- Google Cloud に関するリファレンス アーキテクチャ、図、ベスト プラクティスを確認する。Cloud アーキテクチャ センターをご覧ください。