kikumotoのメモ帳

インフラ・ミドル周りを中心に、興味をもったことを適当な感じで。twitter : @takakiku

hbstudy41に参加してきた

ブログに書くまでが勉強会ということで、hbstudy#41 x IDCFクラウドハンズオン - connpass に参加して、あとLTもしてきました。

もくもくとコードを書いていく(どちらかというと写経ですが)というスタイルでの勉強会でしたが、非常に充実したものとなりました。

講師の方がいろいろハマってくれた(?)おかげて、勉強会らしく皆で問題を解決しながら進んでいる感じもあったよかったです。

自分的にはFabricどころかPython自体もほぼ初めてで、Pythonに少し戸惑いつつも、なんとか最後までたどりついた感じです。

Fabricは、Chefともまた目的が違う感じは受けましたが、便利ツールを構築するにはよいフレームワークなのかもしれませんね。普段がPythonなら、これは多分使うでしょう。

で、IDCFクラウドを別途いじっていたので、その要望をかねてLTさせてもらいました。
資料を公開しておきます。


要望LT後、中の人から耳寄りな情報をいただけたりと、LTした甲斐がありました。
LTするといいことありますね。
ネタと参加する機会があれば今後もなにか話していきたいですね。
もっとも自分は人の後ろを歩いている感じなので、最新の情報を提供するなんてことはできなさそうなので、自分のやり方や困っているところを話す感じになるかな。そんなことぐらいしか話せないけど。。。

最後にこの場をかりて、hbstudyのスタッフ、IDCFのスタッフに感謝いたします。ありがとうございました。

Apacheのログで、リクエスト時間をマイクロ秒で表示する方法

ApacheのLogFormatで %t を指定すると、リクエストの時間が表示されますよね。

複数のサーバのログを集めて結合すると、時間が秒レベルなのでソートしても微妙に順番が変になったりします。

なので、秒より精度の高い時間を出力しようと思いました。
使っているのが Apache2.2系なこともあり、2.2のカスタムログ書式を眺めても、特にミリ秒とかマイクロ秒で出力できる感じなかったので、調べて見つけたのが

でした。
なるほどと思い、とりあえず mod_log_config.c がやっていることを見てみようと、なぜか手元には 2.4.3 のソースがあったのでそちらを見てみました。

