2012年12月31日月曜日

"s3cmd"でリダイレクト機能を設定してみる

スズキです。

以前、下記のように紹介しましたが、S3の機能でリダイレクトできるようになりました。
S3のWebサイトのリダイレクト機能をTelnetで確認してみた
次のようにMetadata(ヘッダ)をつけることで、その機能を利用することができます。


当然、コマンドライン(s3cmd)でも同じ事をしたいのですが、以前、下記のように
S3へのアップロードなどでヘッダを追加する方法を紹介しましたが、
"s3cmd"でヘッダの追加
同様に追加するヘッダのキーとして"Website Redirect Location"を、そのまま
指定したのですが、当然ですがスペースがあったりなどでうまくいきませんでした。

じゃあ無理なのかというと、そうではなくヘッダのキーとしては
"x-amz-website-redirect-location"を指定すればうまくいきます。

"s3cmd"の引数(オプション)は次のような感じになり、実行すると上記の
AWSマネジメントコンソールと同じKey/Valueが設定されます。
# s3cmd put \
> ./index.html \
> s3://ap-northeast-1.yum.suz-lab.com/6/x86_64/index.html \
> -P \
> --add-header=x-amz-website-redirect-location:/6/x64_86/repoview/index.html
※ "-P"はパーミッションをパブリックにするオプションです。

今年は、ここまでかー...去年に比べてだいぶ記事数が減ってしまった...
--------
http://www.suz-lab.com

"Direct Hosting & Cache Distribution"パターンで"yum"リポジトリの作成(S3/CloudFront/R53まで)

スズキです。

下記でアップデート用のRPMを作成したので、今回は、"yum"でアップデートできるように
リポジトリを用意し、公開してみようと思います。
HistoryをSyslogに出力BashのRPMを作ってみた(CentOS6)
せっかくなので、次のCDPを適用した"yum"リポジトリを作成してみます。
図にするとこんな感じです。


ただし全部書くと記事が非常に長くなってしまうので、
まずは器(S3 & CloudFront & R53)の構築方法まで紹介します。

S3の準備


S3の管理ページでの作業です。


バケット名(トップレベルのフォルダ?)を指定します。


作成した状態が確認できます。


バケットのパーミッションは誰でもバケット内のオブジェクトリストが見れるように
しておきます。


"Website Hosting"機能を有効にして"/"でアクセスされた時に表示させる
"Index Document"とエラー時に表示させる"Error Document"を指定します。



CloudFrontの準備



CloudFrontの管理ページでの作業です。


静的なコンテンツ(RPM)のダウンロードなので"Download"を選択します。


"Origin Domain Name"は先ほどS3の"Website Hosting"の設定時に表示されたDNS名
(ap-northeast-1.yum.suz-lab.com.s3-website-ap-northeast-1.amazonaws.com)
を指定します。
"Website Hosting"のDNS名を指定した理由はCloudFront経由でも"Index Document"と"Error Document"が機能するようにしたかったためです。


とりあえず"Object Caching"をCustomizeにして"Minimum TTL"を5分にしておきました。
(このあたりは未検証...)


"yum.suz-lab.com"でCloudFrontを利用できるようにCNAMEの設定もしておきます。
念のためCloudFrontの方のインデックスドキュメント(Default Root Object)も
指定しておきます。


CloudFrontのDNS名も確認しておきます。



Route53の準備




適当なドメインで上記のCloudFront作成時に確認したDNS名
(d38dcqjtn0a8t7.cloudfront.net)と"yum.suz-lab.com"を関連付けます。


レコードはCNAMEで作成します。



コンテンツのS3へのアップロードと表示確認





S3の設定(Website Hosting)で"Index Document"に指定した"index.html"と
"Error Document"で指定した"error.html"を実際にアップロードします。



公開するのでパーミッションはパブリックです。


アップロードされていることが確認できます。


ブラウザで表示ができたら完成です!


後は"yum"リポジトリのコンテンツをEC2で作成してS3にアップロードすれば
"SUZ-LAB Repository"の完成です!
--------
http://www.suz-lab.com

2012年12月30日日曜日

HistoryをSyslogに出力BashのRPMを作ってみた(CentOS6)

スズキです。

以前、BashのHistoryをSyslogに出力する方法を紹介しました。
BashのHistoryをSyslogに出力(CentOS6)
この時はBashをソースからコンパイルし、バイナリは"/usr/local/bin/bash"に配置され、
パッケージ(yum)で入れた"/bin/bash"と二つ存在する状態になっていました。

今回はパッケージ(yum)で入れた"bin/bash"をアップデートする形になように、
上記のBashをRPMとして作成してみました。

準備(必要パッケージのインストールをSRPMのインストール)


ビルドに必要なパッケージとBashのソースRPMをインストールします。
# yum -y install rpm-build texinfo bison ncurses-devel autoconf gettext gcc make
# cd /root/
# rpm -Uvh http://vault.centos.org/6.3/os/Source/SPackages/bash-4.1.2-9.el6_2.src.rpm
# cd rpmbuild/SPECS/

SPECファイルの編集


リリースバージョン(Release)と"make"のオプション(-DSYSLOG_HISTORY)を調整します。
# diff bash.spec.org bash.spec
8c8
< Release: 9%{?dist}
---
> Release: 9%{?dist}_2.suzlab_1
132c132
< make "CFLAGS=$CFLAGS -fwrapv" "CPPFLAGS=-D_GNU_SOURCE -DRECYCLES_PIDS `getconf LFS_CFLAGS`"
---
> make "CFLAGS=$CFLAGS -fwrapv" "CPPFLAGS=-D_GNU_SOURCE -DRECYCLES_PIDS `getconf LFS_CFLAGS` -DSYSLOG_HISTORY"
上記のBashをソースからビルドしなおした記事では、ソース(config-top.h)を直接
編集してましたが、make(gcc)のオプションをつけることで、実はソースをいじらなくても
可能でした...

SPECファイルからRPMの作成しインストール

"bash"と"bash-doc"というRPMパッケージが作成されます。
# rpmbuild -ba bash.spec
# cd ../RPMS/x86_64/
# ls -1
bash-4.1.2-9.el6_2.suzlab_1.x86_64.rpm
bash-doc-4.1.2-9.el6_2.suzlab_1.x86_64.rpm
# rpm -Uvh bash-4.1.2-9.el6_2.suzlab_1.x86_64.rpm 

