カテゴリー別アーカイブ: 未分類

AngularJS 自作ディレクティブ集

| コメントをどうぞ

シンプルなものがほとんどですが、今後も使えそうなものもあるので備忘録として載せておきます。

imgタグをsvgに置き換える

svgクラスが付加されたimgタグをsrcに指定されたsvgに置き換えます。CSSの疑似クラスを使ってsvg内の要素に効果を付けたい時などに使えます。(注:jQueryのロードが必要です)


.directive('img2svg', function($http){
  return {
    restrict: 'EA',
    link: function(scope, elm, attrs){
      $this = $(elm);
      $this.find('img.svg').each(function(){
        var $img = $(this);
        var imgURL = $img.attr('src');

        $http.get(imgURL, {cache:true}).success(function(data) {
          var $svg = $(data)[4];
          $img.replaceWith($svg);
        }, 'xml');
      });
    }
  }
})

サンプル:

<div img2svg>
  <img class="svg" src="hoge.svg">
  <img class="svg" src="piyo.svg">
</div>

特定のイベントを受け取った時に要素にフォーカスを移す

属性値に指定したイベントを要素が受け取った時にフォーカスを移します。


.directive('focusOnEvent', ['$timeout', function($timeout) {
    return {
      restrict:'A',
      link: function(scope, element, attrs) {
        scope.$on(attrs.ngFocusOnEvent, function(){
          $timeout(function() { 
            element[0].focus();
          });
        });
      }
    };
}])

サンプル:
HTML

<body ng-app="sample" ng-controller="SampleCtrl as sample">
  <button ng-click="sample.trigger('btnClicked')">フォーカスを移す</button>
  <input type="text" ng-focus-on-event="btnClicked">
</body>

Controller


.controller('SampleCtrl', ['$scope', function($scope){
  this.trigger = function(event){
    $scope.$broadcast(event);
  }
}]);

指定した値(モデル)と同じ値を持たないかチェック

バリデーション用のディレクティブです。ディレクティブを付与した要素のモデルの値とディレクティブで指定したモデルの値が一致しないかチェックします。


.directive('notSame', function(){
  return {
    require: 'ngModel',
    link: function(scope, $element, attrs, ctrl){
      var validator = function(viewValue) {
        var targetVal = scope.$eval(attrs.notSame);
        if(!viewValue) return viewValue;
        if(viewValue == targetVal){
          ctrl.$setValidity('notSame', false);
          return viewValue;
        }else{
          ctrl.$setValidity('notSame', true);
          return viewValue;
        }
      }
      ctrl.$parsers.unshift(validator);
      ctrl.$formatters.unshift(validator);
    }
  }
})

サンプル:

<div ng-form="form" ng-init="text1='hoge'; text2='hoge'">
  <input type="text" ng-model="text2" not-same="text1" name="textInput2">
  <span ng-show="form.textInput2.$error.notSame">エラー</span>
  <input type="text" ng-model="text3" not-same="'piyo'" name="textInput3">
  <span ng-show="form.textInput3.$error.notSame">エラー</span>
</div>

指定した値(モデル)以上かチェック

バリデーション用のディレクティブです。ディレクティブを付与した要素のモデルの値が指定した値以上かチェックします。不等号を変えれば以下や未満などもできると思います。


.directive('greaterEqual', function(){
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, $element, attrs, ctrl){
      var validate = function(viewValue) {
        var targetVal = scope.$eval(attrs.greaterEqual);
        if(viewValue === undefined || viewValue.length == 0) {
          ctrl.$setValidity('greaterEqual', true);
          return viewValue;
        }
        if(viewValue < targetVal || !isFinite(viewValue)){
          ctrl.$setValidity('greaterEqual', false);
          return viewValue;
        }else{
          ctrl.$setValidity('greaterEqual', true);
          return viewValue;
        }
      };
      ctrl.$parsers.unshift(validate);
      ctrl.$formatters.unshift(validate);
    }
  }
})

ブラウザのリサイズ時に何か処理を行う

サイズ変更時にブラウザが発生させるイベントを拾って属性値に指定したイベントハンドラを実行します。また、スコープにイベントを通知します。


