DRBD を使用した高可用性 MySQL 5.6 クラスタを Compute Engine にデプロイする

Last reviewed 2019-05-10 UTC

このチュートリアルでは、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 つのノードのいずれかと通信できるため、過半数のノードとの通信が維持されます。

次の図は、ここで説明するシステムのアーキテクチャを示しています。

DRBD と Compute Engine を使用して Google Cloud にデプロイされた MySQL 5.6 データベースを示すアーキテクチャ

目標

  • クラスタ インスタンスを作成する。
  • MySQL と DRBD を 2 つのインスタンスにインストールする。
  • DRBD レプリケーションを構成する。
  • Pacemaker をインスタンスにインストールする。
  • インスタンス上で Pacemaker クラスタリングを構成する。
  • インスタンスを作成してクォーラム デバイスとして構成する。
  • フェイルオーバーをテストする。

料金

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを作成できます。

始める前に

  1. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. Compute Engine API を有効にします。

    API を有効にする

  5. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  6. Google Cloud プロジェクトで課金が有効になっていることを確認します

  7. Compute Engine API を有効にします。

    API を有効にする

このチュートリアルでは、特に記載がない限り、Cloud Shell を使用してコマンドを入力します。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

設定

このセクションでは、サービス アカウントの設定、環境変数の作成、IP アドレスの予約を行います。

クラスタ インスタンス用のサービス アカウントを設定する

  1. Cloud Shell を開きます。

    Cloud Shell を開く

  2. サービス アカウントを作成します。

    gcloud iam service-accounts create mysql-instance \
        --display-name "mysql-instance"
    
  3. サービス アカウントに、このチュートリアルに必要な役割を関連付けます。

    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 環境変数を作成する

  1. このチュートリアルに必要な環境変数を設定したファイルを作成します。

    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
    
  2. 現在のセッションで環境変数を読み込み、今後ログインするときに自動的に変数を読み込むように 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 を使用します。

  1. 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}"
    
  2. 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}"
    
  3. 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}
    
  4. 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 を構成する

  1. Google Cloud コンソールで、[VM インスタンス] ページに移動します。

    [VM インスタンス] ページ

  2. database1 インスタンスの行で、[SSH] をクリックしてインスタンスに接続します。

  3. インスタンス メタデータを取得して環境変数に格納するためのファイルを作成します。

    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
    
  4. ファイルからメタデータ変数を読み込みます。

    source ~/.varsrc
    
  5. データディスクをフォーマットします。

    sudo bash -c  "mkfs.ext4 -m 0 -F -E \
    lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb"
    

    mkfs.ext4 オプションについて詳しくは、mkfs.ext4 のマニュアル ページをご覧ください。

  6. DRBD をインストールします。

    sudo apt -y install drbd8-utils
    
  7. DRBD 構成ファイルを作成します。

    sudo bash -c 'cat <<EOF  > /etc/drbd.d/global_common.conf
    global {
        usage-count no;
    }
    common {
        protocol C;
    }
    EOF'
    
  8. 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"
    
  9. DRBD カーネル モジュールを読み込みます。

    sudo modprobe drbd
    
  10. /dev/sdb ディスクの内容を消去します。

    sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
    
  11. DRBD リソース r0 を作成します。

    sudo drbdadm create-md r0
    
  12. DRBD を起動します。

    sudo drbdadm up r0
    
  13. システム起動時に DRBD を無効化して、クラスタ リソース管理ソフトウェアが必要なすべてのリソースを順に起動できるようにします。

    sudo update-rc.d drbd disable
    

database2 上に DRBD を構成する

DRBD パッケージを database2 インスタンスにインストールして構成します。

  1. SSH を使用して database2 インスタンスに接続します。
  2. インスタンス メタデータを取得して環境変数に格納するための .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
    
  3. ファイルからメタデータ変数を読み込みます。

    source ~/.varsrc
    
  4. データディスクをフォーマットします。

    sudo bash -c  "mkfs.ext4 -m 0 -F -E  lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb"
    
  5. DRBD パッケージをインストールします。

    sudo apt -y install drbd8-utils
    
  6. DRBD 構成ファイルを作成します。

    sudo bash -c 'cat <<EOF  > /etc/drbd.d/global_common.conf
    global {
        usage-count no;
    }
    common {
        protocol C;
    }
    EOF'
    
  7. 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"
    
  8. DRBD カーネル モジュールを読み込みます。

    sudo modprobe drbd
    
  9. /dev/sdb ディスクの内容を消去します。

    sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
    
  10. DRBD リソース r0 を作成します。

    sudo drbdadm create-md r0
    
  11. DRBD を起動します。

    sudo drbdadm up r0
    
  12. システム起動時に DRBD を無効化して、クラスタ リソース管理ソフトウェアが必要なすべてのリソースを順に起動できるようにします。

    sudo update-rc.d drbd disable
    