ログインしなおして"/var/log/message"の確認

無事、Historyが出力されました!
# tail /var/log/messages
...
Dec 30 15:49:40 ip-10-200-32-9 -bash: HISTORY: PID=20513 UID=0 tail /var/log/messages

次は"Direct Hosting & Cache Distribution"パターンで作成したRPMを
"yum"リポジトリとして公開です。
--------
http://www.suz-lab.com

2012年12月29日土曜日

IAMリソースをCloudFormationで作成する注意点

スズキです。

下記のようなCloudFormationテンプレートでスタックを作るケースを想定します。


つまり、直接スタックを作成するテンプレートが、IAMリソースを作成するテンプレートを
呼び出す(インクルードされている)状態を想定しています。

このテンプレートから下記のように普通にスタックを作成すると、


次のようにエラーが発生し、ロールバックされてしまいます。


原因はIAMを作成するテンプレートで問題が発生したからです。


実はこの問題、下記のようにIAMリソース作成の確認に関するチェックを
入れてなかったがために発生しました。


ですので、ちゃんとチェックを入れて作成すると、今度は無事作成されます。

ちなみに、直接IAMリソースを作成するテンプレートでスタックを作成しようとすると、


上記のようにスタックを作り始める前にエラーになってくれます。

IAMのCDPも検討したい...
--------
http://www.suz-lab.com

2012年12月28日金曜日

"cloud-init"で起動時に任意のスクリプトを実行する(CentOS6)

スズキです。

下記のように"cloud-init"で、EC2起動時にいろいろと処理を行う方法を紹介してきました。
今回は起動時に任意のスクリプトを実行する設定を試してみます。

設定ファイルの調整とリブート


"cloud_init_modules"に"bootcmd"を追加し、実行するスクリプトも"bootcmd"で
リスト形式で(複数)指定します。
# cat /etc/cloud/cloud.cfg
manage_etc_hosts: localhost
user: root
disable_root: false
ssh_genkeytypes: [ rsa, dsa ]
ssh_pwauth: yes
bootcmd:
 - echo $INSTANCE_ID > /tmp/instance_id.txt

cloud_init_modules:
 - bootcmd
 - resizefs
 - update_etc_hosts
 - ssh
...
設定できたらリブートします。
# reboot

スクリプトのとログの確認


"cloud-init"のスクリプトを読むと"bootcmd"実行直前にシェル変数(INSTANCE_ID)に
インスタンスIDがセットされていたのですが、下記より確認することができました。
# cat /tmp/instance_id.txt 
i-7aa8c079
ログも次の通りです。
# cat /var/log/cloud-init.log 
...
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] cloud-init[INFO]: cloud-init start running: Fri, 28 Dec 2012 07:55:16 +0000. up 8.41 seconds
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] __init__.py[DEBUG]: searching for data source in ['DataSourceNoCloudNet', 'DataSourceConfigDriveNet', 'DataSourceOVFNet', 'DataSourceEc2']
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] DataSourceEc2.py[DEBUG]: removed the following from metadata urls: ['http://instance-data:8773']
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] DataSourceEc2.py[DEBUG]: Using metadata source: 'http://169.254.169.254'
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] DataSourceEc2.py[DEBUG]: crawl of metadata service took 0s
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] __init__.py[DEBUG]: found data source DataSourceEc2
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] cloud-init[DEBUG]: found data source: DataSourceEc2
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] __init__.py[DEBUG]: handling bootcmd with freq=None and args=[]
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] __init__.py[DEBUG]: handling resizefs with freq=None and args=[]
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] cc_resizefs.py[DEBUG]: resizing root filesystem (type=ext4, maj=202, min=65)
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] __init__.py[DEBUG]: handling update_etc_hosts with freq=None and args=[]
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] cc_update_etc_hosts.py[DEBUG]: managing 127.0.1.1 in /etc/hosts
Dec 28 16:55:16 ip-10-0-0-51 [CLOUDINIT] __init__.py[DEBUG]: handling ssh with freq=None and args=[]

とりあえず"cloud_init_modules"まででAMIを作るか。(もくもく勉強会で...)
--------
http://www.suz-lab.com

"cloud-init"で"Key Pair"の公開鍵をEC2起動時に自動で".ssh/authorized_keys"に登録する(CentOS6)

スズキです。

下記のように"cloud-init"で、EC2起動時にいろいろと処理を行う方法を紹介してきました。
今回はEC2起動時の定番の処理である、"Key Pair"の公開鍵を".ssh/authorized_keys"に
登録する処理を"cloud-init"で実現してみます。(といっても設定ファイルの調整のみです)

設定ファイルの調整とリブート


今まで通りの"root"でのログインにするため、下記のように
"user, disable_root, ssh_genkeytypes"を指定して、"cloud_init_modules"に"ssh"も
追加しておきます。
# cat /etc/cloud/cloud.cfg
manage_etc_hosts: localhost
user: root
disable_root: false
ssh_genkeytypes: [ rsa, dsa ]

cloud_init_modules:
 - resizefs
 - update_etc_hosts
 - ssh
...
設定できたらリブートします。
# reboot

".ssh/authorized_keys"とログの確認


".ssh/authorized_keys"は次のように登録されていることが確認できました。
(ということは当然SSHでのログインも成功しています)
# cat /root/.ssh/authorized_keys 

ssh-rsa AAAA...AAAA suz-lab_ap-northeast-1
ログ(/var/log/cloud-init.log)も下記のように該当するものが出力されています。
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] cloud-init[INFO]: cloud-init start running: Thu, 27 Dec 2012 09:15:34 +0000. up 9.67 seconds
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] __init__.py[DEBUG]: searching for data source in ['DataSourceNoCloudNet', 'DataSourceConfigDriveNet', 'DataSourceOVFNet', 'DataSourceEc2']
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] DataSourceEc2.py[DEBUG]: removed the following from metadata urls: ['http://instance-data:8773']
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] DataSourceEc2.py[DEBUG]: Using metadata source: 'http://169.254.169.254'
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] DataSourceEc2.py[DEBUG]: crawl of metadata service took 0s
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] __init__.py[DEBUG]: found data source DataSourceEc2
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] cloud-init[DEBUG]: found data source: DataSourceEc2
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] __init__.py[DEBUG]: handling bootcmd with freq=None and args=[]
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] __init__.py[DEBUG]: handling resizefs with freq=None and args=[]
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] cc_resizefs.py[DEBUG]: resizing root filesystem (type=ext4, maj=202, min=65)
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] __init__.py[DEBUG]: handling set_hostname with freq=None and args=[]
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] cc_set_hostname.py[DEBUG]: populated /etc/hostname with ip-10-0-32-171 on first boot
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] __init__.py[DEBUG]: handling rsyslog with freq=None and args=[]
Dec 27 18:15:34 ip-10-0-32-171 [CLOUDINIT] __init__.py[DEBUG]: handling ssh with freq=None and args=[]