.directive('resize', ['$rootScope', '$window', '$timeout', function($rootScope, $window, $timeout){
  return {
    restrict: 'EA',
    scope: {
      resize: '&'
    },
    link: function(scope){
      var timer = false;
      angular.element($window).on('load resize', function(e){
        if(timer) $timeout.cancel(timer);

        timer = $timeout(function(){
          scope.resize();
        }, 200);
        
      });
    }
  }
}]);

サンプル:
HTML

<body ng-app="sample" ng-controller="SampleCtrl as sample">
  <div resize="sample.resizeHandler()"></div>
</body>

Controller


.controller('SampleCtrl', ['$scope', function($scope){
  this.trigger = function(event){
    $scope.$broadcast(event);
  }

  this.resizeHandler = function(){
    alert('リサイズされました');
  }
}]);

バリデーションエラーをUI Bootstrapのtooltipに表示させる

以前の記事をご覧ください。

Google Maps API マーカー画像

| コメントをどうぞ

Google Maps APIでは任意の画像をマーカーに使用することができますが、自前で用意しなくてもGoogleが提供している多数のマーカー用画像があります。
APIのリファレンスページには特に一覧がまとめられているところがなかったのでまとめてみました。
各画像のURLは画像を右クリックして「画像のURLをコピー」から取得してください。

マーカー:

続きを読む

AWS Market Placeから作成したインスタンスのVolumeを他インスタンスにアタッチしたい。

| コメントをどうぞ

AWSのMarketPlaceから作成したインスタンスのVolumeってProductCodeがついていて、他のインスタンスにセカンダリディスクとしてつけようとすると、Rootデバイス以外にはアタッチ出来ないメッセージが出てはじかれます。

ログイン出来なくなってしまったようなトラブル時に復旧作業が出来ません。。

でも、前は出来たような・・・?自分もiptablesでSSHを閉じちゃってしかも自動起動で
にっちもさっちもの状態になったんですが、前にAWSセミナーに参加した際にエバンジェリストにその事を質問したら「別のインスタンスのセカンダリディスクとしてつければ復旧可能ですよ」と言われて戻った時に試したらそれで復旧できた記憶があります。

・・・で、ちょっと前にSSHを起動できなくしたインスタンスのVolumeを別のインスタンスのセカンダリにつけて復旧させてようとしたらこれが出来ない。rootデバイスじゃないと駄目だよってメッセージでます。ネットで検索してみるとどうやらMarketPlaceから作ったインスタンスのVolumeは他のインスタンスのセカンダリデバイスとしてアタッチ出来ない制限があるらしい。
ログイン出来ないようなトラブル時には一度AWSサポートへお願いして制限を解除してもらうしかない模様。

・・・そうなんだ。。AWSサポート画面を開いてみる。

・・・サービス上限緩和のメニューしか無いよ?

このAWSアカウントは無料サポートのBASICにしか加入してないからこの手のサポートが受けれない・・・?

フォーラムに投げてみると個別対応しますね。というレスついてメールが来たけど文面から察するに有料サポートよろしく的な事っぽかった。

ログイン出来ないインスタンスはTerminateしてやりました。

どうやらMarketPlaceから作ったインスタンスのVolumeにはProductCodeがひっついていて、これがあるとrootデバイス以外にはアタッチできない仕様になっていた!
(前はこんな制限無かった記憶が・・・。上にも書きましたが。)

無料サポートのBASICの人はMarketPlaceから作ったインスタンスでログイン不能にすると詰みます!

ここで海外の掲示板で抜け道を発見。ProductCodeはOS内部にデータとしてあるわけではないようでMarketPlaceで作成したインスタンスのVolumeの中のデータを新規作成したVolumeに移してしまえばOKと書いてある。やってみよう。

  1. MarkePlaceからインスタンス作成
  2. 同じサイズのまっさらのVolumeを作成した↑のインスタンスにセカンダリとしてアタッチ
  3. まっさらのVolumeをフォーマット(ここではxvdj)
  4. # mkfs -t ext4 /dev/xvdj
    
  5. ddコマンドでコピー
  6. # dd bs=65536 if=/dev/xvde of=/dev/xvdj
    
  7. ProductCodeが無いVolumeの出来上がり!

やってみたところ出来上がったVolumeはrootデバイスとして起動出来るし他のインスタンスにセカンダリデバイスとしてもアタッチ出来ました。これなら起動不能やログイン不能になっても復旧作業出来ます。