database1 から database2 への DRBD レプリケーションを開始する

  1. SSH を使用して database1 インスタンスに接続します。
  2. プライマリ ノード上のすべての 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
    
  3. DRBD のステータスを確認します。

    sudo cat /proc/drbd | grep ============
    

    出力は次のようになります。

    [===================>] sync'ed:100.0% (208/307188)M
    
  4. /dev/drbd/srv にマウントするには:

    sudo mount -o discard,defaults /dev/drbd0 /srv
    

MySQL と Pacemaker をインストールする

このセクションでは、MySQL と Pacemaker を各インスタンスにインストールします。

MySQL を database1 にインストールする

  1. SSH を使用して database1 インスタンスに接続します。
  2. 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'
    
  3. 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
    
  4. パッケージ リストを更新します。

    sudo apt update
    
  5. MySQL サーバーをインストールします。

    sudo apt -y install mysql-server
    

    パスワードの入力を求められたら、「DRBDha2」と入力します。

  6. MySQL サーバーを停止します。

    sudo /etc/init.d/mysql stop
    
  7. 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'
    
  8. MySQL サーバー(mysql.conf 内に構成されている)の一時ディレクトリを作成します。

    sudo mkdir /srv/tmp
    sudo chmod 1777 /srv/tmp
    
  9. すべての MySQL データを DRBD ディレクトリ /srv/mysql に移動します。

    sudo mv /var/lib/mysql /srv/mysql
    
  10. /var/lib/mysql を、DRBD でレプリケートされたストレージ ボリューム内の /srv/mysql にリンクします。

    sudo ln -s /srv/mysql /var/lib/mysql
    
  11. /srv/mysql のオーナーを mysql プロセスに変更します。

    sudo chown -R mysql:mysql /srv/mysql
    
  12. InnoDB の初期データを削除して、ディスクを可能な限りクリーンな状態にします。

    sudo bash -c "cd /srv/mysql && rm ibdata1 && rm ib_logfile*"
    

    InnoDB は、MySQL データベース管理システムのストレージ エンジンです。

  13. MySQL を起動します。

    sudo /etc/init.d/mysql start
    
  14. 後でデプロイをテストできるよう、root ユーザーにリモート接続の権限を付与します。

    mysql -uroot -pDRBDha2 -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'DRBDha2' WITH GRANT OPTION;"
    
  15. クラスタ リソース管理によって行われる MySQL の自動起動を無効化します。

    sudo update-rc.d -f mysql disable
    

Pacemaker を database1 にインストールする

  1. 前に作成した .varsrc ファイルからメタデータ変数を読み込みます。

    source ~/.varsrc
    
  2. MySQL サーバーを停止します。

    sudo /etc/init.d/mysql stop
    
  3. Pacemaker をインストールします。

    sudo apt -y install pcs
    
  4. システムの起動時にプライマリ インスタンス上で pcsdcorosyncpacemaker を有効化します。

    sudo update-rc.d -f pcsd enable
    sudo update-rc.d -f corosync enable
    sudo update-rc.d -f pacemaker enable
    
  5. pacemaker を起動する前に、corosync を構成します。

    sudo update-rc.d corosync defaults 20 20
    sudo update-rc.d pacemaker defaults 30 10
    
  6. 認証用のクラスタ ユーザー パスワード(haCLUSTER3)を設定します。

    sudo bash -c "echo  hacluster:haCLUSTER3 | chpasswd"
    
  7. corosync-keygen スクリプトを実行します。これにより、128 ビットのクラスタ認証キーが生成されて /etc/corosync/authkey に書き込まれます。

    sudo corosync-keygen -l
    
  8. authkeydatabase2 インスタンスにコピーします。パスフレーズの入力を求められたら、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
    
  9. 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 つ目のノードをクォーラム デバイスとして追加するときに備えることができます。

  10. corosync 用のサービス ディレクトリを作成します。

    sudo mkdir -p /etc/corosync/service.d
    
  11. Pacemaker を認識するように corosync を構成します。

    sudo bash -c 'cat <<EOF  > /etc/corosync/service.d/pcmk
    service {
        name: pacemaker
        ver: 1
    }
    EOF'
    
  12. デフォルトで 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'
    
  13. corosync サービスと pacemaker サービスを再起動します。

    sudo service corosync restart
    sudo service pacemaker restart
    
  14. Corosync クォーラム デバイス パッケージをインストールします。

    sudo apt -y install corosync-qdevice
    
  15. 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 にインストールする

  1. SSH を使用して database2 インスタンスに接続します。
  2. 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'
    
  3. 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
    
  4. パッケージ リストを更新します。

    sudo apt update
    
  5. MySQL サーバーをインストールします。

    sudo apt -y install mysql-server
    

    パスワードの入力を求められたら、「DRBDha2」と入力します。

  6. MySQL サーバーを停止します。

    sudo /etc/init.d/mysql stop
    
  7. 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'
    
  8. /var/lib/mysql からデータを削除し、レプリケートされた DRBD ボリュームのマウント ポイント ターゲットへのシンボリック リンクを追加します。フェイルオーバーが発生した場合にのみ、DRBD ボリューム(/dev/drbd0)が /srv にマウントされます。

    sudo rm -rf /var/lib/mysql
    sudo ln -s /srv/mysql /var/lib/mysql
    
  9. クラスタ リソース管理によって行われる MySQL の自動起動を無効化します。

    sudo update-rc.d -f mysql disable
    