次は"set-passwords"、特に"ssh_pwauth"。。。
--------
http://www.suz-lab.com

BashのHistoryをSyslogに出力(CentOS6)

スズキです。

セキュリティ要件的に、表記を実現しないといけないことは多々有り、ネットを調べると
いろいろな方法が見つかりましたが、そもそもBashが対応してました。

特に、下記のブログが大変参考になります。
bash 4.1はヒストリーをsyslogにも記録する
”SUZ-LAB AMI”(CentOS6)でも同様のことをやってみました。

必要パッケージのインストール


ソースからビルドをするので"gcc"と"make"が必要です。
# yum -y install gcc
# yum -y install make

Bashソースのダウンロードと展開


いつものやつです。
# cd /usr/local/src
# curl -OL http://ftp.gnu.org/gnu/bash/bash-4.2.tar.gz
# tar xvzf bash-4.2.tar.gz 
# cd bash-4.2

"config-top.h"の修正


ダウンロード&展開したときに下記だった部分を
/* #define SYSLOG_HISTORY */
#if defined (SYSLOG_HISTORY)
#  define SYSLOG_FACILITY LOG_USER
#  define SYSLOG_LEVEL LOG_INFO
#endif
次のように修正します。(SYSLOG_HISTORYを有効にします。)
/* #define SYSLOG_HISTORY */
#define SYSLOG_HISTORY 
#if defined (SYSLOG_HISTORY)
#  define SYSLOG_FACILITY LOG_USER
#  define SYSLOG_LEVEL LOG_INFO
#endif

ビルドとインストール


これも、いつものやつです。
# ./configure
# make
# make install

ログインシェルの変更


"/bin/bash"から"/usr/local/bin/bash"に変更しています。
# vipw 
root:x:0:0:root:/root:/usr/local/bin/bash
...

Syslogの確認


ログインしなおして、上記の設定を有効にし、Syslogを確認してみると、下記のように
実行コマンドに関するログが出力されていることがわかります。
# /var/log/messages
...
Dec 28 11:44:42 ip-10-0-0-51 -bash: HISTORY: PID=19221 UID=0 ls
Dec 28 11:44:47 ip-10-0-0-51 -bash: HISTORY: PID=19221 UID=0 less /var/log/messages
...

あとは、"Fluentd → S3 → Glacier"、... (何回言ってるんだろう...)

RPMにでもしておくか。
--------
http://www.suz-lab.com

CentOS(6)で"audit(d)"のログを"syslog"に出力

スズキです。

"audit(d)"のログは下記のように出力されます。
# cat /var/log/audit/audit.log
...
type=USER_LOGIN msg=audit(1356650120.217:43527): user pid=23041 uid=0 auid=4294967295 ses=4294967295 msg='op=login acct=28756E6B6E6F776E207573657229 exe="/usr/sbin/sshd" hostname=? addr=127.0.0.1 terminal=ssh res=failed'

このログを"syslog"にも出力するようにするには次のように設定します。
("active"を"no"から"yes"に変更)
# cat /etc/audisp/plugins.d/syslog.conf 
...
active = yes
direction = out
path = builtin_syslog
type = builtin 
args = LOG_INFO
format = string

(r)syslogを再起動すると上記の設定が反映されます。
# /etc/init.d/auditd restart
auditd を停止中:                                           [  OK  ]
auditd を起動中:                                           [  OK  ]

設定が反映すると、上述したログが"syslog"として下記のように出力されます。
# cat /var/log/messages
...
Dec 28 08:00:19 ip-10-0-0-87 audispd: node=ip-10-0-0-87 type=USER_LOGIN msg=audit(1356649219.815:43407): user pid=22805 uid=0 auid=4294967295 ses=4294967295 msg='op=login acct=28756E6B6E6F776E207573657229 exe="/usr/sbin/sshd" hostname=? addr=127.0.0.1 terminal=ssh res=failed'

後は下記のようにFluentdでS3に送ってGlacierでアーカイブして...

Fluentdで"Web Storage Archiveパターン"
"各種ログ → rsyslog → fluentd → S3 → Glacier"のパターンに持ち込めると楽...

--------
http://www.suz-lab.com

2012年12月27日木曜日

"cloud-init"で"/etc/hosts"にホスト名を追加を自動で行う(CentOS6)

スズキです。

以前"cloud-init"で、EC2起動時にEBSを自動リサイズする方法を紹介しました。
"cloud-init"でEBSのリサイズを起動時に自動で行う(CentOS6)
"cloud-init"は他にもいろいろと起動時に自動で出来る処理があり、今回は"/etc/hosts"に
ホスト名を追加する設定方法を紹介します。(上記でcloud-initが導入済みとします)

"/etc/hosts"の確認


まあ、いつものやつが入ってます。
# cat /etc/hosts
127.0.0.1       localhost.localdomain localhost

"/etc/cloud/cloud.cfg"の設定


"/etc/hosts"ファイルにホスト名を追加するには"update_etc_hosts"です。
# cat /etc/cloud/cloud.cfg
manage_etc_hosts: localhost

cloud_init_modules:
 - resizefs
 - update_etc_hosts

...

EC2をリブート

# reboot

"/etc/hosts"の再確認


"127.0.1.1"としてホスト名が追加されています。
# cat /etc/hosts
127.0.0.1       localhost.localdomain localhost
# Added by cloud-init
127.0.1.1 ip-10-0-32-143.localdomain ip-10-0-32-143

ログの確認

