2013年01月14日
Bash + Vagrant ⇒ Bagrant
これまでに何度も仮想マシンイメージを作って来て、どこか面倒臭さを感じていた。そんな中、Vagrantに出会い、ソレが欲しかったモノの1つであると感じ、調査・検証・評価。そして、bash実装する事にした。
Bagrantの機能
- Bagrantfileで仮想マシンを定義
- bagrantコマンドで仮想マシンをビルド・起動・停止
- ハイパーバイザーはKVM
利用ライブラリ
自作したvmbuilderのみ。
使い方
詳細はhansode/bagrantを参照の事で、起動までは、下記手順で行える。
- Bagrantfileを作成
$ bagrant init
- 仮想マシンイメージをビルド
$ bagrant build
- 仮想マシンを起動
$ bagrant up
また、hansode/bagrant-boxがBagrantfileを含んだテンプレート集となっているので、Bagrantfileを自作したい方の参考になるはず。
開発期間
移植作業だったので、結構あっさりと実装出来た気がする。
- 設計: 3日(主にVagrantの調査)
- 実装: 2日
今後の予定
開発した動機がそうであるように、何か機能追加される事があったら、自分自身が欲しいと思ったタイミング。
あとがき
これも、まだ、自動化したかった事の1つでしかない。
フィードバックなど
もしBagrantに興味がある方がいらっしゃいましたら、ご一報下さい。
オライリージャパン
売り上げランキング: 307,566
2012年11月01日
複数ディストリビューション対応へ向けて
ギーク達はfedora対応を希望
前回のエントリに反応してくれたギーク達は、CentOSよりもfedora対応を希望していた。『fedora対応…!』と思ったけども、fedoraを使ってないので良くわかってない。それよりは、複数ディストリビューション対応への準備体操として、CentOS 5対応に着手してみた。
検証環境
- RHEL 6.X / CentOS 6.X / Scientific Linux 6.X
- bash 4.00
- git 1.7
- vmbuilder.sh for CentOS
インストール
$ git clone git://github.com/hansode/vmbuilder.git
実行方法
$ cd vmbuilder/kvm/rhel/6/ $ sudo ./vmbuilder.sh --distro-name=centos --distro-ver=5
実行してから約10分程度で実行したディレクトリ直下に仮想マシンイメージが作成される。
2012/11/01現在の対応ディストリビューション
distro-name と distro-ver に指定可能な組み合わせは下記の通り。
- centos 5 (5.x)
- centos 6 (6.x)
- sl 6 (6.x)
新規追加されるタイミングは、今の所、自分が欲しいと思う時か、聞こえて来る周りからの声。
問題点
rhel6環境でrhel5を構築すると、仮想マシンイメージを作成可能ではあるが、rhel5環境としては不完全だ。
- 今のvmbuilder.shの仕様では、ホスト環境のyumコマンドでゲスト環境を構築する
- ゲスト環境におけるrpmdbのフォーマットは、ホスト環境に依存する
個人的に困ってないので、しばらくの間は保留扱い。
改善案
検証すべき項目
- ホスト環境とゲスト環境を一致させる
- 例) rhel5用仮想マシンイメージを構築する場合は、rhel5環境で行う
- post installフェーズで、rpmdbを変換するなどの対応をする
- yumコマンドかyum.confにrpmdbのバージョン指定する方法があれば、指定してみる
上記のうち、 1 が良さそうなので、対応手段は、構築フェーズを分ける事だろうか。
- ゴールとなる仮想マシンをビルドする為のビルド環境(1次chroot環境) を構築
- 構築されたビルド環境(1次chroot環境)にて、ゲスト環境(2次chroot環境)を構築
- ホスト環境にてマシンイメージ化
これで対応出来そうな気がするので、あとは検証・実装するだけの事。この辺をしっかり実装しておかないと、fedora対応も大変そう。
あとがき
環境差異が発生するとは面白い事。
フィードバックなど
希望するネタ等、フィードバック、大歓迎です。
翔泳社
売り上げランキング: 51792
2012年10月25日
コマンドラインで仮想マシンイメージを作ろう!
面倒臭かった。世の中に出回っているCentOS用仮想マシンイメージ作成手順が。
- インストールDVD(ISOファイル)を用意
- virt-installコマンドを多数のオプション指定で実行…
- VNC接続して…
この手順には問題・課題があり、幾つか挙げると、
- 手作業が入るので多少なりとも作業ブレが発生
- 自動化すべく、kickstartを使うとしても、ks.cfg作成などの準備作業が面倒臭い
- libvirt依存、KVM依存
- どうやってテストする…?
Ubuntuであれば、VMBuilderが上記の問題・課題を解決してくれる。
- $ sudo apt-get install ubuntu-vm-builder
- $ sudo vmbuilder [options]....
vmbuilderコマンド実行後、10分ほどで仮想マシンイメージを作成される。
vmbuilderのお手軽さを知っていると、CentOSにおいても同様・同等の事が出来る事を期待した。しかし、残念ながら、VMBuilderはubuntu用だった。ゆえに、VMBuilderではCentOS用の仮想マシンイメージを作成出来ない。VMBuilderに似たツールを探してみたが、満足の行く物は見つからなかった…。
無いなら…作ろう!そして作った。bashで!
検証環境
- RHEL 6.X / CentOS 6.X / Scientific Linux 6.X
- bash 4.00
- git 1.7
※他にkpartxやpartedなどに依存するが、本エントリでは詳細な依存パッケージは省略。
インストール
$ git clone git://github.com/hansode/vmbuilder.git
実行方法
KVM環境がなくても、KVM用仮想マシンイメージを作成可能なのである。
$ cd vmbuilder/kvm/rhel/6/ $ sudo ./vmbuilder.sh
実行してから約10分。実行したディレクトリ直下に仮想マシンイメージが作成される。
⇒ centos-6.3_x86_64.raw
※2012/10/25 現在、 centos-6.3 がデフォルトセット。
動作確認
出来上がった仮想マシンイメージを軽く確認したくなる。その場合は、下記手順でkvm-ctl.shを実行。 ここで初めてKVMが登場する。kvm-ctl.shはkvmコマンドのラッパースクリプトなので、virsh系のコマンドは不要。依然として、libvirtに依存しないまま。
$ sudo ./misc/kvm-ctl.sh start --image-path=./centos-6.3_x86_64.raw
tcp/6901でVNCが口を開けてるので、VNCクライアントで接続する。
仮想マシンにログイン
- user: root
- pass: root
開発用途なので、脆弱なパスフレーズで良いものとしてる。
あとがき
これは、まだ、自動化したかった事の1つでしかない。
フィードバックなど
本エントリはインストール手順と実行手順に留めておき、次のエントリからは開発苦労話などを執筆予定。 希望するネタ等、フィードバック、大歓迎です。
オライリージャパン
売り上げランキング: 122689
2012年06月22日
欲しい情報を正確に
"rpm -qa" の結果を駆使していたけども、どうも使い勝手が悪い。 例えばsedと組み合わせてパッケージ名を取り出そうとすると、時々うまくパース出来ないケースに遭遇。(うまく正規表現をかけてないとも言う)。
rpmのmanをじっくり読んでみると、ノーマルな"rpm -qa"よりも沢山情報を出力可能だった。
検証環境
- CentOS 6.2 (x86_64)
- rpm 4.8.0
インストール済みパッケージ情報のうち、欲しい情報
この他に欲しい物は無い。今のところは。
- インストール日時
- パッケージ名
- バージョン番号
- リリース番号
- アーキテクチャ
これらを一発で出すコマンド。
$ rpm -qa --qf '%{INSTALLTIME} %{NAME} %{Version} %{Release} %{ARCH}\n'
出力例
$ rpm -qa --qf '%{INSTALLTIME} %{NAME} %{Version} %{Release} %{ARCH}\n' | sort -r | head
1338259926 openssh-clients 5.3p1 70.el6 x86_64
1338259923 kernel 2.6.32 220.el6 x86_64
1338259917 dracut-kernel 004 256.el6 noarch
1338259915 dracut 004 256.el6 noarch
1338259913 plymouth 0.8.3 24.el6.centos x86_64
1338259912 libdrm 2.4.25 2.el6 x86_64
1338259910 plymouth-core-libs 0.8.3 24.el6.centos x86_64
1338259909 libedit 2.11 4.20080712cvs.1.el6 x86_64
1338259907 dash 0.5.5.1 3.1.el6 x86_64
1338259906 which 2.19 6.el6 x86_64
『これだけじゃ足りないぜ!』と言う場合は、rpm --querytagsを実行すると使用可能タグを確認可能。
$ rpm --querytags | head ARCH ARCHIVESIZE BASENAMES BUGURL BUILDARCHS BUILDHOST BUILDTIME C CAPABILITY CHANGELOGNAME
いったいいくつあるのか確認してみると、
$ rpm --querytags | wc -l 170
170も。。
あと書き
困った時のman。
技術評論社
売り上げランキング: 19428
2012年03月06日
フォルダに日本語が入ってる時に"make html"が失敗する
Sphinxを利用してドキュメントを作成していたら、make htmlに失敗する現象に遭遇した。
$ make html
sphinx-build -b html -d _build/doctrees . _build/html
Running Sphinx v1.1.2
WARNING: the config value '__file__' is set to a string with non-ASCII characters; this can lead to Unicode errors occurring. Please use Unicode strings, e.g. u'Content'.
loading pickled environment... not yet created
building [html]: targets for 4 source files that are out of date
updating environment: 4 added, 0 changed, 0 removed
reading sources... [ 25%] cloud-client
Exception occurred:
File "/usr/lib/python2.6/site-packages/Sphinx-1.1.2-py2.6.egg/sphinx/environment.py", line 758, in read_doc
pub.set_source(None, src_path.encode(fs_encoding))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 73: ordinal not in range(128)
The full traceback has been saved in /tmp/sphinx-err-Cg4EMC.log, if you want to report the issue to the developers.
Please also report this if it was a user error, so that a better error message can be provided next time.
Either send bugs to the mailing list at ,
or report them in the tracker at . Thanks!
make: *** [html] Error 1
幾つか試してみると、失敗する時は、フォルダ名に日本語が入っている。 この辺を検索してみると、同じように日本語フォルダ/ファイル名問題に失敗してる事例を発見。
- 清水川
- 日本語ファイル名を使うとmake htmlできない問題をちょっと追ってみたい。 元ネタ:
http://twitter.com/kotakanbe/statuses/48632925364826113- Sphinxで日本語ファイル名/ディレクトリ名を扱えるようにするパッチが 出来ました
http://paste.pocoo.org/show/355901/ 人柱とコードレビューアを募集中です。
手元の環境にhttp://paste.pocoo.org/show/355901/を適用してみると動かない。これはSphinxのバージョン差異が問題だった。
- Sphinx 1.0.7
上記パッチを参考に書いたのが、下記検証環境において動作確認したパッチ。
検証環境
- CYGWIN_NT-6.1
- Python 2.6.5
- Sphinx 1.1.2
Sphinx-1.1.2-py2.6.patch(日本語フォルダ/ファイル名を扱えるようにするパッチ)
あとがき
本パッチのベースとなるパッチを作成・公開して下さった @shimizukawa 様、ありがとうございます。
アスキー・メディアワークス
売り上げランキング: 7179
2012年01月27日
原因調査の行き着く先か・・・
原因調査の為、core dumpさせたい時がある。 ulimitを設定すれば良い訳だが、サービス管理はUpstartを利用している。 SysVinitではなく、Upstartでulimitを設定するには、どうしたものか。
検証環境
- RHEL 6.0 / CentOS 6.0 (x86_64)
- Upstart 0.6.5
要件定義
- SysVinitとUpstartで同じ設定ファイルを使いたい
- ジョブ単位で設定したい
作業概要
下記の事前調査を元に作業概要をまとめると、下記の通り。
- /etc/sysctl.confによるカーネルパラメータ設定
- /etc/sysconfig/(ジョブ名) を追記(or作成)し、変数DAEMON_COREFILE_LIMITを定義
- /etc/init/(ジョブ名).conf を修正し、
- /etc/sysconfig/init を読み込む
- /etc/sysconfig/(ジョブ名) を読み込む
- 強制core dumpさせてcore dumpファイルを作成してみる
事前調査
SysVinitの起動スクリプトがulimitを設定する流れを追ってみる。
- サンプルとして/etc/init.d/ssh を確認。
- /etc/init.d/sshの30行目で /etc/rc.d/init.d/functions を読み込んでる
29 # source function library 30 . /etc/rc.d/init.d/functions
- /etc/rc.d/init.d/functionsの239行目でulimit設定してるのが分かる
239 corelimit="ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0}" - 変数 DAEMON_CORE_LIMIT を定義してるのはどこか?
- /etc/rc.d/init.d/functionsの29行目のコメントにより、構成定義してるのは、30行目で読み込んでる/etc/sysconfig/initだと分かる。
28 # Read in our configuration 29 if [ -f /etc/sysconfig/init ]; then 30 . /etc/sysconfig/init 31 else
- /etc/sysconfig/init の内容を確認してみると、
1 # color => new RH6.0 bootup 2 # verbose => old-style bootup 3 # anything else => new style bootup without ANSI colors or positioning 4 BOOTUP=color 5 # column to start "[ OK ]" label in 6 RES_COL=60 7 # terminal sequence to move to that column. You could change this 8 # to something like "tput hpa ${RES_COL}" if your terminal supports it 9 MOVE_TO_COL="echo -en \\033[${RES_COL}G" 10 # terminal sequence to set color to a 'success' color (currently: green) 11 SETCOLOR_SUCCESS="echo -en \\033[0;32m" 12 # terminal sequence to set color to a 'failure' color (currently: red) 13 SETCOLOR_FAILURE="echo -en \\033[0;31m" 14 # terminal sequence to set color to a 'warning' color (currently: yellow) 15 SETCOLOR_WARNING="echo -en \\033[0;33m" 16 # terminal sequence to reset to the default color. 17 SETCOLOR_NORMAL="echo -en \\033[0;39m" 18 # Set to anything other than 'no' to allow hotkey interactive startup... 19 PROMPT=yes 20 # Set to 'yes' to allow probing for devices with swap signatures 21 AUTOSWAP=no 22 # What ttys should gettys be started on? 23 ACTIVE_CONSOLES=/dev/tty[1-6] 24 # Set to '/sbin/sulogin' to prompt for password on single-user mode 25 # Set to '/sbin/sushell' otherwise 26 SINGLE=/sbin/sushellDAEMON_COREFILE_LIMIT は存在しない。 - /etc/sysconfig/sshd の33行目
32 # pull in sysconfig settings 33 [ -f /etc/sysconfig/sshd ] && . /etc/sysconfig/sshd
/etc/sysconfig/sshd を読み込んでるのが分かる。ここでもDAEMON_COREFILE_LIMITは可能だ。 - /etc/sysconfig/sshdは存在しない。
# ls -l /etc/sysconfig/sshd ls: cannot access /etc/sysconfig/sshd: No such file or directory
- ${DAEMON_COREFILE_LIMIT:-0} は、変数値が無い場合 0。設定しない場合は、 0 だと分かる。
sshの場合は、下記2ファイルのうちどちらかで定義すれば良い。
- /etc/sysconfig/init
- /etc/sysconfig/sshd
前者はSysVinit全体に対する設定ファイルで、後者はサービス個別の設定ファイル。 どちらで設定するかは、利用環境に依存する。
環境定義
検証用に fake-service を作成する。
| ジョブ名 | fake-service |
| sys config | /etc/sysconfig/fake-service |
| upstart config | /etc/init/fake-service.conf |
作業内容
core dump取得設定
core dumpファイルを取得する為の準備作業として、カーネルパラメータ設定。
- /etc/sysctl.conf (追記)
-
kernel.core_pattern = /tmp/core kernel.core_uses_pid = 1
/etc/sysctl.confを反映
# sysctl -p
これにより、 /tmp/core.PID としてcore dumpファイルが作成される。
fake-service設定
- /etc/sysconfig/fake-service
-
DAEMON_COREFILE_LIMIT=unlimited
- /etc/sysconfig/init に設定すると、SysVinit全体設定となるので、今回はfake-service限定としておく。
- /etc/init/fake-service.conf
-
respawn script # system global [ -f /etc/sysconfig/init ] && { . /etc/sysconfig/init } # job local [ -f /etc/sysconfig/fake-service ] && { . /etc/sysconfig/fake-service } # /etc/rc.d/init.d/functions line#239> corelimit="ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0}" ulimit -c ${DAEMON_COREFILE_LIMIT:-0} exec sleep 3600 end script- /etc/sysconfig/initを先に読み込む。
- /etc/sysconfig/fake-serviceを次に読み込む。
- DAEMON_COREFILE_LIMIT が定義済みであれば、 DAEMON_COREFILE_LIMITの値。未定義であれば、0。
Upstartのジョブ操作
ジョブが起動してない事を確認。
# initctl status fake-service fake-service stop/waiting
ジョブを起動。
# initctl start fake-service fake-service start/running, process 3500
プロセスIDが 3500 である事が分かる。
プロセスID指定でプロセスを確認。
# ps -p 3500 PID TTY TIME CMD 3500 ? 00:00:00 sleep
Upstartによってexecしてるsleepである事が分かる。
QUITシグナルを送り、強制的にcore dumpさせる。
# kill -QUIT 3500
QUITシグナル送信後のジョブ状態を確認。
# initctl status fake-service fake-service start/running, process 3595
QUITシグナル送信により、プロセスIDが変化してる。3500 → 3595。
core dumpファイルを確認
core dumpファイルが作成されてる事を確認出来る。
# ls -la /tmp/core.3500 -rw-------. 1 root root 319488 Jan 27 19:02 /tmp/core.3500
gdbによる調査・デバッグへと進むのであった・・・。
あと書き
/etc/sysconfig/を使わず、/etc/init/fake-service.conf内でulimitの設定値をハードコードしてしまっても良いのでは無いか?
技術評論社
売り上げランキング: 6581
2012年01月26日
v.s. ログローテート未対応プログラム
- 標準出力しかしないプログラムがあったとする。
- プログラムの出力をログファイルとして保存する為に、標準出力をリダイレクトしてログファイルを作成して対応したとする。
こんな状況。
$ program > /path/to/command.log
このログファイルを、どうにかしてをローテートしたい。さて、どうする?
flog(file logger)と言う選択肢
いくつかあるであろう解決策の1つとして、今回はflogを使って解決した。
WHAT IS IT? =========== flog (file logger) is a program that reads input from STDIN and writes to a file. if a SIGHUP is received, the file will be reopened, allowing for log rotation [see logrotate(8) on RH.] The log file will only be reopened if flog detects that rotation has occurred (ie, old file gone or inode changed). flog is very small (less than 500 bytes memory footprint.)
コマンドで説明すると下記の通り。
$ program | flog /path/to/log $ mv -i /path/to/log /path/to/log.1 $ kill -HUP "flog's PID"
後はHUPシグナル送信をlogrotate(8)内で行えば良いだけの事。 flogへのシグナル送信である所がミソ。
検証環境
- RHEL 6.0 / CentOS 6.0 (x86_64)
- alien 8.81
- flog 1.8
- upstart 0.6.5
- logrotate 3.7.8
要件定義
- サービス監視プログラムは修正しない
- 標準出力をログファイルへ出力・保存
- サービスを再起動する事無く、ログファイルを安全にローテート
作業概要
- flog環境構築
- 残念ながらflogのrpmは無く、debは存在するので、debからrpmを作成する。
- flogのdebパッケージをダウンロード
- alienを使ってdebからrpmへ変換
- flogをインストール
- upstart configを作成
- logrotate configを作成
- ログローテート確認
環境定義
| サービスプログラム | /tmp/fake-service.sh |
| ログファイル | /var/log/fake-service.log |
| upstart | /etc/init/fake-service.conf |
| logrotate | /etc/logrotate.d/fake-service |
事前作業
- alienでパッケージ変換(deb→rpm)により、alienがインストールされている事
作業内容
flog環境構築
fakerootをインストール
$ sudo yum install -y fakeroot
flogのdebパッケージを取得
$ curl -O http://ftp.jaist.ac.jp/pub/Linux/ubuntu//pool/universe/f/flog/flog_1.8-3_amd64.deb
alienでdebをrpmへ変換
$ fakeroot alien --to-rpm ./flog_1.8-3_amd64.deb flog-1.8-4.x86_64.rpm generated find: `flog-1.8': No such file or directory $ ls -l flog-1.8-4.x86_64.rpm -rw-r--r-- 1 hansode hansode 9801 Jan 25 18:34 flog-1.8-4.x86_64.rpm
変換したrpmをインストール
$ sudo rpm -ivh flog-1.8-4.x86_64.rpm
インストールされている事を確認
$ which flog /usr/bin/flog $ rpm -qf `which flog` flog-1.8-4.x86_64
ダミーのfake-service
実際に何か出力するだけのダミースクリプトを配置。
- /tmp/fake-service.sh
-
#!/bin/sh while date; do sleep 1; done
実行権限付与。
$ chmod +x /tmp/fake-service.sh
upstart設定とlogrotate設定
start on runlevel [2345]
stop on runlevel [016]
respawn
exec /tmp/fake-service.sh \
| /usr/bin/flog \
-p /var/run/fake-service.pid \
/var/log/fake-service.log
- fake-serviceの標準出力をflogが受け取り、/var/log/fake-service.logとして出力
- -pオプションでflogのPIDを /var/log/fake-service.log として記録
/var/log/fake-service.log {
rotate 10
compress
missingok
sharedscripts
create 0644 root root
postrotate
pid_file=/var/run/fake-service.pid
[ -f ${pid_file} ] || exit 0
pid=`cat ${pid_file}`
ps -p ${pid} >/dev/null || exit 0
kill -HUP ${pid}
endscript
}
- postrotateで、ローテート後の処理を定義可能。
- flogプロセスにHUPシグナルを送信
- flogのPIDは、PIDファイルから取得可能
ログローテート準備
サービスを起動。
$ sudo initctl start fake-service fake-service start/running, process 28692
この例ではPIDが 28692。ログローテート確認時にも利用するのでメモ。
pidファイルを確認。
$ ls -la /var/run/fake-service.pid -rw-r--r-- 1 root root 6 Jan 26 19:19 /var/run/fake-service.pid $ cat /var/run/fake-service.pid 28694
flogのPIDが 28694 である事が分かる。
$ ps -fp `cat /var/run/fake-service.pid` UID PID PPID C STIME TTY TIME CMD root 28694 28692 0 19:19 ? 00:00:00 /usr/bin/flog -p /var/run/fake-service.pid /var/log/fake-service.log
プロセスID指定で確認してみると、flogである事が分かる。親PIDはupstartのPIDである事も分かる。
| プロセス | PID |
|---|---|
| fake-service | 28692 |
| flog | 28694 |
ローテート前のログ状態を確認。
$ ls -l /var/log/fake-service.log* -rw-r--r-- 1 root root 12758 Jan 26 19:21 /var/log/fake-service.log
ローテート前なので、ログファイルが1つ。
ログローテート実行
ログローテートしてみる。
$ sudo logrotate -f /etc/logrotate.d/fake-service
ログローテート後の確認
サービスのPIDに変化が無い事を確認。
$ sudo initctl status fake-service fake-service start/running, process 28692
pidファイルを確認。
$ ls -la /var/run/fake-service.pid -rw-r--r-- 1 root root 6 Jan 26 19:19 /var/run/fake-service.pid $ cat /var/run/fake-service.pid 28694
pidファイルのPIDでプロセスを確認。
$ ps -fp `cat /var/run/fake-service.pid` UID PID PPID C STIME TTY TIME CMD root 28694 28692 0 19:19 ? 00:00:00 /usr/bin/flog -p /var/run/fake-service.pid /var/log/fake-service.log
flogである事が分かる。
ローテート後のログ状態を確認。
$ ls -la /var/log/fake-service.log* -rw-r--r-- 1 root root 3599 Jan 26 19:34 /var/log/fake-service.log -rw-r--r-- 1 root root 485 Jan 26 19:32 /var/log/fake-service.log.1.gz
ローテートされている事が分かる。
$ sudo initctl status fake-service fake-service start/running, process 28692
| プロセス | PID |
|---|---|
| fake-service | 28692 |
| flog | 28694 |
PIDは変化してない。
もう一度ログローテート
ローテートを実行。
$ sudo logrotate -f /etc/logrotate.d/fake-service
ログファイルを確認。
$ ls -la /var/log/fake-service.log* -rw-r--r-- 1 root root 235 Jan 26 19:37 /var/log/fake-service.log -rw-r--r-- 1 root root 787 Jan 26 19:37 /var/log/fake-service.log.1.gz -rw-r--r-- 1 root root 485 Jan 26 19:32 /var/log/fake-service.log.2.gz
ローテートされている事を確認。
あと書き
ログローテートを考慮しないプログラムに遭遇して困ったら、flogが悩みを解決してくれるだろう。
技術評論社
売り上げランキング: 6253
2012年01月25日
debをrpmへ変換したい
rpmは無いけどもdebには存在する場合に時々使える。 小さいパッケージであればalienで変換すれば手軽にrpmへ変換が可能。
検証環境
- RHEL 6.0 / CentOS 6.0 (x86_64)
- alien 8.81
作業概要
- alianのtarballをダウンロード
- tarballからrpmを作成
作業内容
依存パッケージをインストール
$ sudo yum install -y rpm-build perl-ExtUtils-MakeMaker
tarballを取得
$ curl -O http://ftp.debian.org/debian/pool/main/a/alien/alien_8.81.tar.gz
tarballからrpmをビルド
$ rpmbuild -ta alien_8.81.tar.gz
ビルドしたrpmをインストール
$ sudo rpm -ivh ~/rpmbuild/RPMS/noarch/alien-8.81-1.noarch.rpm
インストールされてる事を確認
$ which alien /usr/bin/alien $ rpm -qf `which alien` alien-8.81-1.noarch
2011年12月19日
名前は聞いた事があるのに、構築しなかった環境の1つ
DRBD環境構築が必要だったので、DRBD環境を構築。
構築完了したのは1ヶ月半も前の事。作業記録のタイムスタンプを見ると、11/08。 アウトプットするまでに随分と時間がかかってしまった事に反省。
検証環境
- RHEL 6.0 / CentOS 6.0 (i686)
- drbd 8.4.0
要件定義
作業概要
- DRBDをインストール
- DRBDの設定ファイルを作成
- DRBDを起動
- データ同期確認
サーバ構成
| ノード名 | 用途 | IPアドレス | NIC |
|---|---|---|---|
| node1 | master | 192.0.2.2 | eth0 |
| node2 | backup | 192.0.2.3 | |
| - | Virtual IP | 192.0.2.254 |
作業内容
事前作業
DRBDをビルドするに辺り必要なパッケージをインストール。
$ sudo yum install -y gcc make automake autoconf flex rpm-build kernel-devel libxslt fakeroot
rpmbuildで必要となるディレクトリ構造を作成。く
$ mkdir -p /home/centos/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
ソースをダウンロード
$ curl -O http://oss.linbit.com/drbd/8.4/drbd-8.4.0.tar.gz
ダウンロードしたソースを伸長。
$ tar zxvf drbd-8.4.0.tar.gz
configureスクリプトを実行。
$ cd drbd-8.4.0 $ ./configure
fakerootを経由してmakeを実行。fakerootを使う理由は、rpmをビルドするにはroot権限であるから。fakerootがroot権限であるかのような振る舞いをしてくれる。
$ fakeroot make rpm km-rpm
無事にビルドが完了すると、下記rpmが作成される。
$ ls -1 /home/centos/rpmbuild/RPMS/i386/ drbd-8.4.0-1.el6.i386.rpm drbd-bash-completion-8.4.0-1.el6.i386.rpm drbd-heartbeat-8.4.0-1.el6.i386.rpm drbd-km-2.6.32_71.el6.i686-8.4.0-1.el6.i386.rpm drbd-pacemaker-8.4.0-1.el6.i386.rpm drbd-udev-8.4.0-1.el6.i386.rpm drbd-utils-8.4.0-1.el6.i386.rpm drbd-xen-8.4.0-1.el6.i386.rpm
ビルド済みrpmで必要なのは drbd-utilsとdrbd-km。これらをインストール。
$ sudo rpm -ivh \ /home/centos/rpmbuild/RPMS/i386/drbd-utils-8.4.0-1.el6.i386.rpm \ /home/centos/rpmbuild/RPMS/i386/drbd-km-2.6.32_71.el6.i686-8.4.0-1.el6.i386.rpm
カーネルモジュールをロードしてみる。
$ lsmod | grep drbd $ sudo modprobe drbd $ lsmod | grep drbd drbd 274063 0 libcrc32c 815 1 drbd
"/etc/init.d/drbd start "実行にmodprobe drbdが実行されるので、ここではmodprobeコマンドでカーネルモジュールを正常にロード出来る事を確認するだけで良い。
起動対象サービスに入ってるのを確認しておく。
$ chkconfig --list drbd drbd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
デバイスファイル用意
今回はrawファイルを作成しループバックマウントしてDRBD用デバイスファイルを調達する。
$ sudo dd if=/dev/zero of=/var/tmp/drbd.img bs=1M count=128 $ sudo losetup -f /dev/loop0
作ったrawファイルを空きデバイス/dev/loop0にマッピングさせる。
$ sudo losetup /dev/loop0 /var/tmp/drbd.img $ sudo losetup -a /dev/loop0: [fd00]:266486 (/var/tmp/drbd.img)
これでDRBD用の同期対象デバイスが出来上がった。
DRBD設定
必要に応じて/etc/hostsにホスト登録しておく。 理由は、configでIPアドレス指定するにも関わらず、名前解決に失敗すると起動しない為。
$ sudo vi /etc/hosts > 192.0.2.2 drbd-primary > 192.0.2.3 drbd-secondary
configを追加。ドキュメントで拡張子は「.res」が推奨されているので、sandbox.resとして作成。
- /etc/drbd.d/sandbox.res
-
resource sandbox { protocol C; device /dev/drbd0; disk /dev/loop0; meta-disk internal; on drbd-primary { address 192.0.2.2:7801; } on drbd-secondary { address 192.0.2.3:7801; } }
DRBDデバイスを初期化
$ sudo drbdadm create-md sandbox Writing meta data... initializing activity log NOT initializing bitmap New drbd meta data block successfully created. success
※注意: iptablesが有効になってるとDRBD通信が行われない場合がある
DRBDを起動。
$ sudo /etc/init.d/drbd start
Starting DRBD resources: [
create res: sandbox
prepare disk: sandbox
adjust disk: sandbox
adjust net: sandbox
]
.....
DRBDが起動すると/proc/drbdが作成される。
$ cat /proc/drbd
version: 8.4.0 (api:1/proto:86-100)
GIT-hash: 28753f559ab51b549d16bcf487fe625d5919c49c build by centos@centos, 2011-11-08 16:16:36
0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r-----
ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:131032
この時、どちらもsecondaryになっているのが分かる。
データ同期確認
primary側でファイルを作成し、secondaryへデータ同期が行われるのを確認する。
ndoe1: (secondary→primary)
node1をprimaryに昇格させる。
$ sudo drbdadm primary --force sandbox
primaryからsecondaryへの同期処理が開始され、しばらくすると同期完了する。
$ cat /proc/drbd
version: 8.4.0 (api:1/proto:86-100)
GIT-hash: 28753f559ab51b549d16bcf487fe625d5919c49c build by centos@centos, 2011-11-08 16:16:36
0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:2664 nr:0 dw:0 dr:3476 al:0 bm:0 lo:0 pe:3 ua:3 ap:0 ep:1 wo:b oos:128600
[>....................] sync'ed: 3.2% (128600/131032)K
finish: 0:00:45 speed: 2,432 (2,432) K/sec
$ cat /proc/drbd
version: 8.4.0 (api:1/proto:86-100)
GIT-hash: 28753f559ab51b549d16bcf487fe625d5919c49c build by centos@centos, 2011-11-08 16:16:36
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:131032 nr:0 dw:0 dr:131696 al:0 bm:8 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0
DRBDデバイスを確認。設定通り/dev/drbd0が作成されているのが分かる。
$ ls -la /dev/drbd0 brw-rw---- 1 root disk 147, 0 Nov 8 17:19 /dev/drbd0
通常のディスクデバイスファイルと同様にDRBDデバイスをフォーマットし、マウントすれば利用可能となる。
$ sudo mkfs -t ext4 /dev/drbd0 $ sudo mkdir /mnt/drbd0 $ sudo mount -t ext4 /dev/drbd0 /mnt/drbd0
マウント後の内容確認。
$ ls -la /mnt/drbd0/ total 17 drwxr-xr-x 3 root root 1024 Nov 8 17:22 . drwxr-xr-x. 3 root root 4096 Nov 8 17:23 .. drwx------ 2 root root 12288 Nov 8 17:22 lost+found
primary・secondary間でデータ同期されるのを確認するため、ファイルを作成してみる。
$ sudo touch /mnt/drbd0/test.txt $ ls -la /mnt/drbd0/ total 17 drwxr-xr-x 3 root root 1024 Nov 8 17:23 . drwxr-xr-x. 3 root root 4096 Nov 8 17:23 .. drwx------ 2 root root 12288 Nov 8 17:22 lost+found -rw-r--r-- 1 root root 0 Nov 8 17:23 test.txt
node1:(primary→secondary)
DRBDが使用中だとsecondaryへ降格出来ないので、デバイスをumountする。
$ sudo umount /mnt/drbd0
secondaryへ降格させる。
$ sudo drbdadm secondary sandbox
$ cat /proc/drbd
version: 8.4.0 (api:1/proto:86-100)
GIT-hash: 28753f559ab51b549d16bcf487fe625d5919c49c build by centos@centos, 2011-11-08 16:16:36
0: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
ns:139687 nr:0 dw:8655 dr:132451 al:10 bm:8 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0
これにより、他のsecondaryがprimaryへ昇格可能状態となる。
node2: (secondary→primary)
node2をprimaryへ昇格させる。
$ sudo drbdadm primary sandbox
/proc/drbdでprimaryになっているのが分かる。
$ cat /proc/drbd
version: 8.4.0 (api:1/proto:86-100)
GIT-hash: 28753f559ab51b549d16bcf487fe625d5919c49c build by centos@centos, 2011-11-08 16:16:36
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:0 nr:139687 dw:139687 dr:664 al:0 bm:8 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0
DRBDデバイスの内容を確認する為、マウントする。
$ sudo mkdir /mnt/drbd0 $ sudo mount -t ext4 /dev/drbd0 /mnt/drbd0/
マウントポイントの内容を確認。node1で作成した test.txt が存在しているのが分かる。
$ ls -la /mnt/drbd0/ total 17 drwxr-xr-x 3 root root 1024 Nov 8 17:23 . drwxr-xr-x. 3 root root 4096 Nov 8 17:25 .. drwx------ 2 root root 12288 Nov 8 17:22 lost+found -rw-r--r-- 1 root root 0 Nov 8 17:23 test.txt
node2: (primary→secondary)
umountし、secondaryへ降格させる。
$ sudo umount /mnt/drbd0 $ sudo drbdadm secondary sandbox
/dev/drbdでsecondaryに降格している事を確認。
$ cat /proc/drbd
version: 8.4.0 (api:1/proto:86-100)
GIT-hash: 28753f559ab51b549d16bcf487fe625d5919c49c build by centos@centos, 2011-11-08 16:16:36
0: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
ns:18 nr:139687 dw:139705 dr:671 al:3 bm:8 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0
これでnode1, node2がどちらもsecondaryになってる状態。 後はnode1をprimaryに昇格させて、同期させるだけ。
あと書き
DRBDのバージョンによってコマンド名、引数に違いがあるので、よく確認すべし。
2011年11月10日
複数NICと複数IPアドレス、複数VIP
本エントリは、前エントリ 『Linux + ucarpによるサーバ冗長化』 の続編。前エントリでは、単一ネットワークにおける冗長化。それに対し、本エントリでは複数ネットワークを扱う。
検証環境
- RHEL 6.0 / CentOS 6.0
- ucarp 1.5.2-1.el6
要件定義
- 障害が発生したネットワークのVIPのみfailover
- 正常ネットワークのVIPはfailoverしなくて良い
作業概要
- VIPの数だけconfigを作成
- ucarpを起動
- サービスの状態を確認
サーバ構成
| node1 | node2 | vip | |
|---|---|---|---|
| 役割 | master | backup | |
| eth2 | 192.0.2.2/25 | 192.0.2.3/25 | 192.0.2.126/25 |
| eth3 | 192.0.2.130/25 | 192.0.2.131/25 | 192.0.2.254/25 |
事前作業
- Linux + ucarpによるサーバ冗長化により、ucarp環境が構築されている事
- 前エントリで作成した /etc/ucarp/vip-001.conf が存在する場合は、/etc/ucarp/vip-001.conf.saved など、 suffixが .conf にならないようにしておく事。.savedにしておけば、include対象外となる。
# mv -i /etc/ucarp/vip-001.conf /etc/ucarp/vip-001.conf.saved
作業内容
設定値に従い、ucarpの設定ファイルを作成。 今回はVIP数が2つなので、confファイルとIDが2つ用意する必要がある。
ucarp設定: node1編
- node1:/etc/ucarp/vip-002.conf
-
SOURCE_ADDRESS=192.0.2.2 ID=002 BIND_INTERFACE=eth2 VIP_ADDRESS=192.0.2.126 OPTIONS="--shutdown --preempt"
- node1:/etc/ucarp/vip-003.conf
-
SOURCE_ADDRESS=192.0.2.130 ID=003 BIND_INTERFACE=eth3 VIP_ADDRESS=192.0.2.254 OPTIONS="--shutdown --preempt"
ucarp設定: node2編
- node2:/etc/ucarp/vip-002.conf
-
SOURCE_ADDRESS=192.0.2.3 ID=002 BIND_INTERFACE=eth2 VIP_ADDRESS=192.0.2.126 OPTIONS="--shutdown --preempt"
- node2:/etc/ucarp/vip-003.conf
-
SOURCE_ADDRESS=192.0.2.131 ID=003 BIND_INTERFACE=eth3 VIP_ADDRESS=192.0.2.254 OPTIONS="--shutdown --preempt"
ucarp起動
前エントリ同様に、今回の設定でも重要なのは、ucarpの起動順番。 これは、先にucarpを起動させたノードがucarp-masterとなる為である。
- master(今回はnode1)
- backup(今回はnode2)
起動順番は十分気をつける。
node1# /etc/init.d/ucarp start
node2# /etc/init.d/ucarp start
正常時(ucarp起動後)
各ノードで "ip addr show" を実行すると、どちらにVIPが割り当てられているかを確認出来る。 ucarp起動順番やネットワークに問題がなければ、下記のようにmasterノードにVIPが割り当てられる。
- node1
-
# ip addr show eth2 | grep -w inet inet 192.0.2.2/25 brd 192.0.2.127 scope global eth2 inet 192.0.2.126/32 scope global eth2# ip addr show eth3 | grep -w inet inet 192.0.2.130/25 brd 192.0.2.255 scope global eth3 inet 192.0.2.254/32 scope global eth3 - node2
-
# ip addr show eth2 | grep -w inet inet 192.0.2.3/25 brd 192.0.2.127 scope global eth2# ip addr show eth3 | grep -w inet inet 192.0.2.131/25 brd 192.0.2.255 scope global eth3
ノード単位でfailover/failback
前エントリと同様に、ucarpプロセスを起動・停止させる事により、failoverを確認出来る。
- node1
-
# /etc/init.d/ucarp stop # /etc/init.d/ucarp start
- node2
-
# /etc/init.d/ucarp stop # /etc/init.d/ucarp start
- 切り替わる途中経過は、/var/log/messageで確認可能
-
# tail -F /var/log/message
failover時の状態
MASTERがnode1からnode2へ切り替わった時の/var/log/message出力例。 node2のstateがMASTERへ遷移しているのが分かる。
- node1(master⇒backup):/var/log/message
-
Nov 10 02:53:01 centos ucarp[1437]: [WARNING] Spawning [/usr/libexec/ucarp/vip-down eth2 192.0.2.126] Nov 10 02:53:01 centos ucarp[1446]: [WARNING] Spawning [/usr/libexec/ucarp/vip-down eth3 192.0.2.254] Nov 10 02:53:01 centos ucarp: all ucarp daemons stopped and IP addresses unassigned
- node2(backup⇒master):/var/log/message
-
Nov 10 02:53:02 centos ucarp[1426]: [WARNING] Switching to state: MASTER Nov 10 02:53:02 centos ucarp[1435]: [WARNING] Switching to state: MASTER Nov 10 02:53:02 centos ucarp[1435]: [WARNING] Spawning [/usr/libexec/ucarp/vip-up eth3 192.0.2.254] Nov 10 02:53:02 centos ucarp[1426]: [WARNING] Spawning [/usr/libexec/ucarp/vip-up eth2 192.0.2.126]
VIPの数だけucarpプロセスが起動
Q. 下記状態では、ucarpはどんな動きをするのだろうか?
- VIP#1 一方のネットワークに障害発生
- VIP#2 もう一方のネットワークは正常
A. 障害発生中のVIPのみ切り替わる。
- VIP#1 MASTERからBACKUPへ切り替わる
- VIP#2 MASTERのまま
ucarpは、VIPの数と同等のプロセスが起動し、masterとbackupが通信し合って監視する。 VIPが2つある場合、ucarpプロセスも2つ。下記の通り、VIPが2の場合のucarpプロセスは、2つあるのが分かる。
# ps -ef | egrep '[u]carp' root 1756 1 0 05:08 ? 00:00:00 /usr/sbin/ucarp --daemonize --interface=eth2 --pass=love --srcip=192.0.2.2 --vhid=002 --addr=192.0.2.126 --shutdown --preempt --upscript=/usr/libexec/ucarp/vip-up --downscript=/usr/libexec/ucarp/vip-down root 1764 1 0 05:08 ? 00:00:00 /usr/sbin/ucarp --daemonize --interface=eth3 --pass=love --srcip=192.0.2.130 --vhid=003 --addr=192.0.2.254 --shutdown --preempt --upscript=/usr/libexec/ucarp/vip-up --downscript=/usr/libexec/ucarp/vip-down
2本ある監視ラインのうち、1本をdownさせてみるとどうなるのか
監視ライン1本をdownさせ、ucarpプロセスが独立して動作するのを観察してみる。
【方法】node1のeth1をdownさせる
- node1
-
# ifdown eth3
- node1:/var/log/message
-
Nov 10 05:29:24 centos ucarp[1764]: [ERROR] exiting: pfds[0].revents = 8
⇒ eth3を監視していたucarpが異常終了 - node2:/var/log/message
-
Nov 10 05:29:25 centos ucarp[1811]: [WARNING] Switching to state: MASTER Nov 10 05:29:25 centos ucarp[1811]: [WARNING] Spawning [/usr/libexec/ucarp/vip-up eth3 192.0.2.254]
⇒ eth3側のvipがupしている - node1
-
# ps -ef | egrep '[u]carp' root 1756 1 0 05:08 ? 00:00:00 /usr/sbin/ucarp --daemonize --interface=eth2 --pass=love --srcip=192.0.2.2 --vhid=002 --addr=192.0.2.126 --shutdown --preempt --upscript=/usr/libexec/ucarp/vip-up --downscript=/usr/libexec/ucarp/vip-down
⇒ ucarpプロセスは1つ - node1
-
# ps -ef | egrep '[u]carp' root 1803 1 0 05:29 ? 00:00:00 /usr/sbin/ucarp --daemonize --interface=eth2 --pass=love --srcip=192.0.2.3 --vhid=002 --addr=192.0.2.126 --shutdown --preempt --upscript=/usr/libexec/ucarp/vip-up --downscript=/usr/libexec/ucarp/vip-down root 1811 1 0 05:29 ? 00:00:00 /usr/sbin/ucarp --daemonize --interface=eth3 --pass=love --srcip=192.0.2.131 --vhid=003 --addr=192.0.2.254 --shutdown --preempt --upscript=/usr/libexec/ucarp/vip-up --downscript=/usr/libexec/ucarp/vip-down
⇒ ucarpプロセスは2つ
【確認】 down後のucarp状態
【確認】 ucarpプロセスはどうなっているのか
この結果により、eth3側のみfailoverしている事が分かる。 VIPを更に1つ2つ追加しても、問題なく動作してくれるだろう。
あとがき
/etc/ucarp/vip-*.conf を追加した後は、upscript/downscriptを充実させれば良いだけか。