Pacemaker を database2 にインストールする

  1. .varsrc ファイルからメタデータ変数を読み込みます。

    source ~/.varsrc
    
  2. Pacemaker をインストールします。

    sudo apt -y install pcs
    
  3. 前にコピーした Corosync authkey ファイルを /etc/corosync/ に移動します。

    sudo mv ~/authkey /etc/corosync/
    sudo chown root: /etc/corosync/authkey
    sudo chmod 400 /etc/corosync/authkey
    
  4. システム起動時にスタンバイ インスタンス上で pcsdcorosyncpacemaker を有効化します。

    sudo update-rc.d -f pcsd enable
    sudo update-rc.d -f corosync enable
    sudo update-rc.d -f pacemaker enable
    
  5. pacemaker を起動する前に、corosync を構成します。

    sudo update-rc.d corosync defaults 20 20
    sudo update-rc.d pacemaker defaults 30 10
    
  6. 認証用のクラスタ ユーザー パスワードを設定します。このパスワードは、database1 インスタンスに使用したもの(haCLUSTER3)と同じです。

    sudo bash -c "echo  hacluster:haCLUSTER3 | chpasswd"
    
  7. 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"
    
  8. Corosync サービス ディレクトリを作成します。

    sudo mkdir /etc/corosync/service.d
    
  9. Pacemaker を認識するように corosync を構成します。

    sudo bash -c 'cat <<EOF  > /etc/corosync/service.d/pcmk
    service {
    name: pacemaker
    ver: 1
    }
    EOF'
    
  10. デフォルトで 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'
    
  11. corosync サービスと pacemaker サービスを再起動します。

    sudo service corosync restart
    sudo service pacemaker restart
    
  12. Corosync クォーラム デバイス パッケージをインストールします。

    sudo apt -y install corosync-qdevice
    
  13. 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
    
  14. 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)
    