# cat /etc/cloud/cloud.cfg
...
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] cloud-init[INFO]: cloud-init start running: Thu, 27 Dec 2012 03:11:40 +0000. up 8.96 seconds
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] __init__.py[DEBUG]: searching for data source in ['DataSourceNoCloudNet', 'DataSourceConfigDriveNet', 'DataSourceOVFNet', 'DataSourceEc2']
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] DataSourceEc2.py[DEBUG]: removed the following from metadata urls: ['http://instance-data:8773']
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] DataSourceEc2.py[DEBUG]: Using metadata source: 'http://169.254.169.254'
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] DataSourceEc2.py[DEBUG]: crawl of metadata service took 0s
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] __init__.py[DEBUG]: found data source DataSourceEc2
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] cloud-init[DEBUG]: found data source: DataSourceEc2
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] __init__.py[DEBUG]: handling resizefs with freq=None and args=[]
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] cc_resizefs.py[DEBUG]: resizing root filesystem (type=ext4, maj=202, min=65)
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] __init__.py[DEBUG]: handling update_etc_hosts with freq=None and args=[]
Dec 27 12:11:40 ip-10-0-32-143 [CLOUDINIT] cc_update_etc_hosts.py[DEBUG]: managing 127.0.1.1 in /etc/hosts
...

次はSSHまわり...
--------
http://www.suz-lab.com

2012年12月26日水曜日

"cloud-init"でEBSのリサイズを起動時に自動で行う(CentOS6)

スズキです。

以前、下記のようにEC2(CentOS6)起動時にブートディスク(EBS)のサイズを
デフォルトより大きいものに指定して、起動後"resize2fs"でOS的にも使える容量を
拡張する方法を紹介しました。
サイズの小さなAMIからブートディスク(EBS)を大きくしてEC2を起動
今回は、その"resize2fs"に相当する作業をEC2起動時に"cloud-init"を利用して自動で
行うようにしてみます。

"cloud-init"のインストールと設定


"yum"でインストールできます。
# yum -y install cloud-init

設定ファイルは下記の通りです。(resizefsのみ有効)
# cat /etc/cloud/cloud.cfg
cloud_init_modules:
 - resizefs

自動起動を有効化
# chkconfig cloud-init on

上記を仕込んだEC2をAMI化してEC2の起動に利用するようにします。

EC2起動ににEBSのサイズを変更(拡張)


下記のよう上記で作成したAMIをAWSマネジメントコンソールで拡張可能です。


サイズを変更(拡張)して右側(図には入らなかった...)のボタンを押すと、そのサイズが
EBSに反映されます。


OS(CentOS6)上で確認



ちゃんとEBS拡張時に指定したサイズ(10G)になっています。
# df -h
Filesystem            Size  Used Avail Use% マウント位置
/dev/xvde1            9.9G  2.3G  7.1G  25% /
none                  296M     0  296M   0% /dev/shm

ログでもリサイズされていることがわかります。
# cat /var/log/cloud-init.log
...
Dec 26 22:43:32 ip-10-0-32-140 [CLOUDINIT] cloud-init[INFO]: cloud-init start running: Wed, 26 Dec 2012 13:43:32 +0000. up 30.35 seconds
Dec 26 22:43:32 ip-10-0-32-140 [CLOUDINIT] __init__.py[DEBUG]: searching for data source in ['DataSourceNoCloudNet', 'DataSourceConfigDriveNet', 'DataSourceOVFNet', 'DataSourceEc2']
Dec 26 22:43:32 ip-10-0-32-140 [CLOUDINIT] DataSourceEc2.py[DEBUG]: removed the following from metadata urls: ['http://instance-data:8773']
Dec 26 22:43:32 ip-10-0-32-140 [CLOUDINIT] DataSourceEc2.py[DEBUG]: Using metadata source: 'http://169.254.169.254'
Dec 26 22:43:32 ip-10-0-32-140 [CLOUDINIT] DataSourceEc2.py[DEBUG]: crawl of metadata service took 0s
Dec 26 22:43:32 ip-10-0-32-140 [CLOUDINIT] __init__.py[DEBUG]: found data source DataSourceEc2
Dec 26 22:43:32 ip-10-0-32-140 [CLOUDINIT] cloud-init[DEBUG]: found data source: DataSourceEc2
Dec 26 22:43:32 ip-10-0-32-140 [CLOUDINIT] __init__.py[DEBUG]: handling resizefs with freq=None and args=[]
Dec 26 22:43:32 ip-10-0-32-140 [CLOUDINIT] cc_resizefs.py[DEBUG]: resizing root filesystem (type=ext4, maj=202, min=65)

"SUZ-LAB AMI"に組み込んでおこう。
--------
http://www.suz-lab.com

"IAM Role"をCloudFormationでつくってみた

スズキです。

テンプレートは下記のような感じです。

suz-lab_iam-base.json
{
    "AWSTemplateFormatVersion": "2010-09-09", 
    "Description": "SUZ-LAB Formation IAM Base", 
    "Mappings": {
        "AvailabilityZoneMap": {
            "ap-northeast-1": {
                "AzA": "ap-northeast-1a", 
                "AzB": "ap-northeast-1b", 
                "AzC": "ap-northeast-1c"
            }
        }
    }, 
    "Parameters": {
        "PowerUserName": {
            "Default": "power-user", 
            "Description": "Power User Name", 
            "Type": "String"
        }
    }, 
    "Resources": {
        "IAMRolePowerUser": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Statement": [ {
                        "Effect": "Allow",
                        "Principal": { "Service": [ "ec2.amazonaws.com" ] },
                        "Action": [ "sts:AssumeRole" ]
                    } ]
                },
                "Path": "/"
            }
        },
        "IAMPolicyPowerUser": {
            "Type": "AWS::IAM::Policy",
            "Properties": {
                "PolicyName": { "Ref": "PowerUserName" },
                "PolicyDocument": {
                    "Statement": [ {
                        "Effect": "Allow",
                        "NotAction": "iam:*",
                        "Resource": "*"
                    } ]
                },
                "Roles": [ { "Ref": "IAMRolePowerUser" } ]
            }
        },
        "IAMInstanceProfilePowerUser": {
            "Type": "AWS::IAM::InstanceProfile",
            "Properties": {
                "Path": "/",
                "Roles": [ { "Ref": "IAMRolePowerUser" } ]
            }
        }
    },
    "Outputs": {
        "GithubMarkdown": {
            "Description": "Github Markdown",
            "Value": "https://github.com/suz-lab/suz-lab-centos-ami/blob/master/share/cloudfromation/suz-lab_iam-base.md"
        }, 
        "GithubJson": {
            "Description": "Github JSON",
            "Value": "https://github.com/suz-lab/suz-lab-centos-ami/blob/master/share/cloudfromation/suz-lab_iam-base.json"
        }, 
        "S3JsonApNortheast1": {
            "Description": "S3 JSON ap-northeast-1",
            "Value": "http://ap-northeast-1.template.suz-lab.com.s3.amazonaws.com/template/suz-lab_iam-base/0.0.1.json"
        }, 
        "CacooImage": {
            "Description": "Cacoo Image",
            "Value": "https://cacoo.com/diagrams/XXXXXXXXXXXXXXXX-XXXXX.png"
        }
    } 
}

