カテゴリー別アーカイブ: MySQL

AWS上のZabbixをPacemakerで冗長化 その3(MySQLReplicate編)

| コメントをどうぞ

前回はAWS上のZabbixをPacemaker + DRBDで冗長化しましたので今回は、

● Pacemaker + MySQLレプリケーション(SemiSync)

をやります。MySQLは整合性の高いSemiSyncを採用します。SemiSyncはMySQL5.5以降で使えます。5.5以降はデフォルトのリポジトリには無いのでMySQL5.5以降があるリポジトリを追加するかソースからインストールします。


前提条件としてMySQLは既にインストール/Replication設定済みとします。(導入部分も書くと長くなる為。機会があれば別途導入方法も書きます。)

  • Pacemaker(HeartbeatV2) + MySQLレプリケーション(Semisync)

  • cluster3

    DRBDの時と同じように前回のheartbeatの設定ファイル、cib.xml等が/var/lib/heartbeat/crmに残っている為、一旦削除します。
    (稼働/待機両方で消します。残っていると同期されて元に戻ってしまう為)

    ● 稼働/待機系で前回の設定ファイル削除(/var/lib/heartbeat/crmの下を全消しでOK)

    # rm /var/lib/heartbeat/crm/* -fr
    

    ● 一旦heartbeatを起動

    # /etc/init.d/heartbeat start
    

    MySQL用のxmlファイルを置いて起動しても何故かうまく行かず初期のcibに上書きされてしまう場合は一旦起動後に置き換える事で上手く行きます。

    ● cib.xml無しで起動すると以下のようになります。(クラスタホストが認識されているだけの状態)

    ============
    Last updated: Fri Dec  5 12:46:25 2014
    Stack: Heartbeat
    Current DC: zabbixcluster-2 (e1c9433f-8e5b-8681-2867-5a4dd5880dfe) - partition w
    ith quorum
    Version: 1.0.13-30bb726
    2 Nodes configured, unknown expected votes
    0 Resources configured.
    ============
    
    Online: [ zabbixcluster-1 zabbixcluster-2 ]
    

    ● ここでZabbix+MySQLレプリケーション用のファイルを以下のようにどこかのディレクトリ(/tmpなどどこでもOK)用意します。

    ※nodeidなどは環境に合わせて適宜置き換えます。

    <cib epoch="19" num_updates="0" admin_epoch="0" validate-with="pacemaker-1.0" crm_feature_set="3.0.1" have-quorum="1" dc-uuid="f76af805-bfff-66bd-3d83-95a20a3807ef" cib-last-written="Mon Dec  8 16:12:17 2014">
      <configuration>
        <crm_config>
          <cluster_property_set id="cib-bootstrap-options">
            <nvpair id="cib-bootstrap-options-default-resource-stickiness" name="default-resource-stickiness" value="INFINITY"/>
            <nvpair id="cib-bootstrap-options-no-quorum-policy" name="no-quorum-policy" value="ignore"/>
            <nvpair id="cib-bootstrap-options-stonith-enabled" name="stonith-enabled" value="false"/>
            <nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="1.0.13-30bb726"/>
            <nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="Heartbeat"/>
          </cluster_property_set>
          <cluster_property_set id="mysql_replication">
            <nvpair id="mysql_replication-prm_mysqld_REPL_INFO" name="prm_mysqld_REPL_INFO" value="zabbixcluster-1|mysql-bin.000103|2698"/>
          </cluster_property_set>
        </crm_config>
        <nodes>
          <node id="f76af805-bfff-66bd-3d83-95a20a3807ef" type="normal" uname="zabbixcluster-1"/>
          <node id="e1c9433f-8e5b-8681-2867-5a4dd5880dfe" type="normal" uname="zabbixcluster-2"/>
        </nodes>
        <resources>
          <master id="ms_mysqld">
            <meta_attributes id="ms_mysqld-meta_attributes">
              <nvpair id="ms_mysqld-meta_attributes-master-max" name="master-max" value="1"/>
              <nvpair id="ms_mysqld-meta_attributes-master-node-max" name="master-node-max" value="1"/>
              <nvpair id="ms_mysqld-meta_attributes-clone-max" name="clone-max" value="2"/>
              <nvpair id="ms_mysqld-meta_attributes-clone-node-max" name="clone-node-max" value="1"/>
              <nvpair id="ms_mysqld-meta_attributes-notify" name="notify" value="true"/>
            </meta_attributes>
            <primitive class="ocf" id="prm_mysqld" provider="heartbeat" type="mysql">
              <instance_attributes id="prm_mysqld-instance_attributes">
                <nvpair id="prm_mysqld-instance_attributes-binary" name="binary" value="/usr/bin/mysqld_safe"/>
                <nvpair id="prm_mysqld-instance_attributes-replication_user" name="replication_user" value="replicate"/>
                <nvpair id="prm_mysqld-instance_attributes-replication_passwd" name="replication_passwd" value="bsp12345"/>
              </instance_attributes>
              <operations>
                <op id="prm_mysqld-start-0" interval="0" name="start" timeout="120s"/>
                <op id="prm_mysqld-stop-0" interval="0" name="stop" timeout="120s"/>
                <op id="prm_mysqld-monitor-20s" interval="20s" name="monitor" timeout="30s"/>
              </operations>
            </primitive>
          </master>
          <group id="group_zabbix">
            <primitive class="lsb" id="mysqld" type="mysqld">
              <operations>
                <op id="mysqld-start-0" interval="0" name="start" timeout="60">
                  <instance_attributes id="mysqld-start-0-instance_attributes">
                    <nvpair id="mysqld-start-0-instance_attributes-prereq" name="prereq" value="fencing"/>
                    <nvpair id="mysqld-start-0-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="mysqld-monitor-10" interval="10" name="monitor" timeout="60">
                  <instance_attributes id="mysqld-monitor-10-instance_attributes">
                    <nvpair id="mysqld-monitor-10-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="mysqld-stop-0" interval="0" name="stop" timeout="60">
                  <instance_attributes id="mysqld-stop-0-instance_attributes">
                    <nvpair id="mysqld-stop-0-instance_attributes-on_fail" name="on_fail" value="ignore"/>
                  </instance_attributes>
                </op>
              </operations>
            </primitive>
            <primitive class="lsb" id="httpd" type="httpd">
              <operations>
                <op id="httpd-start-0" interval="0" name="start" timeout="60">
                  <instance_attributes id="httpd-start-0-instance_attributes">
                    <nvpair id="httpd-start-0-instance_attributes-prereq" name="prereq" value="fencing"/>
                    <nvpair id="httpd-start-0-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="httpd-monitor-10" interval="10" name="monitor" timeout="60">
                  <instance_attributes id="httpd-monitor-10-instance_attributes">
                    <nvpair id="httpd-monitor-10-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="httpd-stop-0" interval="0" name="stop" timeout="60">
                  <instance_attributes id="httpd-stop-0-instance_attributes">
                    <nvpair id="httpd-stop-0-instance_attributes-on_fail" name="on_fail" value="ignore"/>
                  </instance_attributes>
                </op>
              </operations>
            </primitive>
            <primitive class="lsb" id="zabbix_server" type="zabbix_server">
              <operations>
                <op id="zabbix_server-start-0" interval="0" name="start" timeout="60">
                  <instance_attributes id="zabbix_server-start-0-instance_attributes">
                    <nvpair id="zabbix_server-start-0-instance_attributes-prereq" name="prereq" value="fencing"/>
                    <nvpair id="zabbix_server-start-0-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="zabbix_server-monitor-10" interval="10" name="monitor" timeout="60">
                  <instance_attributes id="zabbix_server-monitor-10-instance_attributes">
                    <nvpair id="zabbix_server-monitor-10-instance_attributes-on_fail" name="on_fail" value="restart"/>
                  </instance_attributes>
                </op>
                <op id="zabbix_server-stop-0" interval="0" name="stop" timeout="60">
                  <instance_attributes id="zabbix_server-stop-0-instance_attributes">
                    <nvpair id="zabbix_server-stop-0-instance_attributes-on_fail" name="on_fail" value="ignore"/>
                  </instance_attributes>
                </op>
              </operations>
            </primitive>
          </group>
        </resources>
        <constraints>
          <rsc_colocation id="zabbix_master" rsc="ms_mysqld" rsc-role="Master" score="INFINITY" with-rsc="group_zabbix"/>
          <rsc_order first="ms_mysqld" first-action="promote" id="mysql_master" score="INFINITY" then="group_zabbix" then-action="start"/>
        </constraints>
        <rsc_defaults>
          <meta_attributes id="rsc-options">
            <nvpair id="rsc-options-resource-stickiness" name="resource-stickiness" value="INFINITY"/>
            <nvpair id="rsc-options-migration-threshold" name="migration-threshold" value="1"/>
          </meta_attributes>
        </rsc_defaults>
      </configuration>
    </cib>
    

    ● 上記で作成したcib.xmlをheartbeatを起動したまま以下のコマンドで置き換えます。

    # cibadmin --replace --xml-file cib.xml.mysql_repl
    

    ● そうするとすぐにheartbeat側で反映されます。

    Online: [ zabbixcluster-1 zabbixcluster-2 ]
    
     Master/Slave Set: ms_mysqld
         Masters: [ zabbixcluster-1 ]
         Slaves: [ zabbixcluster-2 ]
     Resource Group: group_zabbix
         mysqld     (lsb:mysqld):   Started zabbixcluster-1
         httpd      (lsb:httpd):    Started zabbixcluster-1
         zabbix_server      (lsb:zabbix_server):    Started zabbixcluster-1
    

    heartbeatで用意されているOCFを使うとMySQLプロセスの他にMaster/Slaveの状態も監視して、フェイルオーバー時に自動で「CHANGE MASTER」迄実行してMasterとSlaveの切替をしてくれます。heartbeatのcolocationとorderで指定する事によって、MySQLがMasterで動いている方でZabbix、httpdを起動するクラスタが構成出来ます。(片系が壊れてもMasterで動いている方で稼働します。)

    ● MySQLレプリケーションで片系故障時

    Online: [ zabbixcluster-2 ]
    
     Master/Slave Set: ms_mysqld
         Masters: [ zabbixcluster-2 ]
         Stopped: [ prm_mysqld:0 ]
     Resource Group: group_zabbix
         mysqld     (lsb:mysqld):   Started zabbixcluster-2
         httpd      (lsb:httpd):    Started zabbixcluster-2
         zabbix_server      (lsb:zabbix_server):    Started zabbixcluster-2
    

    MySQLに障害が発生して長時間Slaveが止まっていたり、何等かの理由でMySQLが起動してもSlave側が同期してくれていない場合があります。この時pacemakerからはMaster/Slaveとして動作しているように見える為異常を検知しません。MySQLにログインしてSLAVEのステータス確認コマンドを実行しないとわかりません。

    ● スレーブの状態確認コマンド(スレーブ側で実行)

    mysql> show slave status\G
    

    ● コマンド結果

                   Slave_IO_State: Waiting for master to send event
                      Master_Host: zabbixcluster-2
                      Master_User: replicate
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000136
              Read_Master_Log_Pos: 455117
                   Relay_Log_File: mysqld-relay-bin.000002
                    Relay_Log_Pos: 455263
            Relay_Master_Log_File: mysql-bin.000136
                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
                  Replicate_Do_DB:
              Replicate_Ignore_DB:
               Replicate_Do_Table:
           Replicate_Ignore_Table:
          Replicate_Wild_Do_Table:
      Replicate_Wild_Ignore_Table:
                       Last_Errno: 0
                       Last_Error:
                     Skip_Counter: 0
              Exec_Master_Log_Pos: 455117
                  Relay_Log_Space: 455420
                  Until_Condition: None
                   Until_Log_File:
                    Until_Log_Pos: 0
               Master_SSL_Allowed: No
               Master_SSL_CA_File:
               Master_SSL_CA_Path:
                  Master_SSL_Cert:
                Master_SSL_Cipher:
                   Master_SSL_Key:
            Seconds_Behind_Master: 0
    Master_SSL_Verify_Server_Cert: No
                    Last_IO_Errno: 0
                    Last_IO_Error:
                   Last_SQL_Errno: 0
                   Last_SQL_Error:
      Replicate_Ignore_Server_Ids:
                 Master_Server_Id: 2
    1 row in set (0.00 sec)
    

    重要なところは、

                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
    

    の2つがYesとなっていないとMaster/Slave動作出来ていても実際はレプリケーションされていません。(他にもレプリの遅延時間とか見ないとなりませんが、とりあえずこの2つがYesでないとはじまりませんので。)Master側は動いているので監視は継続されますが、フェイルオーバーした際に不整合でZabbixがおかしくなります。

    この部分をZabbixで監視します。Slave側のMySQLへ接続して「show slave status\G」を実行するスクリプトを作成してZabbixの外部チェックで監視します。内容はSlave側のMySQLへ接続して「show slave status\G」を実行するものなら何でも良いです。本構成ではZabbixはMySQLがMasterで動作しているサーバで動くようになっていますのでフェイルオーバー後も問題無くSlaveの状態監視を継続出来ます。

    ※ 双方向で「show slave status\G」が実行出来るように権限設定しておく必要があります。

    スクリプトはこんな感じのものでも期待した動作してくれます。

    #!/bin/sh
    
    SLAVEHOST=`sudo /usr/sbin/crm_mon -1 | grep Slaves | sed 's/^  *//g' | awk '{print $3}'`
    STATUS="show slave status\\G"
    
    case "$1" in
    io)
    mysql -h $SLAVEHOST -e "$STATUS" | grep -w "Slave_IO_Running" | grep "Yes" | sed 's/^  *//g'
    ;;
    sql)
    mysql -h $SLAVEHOST -e "$STATUS" | grep -w "Slave_SQL_Running" | grep "Yes"| sed 's/^  *//g'
    ;;
    esac
    

    ● ZabbixでのSlave状態監視画面
    slavestatus

    これでSlave側の同期していない状態を検知出来ます。障害検知したら手動でMySQLレプリケーションの不整合を修正します。修正パターンが何パターンかありここの自動化は見合わせました。(無理に自動化するとトドメさしかねない。。)

    以上で3回に渡ってAWS上のZabbix冗長構成を、

    ● Pacemaker + RDS (1回目)
    ● Pacemaker + DRBD (2回目)
    ● Pacemaker + MySQLレプリケーション(3回目)

    のパターンで構築する方法のご紹介を終了します。

    MySQLのLOAD DATA INFILEで大はまりした話

    | 1件のフィードバック

    MySQLにCSVファイルをインポートする際にはLOAD DATA INFILE構文を使います。
    とあるシステムのテーブルにCSVファイルをインポートしたところ、なぜかシステムが正常に動作しなくなり大はまりしました。今回はそんなお話です。

    続きを読む