クラスタを起動する

  1. SSH を使用して database2 インスタンスに接続します。
  2. .varsrc ファイルからメタデータ変数を読み込みます。

    source ~/.varsrc
    
  3. クラスタノードに対して認証を行います。

    sudo pcs cluster auth --name mysql_cluster ${DATABASE1_INSTANCE_NAME} ${DATABASE2_INSTANCE_NAME} -u hacluster -p haCLUSTER3
    
  4. クラスタを起動します。

    sudo pcs cluster start --all
    
  5. クラスタのステータスを確認します。

    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、クォーラム リソースを設定します。

  1. SSH を使用して database1 インスタンスに接続します。
  2. Pacemaker の pcs ユーティリティを使用して、いくつかの変更をファイルに入れて待機させます。これらの変更は、後で Cluster Information Base(CIB)にアトミックに push します。

    sudo pcs cluster cib clust_cfg
    
  3. クォーラム デバイスは後でデプロイするため、STONITH を無効化します。

    sudo pcs -f clust_cfg property set stonith-enabled=false
    
  4. クォーラム関連の設定を無効化します。クォーラム デバイスノードは後で設定します。

    sudo pcs -f clust_cfg property set no-quorum-policy=stop
    
  5. 復元後に Pacemaker からリソースが戻されないようにします。

    sudo pcs -f clust_cfg resource defaults resource-stickiness=200
    
  6. クラスタ内に 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
    
  7. 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
    
  8. DRBD ディスクにマウントするファイル システム リソースを作成します。

    sudo pcs -f clust_cfg resource create mystore_FS Filesystem \
        device="/dev/drbd0" \
        directory="/srv" \
        fstype="ext4"
    
  9. DRBD リソースがディスク リソースと同じ VM 上に配置されるようにクラスタを構成します。

    sudo pcs -f clust_cfg constraint colocation add mystore_FS with primary_mysql INFINITY with-rsc-role=Master
    
  10. DRBD プライマリが昇格された後にのみディスク リソースを起動するようにクラスタを構成します。

    sudo pcs -f clust_cfg constraint order promote primary_mysql then start mystore_FS
    
  11. 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
    
  12. MySQL リソースがディスク リソースと同じ VM 上に配置されるようにクラスタを構成します。

    sudo pcs -f clust_cfg constraint colocation add mysql_service with mystore_FS INFINITY
    
  13. DRBD ファイル システムが起動されてから MySQL サービスが起動されることを確認します。

    sudo pcs -f clust_cfg constraint order mystore_FS then mysql_service
    
  14. アラート エージェントを作成し、アラートを受信するようにログファイルにパッチを追加します。

    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
    
  15. 変更をクラスタに commit します。

    sudo pcs cluster cib-push clust_cfg
    
  16. すべてのリソースがオンラインになっていることを確認します。

    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
    

クォーラム デバイスを構成する

  1. SSH を使用して qdevice インスタンスに接続します。
  2. pcscorosync-qnetd をインストールします。

    sudo apt update && sudo apt -y install pcs corosync-qnetd
    
  3. Pacemaker / Corosync 構成システム デーモン(pcsdサービスを起動し、システム起動時に有効化します。

    sudo service pcsd start
    sudo update-rc.d pcsd enable
    
  4. 認証用のクラスタ ユーザー パスワード(haCLUSTER3)を設定します。

    sudo bash -c "echo  hacluster:haCLUSTER3 | chpasswd"
    
  5. クォーラム デバイスのステータスを確認します。

    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 上でクォーラム デバイス設定を構成する

  1. SSH を使用して database1 ノードに接続します。
  2. .varsrc ファイルからメタデータ変数を読み込みます。

    source ~/.varsrc
    
  3. クラスタのクォーラム デバイスノードを認証します。

    sudo pcs cluster auth --name mysql_cluster ${QUORUM_INSTANCE_NAME} -u hacluster -p haCLUSTER3
    
  4. クォーラム デバイスをクラスタに追加します。ffsplit アルゴリズムを使用します。このアルゴリズムにより、50% 以上の得票に基づいてアクティブ ノードが決定されることが保証されます。

    sudo pcs quorum device add model net host=${QUORUM_INSTANCE_NAME} algorithm=ffsplit
    
  5. クォーラム設定を 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"
    
  6. corosync サービスを再起動して新しいクォーラム デバイス設定を再読み込みします。

    sudo service corosync restart
    
  7. corosync クォーラム デバイス デーモンを起動し、システム起動時に有効化します。

    sudo service corosync-qdevice start
    sudo update-rc.d corosync-qdevice defaults
    

database2 上でクォーラム デバイス設定を構成する

  1. SSH を使用して database2 ノードに接続します。
  2. .varsrc ファイルからメタデータ変数を読み込みます。

    source ~/.varsrc
    
  3. クォーラム設定を 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"
    
  4. corosync サービスを再起動して新しいクォーラム デバイス設定を再読み込みします。

    sudo service corosync restart
    
  5. Corosync クォーラム デバイス デーモンを起動し、システム起動時に有効化するように構成します。

    sudo service corosync-qdevice start
    sudo update-rc.d corosync-qdevice defaults
    

クラスタのステータスを確認する

次のステップとして、クラスタ リソースがオンラインになっていることを確認します。

  1. SSH を使用して database1 インスタンスに接続します。
  2. クラスタのステータスを確認します。

    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
    
  3. クォーラムのステータスを表示します。

    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
    
  4. クォーラム デバイスのステータスを表示します。

    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 として内部ロードバランサを構成する

  1. Cloud Shell を開きます。

    Cloud Shell を開く

  2. 非マネージド インスタンス グループを作成し、グループに 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}
    
  3. 非マネージド インスタンス グループを作成し、グループに 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}
    
  4. port 3306 のヘルスチェックを作成します。

    gcloud compute health-checks create tcp mysql-backend-healthcheck \
        --port 3306
    
  5. リージョン内部のバックエンド サービスを作成します。

    gcloud compute backend-services create mysql-ilb \
        --load-balancing-scheme internal \
        --region ${CLUSTER_REGION} \
        --health-checks mysql-backend-healthcheck \
        --protocol tcp
    
  6. バックエンド サービスに、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}
    
  7. ロードバランサの転送ルールを作成します。

    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
    
  8. 内部ロードバランサのヘルスチェックを許可するファイアウォール ルールを作成します。

    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
    
  9. ロードバランサのステータスを確認するには、Google Cloud コンソールの [ロード バランシング] ページに移動します。

    [ロード バランシング] ページを開く

  10. [mysql-ilb] をクリックします。

    画像

    クラスタでは常に 1 つのインスタンスだけが MySQL を実行できるため、内部ロードバランサの観点から 1 つのインスタンスのみが正常な状態になります。

    画像