上記のテンプレートでCloudFormationのスタックを下記のように作成してみます。


IAMの方も、該当Roleが作成されています。


当然、EC2起動時に、そのRoleを指定することもできます。


社内をヒアリングして、いつも作ってるIAMリソースを洗い出そう。
--------
http://www.suz-lab.com

2012年12月25日火曜日

Squid経由でAWSマネジメントコンソールにアクセスしてソースIP制限したり認証したりログを取ったり

スズキです。

AWSマネジメントコンソールは非常に便利なのですが、基本的に、どこから
(漫画喫茶から)でも利用できてしまい、誰が何をやったかのログも現状、取得することが
できません。

しかし実は、IAMで利用できるポリシーでAPIのアクセス制限に下記のようにソースIPを
指定することができます。

{ "Statement": [
  {
    "Effect": "Allow",
    "Action": "*",
    "Resource": "*",
    "Condition": {
      "IpAddress": { "aws:SourceIp": "xxx.xxx.xxx.xxx" }
    }
  }
] }
この状態で指定したIP(xxx.xxx.xxx.xxx)以外からAWSマネジメントコンソールに
アクセスすると下記のようにログインはできるのですが、おそらくAPIを利用して
取得しているリソースにアクセスすることができません。


なので、とりあえず「どこからでも利用できてしまう」課題は解決できます。

そして、もう一つ「ユーザーの操作ログが取得できない」課題ですが下記のように
AWS上(AWSでなくてもいいけど)にHTTP(S)のプロキシーサーバ(Squid)をたてて
「誰が何をしたか?」のログが取得できないか試してみました。


結論からいいますと、

SquidでProxyを利用するときに認証(User/Passを発行)を
必要とする設定にすることで、Squidのアクセスログに、そのユーザー名が表示され
誰がいつAWSマネジメントコンソールにアクセスしているかは確認できます。

しかし、そもそもHTTPS通信なので、出力されるログはCONNECTのもののみで、
当然(暗号化されてるので)、メソッドやパス、パラメータはわかりません。

それを補うために"iptables"でOutboundの443とInboundの3128の通信ログも
取得しCONNECT以外のTCP(ヘッダ)レベルのログも取得できるようにしたが、
今度は当然、ユーザーとの紐付けができない。

といった感じでした...

それでも無いよりはましだと思いますし、いろいろなAWSアカウントへのアクセスを
Squidのユーザー管理(認証)で一括で制御できることは何かと便利だと思いますので、
次に作り方を(ざっくり)紹介します。

EC2(Squid)に適用するセキュリティグループの設定


オープンプロキシーにならないように必要なものだけ許可しましょう。
※当然EIP(上記のxxx.xxx.xxx.xxx)をつけてインターネットへと直接通信できる前提です。


パッケージ(Squid & Apache)のインストール


Squidは当然ですが、htpasswdを利用したいがためにApacheもインストールしています。
# yum -y install squid
...
# yum -y install httpd
...

Squid起動のための準備(ディレクトリ & パスワードファイル)


ログ出力ディレクトリの準備
# mkdir -p /opt/suz-lab/var/log/apache
# mkdir -p /opt/suz-lab/etc/squid
# touch /opt/suz-lab/etc/squid/squid.log
# chown squid.squid /opt/suz-lab/etc/squid/squid.log 
パスワードファイルの準備
# htpasswd -c /opt/suz-lab/etc/squid/squid.htpasswd suzuki
New password: 
Re-type new password: 

Squidの設定ファイル


設定ファイルはこんな感じにしました。
(ソースIP制限はセキュリティグループに任せています)
# cat /etc/squid/squid.conf
auth_param basic program /usr/lib64/squid/ncsa_auth /opt/suz-lab/etc/squid/squid.htpasswd
auth_param basic children 20
auth_param basic realm SUZ-LAB Proxy Server
auth_param basic credentialsttl 1 hours

acl port_https port       443
acl auth_basic proxy_auth REQUIRED

http_access allow all auth_basic port_https
http_access deny  all
cache       deny  all

http_port 3128
coredump_dir /var/spool/squid
logformat combined %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %<st "%{Referer}>h" "%{User-Agent}>h" %Ss:%Sh
access_log /opt/suz-lab/var/log/apache/squid.log combined
そしてSquidの起動です。
# chkconfig squid on
# /etc/init.d/squid start
squid を起動中: .                                          [  OK  ]

ブラウザ側(Mac & Chrome)のプロキシー設定


Chromeの右上のボタン?から開始です。



最後にOSにいろいろ確認とられたり、ChromeがポップアップでUser/Passを
きいてくるかも知れませんが、適当に処理して下さい。

再度AWSコンソールにアクセス


今度は無事リソースにアクセスできています。


Squidのログはこんな感じです。(ちゃんとユーザー"suzuki"も出力されてます)
yyy.yyy.yyy.yyy - suzuki [24/Dec/2012:21:19:26 +0900] "CONNECT aws.amazon.com:443 HTTP/1.1" 200 4061 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11" TCP_MISS:DIRECT
yyy.yyy.yyy.yyy - suzuki [24/Dec/2012:21:19:26 +0900] "CONNECT aws.amazon.com:443 HTTP/1.1" 200 122 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11" TCP_MISS:DIRECT
yyy.yyy.yyy.yyy - suzuki [24/Dec/2012:21:19:26 +0900] "CONNECT console.aws.amazon.com:443 HTTP/1.1" 200 5096 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11" TCP_MISS:DIRECT
yyy.yyy.yyy.yyy - suzuki [24/Dec/2012:21:19:29 +0900] "CONNECT aws.amazon.com:443 HTTP/1.1" 200 3007 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11" TCP_MISS:DIRECT

