Thirdware Linux-HA による nginx Web サーバのクラスタ構築 HOWTO 2012 年 3 月 1 日初版 株式会社サードウェア
目次 1 はじめに...1 1.1 対象読者...1 1.2 想定するサーバ環境...1 1.3 注意事項...1 2 OS 環境の準備...2 2.1 CentOS 6.2 のインストールと初期設定...2 2.2 Thirdware Linux-HA クラスタスタックのインストール...2 RHEL6 CentOS6 Scientific Linux 6 の場合...2 RHEL5 CentOS5 の場合...2 2.3 nginx パッケージのインストール...3 3 DRBD の設定...3 4 nginx クラスタ化のためのデータ領域の準備...5 5 nginx クラスタの構築...5 6 nginx リソースエージェント...7
改訂履歴 版番号改訂年月日作成者備考 1 2012 年 3 月 1 日 mkubo 初版作成
1 はじめに nginx ( えんじんえっくす と発音 ) はロシアの Igor Sysoev が開発 配布するオープンソースの Web サーバソフトウェアで リバースプロキシサーバやメールプロキシとしても利用できる 少ないリソースで軽快に動作することや設定の容易さから nginx を採用する Web サイトが急速に増えている 開発者自身による商用サポートが始まったこともあって 今後さらに採用事例が増加すると期待されている 本書では Thirdware Linux-HA クラスタスタックを使って nginx を HA クラスタとして動作させるための設定手順の概要を紹介する 1.1 対象読者 このドキュメントは 以下の知識や経験を有する技術者を対象としている Linux サーバのインストール 運用管理ができること Thirdware Linux-HA による HA クラスタシステムの構築と運用の基礎知識を持っていること nginx のインストールと運用ができること 本書では Linux のインストールからクラスタ構築までの流れをひととおり説明するが 初心者向けとしては説明が不親切な箇所があるかもしれない 1.2 想定するサーバ環境 本書が想定するサーバ環境は Linux ならびに nginx が動作する IA サーバ (32 ビット 64 ビット ) である 以下の説明では KVM 仮想環境のゲスト OS を用いている そのハードウェアおよびソフトウェアの特徴は以下のとおりである 仮想 CPU は 1 個 メモリは 512MB 割り当ててある 仮想ディスクは 8GB を割り当ててある ( デバイス名は /dev/vda) 仮想ネットワークインタフェースは 3 つ割り当ててある (et0 eth1 eth2) CnetOS 6.2 (64 ビット ) を最小構成でインストールしてある 仮想ディスクは OS 領域に 4 ギガバイト スワップ領域に 500 メガバイト DRBD によるレプリケーション領域に残り全部を割り当てる 1.3 注意事項 本書は nginx を HA クラスタ構成にするための基本的な流れを説明したマニュアルという位置付けになっている このため 各種設定パラメータも必要最小限の項目に絞っている パフォーマンスや運用上のポリシーにもとづく追加パラメータは含まれていない 株式会社サードウェア 1
2 OS 環境の準備 Thirdware Linux-HA による nginx Web サーバのクラスタ構築 HOWTO 2.1 CentOS 6.2 のインストールと初期設定 ステップ 1: Linux をインストールする CentOS 6.2 の DVD イメージを使って OS をインストールする ハードディスクのパーティションを作成するときに カスタム を選び DRBD によるレプリケーション領域を空けておくこと以外は 一般的なインストール手順と変わらない ステップ 2: SELinux を無効にするインストール後最初の起動時に SELinux を無効にする (/etc/sysconfig/selinux の SELINUX= 行を enforcing から disabled に書き換える ) ステップ 3: パケットフィルタリングを調整する DRBD や heartbeat はクラスタノード間の通信が不可欠なため クラスタノード間の 7788/tcp 694/udp 22/tcp を宛先とするパケットを許可するよう iptables ( または ip6tables) のフィルタリング定義を調整する ネットワークを設定するネットワークは 以下の条件を満たすように設定する これは インストール時でもインストール後の調整でもかまわない eth0 はサーバセグメントの LAN に接続する eth1 および eth2 は クラスタノード間で通信できるような IP アドレスを設定する ( 物理サーバを使う場合は eth1 同士 eth2 同士をネットワークケーブルで直結することを推奨する ) 2.2 Thirdware Linux-HA クラスタスタックのインストール LINBIT クラスタスタック サポート契約ユーザ向けに提供される認定バイナリのリポジトリを使うのがもっとも間違いが少なく 将来のメンテナンスも容易になる 未契約ユーザの場合は 以下のパッケージを使うのがよいと思われる (2012 年 2 月現在 ) ただし 以下の方法は未検証である RHEL6 CentOS6 Scientific Linux 6 の場合 Heartbeat および Pacemaker は Linux-HA Japan プロジェクト 1 が提供している Pacemaker リポジトリパッケージ が利用できる DRBD のバイナリ RPM パッケージは ELRepo プロジェクト 2 が DRBD 8.3.x の最新バージョンを提供しているので これを利用するといいと思われる RHEL5 CentOS5 の場合 Heartbeat および Pacemaker は Linux-HA Japan プロジェクト 3 が提供している Pacemaker リポジトリパッケージ が利用できる DRBD のバイナリ RPM パッケージは CentOS extra リポジトリに drbd83 パッケージが用意されているので これを使うのがいいと思われる 1 http://linux-ha.sourceforge.jp/wp/dl/packages 2 http://elrepo.org/tiki/tiki-index.php 3 http://linux-ha.sourceforge.jp/wp/dl/packages 株式会社サードウェア 2
2.3 nginx パッケージのインストール nginx は 同ソフトの開発コミュニティ Web サイト (http://nginx.org/en/download.html) から安定バージョンのビルド済みパッケージをダウンロードできるので これを使った 3 DRBD の設定 ステップ 1: レプリケーション用パーティションを確保するインストール時に空けておいたディスク領域を fdisk コマンドなどでパーティションとして確保する 必要に応じて再起動して OS にパーティションを認識させる 以下の例では /dev/vda3 が DRBD のレプリケーション領域である ステップ 2: DRBD 設定ファイルを作成するクラスタのどちらか 1 台で DRBD 設定ファイルを作成し 他方に ssh コマンドでリモートコピーする 設定例は以下のようになる /etc/drbd.conf # You can find an example in /usr/share/doc/drbd.../drbd.conf.example include "drbd.d/global_common.conf"; include "drbd.d/*.res"; /etc/drbd.d/global_common.conf global { usage-count yes; # minor-count dialog-refresh disable-ip-verification common { protocol C; handlers { pri-on-incon-degr "/usr/lib/drbd/notify-pri-on-incon-degr.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f"; pri-lost-after-sb "/usr/lib/drbd/notify-pri-lost-after-sb.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f"; local-io-error "/usr/lib/drbd/notify-io-error.sh; /usr/lib/drbd/notify-emergency-shutdown.sh; echo o > /proc/sysrq-trigger ; halt -f"; # fence-peer "/usr/lib/drbd/crm-fence-peer.sh"; # split-brain "/usr/lib/drbd/notify-split-brain.sh root"; # out-of-sync "/usr/lib/drbd/notify-out-of-sync.sh root"; # before-resync-target "/usr/lib/drbd/snapshot-resync-target-lvm.sh -p 15 -- -c 16k"; # after-resync-target /usr/lib/drbd/unsnapshot-resync-target-lvm.sh; startup { # wfc-timeout degr-wfc-timeout outdated-wfc-timeout wait-after-sb disk { # on-io-error fencing use-bmbv no-disk-barrier no-disk-flushes 株式会社サードウェア 3
# no-disk-drain no-md-flushes max-bio-bvecs net { max-buffers # max-epoch-size ko-count allow-two-primaries cram-hmac-alg sharedsecret # after-sb-0pri after-sb-1pri after-sb-2pri data-integrity-alg notcp-cork # sndbuf-size rcvbuf-size timeout connect-int ping-int ping-timeout syncer { # rate after al-extents use-rle cpu-mask verify-alg csums-alg /etc/drbd.d/r0.res resource r0 { protocol C; syncer { rate 60M; disk { on-io-error detach; device /dev/drbd0; disk /dev/vda3; on nginx1.example.com { address 10.10.0.1:7788; meta-disk internal; on nginx2.example.com { address 10.10.0.2:7788; meta-disk internal; ステップ 3: メタデータ領域を作成する両方のクラスタノードで次のコマンドを実行する drbdadm create-md r0 ステップ 4: 初期同期を実行する両方のクラスタノードで DRBD を起動する /etc/init.d/drbd start どちらか一方のノードを初期プライマリ状態に昇格して レプリケーション領域全体をフル同期する drbdadm -- --overwrite-data-of-peer primary r0 ステップ 5: DRBD レプリケート領域にファイルシステムを作成する CentOS 6.2 では ext4 ファイルシステムがデフォルトのファイルシステムなので DRBD レプリケート領域に ext4 ファイルシステムを作成する 株式会社サードウェア 4
mkfs.ext4 /dev/drbd0 以上のステップを実行することによって DRBD レプリケーション領域が初期化され HA クラスタのための共有ディスクとして使用できるようになる 4 nginx クラスタ化のためのデータ領域の準備 コミュニテイサイトからダウンロードした nginx パッケージは 設定ファイルが /etc/nginx コンテンツ領域が /usr/share/nginx ディレクトリになっている HA クラスタシステムでは アクティブなノードがこれらの領域にアクセスできるよう 準備を行う必要がある 共有データ領域にアクセスするには (1) 共有データ領域を /usr/share/nginx ディレクトリにマウントする (2) 別のマウントポイントにマウントした共有データ領域に対するシンボリックリンクを張る という 2 とおりの方法が考えられる ここではシンボリックリンクを使うこととする ステップ 1: DRBD レプリケート領域のためのマウントポイントを作成する両ノードで適当なマウントポイントディレクトリを作成する ( ここでは /h という名前を使う ) mkdir /h ステップ 2: プライマリノードで共有データ領域をマウントするどちらか一方のノードの DRBD をプライマリに昇格させ //h にマウントする drbdadm primary r0 mount /dev/drbd0 /h ステップ 3: プライマリノードでコンテンツ領域を共有データ領域にコピーする mkdir -p /h/usr/share cp -a /usr/share/nginx /h/usr/share ステップ 4: 両ノードで共有データ領域に対するシンボリックリンクを作成する mv /usr/share/nginx /usr/share/nginx.orig ln -sf /h/usr/share/nginx /usr/share/ 現在セカンダリになっているノードでは 壊れたシンボリックリンク が作成されるが クラスタとしてアクティブな状態になった場合には 正常に共有データ領域にアクセスできる 設定ファイル (/etc/nginx) についても 同様のシンボリックリンクを張っておくことができる このようにしておけば アクティブノードで 1 回だけ設定を変更すれば フェールオーバしてもその設定が引き継がれるようになる 5 nginx クラスタの構築 nginx のクラスタシステムの構成は ターゲットプログラムが違うことを除いて 他のサーバアプリケーションのクラスタシステムと同じである すなわち クラスタとして以下のリソースを制御する必要がある クライアントにサービスを提供するための仮想 IP アドレス コンテンツ領域 ( およびオプションとして設定ファイル ) にアクセスするためのディスクデータの管理 株式会社サードウェア 5
DRBD 自体のロール ( プライマリまたはセカンダリ ) の制御 アクティブノードでプライマリ DRBD を /h にマウントする nginx プログラム自体 したがって クラスタの構築手順は以下のようになる ステップ 1: Heartbeat 設定ファイルの作成どちらかのノードで /etc/ha.d/ha.cf および /etc/ha.d/authkeys を作成して 他方にリモートコピーする /etc/ha.d/ha.cf crm bcast bcast node node yes eth1 eth2 nginx1.example.com nginx2.example.com /etc/ha.d/authkeys auth 2 2 sha1 rjvf67w1tjjnfy60ez0qwie ステップ 2: Heartbeat を起動する DRBD が起動していれば停止した上で 両ノードで Heartbeat を起動する /etc/init.d/heartbeat start 以下の設定作業は 2 つの端末ウィンドウを開き 一方で crm_mon コマンドを実行しておき 他方で crm コマンドによる設定作業を進めるのが効率的だ ステップ 3: クラスタの動作オプション (property) を設定する crm コマンドで対話モードの crm シェルを起動し configure モードで以下の設定を行う property default-resource-stickiness="200" \ no-quorum-policy="ignore" \ stonith-enabled="false" 設定を入力したら commit コマンドで動作中のクラスタに反映させる ステップ 4: DRBD の動作条件を設定する primitive res_drbd_r0 ocf:linbit:drbd \ params drbd_resource="r0" \ op start interval="0" timeout="240" \ op stop interval="0" timeout="100" ms ms_drbd_r0 res_drbd_r0 \ meta master-max="1" master-node-max="1" clone-max="2" clone-node-max="1" notify="true" ステップ 5: その他のリソースを登録する primitive res_ip ocf:heartbeat:ipaddr2 \ params ip="10.30.101.10" cidr_netmask="16" \ op monitor interval="50" timeout="30" primitive res_mount ocf:heartbeat:filesystem \ params device="/dev/drbd0" fstype="ext4" directory="/h" options="noatime" \ op monitor interval="10" timeout="60" \ op start interval="0" timeout="60" \ op stop interval="0" timeout="60" primitive res_nginx ocf:heartbeat:nginx \ params configfile="/etc/nginx/nginx.conf" 株式会社サードウェア 6
status10url="http://localhost/index.html" \ op start interval="0" timeout="60" \ op stop interval="0" timeout="120" \ op monitor interval="10" timeout="30" colocation c_nginx inf: nginx ms_drbd_r0:master order o_nginx inf: ms_drbd_r0:promote nginx:start ステップ 6: commit してクラスタに反映するこれらの設定を commit すると nginx サーバのクラスタシステムが動作を開始する 正常に動作しているクラスタでは crm_mon コマンドの出力は以下のような感じになる ============ Last updated: Wed Feb 29 14:26:58 2012 Stack: Heartbeat Current DC: nginx2.example.com (371a0f12-6959-405c-9af0-2763013510b1) - partition with quorum Version: 1.0.11-6e010d6b0d49a6b929d17c0114e9d2d934dc8e04 2 Nodes configured, unknown expected votes 2 Resources configured. ============ Online: [ nginx2.example.com nginx1.example.com ] Master/Slave Set: ms_drbd_r0 Masters: [ nginx1.example.com ] Slaves: [ nginx2.example.com ] Resource Group: nginx res_mount (ocf::heartbeat:filesystem): Started nginx1.example.com res_ip (ocf::heartbeat:ipaddr2): Started nginx1.example.com res_nginx (ocf::heartbeat:nginx): Started nginx1.example.com 6 nginx リソースエージェント nginx リソースエージェントは nginx サーバプログラムの起動 停止 モニタを受け持つシェルスクリプトで 以下のような動作パラメータを受け付ける モニタについては OCF_CHECK_LEVEL 変数をサポートしている OCF_CHECK_LEVEL は op monitor 行に追加パラメータとして指定する ( デフォルト値は 無定義 ]) デフォルト (OCF_CHECK_LEVEL は無定義 ) nginx プロセスの存在のみをチェックする OCF_CHECK_LEVEL<20 デフォルトのチェックを行う これに加えて status10url で指定された URL にアクセスして status10regex に指定された正規表現にマッチする応答が返ってくることをチェックする OCF_CHECK_LEVEL<30 デフォルトのチェックを行う これに加えて testconffile に登録されたモニタ条件 あるいは testurl に指定された URL にアクセスして test20regex に指定された正規表現マッチする応答が返ってくることをチェックする 株式会社サードウェア 7
OCF_CHECK_LEVEL<40 external_monitor30_cmd に指定されたコマンドを実行する パラメータ 必須 / 任意 説明 configfile 任意 nginx の設定ファイルをフルパスで指定する コミュニティからダウンロードしたパッケージの場合は /etc/nginx/nginx.conf になる httpd 任意 サーバの実行プログラムのフルパス名 デフォルトで自動検出されるようなので 指定しなくても問題ない port 任意 status*url を指定して nginx をモニタするときにアクセスするポート番号 デフォルトは 80 なので 多くの場合指定しなくても問題ない status10url 任意 上の説明を参照 status10regex 任意 上の説明を参照 testclient 任意 上の説明を参照 testurl 任意 上の説明を参照 test20regex 任意 上の説明を参照 testconffile 任意 上の説明を参照 test20name 任意 今のところスクリプト中で使用されていない external_monitor30_cmd 任意 上の説明を参照 options 任意 nginx コマンドの動作オプションを指定する たとえば基本的なモニタに加えて /nginx_status の応答を調べたい場合 次のようにリソースを定義する primitive res_nginx ocf:heartbeat:nginx \ params configfile="/etc/nginx/nginx.conf" status10url="/nginx_status" \ op start interval="0" timeout="60" \ op stop interval="0" timeout="120" \ op monitor interval="20" timeout="30" OCF_CHECK_LEVEL="10" \ op monitor interval="10" timeout="30" OCF_CHECK_LEVEL="0" 株式会社サードウェア 8