MySQL クライアントからクラスタに接続する

  1. SSH を使用して mysql-client インスタンスに接続します。
  2. パッケージ定義を更新します。

    sudo apt-get update
    
  3. MySQL クライアントをインストールします。

    sudo apt-get install -y mysql-client
    
  4. テーブルを作成してサンプルデータを取り込むスクリプト ファイルを作成します。

    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
    
  5. テーブルを作成します。

    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 インスタンスが引き続きマスターのロールを保持するかどうかを確認します。
  • database1database2 の間にネットワーク パーティションを作成して、スプリット ブレインの問題をシミュレートします。

  1. Cloud Shell を開きます。

    Cloud Shell を開く

  2. database1 インスタンスを停止します。

    gcloud compute instances stop ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE}
    
  3. クラスタのステータスを確認します。

    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
    
  4. database1 インスタンスを起動します。

    gcloud compute instances start ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE}
    
  5. クラスタのステータスを確認します。

    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
    
  6. database2 インスタンスを停止します。

    gcloud compute instances stop ${DATABASE2_INSTANCE_NAME} \
        --zone=${DATABASE2_INSTANCE_ZONE}
    
  7. クラスタのステータスを確認します。

    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
    
  8. database2 インスタンスを起動します。

    gcloud compute instances start ${DATABASE2_INSTANCE_NAME} \
        --zone=${DATABASE2_INSTANCE_ZONE}
    
  9. クラスタのステータスを確認します。

    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
    
  10. database1database2 の間にネットワーク パーティションを作成します。

    gcloud compute firewall-rules create block-comms \
        --description="no MySQL communications" \
        --action=DENY \
        --rules=all \
        --source-tags=mysql \
        --target-tags=mysql \
        --priority=800
    
  11. 数分経ったら、クラスタのステータスを確認します。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
    
  12. ネットワーク ファイアウォール ルールを削除してネットワーク パーティションを削除します(プロンプトが表示されたら、Y キーを押します)。

    gcloud compute firewall-rules delete block-comms
    
  13. クラスタが正常な状態に戻ったことを確認します。

    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
    
  14. SSH を使用して mysql-client インスタンスに接続します。

  15. シェルで、前に作成したテーブルのクエリを実行します。

    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 |
    +----+---------------------+------------+
    

フェイルオーバー シーケンス

クラスタ内のプライマリ ノードが停止した場合、次のようにフェイルオーバーが行われます。

  1. クォーラム デバイスとスタンバイ ノードの両方が、プライマリ ノードとの接続を失います。
  2. クォーラム デバイスがスタンバイ ノードに投票します。スタンバイ ノードも自身に投票します。
  3. スタンバイ ノードがクォーラムを獲得します。
  4. スタンバイ ノードがプライマリに昇格されます。
  5. 新しいプライマリ ノードは次の処理を行います。
    1. DRBD をプライマリにプロモートする
    2. DRBD の MySQL データディスクをマウントする
    3. MySQL を起動する
    4. ロードバランサに対して正常な状態になる
  6. ロードバランサが新しいプライマリ ノードにトラフィックを送信し始めます。

クリーンアップ

プロジェクトの削除

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