"iptables"でログ出力


下記のように"INPUT:3128"と"OUTPUT:443"で取得することにします。
# chkconfig iptables on
# /etc/init.d/iptables start
# /sbin/iptables -A INPUT  -p tcp --dport 3128 -j LOG
# /sbin/iptables -A OUTPUT -p tcp --dport 443  -j LOG
# /etc/init.d/iptables save
iptables: ファイアウォールのルールを /etc/sysconfig/iptable[  OK  ]中: 
# /etc/init.d/iptables restart
iptables: ファイアウォールルールを消去中:                  [  OK  ]
iptables: チェインをポリシー ACCEPT へ設定中filter         [  OK  ]
iptables: モジュールを取り外し中:                          [  OK  ]
iptables: ファイアウォールルールを適用中:                  [  OK  ]
# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
LOG        tcp  --  anywhere             anywhere            tcp dpt:squid LOG level warning 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
LOG        tcp  --  anywhere             anywhere            tcp dpt:https LOG level warning 
ログは次のように出力されます。
Dec 24 21:28:19 ip-10-0-0-4 kernel: IN=eth0 OUT= MAC=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx SRC=yyy.yyy.yyy.yyy DST=10.0.0.4 LEN=617 TOS=0x00 PREC=0x00 TTL=51 ID=39187 DF PROTO=TCP SPT=51590 DPT=3128 WINDOW=8192 RES=0x00 ACK PSH URGP=0 
Dec 24 21:28:19 ip-10-0-0-4 kernel: IN= OUT=eth0 SRC=10.0.0.4 DST=zzz.zzz.zzz.zzz LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=50434 DF PROTO=TCP SPT=40967 DPT=443 WINDOW=648 RES=0x00 ACK URGP=0 

最後に


誰が何をやったかを完全に追いかけれるログは取得できませんでしたが、
複数のアカウントがある場合などは、IAMは共用のアカウントを一つ作って
関係者はそれでSquid経由でアクセスすることにし、各ユーザーの制御はSquidの
認証で一元管理するってやり方はありかも知れません。
(cloudpackはアカウントが多すぎて、該当するメンバーをすべてのアカウントの
IAMに登録するのは現状厳しい...どうせ全員、全アカウントにログインするし...)

また、Squidの認証はLDAPと連携できますし、OpenVPNでVPN接続した後に
プロキシーを使えば、ソースIPもユーザー毎に変えることができるはずなので、
"iptables"のログもより意味を持ってくると思います。

どっかでLDAP、がんばらないとなー...
--------
http://www.suz-lab.com

2012年12月23日日曜日

NATインスタンス(EC2)での通信ログを取得

スズキです。

まず、NATインスタンス(EC2)は下記のように作ることができます。
VPCのNATインスタンスを作ってみる(iptables編)
このNATインスタンスを通過する通信をログに出力する方法です。
(いろいろやり方はあると思いますが"iptables"を使った方法です)

一旦"iptables"を初期化

# iptables -t nat -F
# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

"iptables"の設定(ログ出力とNAT)

# iptables -t nat -A POSTROUTING -j LOG
# iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 -j MASQUERADE
# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere            LOG level warning 
MASQUERADE  all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

出力ログ(syslog)の確認

Dec 23 21:54:49 ip-10-0-8-10 kernel: IN= OUT=eth0 SRC=xxx.xxx.xxx.xxx DST=27.0.2.83 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=29593 DF PROTO=TCP SPT=48918 DPT=80 WINDOW=14600 RES=0x00 SYN URGP=0 
Dec 23 21:54:50 ip-10-0-8-10 kernel: IN= OUT=eth0 SRC=xxx.xxx.xxx.xxx DST=27.0.2.83 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=10399 DF PROTO=TCP SPT=48919 DPT=80 WINDOW=14600 RES=0x00 SYN URGP=0 
Dec 23 21:54:51 ip-10-0-8-10 kernel: IN= OUT=eth0 SRC=xxx.xxx.xxx.xxx DST=27.0.2.83 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=51974 DF PROTO=TCP SPT=48920 DPT=80 WINDOW=14600 RES=0x00 SYN URGP=0

"iptables"の設定の永続化

# /etc/init.d/iptables save
iptables: ファイアウォールのルールを /etc/sysconfig/iptable[  OK  ]中: 
# /etc/init.d/iptables restart
iptables: ファイアウォールルールを消去中:                  [  OK  ]
iptables: チェインをポリシー ACCEPT へ設定中filter nat     [  OK  ]
iptables: モジュールを取り外し中:                          [  OK  ]
iptables: ファイアウォールルールを適用中:                  [  OK  ]
# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere            LOG level warning 
MASQUERADE  all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

ログの量は多くなってしまいますが、FluentdがS3に送って、
S3がGlacierに保存してくれるはずです...
--------
http://www.suz-lab.com

Apacheのログ(アクセス/エラー)をS3にアーカイブ

スズキです。

以前、Fluentdで"syslog"をS3にアーカイブする方法を紹介しました。

Fluentdで"Web Storage Archiveパターン"
今回はApacheの(アクセス/エラー)ログをS3にアーカイブしてみます。

エラーログをS3にアーカイブ


これは、そもそもApacheのエラーログを"syslog"に出力できれば、上記の方法で終了です。

"syslog"への出力は設定ファイル(/etc/httpd/conf/httpd.conf)を下記のように
することで可能です。
...
#ErrorLog logs/error_log
ErrorLog syslog
...
Apacheをリスタートすると"syslog"にApacheのエラーログが下記のように出力されます。
...
Dec 23 16:55:43 ip-10-100-0-236 httpd[22042]: [error] [client xxx.xxx.xxx.xxx] Directory index forbidden by Options directive: /var/www/html/
Dec 23 16:55:43 ip-10-100-0-236 httpd[22045]: [error] [client xxx.xxx.xxx.xxx] File does not exist: /var/www/html/favicon.ico

もう"syslog"の世界なので、前述した方法でFluentdがS3にアーカイブしてくれます。

アクセスログをS3にアーカイブ