ただ、この作業をしたインスタンスを使用していく必要があるので普通に作成して使用していたインスタンスがトラブル発生した場合は当然手も足もでません。

インスタンス作成時に最初にこの作業してから使っていった方が良いかもしれませんね。

しかし・・・

ProductCodeを除去するこのような作業をしたインスタンスを使っていく場合は以降AWSのサポート外になる模様。。

うーん。。でもそもそも無料サポートのBASICは上限緩和しかサポートメニュー無いから恐れる事はないか・・・?

PostgreSQLとOracleで緯度経度から半径nメートル内検索を実行してみる。

| コメントをどうぞ

昨今では各種データベースで地図情報を扱うジオメトリ型がサポートされています。
今回はその中からPostgreSQL(+ PostGIS)とOracle(+ Oracle Spatial)についてデータベースに保存された緯度経度から半径nメートル内にある対象を検索する方法についてご紹介します。

続きを読む

org.json.JSONObjectにおけるnullの取扱い

| コメントをどうぞ

java.util.HashMapだとキー自体が存在しない場合はnullを返却してくれるのですが、org.json.JSONObjectはエラーを投げてきます。

Map<String, String> map = new HashMap<String, String>();
JSONObject json = new JSONObject();

Object mo = map.get("test");
<!--more-->

// org.json.JSONExceptionが発生(JSONObject["test"] not found.)
Object jo = json.get("test");

よって構造が不明なJSONObjectの場合、JSONObject # get()する前にキーの存在のチェック等をする必要があります。

キーの存在およびJSON値nullかどうかの判定方法を、以下の例を用いて示します。

JSONの例

{
    a : "json",
    b : 123,
    c : null
}

JSONObject # isNull()

値がnullまたはキー自体が存在しない場合はtrueを返却してくれます。

json.isNull("c") -> true
json.isNull("d") -> true

なお値がnullJSONは、JSONObject.NULLオブジェクトとして扱われます。

jo.get("c") == JSONObject.NULL -> ture

以下の方法はオブジェクトがnullかどうかの判定のため、JSON値null判定はできません。

json.get("c") == null -> false

JSONObject # has()

キーが存在する場合はtrueを返却してくれます。