そしたら、なんかこんなコードが。

        else if (!strncmp(fmt, "usec", 4)) {
            fmt += 4;
            if (!*fmt) {
                fmt_type = TIME_FMT_ABS_USEC;
            }
            else if (!strcmp(fmt, "_frac")) {
                fmt_type = TIME_FMT_ABS_USEC_FRAC;
            }

ん?マイクロ秒レベルで出力できる感じじゃん。
ということで、2.4のドキュメント見てみるも、何も書いてない。
とりあえず、英語版を、ということで見てみると、

the following format tokens are supported:
sec	number of seconds since the Epoch
msec	number of milliseconds since the Epoch
usec	number of microseconds since the Epoch
msec_frac	millisecond fraction
usec_frac	microsecond fraction

ちゃんと書いてあるじゃないですか。
ということで、Apache2.4 以降では LogFormat に

%{usec}t

と書くと、リクエストの時間がエポックからのマイクロ秒でログ出力されます。(スイマセン、知りませんでした。)

が、今使っているのは2.2系。
2.4のmod_log_config.cそのままはさすがにビルドできなかったので、この部分だけ抜き出したmod_log_config.c を作りました。こちら

ということで、これをhttpdのソースのmodules/loggersにコピーして

$ apxs -c mod_log_config.c
$ su
# apxs -i mod_log_config.la

という感じで apxs でビルド・インストールすれば、2.2でも同じようにマイクロ秒で出力できるようになりました。

これで、少し解析が楽になる。

kickstartのpostscript処理をコンソール出力するメモ

kickstartのpostscript処理ですがリアルなマシンだと

にあるように、chvt すればいんだけど、KVM仮想マシンにインストールするときはこれでは動作しない。

シリアルコンソールに出力しているので、結局、上記を参考にキックスタートファイルに

%post
exec < /dev/tty3 > /dev/ttyS0

yum -y update

のようにしたらできた。

これでいいのかよくわからない。
正しい方法あればコメントいただけるとうれしいです。

SpotInstance + ENI(固定IP)in VPC で財布に優しいテスト環境を作る

久しぶりの更新です。

Amazon VPCのいいところの1つは、固定プライベートIPを設定できるところですよね。
で、ちょうど固定プライベートIPで作業する必要があったので、オンデマンドm1.smallをVPC内に数インスタンス起動してたのですが、そこそこ費用がいってしまいました。
t1.microはまだVPCで使えないし、SpotInstanceだと固定プライベートIP指定で起動できないし、オンデマンドm1.smallでもそこそこ費用いくしと悩んでいたのですが、Elastic Network Interface(ENI)を使うことで、財布に優しい環境をつくることができました。
以下、やったことのメモです。

まずVPCを作っておきます。たとえば CIDR 10.0.0.0/16 で作って、Subnet を 10.0.0.0/24 としておく。このあたりは Wizardのデフォルト通りでOK。
で、もう1つSubnetを作っておく。ここでは10.0.1.0/24としておく。

この状態で、SpotInstanceを10.0.0.0/24で起動する。この10.0.0.0/24に接続するeth0はdhcpにより動的にIPが定まる。一応、このインスタンスに直接アクセスするために、EIPも割り当てておく。

ここで10.0.1.0/24に接続するENIをIP指定(例:10.0.1.11)で作成し、作成したインスタンスにアタッチする。インスタンスでは/etc/sysconfig/network-scripts/ifcfg-eth1(Amazon Linuxの場合)に

DEVICE=eth1
BOOTPROTO=static
IPADDR=10.0.1.11
NETMASK=255.255.255.0
ONBOOT=yes
TYPE=Ethernet

を記述し、ネットワークを再起動する。これで、このSpotInstanceは固定プライベートIPが使える。

そして、この状態でAMIを作って、以降はこのAMIからSpotIntanceを起動し、同じ固定IPを持つENIをアタッチすればSpotInstanceであっても特定のサブネットに対しては常に同じIPを持つ環境を容易に再現できるようになる。

これで、財布に優しい固定プライベートIP環境ができたので実験がしやすくなりました。Yeah!

これLTネタになるかな?いや、ショボすぎだろ。

ところで

SpotInstanceはm1.mediumってお得感がありますよね。東京リージョンだとこのブログ書いている時点で

タイプ オンデマンド スポット
m1.small $0.092 $0.041
m1.medium $0.184 $0.058

という価格。割引率もm1.mediumの方がいいですし、$1=\80とすれば、スポットの価格差は1時間あたり1.36円。
オンデマンドのm1.smallより安いし、この価格差ならコスパ的にm1.mediumかなって感じで、m1.mediumのSpotInstanceをよく使ってます。

価格も安定していて、m1.smallだと

な感じですが、m1.mediumだと

な感じ。
まぁたまーに跳ね上がるのはSpotInstanceってことで割り切れば、m1.mediumの方が突然落とされる確率は低そうですね。今後はどうなるかわかりませんが。。。

Amazon VPCに接続するためのVyatta向け設定ファイルを作成するWebツールを作ってみました

さくらのクラウド(β)とAmazon VPCをつなげるテストをいろいろやっているのだけど、毎度Vyattaの設定ファイルとかを書くのが面倒なので、Amazon VPCからダウンロードする設定情報をVyatta向けに変換するツールを作成してみました。

ローカルで使うのであればrubyで多分書くのですが、需要があるか不明ですが他の方にも使いやすいように、Webツールという感じで公開してみました。

http://gen-vyatta-conf.fluxflex.com/
http://gen-vyatta-conf.peachbeach.info/

Javascript のみで完結していて、通信は一切しないのでPSKなどを抜くようなことは一切していません。ちなみに、Javascript はまだ勉強不足なので、いたらないところは多々あると思います、、、ご容赦を!

想定環境

とりあえず自分で試したときの環境は以下のようなイメージです。さくらのクラウド(β)で、Vyatta(6.3)をたてて、プライベートネットワーク(192.168.1.0/24)内にサーバを起動している感じです。このサーバのデフォルトゲートウェイは、Vyattaを向くように設定しておきます。
AWS では、VPC を構築して、その中に EC2 Instance を起動しているという感じとなります。

VPCの構築は以前の記事(さくらのVPSにVyattaを入れて、Amazon VPCにVPN接続 - kikumotoのメモ帳)を参照してください。

使い方

http://gen-vyatta-conf.peachbeach.info/ の使い方を簡単に説明します。

VyattaでIPSecを利用するネットワークインターフェイス」には、Vyattaがインターネットに接しているネットワークインターフェイスを入力します。上記の図では eth0 となります。

ローカルネットワーク情報」には、VPNで接続したいローカルネットワークを入力します。上記の図では 192.168.1.0/24 となります。

Amazon VPC のネットワーク情報」には、Amazon VPCを構築する時に設定したVPC IP CIDR Blockを入力します。上記の図では、10.0.0.0/16 となります。

Amazon VPCからダウンロードした設定情報」では、Amazon VPCを構築するときに Vendor を Generic としてダウンロードしたIPSec VPNの設定ファイルの内容をそのままコピペします。

以上4つのすべてを入力したら、「作成」ボタンを押します。

そうすると、下側に「Vyatta設定」と「Vyattaパケット転送スクリプト」が出力されます。これらの内容を持つファイルをVyatta内に作成します。ここでは、Vyatta設定を vpc_config.txt、Vyattaパケット転送スクリプトvpc_setup.sh として保存したとして話を進めます。

Vyatta にて以下のように実行して設定をマージします。(警告の原因はよくわかってません)

$ configure
# merge /path/to/vpc_config.txt
Warning: file does NOT appear to be a valid config file.
Do you want to continue? [no] Y
# commit
# save
# exit

次に、vpc_setup.sh を実行します。

$ sudo sh /path/to/vpc_setup.sh

以上で、VPNで2つのネットワークが接続されるので、例えばさくらのサーバ側から

$ ping 10.0.1.101
PING 10.0.1.101 (10.0.1.101) 56(84) bytes of data.
64 bytes from 10.0.1.101: icmp_req=1 ttl=62 time=10.9 ms
64 bytes from 10.0.1.101: icmp_req=2 ttl=62 time=10.7 ms

とすれば、接続されていることが確認できます。

もちろん、EC2 Instance にもログインできます。

公開サイトについて

http://gen-vyatta-conf.fluxflex.com/ ですが、URLからわかるように fluxflexを使っています。
ソース自体は https://github.com/kikumoto/gen-vyatta-conf-for-vpc にあります。fluxflex の github 連携を使うようにしました。

この fluxflex の github 連携はとっても便利ですね。git pushしたらすぐデプロイされて、サイトが更新されるのでよけいなコマンドの実行が減ってとてもいいです。

2012/06/30 に fluxflex が終了なので DotCloud に移行しました。(2012/06/17)

さいごに

需要あるのか疑わしいですが、使ってもらえるとうれしいです。

Diablo版Swiftインストール:ストレージサーバ編

前回、前々回からの続きで最後にストレージサーバを構築したときの手順をメモしておく。

構成とOS環境

keystone やプロクシサーバと同様。

パッケージインストール

ストレージサーバに必要なパッケージは以下のようにしてインストールした。

# yum install python-greenlet python-netifaces
# yum --disablerepo=diablo install openstack-swift-object openstack-swift-account openstack-swift-container xinetd

データ保存ディスクの準備

今回は、/dev/sdb に接続されたディスクにデータを保存する構成とした。そのために、fdisk で /dev/sdb 全体を1つのパーティションをつくり /dev/sdb1 として構成した。
これを以下のように XFS でフォーマットし、マウントしておく。

# yum -y install xfsprogs
# mkfs.xfs -i size=1024 /dev/sdb1
# echo "/dev/sdb1 /srv/node/sdb1 xfs noatime,nodiratime,nobarrier,logbufs=8 0 0" >> /etc/fstab
# mkdir -p /srv/node/sdb1
# mount /srv/node/sdb1
# chown -R swift:swift /srv/node

rsync

Swiftではデータの復旧などにrsyncを使うので、rsyncに関する設定をおこなっておく。まず、/etc/rsyncd.confを以下の内容で作成。address 部分は各ストレージサーバのIPに対応したものとなる。

uid = swift
gid = swift
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
address = 192.168.0.101

[account]
max connections = 25
path = /srv/node/
read only = false
lock file = /var/lock/account.lock

[container]
max connections = 25
path = /srv/node/
read only = false
lock file = /var/lock/container.lock

[object]
max connections = 25
path = /srv/node/
read only = false
lock file = /var/lock/object.lock

サービスと起動させるために、/etc/xinetd.d/rsync を以下のように記述し

service rsync
{
	disable	= no
	flags		= IPv4
	socket_type     = stream
	wait            = no
	user            = root
	server          = /usr/bin/rsync
	server_args     = --daemon
	log_on_failure  += USERID
}

xinetd サービスを再起動する。

# service xinetd restart

swift共通設定

プロクシサーバから /etc/swift 配下にある

  • swift.conf
  • account.ring.gz
  • container.ring.gz
  • object.ring.gz

を scp などで/etc/swiftにコピーしてくる。

ストレージサーバ設定

/etc/swift に account-server.conf, container-server.conf, object-server.conf を以下の内容で作成。各ファイルのbind_ipが、各ストレージサーバのIPに対応するように記述する。

account-server.conf
[DEFAULT]
bind_ip = 192.168.0.101
workers = 2
mount_check = false
user = swift
log_facility = LOG_LOCAL2

[pipeline:main]
pipeline = account-server

[app:account-server]
use = egg:swift#account

[account-replicator]

[account-auditor]

[account-reaper]
container-server.conf
[DEFAULT]
bind_ip = 192.168.0.101
workers = 2
mount_check = false
user = swift
log_facility = LOG_LOCAL2

[pipeline:main]
pipeline = container-server

[app:container-server]
use = egg:swift#container

[container-replicator]

[container-updater]

[container-auditor]
object-server.conf
[DEFAULT]
bind_ip = 192.168.0.101
workers = 2
mount_check = false
user = swift
log_facility = LOG_LOCAL2

[pipeline:main]
pipeline = object-server

[app:object-server]
use = egg:swift#object

[object-replicator]

[object-updater]

[object-auditor]

ファイルのオーナーを修正しておく。

# chown -R swift.swift /etc/swift

以上で設定ができたので、

# swift-init main start

で起動する。

動作確認

すべてのストレージサーバをセットアップした後、以下のようにして動作確認を行った。

コンテナを作成する。

$ swift -A http://172.16.0.99:5000/v1.0 -U demo -K secrete post folder1

コンテナにファイルをアップする。

$ swift -A http://172.16.0.99:5000/v1.0 -U demo -K secrete upload folder1 file1.txt

コンテナの内容を確認

$ swift -A http://172.16.0.99:5000/v1.0 -U demo -K secrete list folder1

以上で、DiabloSwiftの環境ができた。
今後は、これをベースにいろいろいじっていきたい。。。けれど、はたして。。。

Diablo版Swiftインストール:プロクシサーバ編

前回の記事 Diablo版Swiftインストール:keystone編 に引き続き、Swift環境として必要となるプロクシサーバを構築した時のメモ。

構成とOS環境

前回の記事の通りであるが、今回はストレージサーバのIP情報も必要となるので、それらについては以下の通り。

ストレージ1 192.168.0.101/24
ストレージ2 192.168.0.102/24
ストレージ3 192.168.0.103/24
ストレージ4 192.168.0.104/24

また、各ストレージには /dev/sdb としてデータ保存用ディスクが1つ接続されており、/dev/sdb1 という1つのパーティションのみ存在するものとしている。これについてはストレージサーバ編でも記述予定。

パッケージインストール

プロクシサーバに必要なパッケージは以下のようにしてインストールした。

# yum install python-greenlet python-httplib2 python-netifaces
# yum --disablerepo=diablo install openstack-swift-proxy openstack-keystone memcached python-memcached xinetd

openstack-keystone はプロクシサーバが Keystone にアクセスするために利用しているので必要。

プロクシサーバの設定

まずは memcached を起動しておく。

# chkconfig memcached on
#service memcached start

/etc/swift/swift.conf の記述。適当な文字列を設定しておく。

[swift-hash]
# random unique string that can never change, keep it secret and do NOT lose it
swift_hash_path_suffix = hogehoge_2011_10_24_xxxxxx

今回はSSLは使わないので、証明書などの作成は行わなかった。

そのうえで、/etc/swift/proxy-server.conf を以下のように作成した。

[DEFAULT]
# Enter these next two values if using SSL certifications
#cert_file = /etc/swift/cert.crt
#key_file = /etc/swift/cert.key
bind_port = 8080
workers = 8
user = swift

[pipeline:main]
#pipeline = healthcheck cache tempauth proxy-server
pipeline = healthcheck cache swift3 keystone proxy-server

[app:proxy-server]
use = egg:swift#proxy
allow_account_management = true
account_autocreate = true

#[filter:tempauth]
#use = egg:swift#tempauth
#user_system_root = testpass .admin https://192.168.30.133:8080/v1/AUTH_system

[filter:keystone]
use = egg:keystone#tokenauth
auth_protocol = http
auth_host = 172.16.0.99
auth_port = 5001
admin_token = 999888777666
delay_auth_decision = 0
service_protocol = http
service_host = 172.16.0.99
service_port = 5000
service_pass = dTpw

[filter:swift3]
use = egg:swift#swift3

[filter:healthcheck]
use = egg:swift#healthcheck

[filter:cache]
use = egg:swift#memcache
memcache_servers = 172.16.0.100:11211

ringファイルの作成

ringファイルの作成は以下のスクリプトで行った。パラメータの説明などはOpenStackの大容量ストレージサービス、Swiftの使い方 − TechTargetジャパン 仮想化が詳しい。

#!/bin/bash
export LANG=C
set -x
cd /etc/swift

PART_POWER=10
REPLICAS=3
MIN_PART_HOURS=1

#
# (1) Initialize builder files
#
swift-ring-builder account.builder create ${PART_POWER} ${REPLICAS} ${MIN_PART_HOURS}
swift-ring-builder container.builder create ${PART_POWER} ${REPLICAS} ${MIN_PART_HOURS}
swift-ring-builder object.builder create ${PART_POWER} ${REPLICAS} ${MIN_PART_HOURS}

#
# (2) Add devices
#
# zone 1
swift-ring-builder account.builder   add z1-192.168.0.101:6002/sdb1 1
swift-ring-builder container.builder add z1-192.168.0.101:6001/sdb1 1
swift-ring-builder object.builder    add z1-192.168.0.101:6000/sdb1 1

# zone 2
swift-ring-builder account.builder   add z2-192.168.0.102:6002/sdb1 1
swift-ring-builder container.builder add z2-192.168.0.102:6001/sdb1 1
swift-ring-builder object.builder    add z2-192.168.0.102:6000/sdb1 1

# zone 3
swift-ring-builder account.builder   add z3-192.168.0.103:6002/sdb1 1
swift-ring-builder container.builder add z3-192.168.0.103:6001/sdb1 1
swift-ring-builder object.builder    add z3-192.168.0.103:6000/sdb1 1

# zone 4
swift-ring-builder account.builder   add z4-192.168.0.104:6002/sdb1 1
swift-ring-builder container.builder add z4-192.168.0.104:6001/sdb1 1
swift-ring-builder object.builder    add z4-192.168.0.104:6000/sdb1 1

#
# (3) create ring files (rebalance)
#
swift-ring-builder account.builder rebalance
swift-ring-builder container.builder rebalance
swift-ring-builder object.builder rebalance

ここで、オーナの設定をしておく。

# chown -R swift:swift /etc/swift

以上で設定が完了なので

# swift-init proxy start

プロクシサーバを起動する。

現時点で動作確認する手段が不明なので、とりあえず 8080 ポートが python プロセスにより LISTEN されていればOK。

以上で、プロクシサーバの構築は終了。次回は最後に残ったストレージサーバについて記述予定。