エラーログとは異なり、アクセスログを"syslog"に出力する仕組みはありません。
(パイプなどで外部プログラムを利用することで出力することは可能です)

ただ、幸いにもFluentdの"tail"のフォーマットには"syslog"以外に"apache"も標準で
用意されています。ですので、Apacheのアクセスログは直接Fluentdが"tail"して、
S3にアーカイブするようにします。

Fluentdの設定ファイルは、こんな感じになりました。
<source>
    type     tail
    format   apache
    path     /var/log/httpd/access_log
    pos_file /opt/suz-lab/var/lib/td-agent/pos/tail.apache.pos
    tag      tail.apache
</source>
<match tail.apache>
    type s3
    aws_key_id        ACCESS_KEY
    aws_sec_key       SECRET_KEY
    s3_bucket         log2.suz-lab.com
    s3_endpoint       s3-ap-northeast-1.amazonaws.com
    path              apache/
    buffer_path       /opt/suz-lab/var/lib/td-agent/buf/s3.apache
    time_slice_format %Y/%m/%d/ip-10-100-0-236/%H
    flush_interval    10m
</match>
このままだとパーミッションの問題が発生したので、Apacheのログ出力先ディレクトリの
パーミッションも下記のように調整しました。
# chmod 755 /var/log/httpd/