json.has("c") -> true
json.has("d") -> false

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回目)

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

    AWS上のZabbixをPacemakerで冗長化 その2(DRBD編)

    | コメントをどうぞ

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

    ● Pacemaker + DRBD

    をやります。


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

  • Pacemaker(HeartbeatV2) + DRBD

  • cluster2

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

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

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

    ● 一旦heartbeatを起動

    # /etc/init.d/heartbeat start
    

    DRBD用のxmlファイルを置いて起動するつもりでしたが、何故かうまく行かず一旦起動後に置き換える
    方法を取らないとならなくなっている為。heartbeatでxmlを修正したのにうまく行かない事がありますが
    その場合も置き換えで上手く行く場合が多いです。

    ● 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+DRBD用のファイルを以下のようにどこかのディレクトリ(/tmpなどどこでもOK)用意します。

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

    <cib validate-with="pacemaker-1.0" crm_feature_set="3.0.1" have-quorum="1" dc-uuid="e1c9433f-8e5b-8681-2867-5a4dd5880dfe" admin_epoch="0" epoch="20" num_updates="0" cib-last-written="Wed Sep 17 10:46:40 2014">
      <configuration>
        <crm_config>
          <cluster_property_set id="cib-bootstrap-options">
            <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"/>
            <nvpair id="cib-bootstrap-options-default-resource-stickiness" name="default-resource-stickiness" value="200"/>
            <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"/>
          </cluster_property_set>
        </crm_config>
        <nodes>
          <node id="f76af805-bfff-66bd-3d83-95a20a3807ef" uname="zabbixcluster-1" type="normal"/>
          <node uname="zabbixcluster-2" type="normal" id="e1c9433f-8e5b-8681-2867-5a4dd5880dfe">
            <instance_attributes id="nodes-e1c9433f-8e5b-8681-2867-5a4dd5880dfe"/>
          </node>
        </nodes>
        <resources>
          <master id="ms_drbd_r0">
            <meta_attributes id="ms_drbd_r0-meta_attributes">
              <nvpair id="ms_drbd_r0-meta_attributes-master-max" name="master-max" value="1"/>
              <nvpair id="ms_drbd_r0-meta_attributes-master-node-max" name="master-node-max" value="1"/>
              <nvpair id="ms_drbd_r0-meta_attributes-clone-max" name="clone-max" value="2"/>
              <nvpair id="ms_drbd_r0-meta_attributes-clone-node-max" name="clone-node-max" value="1"/>
              <nvpair id="ms_drbd_r0-meta_attributes-notify" name="notify" value="true"/>
            </meta_attributes>
            <primitive class="ocf" id="drbd_r0" provider="linbit" type="drbd">
              <instance_attributes id="drbd_r0-instance_attributes">
                <nvpair id="drbd_r0-instance_attributes-drbd_resource" name="drbd_resource" value="r0"/>
              </instance_attributes>
              <operations>
                <op id="drbd_r0-monitor-20" interval="20" name="monitor" role="Slave" timeout="20"/>
                <op id="drbd_r0-monitor-10" interval="10" name="monitor" role="Master" timeout="20"/>
                <op id="drbd_r0-start-0" interval="0" name="start" timeout="240"/>
                <op id="drbd_r0-stop-0" interval="0" name="stop" timeout="100"/>
              </operations>
            </primitive>
          </master>
          <group id="group_zabbix">
            <primitive class="ocf" id="mount_r0" provider="heartbeat" type="Filesystem">
              <instance_attributes id="mount_r0-instance_attributes">
                <nvpair id="mount_r0-instance_attributes-device" name="device" value="/dev/drbd0"/>
                <nvpair id="mount_r0-instance_attributes-fstype" name="fstype" value="ext4"/>
                <nvpair id="mount_r0-instance_attributes-directory" name="directory" value="/drbd0"/>
                <nvpair id="mount_r0-instance_attributes-options" name="options" value="noatime"/>
              </instance_attributes>
              <operations>
                <op id="mount_r0-monitor-10" interval="10" name="monitor" timeout="60"/>
                <op id="mount_r0-start-0" interval="0" name="start" timeout="60"/>
                <op id="mount_r0-stop-0" interval="0" name="stop" on-fail="stop" timeout="60"/>
              </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="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="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="db_on_drbd" rsc="mount_r0" score="INFINITY" with-rsc="ms_drbd_r0" with-rsc-role="Master"/>
          <rsc_order first="ms_drbd_r0" first-action="promote" id="order_db_after_drbd" score="INFINITY" then="group_zabbix" then-action="start"/>
        </constraints>
      </configuration>
    </cib>
    

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

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

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

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

    heartbeatで用意されているOCFを使うとDRBDプロセスの他にMaster/Slaveの状態も監視してくれるのでheartbeatのcolocationとorderで指定する事によって、DRBDがMasterで動いている方でZabbix、mysql、httpdを起動するクラスタが構成出来ます。(片系が壊れてStandAloneになってもMasterで動いている方で稼働します。)

    ● DRBDで片系故障時

    Online: [ zabbixcluster-2 ]
    OFFLINE: [ zabbixcluster-1 ]
    
     Master/Slave Set: ms_drbd_r0
         Masters: [ zabbixcluster-2 ]
         Stopped: [ drbd_r0:0 ]
     Resource Group: group_zabbix
         mount_r0   (ocf::heartbeat:Filesystem):    Started zabbixcluster-2
         httpd      (lsb:httpd):    Started zabbixcluster-2
         mysqld     (lsb:mysqld):   Started zabbixcluster-2
         zabbix_server      (lsb:zabbix_server):    Started zabbixcluster-2
    

    Zabbixサーバに意図的に障害を起こさせるテストをしていた際に気づいたのですが、状況によってはZabbixサーバが完全に死なない場合があります。親プロセス(usr/sbin/zabbix_server -c /etc/zabbix/zabbix_server.conf)のみがしぶとく生き残る為にheartbeatからは生きているように見えるのですが、実際は監視自体は止まってしまっている場合があります。今回発生が確認出来たのはMySQLは動いているけどZabbixは接続出来ないという状態を動作中に発生させた場合になりました。何らかの対処が必要になります。

    Font Awesomeをpngで出力できるツールまとめ

    | 1件のフィードバック

    とても便利なFontAwesomeですが、マルチブラウザ対応やパフォーマンスを考えてどうしても静止画像にしたい場合もあります。
    というわけでFont Awesomeをpngにするツールを調べたのでまとめです。
    色々なツールがあり、いいところ・惜しいところあります。
    場合により組み合わせて使うと便利だと思います。
    続きを読む

    AWS上のZabbixをPacemaker(HeartbeatV2)で冗長化

    | 1件のフィードバック

    AWS上で監視システムにZabbixを動かしておられる方も多いかと思います。AWSとZabbixは相性が良いので今後も増えていくと予想されます。しかしZabbix単体では冗長構成をとる機能が無い為、Zabbixが停止すると監視も止まります。「ちょっとくらい監視がとまっても業務は止まらないから良い。」と割り切れる場合はOKですが、監視が止まったら困るケースもあります。監視をサービス提供している場合は特にそうなります。じゃあ冗長化しましょうという事になりますが、商用のクラスタソフトはなかなかお高く手が出しづらい状況です。そこでオープンソースのツールを使って冗長化します。

    Pacemaker(Heartbeat)で無料でZabbixを冗長化

    Linuxでは古くからLinux-HAというプロジェクトがありHeartbeatというツールがあります。HeartbeatV1→V2→V3と進化してミドルウェアの制御部分を分離してPacemakerとなりました。V2(たぶんV3も)まではHeartbeatがミドルウェア部分も制御していました。
    (V2までしか触ってなかったのでここらへんの知識はあいまい。)
    歴史がありますので実績も十分です。(商用環境でも採用されています。)
    HeartbeatとLVS(LinuxVirtualServer)を組み合わせてロードバランサーを安価に構築したりする事も可能です。
    ただ、昔は実機のロードバランサーが高価だった為に結構構築されていましたが、今はAWSでELBとか出てきたのであまり見かけなくなりました。

    HeartbeatV1

    初期のころのHeartbeatでOS単位で冗長化出来ます。フェイルオーバー時に待機系でキックするミドルウェアを指定可能です。(メジャーなミドルウェア最初からリソースエージェントが用意されています。無い場合は作りますがシンプルなので容易に作成できると思います。)

    但しフェイルオーバーのトリガーに出来るのはOSの死活のみでミドルウェアが停止してもOSが生きていたらフェイルオーバーはしてくれません。この為当時は別途シェルスクリプトなどと連携させてミドルウェアが停止したらHeartbeatの切替コマンドを実行させるなどで強引に対応しました。また、クラスタ構成は1対1の2台構成までです。

    HeartbeatV2~

    V2になって進化してミドルウェアもフェイルオーバー対象に出来るようになりました。クラスタ構成も1対Nが
    可能になり、3台クラスター、5台クラスターという構成も可能になりました。但しcib.xmlファイルというものを作成する必要があり、更には冗長構成にするには色々と複雑な設定をしていく必要がありました。この為、この時代でもHeartbeatV1を利用しているケースが結構ありました。ただ、メジャーなミドルウェアは最初からOCF(OpenClusterFramework)というものが用意されているのでこちらを利用すると冗長化はしやすいです。(無い場合は自分で作成)

    Pacemaker

    V2にあったミドルウェアを制御するcrm(クラスタリソースマネージャ)分離してpacemakerになり、GUIで設定出来たり、crm configureで簡単にクラスタ構成を組めるようになったようです。何故「~ようです」と書いたかというと使ってみた感じ劇的に簡単になったか?と聞かれると微妙・・・。cib.xmlを書いた経験のある方ならcib.xmlを手書きしてしまっても構わないような感じではあります。ちなみにGUI版は触った事ないのでわかりません。

    AWS上でHeartbeatで冗長化するには?

    前置きが長くなりましたが、ここからAWSで冗長化を考えます。Heartbeat及びpacemakerはクラウドとか流行るより昔に生まれたので実機(オンプレミス)での冗長構成を念頭に開発されている部分があります。(シリアルケーブルで死活通信が可能など。)
    どのサーバがサービス稼働中なのかの区別にサービス稼働中にVIPをつける方式がとても多いです。WEBサーバを冗長構成で組んでいるとして、エンドユーザにはVIPにアクセスさせます。Heartbeatがフェイルオーバー時に待機系にVIPを付け替える事によってエンドユーザはサーバが切り替わっても継続したサービスを受けれる仕組みです。しかしAWSではこの方式だと問題があります。

    AWSはマルチキャストのパケットが通らない。

    仕様上許しておらずマルチキャストパケットは破棄されます。何が困るかというとVIPを付け替える際にブロードキャストして知らせるわけですが、AWSでは破棄されるので勝手にVIP名乗っているだけで誰も(周りのサーバは)VIPを知らないので通信できません。ですので、

    VIPの変わりにELBで代用します。

    エンドユーザのアクセスをELBにしてELBのヘルスチェックを使って稼働系のインスタンスへ振り分ける事でこの問題が回避出来きるのでELB+Pacemaker(HeartbeatV2)を基本設計にAWS上でのZabbixの冗長化を行います。ZabbixをAWSで冗長構成を組むのに大まかに以下のパターンがあります。

    1. Pacemaker(HeartbeatV2) + RDS

    2. cluster1

      ● AWS上でVPC内にAvailabilityZoneをActiveとStandbyで分けてZabbixを動かしDR対応させる。
      ● AWSではマルチキャストを通さない仕様でVIP方式の冗長が利用出来ない為、ELBによるヘルスチェックを実施。
      ● データベースをRDS Multi-Azを採用することにより、汎用性、運用効率を上げる。
      ● Pacemakerでミドルウェア単位でグループ化してActive-Standbyの冗長を構成。
         グループ:Apache,Zabbix,Swatch
              ※Apacheは常時起動でそれ以下をグループ化してもOK

      ・・・なんでSwatchがいるの?と言うとやってみて分かった事ですがRDSのフェイルオーバー後はZabbixサーバが止まります。毎回DBに接続するアプリであれば問題は無いのですがZabbixのようなDBに接続しっぱなしのdaemonなどは一旦切断して再接続しないとならないようです。ここにも書いてありました。

      Amazon Web Services ブログ
      http://aws.typepad.com/aws_japan/2012/05/multi-az-option-for-amazon-rds-for-oracle-database.html

      そこでこの問題を、

      ● RDSフェイルオーバー時にZabbixの監視が停止する問題をSwatchで対処。している為クラスタグループにSwatchがいます。(他に妙案が浮かばなかった。。)

      動かした状態のクラスタモニタ

      Online: [ zabbixcluster-1 zabbixcluster-2 ]
      
       Resource Group: zabbixcluster
           apache     (lsb:httpd):    Started zabbixcluster-1
           zabbix_server      (lsb:zabbix_server):    Started zabbixcluster-1
           swatch     (lsb:swatch):   Started zabbixcluster-1
      

    3. Pacemaker(HeartbeatV2) + DRBD

    4. cluster2

      ゾーンを分けてELBでヘルスチェックまでは基本同じで、
      ● データベースをMySQL、データ格納領域をDRBDで同期。
      ● Pacemakerでミドルウェア単位でグループ化してActive-Standbyの冗長を構成。 
         クラスタグループ:Apache,Zabbix,MySQL,DRBD
                  ※DRBDのMaster/Slave切替もPacemakerで制御。

      動かした状態のクラスタモニタ

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

    5. Pacemaker(HeartbeatV2) + MySQLレプリケーション

    6. cluster3



    ゾーンを分けてELBでヘルスチェックまでは基本同じで、
    ● データベースをMySQL、データをレプリケーションでSlaveに同期。(Semi-Sync方式)
    ● Pacemakerでミドルウェア単位でグループ化してActive-Standbyの冗長を構成。
       クラスタグループ:Apache,Zabbix,MySQL
                ※MySQLのMaster/Slave切替もPacemakerで制御。

    動かした状態のクラスタモニタ

    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
    

    それぞれのメリット/デメリット

    RDS採用のメリット/デメリット
    ● メリット

    1. AWSコンソールからLaunch出来るので導入がし易い。
    2. バックアップ/リカバリの方法もスナップショットで行える。
    3. EC2インスタンスとRDSが分離しているのでEC2インスタンスだけインスタンスタイプを変更したり、RDSだけインスタンスタイプを変更したりといった運用が可能。

    ● デメリット

    1. EC2インスタンスとRDSインスタンスの料金が発生する。Multi-AZにする場合は更に費用が発生。
    2.      ※結構馬鹿にならない料金になります。ここが最大のネック。

    3. RDSはデータベースの管理者権限が取得出来ない為、それに伴う諸々の不便さが存在する。
    4. RDSは時刻がUTCだったりと日本仕様で無い部分があり対策が必要。
    5. フェイルオーバーにかかる時間がDRBDやMySQLレプリケーションより遅い。

    DRBD採用のメリット/デメリット
    ● メリット

    1. 離れたディスク(Volume)をRAID1のように利用出来る為、データの整合性が高い。
    2. カーネルモジュールで動作する為、CPUやメモリへの負担が小さい。
    3. Volume間を繋ぐ回線速度が速いほどデータのディスク性能を上げる事が出来る。
    4. RDS採用よりもコストを抑えられる。

    ● デメリット

    1. ディスク性能が回線速度に大きく依存する為、速い回線にする必要がある。AWSではインスタンスタイプで回線速度が決まっている為、CPU、メモリに余裕があってもDRBDの為だけにインスタンタイプを高スペックにする必要がある。
    2. データを同時に書き込む仕様で不整合が発生しにくいはずだが、AWSでは発生しやすく、同期がはずれてStandAloneの状態になりやすい。
    3. ※特に大きいファイルが一瞬で書き終わる時に発生しやすい模様。有り得ない早さで書き終わる時があるのでAWS側のパフォーマンスを上げる為の仕組みか何かが作用しているかもしれません。ストレージゲートウェイでも似たような事象があるのでEC2インスタンスもデータを書き込む時にキャッシュしたりしてるかもしれません。

    4. 不整合発生時のリカバリ時など運用面で効率はRDSに劣る。

    MySQLレプリケーションのメリット/デメリット
    ● メリット

    1. 広く利用されてきた方式の為、情報が豊富で導入や運用がし易い。
    2. DRBDよりも同期速度は速い。
    3. MySQL5.5以降の機能のSemi-Syncを使うとデータの整合性が高くなる。
    4. RDS採用よりもコストを抑えられる。

    ● デメリット

    1. DRBD程ではないが、性能は回線速度に依存する。
    2. CPUやメモリへの負担はDRBDよりも高い。
    3. Semi-Syncを採用してもDRBDより整合性では劣る。
    4. 不整合発生時のリカバリ時など運用面で効率はRDSに劣る。



    これらを踏まえて実際に構築して比べてみると性能面では、

    RDS > MySQLレプリ > DRBD
    

    耐障害性(フェイルオーバーの迅速さ)では、

    DRBD > MySQLレプリ > RDS
    

    導入の容易さや運用効率では、

    RDS > MySQLレプリ > DRBD
    

    と、感じましたがここらへんはもっと時間をかけて調査しないと何とも言えない部分もあります。。
    DRBDはmicroだとかなり厳しいパフォーマンスでしたが、largeに上げたら一昔前のハードディスクくらいの性能出しましたし、MySQLレプリもSemi-SyncだとDRBDじゃなくても良いんじゃないか?という整合性を保ってくれます。更にはAWSのDRBDは単に構築した段階ではうまく同期とれているように見えましたが、ディスクに大きいデータを書き込むような状況下では不整合しやすかったりなど(DRBDって同時書込みのはずなのに)
    まだまだテストや工夫しないとならないようです。

    では、各パターンの実際の設定やちょっとしたテストに入って行きたいと思いますが、長くなりましたので次回書きます。次回はパターンの1つめの、

  • Pacemaker(HeartbeatV2) + RDS
  • の設定とテスト結果を書きます。

    EclipseのTomcat Loaderで各種ログファイルを出力する

    | コメントをどうぞ

    EclipseでWebアプリケーションを開発する際、Tomcat Loaderを利用しているのですが、デフォルトの設定ではTomcatの各種ログファイルが出力されません。

    普段はあまり問題にならないのですが、デバッグの際にログファイルが必要になることがあります。
    今回はEclipseからTomcatを起動する際のログ出力設定についてご紹介します。・・・と言うか自分の備忘録ですが・・・

    続きを読む