すると、S3に次のようにアクセスログがアーカイブされるようになります。
2012-12-23T19:25:51+09:00 tail.apache {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/","code":"403","size":"5039","referer":"-","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11"}
2012-12-23T19:25:51+09:00 tail.apache {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/favicon.ico","code":"404","size":"288","referer":"-","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11"}
2012-12-23T19:25:52+09:00 tail.apache {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/favicon.ico","code":"404","size":"288","referer":"-","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11"}

そしてEMRのHiveで...
--------
http://www.suz-lab..com

VPCの"DHCP Options Set"でNTPサーバを指定する

スズキです。

以前、VPCの"DHCP Options Set"でDNSサーバを指定する方法を紹介しました。
VPCの"DHCP Options Set"でEC2のDNS情報を変更する
実は、この"DHCP Options Set"、下記のようにNTPサーバも指定できます。


そしてVPCの"DHCP Options Set"を上記のものに変更します。

それから、CentOS(6)なら下記を実行することにより、
# /etc/init.d/network restart
"/etc/ntp.conf"に次のように追加されます。
# cat /etc/ntp.conf
...
server 10.100.0.247  # added by /sbin/dhclient-script
ちなみにデフォルトの設定はコメントアウトしておいています。
# server 0.centos.pool.ntp.org
# server 1.centos.pool.ntp.org
# server 2.centos.pool.ntp.org
そしてNTPを再起動することにより有効化します。
(次からは起動時に自動で処理されるはずです)
# /etc/init.d/ntpd restart

当然VPC内のEC2がアクセスする(VPC内の)NTPサーバは外部のNTPサーバと
通信しなければいけないので、DHCPからのサーバ情報を反映させたくありません。

このような場合は下記のように"PEERNTP=no"と設定します。
# cat /etc/sysconfig/network-scripts/ifcfg-eth0 
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=on
PEERNTP=no
PEERDNS=yes
※ちなみに"/etc/resolv.conf"にDNS情報も反映させたくない場合は"PEERDNS=no"です。

図にすると、こんな感じでしょうか?


これも、"SUZ-LAB Formation"に組み込めるか!?
--------
http://www.suz-lab.com

TwemproxyからElastiCacheに分散(同じキーは同じElastiCacheへ)してみる

スズキです。

下記とおり、ようやくVPC上にElastiCacheがきてくれましたが、
VPC上のElastiCacheを試してみた
やはり、キャッシュクラスタはAZをまたがることができず、また、ノード毎に
エンドポイントが用意されているので、キーの分散(同じキーは同じサーバへ)は
自分で行う必要があります。

この"キーの分散"をアプリ側でやるのではなく、インフラ(ミドルウェア)で
吸収できないかなー?と調べてみたら、下記のようなプロダクトがありました。
twemproxy (nutcracker)

twemproxy (pronounced "two-em-proxy"), aka nutcracker
is a fast and lightweight proxy for memcached and redis protocol.
It was primarily built to reduce the connection count
on the backend caching servers.

"twemproxy"(トゥーエンプロキシーと発音)は"nutcracker"とも呼ばれ、
"memcached"と"redis"のプロトコルのための高速で軽量なプロキシーです。
バックエンド(キャッシュ)サーバへの接続数を減少させるために作られました。
まあ文字通り、Twitterでも使われているプロダクトのようです。

そして特長の一つに下記が挙がっています。
Supports multiple hashing modes including consistent hashing and distribution.

"Consistent Hashing"に分散を含む多くのハッシュ方法をサポートしています。
"Consistent Hashing"に関しては下記が非常によく解説されており、一読をオススメします。
第4回 memcachedの分散アルゴリズム:memcachedを知り尽くす
要は"twemproxy"を使えばキーの分散(同じキーは同じサーバへ)をミドルウェアレベルで
実現可能となります。

ということで、下記のような環境を構築してみますが、ElastiCacheの構築は最初に
紹介したブログ記事で構築できるので、今回はEC2上に"twemproxy"を
インストールするところから始めます。


Twemproxyをインストールするための準備


Twemproxyをインストールするときに、CentOS(6.3)の"yum"でインストールできる
"autoconf"はバージョンが古いと言われてしまうので、その周辺も含め、最新版を
インストールします。

"autoconf"のインストール
# curl -OL http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
# tar xvzf autoconf-2.69.tar.gz 
# cd autoconf-2.69
# ./configure 
# make
# make install
"automake"のインストール
# curl -OL http://ftp.gnu.org/gnu/automake/automake-1.12.tar.gz
# tar xvzf automake-1.12.tar.gz 
# cd automake-1.12
# ./configure 
# make
# make install
"libtool"のインストール
# curl -OL http://ftp.jaist.ac.jp/pub/GNU/libtool/libtool-2.4.2.tar.gz
# tar xvzf libtool-2.4.2.tar.gz 
# cd libtool-2.4.2
# ./configure 
# make
# make install

Twemproxyをインストール

# curl -OL https://github.com/twitter/twemproxy/archive/v0.2.2.zip
# unzip v0.2.2.zip
# cd twemproxy-0.2.2/
# /usr/local/bin/autoreconf -fvi
# ./configure
# make
# make install

Twemproxyの設定と起動


まず、下記のような設定ファイルを作成します。

nutcracker.yml
cache:
  listen: 0.0.0.0:11211
  hash: fnv1a_64
  distribution: ketama
  servers:
    - 10.100.64.217:11211:1
    - 10.100.64.190:11211:1
    - 10.100.65.53:11211:1
    - 10.100.65.181:11211:1
    - 10.100.66.110:11211:1
    - 10.100.66.56:11211:1
  • listen
    • IPアドレスとポートを指定します。
  • hash
    • ハッシュ方法を指定します。(何が何かはよくわかりません...)
  • distribution
    • 分散方法を指定します。(ketamaが"Consistent Hashing"です)
  • servers
    • "サーバ:ポート:重み"で指定します。ただし"サーバ"はDNS名が
      利用できなかったのでIPアドレスを引いて指定しています。
次に、下記で"Twemproxy"を起動します。
/usr/local/bin/nutcracker -d -i 1000 -c ./nutcracker.yml
  • -d
    • デーモンとして起動します。
  • -i
    • 統計情報を集めるインターバルです。
  • -c
    • 利用する設定ファイルです。
IPアドレスで指定してしまうと変更してしまったときに下記で紹介したような対応が
必要になります。
HAProxyをDNS名で指定したバックエンドのIPアドレスが変わったらリロードする

動作確認


一度保存した値は、取得するときも同じサーバから取得できていることがわかります。
# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
set suz1 0 0 4
suz1
STORED
get suz1
VALUE suz1 0 4
suz1
END
get suz1
VALUE suz1 0 4
suz1
END
set suz2 0 0 4
suz2
STORED
get suz2
VALUE suz2 0 4
suz2
END
get suz2
VALUE suz2 0 4
suz2
END
また統計情報をみることで、キーによって、いくつかのサーバに分散されていることも
わかります。
# telnet 127.0.0.1 22222
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
{
    "cache": {
        "10.100.64.190:11211:1": {
            "in_queue": 0, 
            "in_queue_bytes": 0, 
            "out_queue": 0, 
            "out_queue_bytes": 0, 
            "request_bytes": 23, 
            "requests": 4, 
            "response_bytes": 10, 
            "responses": 4, 
            "server_connections": 1, 
            "server_eof": 0, 
            "server_err": 0, 
            "server_timedout": 0
        }, 
        "10.100.64.217:11211:1": {
            "in_queue": 0, 
            "in_queue_bytes": 0, 
            "out_queue": 0, 
            "out_queue_bytes": 0, 
            "request_bytes": 51, 
            "requests": 3, 
            "response_bytes": 69, 
            "responses": 3, 
            "server_connections": 1, 
            "server_eof": 0, 
            "server_err": 0, 
            "server_timedout": 0
        }, 
        "10.100.65.181:11211:1": {
            "in_queue": 0, 
            "in_queue_bytes": 0, 
            "out_queue": 0, 
            "out_queue_bytes": 0, 
            "request_bytes": 0, 
            "requests": 0, 
            "response_bytes": 0, 
            "responses": 0, 
            "server_connections": 0, 
            "server_eof": 0, 
            "server_err": 0, 
            "server_timedout": 0
        }, 
        "10.100.65.53:11211:1": {
            "in_queue": 0, 
            "in_queue_bytes": 0, 
            "out_queue": 0, 
            "out_queue_bytes": 0, 
            "request_bytes": 0, 
            "requests": 0, 
            "response_bytes": 0, 
            "responses": 0, 
            "server_connections": 0, 
            "server_eof": 0, 
            "server_err": 0, 
            "server_timedout": 0
        }, 
        "10.100.66.110:11211:1": {
            "in_queue": 0, 
            "in_queue_bytes": 0, 
            "out_queue": 0, 
            "out_queue_bytes": 0, 
            "request_bytes": 96, 
            "requests": 7, 
            "response_bytes": 155, 
            "responses": 7, 
            "server_connections": 1, 
            "server_eof": 0, 
            "server_err": 0, 
            "server_timedout": 0
        }, 
        "10.100.66.56:11211:1": {
            "in_queue": 0, 
            "in_queue_bytes": 0, 
            "out_queue": 0, 
            "out_queue_bytes": 0, 
            "request_bytes": 21, 
            "requests": 2, 
            "response_bytes": 5, 
            "responses": 2, 
            "server_connections": 1, 
            "server_eof": 0, 
            "server_err": 0, 
            "server_timedout": 0
        }, 
        "client_connections": 0, 
        "client_eof": 0, 
        "client_err": 3, 
        "forward_error": 0, 
        "fragments": 3, 
        "server_ejects": 0
    }, 
    "service": "nutcracker", 
    "source": "ip-10-100-0-236", 
    "timestamp": 1356201522, 
    "uptime": 17075, 
    "version": "0.2.2"
}
Connection closed by foreign host.

次はELB(internal)と絡めてみよう。
--------
http://www.suz-lab.com

2012年12月22日土曜日

VPC上のElastiCacheを試してみた

スズキです。

ついにVPC上でElastiCacheが使えるようになりました。
Amazon ElastiCache announces support for Amazon VPC
ということで早速、VPC上にElastiCacheを作ってみました。

"Cache Subnet Group"の作成


ElastiCacheが利用するVPCのサブネットを登録します。

 

とりあえず、全AZ(ap-northeast-1a/b/c)をカバーするように登録しておきました。

"Cache Cluster"の作成


これは、今までとほぼ同じです。


違いは作成時に、先ほど作成した"Cache Subnet Group"と"VPC Security Group"を
設定するところでしょうか?

調子に乗って、全AZ(ap-northeast-1a/b/c)にも作成してしまいました。


Telnetで確認


下記で紹介した方法(telnet)で確認してみます。
CentOSにMemcachedをインストール&確認
# telnet cache-a.bia10i.0001.apne1.cache.amazonaws.com 11211
Trying 10.3.64.104...
Connected to cache-a.bia10i.0001.apne1.cache.amazonaws.com.
Escape character is '^]'.
stats
STAT pid 1
...

上記の6ノードに対して確認できました。

次は「Twemproxy」とからめてみよう。
--------
http://www.suz-lab.com