2012年9月29日土曜日

他社のVPCへのVPNアクセスはOpenVPN経由にして自社ネットワークを守る

スズキです。

下記のようにVPCとOpenVPNについて書いてきましたが、
ようやくCDPネタにつながります。

今回の対象は「CloudHubパターン」です。




このパターンの「注意点」に
VPNゲートウェイに接続しているネットワーク(拠点)は
お互いに通信できてしまうので、アクセス制限が必要なら
各拠点のVPNルーターで行う必要がある。
といった記載があります。

下記のようにVPNゲートウェイにつなぐ拠点がすべて自社の場合は、拠点側のVPNの設定が
簡単になり、VPNハブがクラウド化により信頼性も高くなるので非常に有用なのですが、


メンテナンスなどで他社をVPNゲートウェイにつないでしまうと、他社のネットワークから
直接、自社のネットワークにアクセスできてしまいます。
すると、VPNなのに自社の拠点で他社からのアクセスを制限する設定が必要になってしまい
微妙な感じになってしまいます。


ということで一つの解決方法として、他社からのメンテナンスアクセスは、
VPNゲートウェイ経由ではなく下記のようにOpenVPNでインターネットゲートウェイ経由で
VPNを張り、対象インスタンスにアクセスする方法が考えられます。


この場合VPC内の"ルーティング"や"Network ACLs"、そして"セキュリティグループ"などで、
何らかの制限をかけることが可能になります。

上記の実現方法は、次の記事で詳しく紹介しています。
VPCのプライベートなサブネットにOpenVPNでVPN接続

OpenVPNだけじゃなくOpenswanも試して、IPhoneとつなげてみるか...
--------
http://www.suz-lab.com

2012年9月28日金曜日

VPCのプライベートなサブネットにOpenVPNでVPN接続

スズキです。

下記でVPC上にOpenVPNサーバを構築し、
適当なクライアント(Mac)からVPN接続ができるようになったので
いよいよ、一番やりたかった、上記のVPN接続で、次のようなVPC上の
プライベートなサブネットに配置されているEC2との通信を行ってみます。



まずは"OpenVPN Server"の設定ですが、このEC2インスタンスは
NATインスタンスである必要があるため下記のように"Souce / Dest Check"を無効にします。




そして下記のように"/etc/sysctl.conf"を設定しIPフォワード機能を有効にします。
# Controls IP packet forwarding
#net.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1
"/etc/sysctl.conf"の反映は次のコマンドで行います。
# sysctl -p


さらにOpenVPNクライアントでVPCのサブネットに関するルーティングを設定するため、
OpenVPNサーバの設定(/etc/openvpn/server.conf)に下記を追加します。
push "route 10.0.0.0 255.255.255.0"
push "route 10.0.2.0 255.255.255.0"
Publicサブネット(10.0.0.0/24)のNATインスタンスとPrivateサブネット(10.0.2.0/24)の
EC2インスタンスにOpenVPNクライアントからアクセスできるように設定しています。

最終的なOpenVPNサーバの設定ファイルは次のようになっています。
# grep -v "^#" /etc/openvpn/server.conf | grep -v "^;" | grep -v "^$"
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 10.0.0.0 255.255.255.0"
push "route 10.0.2.0 255.255.255.0"
keepalive 10 120
comp-lzo
persist-key
persist-tun
status openvpn-status.log
verb 3


ここまでの設定で、OpenVPNクライアント(10.8.0.6)からOpenVPNサーバ(10.0.0.166)に
通信できるようになります。(OpenVPNサーバの"10.8.0.1"の方は既に通信できています)
$ ping 10.0.0.166
PING 10.0.0.166 (10.0.0.166): 56 data bytes
64 bytes from 10.0.0.166: icmp_seq=0 ttl=64 time=10.960 ms
64 bytes from 10.0.0.166: icmp_seq=1 ttl=64 time=11.723 ms
64 bytes from 10.0.0.166: icmp_seq=2 ttl=64 time=11.373 ms


最後にプライベートサブネット(10.0.2.0/24)と通信するための設定です。

といっても、このサブネットの10.8.0.0/24(OpenVPNクライアント)へのルーティングを
下記のようにNATインスタンス(OpenVPNサーバ)に設定するだけです。



これで準備が完了したので、接続テストをしてみます。

まずは、プライベートサブネットのEC2(10.0.2.54)からOpenVPNで接続したオフィスのMac(10.8.0.6)に通信してみます。
# ping 10.8.0.6
PING 10.8.0.6 (10.8.0.6) 56(84) bytes of data.
64 bytes from 10.8.0.6: icmp_seq=1 ttl=63 time=17.5 ms
64 bytes from 10.8.0.6: icmp_seq=2 ttl=63 time=17.3 ms
64 bytes from 10.8.0.6: icmp_seq=3 ttl=63 time=18.3 ms
無事、通信できました。

次は、オフィスのMac(10.8.0.6)からEC2(10.0.2)
$ ping 10.0.2.54
PING 10.0.2.54 (10.0.2.54): 56 data bytes
64 bytes from 10.0.2.54: icmp_seq=0 ttl=63 time=7.907 ms
64 bytes from 10.0.2.54: icmp_seq=1 ttl=63 time=14.115 ms
64 bytes from 10.0.2.54: icmp_seq=2 ttl=63 time=13.294 ms

ちなみにオフィスのMacのルーティングは下記の通りです。
$ netstat -nr
Routing tables

Internet:
Destination   Gateway            Flags    Refs    Use  Netif  Expire
default       10.33.22.253       UGSc       27      0    en2
10/24         10.8.0.5           UGSc        0      0   tun0
10.0.2/24     10.8.0.5           UGSc        1      0   tun0
10.8.0.1/32   10.8.0.5           UGSc        0      0   tun0
10.8.0.5      10.8.0.6           UH          4      0   tun0
10.33.22/24   link#7             UCS         2      0    en2
10.33.22.53   127.0.0.1          UHS         0      0    lo0
10.33.22.253  0:9:41:fa:7a:35    UHLWIir    28      0    en2    1097
10.33.22.255  ff:ff:ff:ff:ff:ff  UHLWbI      0      1    en2
127           127.0.0.1          UCS         0      0    lo0
127.0.0.1     127.0.0.1          UH          6  20896    lo0
169.254       link#7             UCS         0      0    en2
ちゃんと、OpenVPNサーバからプッシュしたルーティング(10.0.0.0/24と10.0.2.0/24)が
設定されていることがわかります。

そしてCDPネタへ...
--------
http://www.suz-lab.com

Mac(10.8)からCentOS(6.3)にOpenVPNでVPN接続

スズキです。

下記でCentOS上にOpenVPNサーバを稼働させることができたので、
VPC上にOpenVPN(CentOS6)をインストール
次は、そのサーバにクライアントマシン(Mac)からVPN接続を試してみます。


(1) [サーバ側作業] クライアントの鍵と証明書の作成準備

# cd /usr/share/doc/openvpn-2.2.2/easy-rsa/2.0/
# source ./vars 
NOTE: If you run ./clean-all, I will be doing a rm -rf on /usr/share/doc/openvpn-2.2.2/easy-rsa/2.0/key
CA(認証局)やサーバの鍵と証明書を作成した場所と同じところで作成します。


(2) [サーバ側作業] クライアントの鍵と証明書の作成

# ./build-key client1
Generating a 1024 bit RSA private key
..++++++
..++++++
writing new private key to 'client1.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [CA]:
Locality Name (eg, city) [SanFrancisco]:
Organization Name (eg, company) [Fort-Funston]:
Organizational Unit Name (eg, section) [changeme]:
Common Name (eg, your name or your server's hostname) [client1]:
Name [changeme]:
Email Address [mail@host.domain]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /usr/share/doc/openvpn-2.2.2/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'CA'
localityName          :PRINTABLE:'SanFrancisco'
organizationName      :PRINTABLE:'Fort-Funston'
organizationalUnitName:PRINTABLE:'changeme'
commonName            :PRINTABLE:'client1'
name                  :PRINTABLE:'changeme'
emailAddress          :IA5STRING:'mail@host.domain'
Certificate is to be certified until Sep 25 18:24:58 2022 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
とりあえず、デフォルト設定で作成します。

すると、下記のようにクライアントに関するファイルが追加されます。
# ls -1 keys/
01.pem
02.pem
ca.crt
ca.key
client1.crt
client1.csr
client1.key
dh1024.pem
index.txt
index.txt.attr
index.txt.attr.old
index.txt.old
serial
serial.old
server.crt
server.csr
server.key
クライアントの鍵は"client1.key"で証明書は"client1.crt"となります。


(3) [クライアント側作業] Tunnelblick(Mac用OpenVPNクライアント)のインストール

Macで利用できるOpenVPNのGUIクライアント(tunnelblick)をインストールします。

tunnelblick - OpenVPN GUI for Mac OS X - Google Project Hosting
Stable版を利用としたら、10.8(Mountain Lion)にはオススメしないとのことなので、


10.8(Mountain Lion)も対応していることになっている、下記のベータ版を利用しました。


ダウンロードしてクリックすると下記画面からインストールすることができます。



(4) [クライアント側作業] 鍵と証明書ファイルの配置

$ cd
$ cd Library/openvpn/
$ ls
ca.crt  client1.crt client1.key
サーバ側で作成したクライアントの鍵(client1.key)と証明書(client1.crt)、
そしてCA(認証局)の証明書(ca.crt)をユーザーのホームディレクトリの
"Library/openvpn/"に配置します。


(5) [クライアント側作業] OpenVPNの設定ファイルの配置と編集

サーバ側の下記のファイルを"client1.conf"として鍵は証明書を配置した同じディレクト
(ユーザーのホームディレクトリの"Library/openvpn/")に配置します。
"/usr/share/doc/openvpn-2.2.2/sample-config-files/client.conf"
そして、下記の部分を、
...
remote my-server-1 1194
...
cert client.crt
key client.key
...
次のように変更します。
...
remote 54.249.30.190 1194
...
cert client1.crt
key client1.key
...
"remote"はサーバのグローバルIPアドレス(EIP)に、クライアントの鍵と証明書は、
上記で作成・配置したもの(client1.key/client1.crt)に変更します。
$ ls
ca.crt  client1.conf client1.crt client1.key
最終的に、ユーザーのホームディレクトリの"Library/openvpn/"配下は
上記のようになります。


(6) [クライアント側作業] TunnelBlickの起動

"client1"に接続できるようになっているので、


選択することで、"client1"の設定、つまりVPC上のサーバとVPN接続することができます


$ ifconfig tun0
tun0: flags=8851 mtu 1500
 inet 10.8.0.6 --> 10.8.0.5 netmask 0xffffffff 
 open (pid 4218)
トンネルインターフェース(tun0)が"10.8.0.6"で設定されていることがわかります。

$ netstat -nr
Routing tables

Internet:
Destination     Gateway            Flags    Refs   Use  Netif  Expire
default         192.168.11.1       UGSc       30     0    en0
10.8.0.1/32     10.8.0.5           UGSc        0     0   tun0
10.8.0.5        10.8.0.6           UH          1     0   tun0
127             127.0.0.1          UCS         0     0    lo0
127.0.0.1       127.0.0.1          UH          5  7943    lo0
169.254         link#4             UCS         0     0    en0
192.168.11      link#4             UCS         3     0    en0
192.168.11.1    0:16:1:8b:a:f4     UHLWIir    31  1077    en0    1179
192.168.11.31   d0:23:db:45:5f:be  UHLWIi      0   145    en0     511
192.168.11.32   127.0.0.1          UHS         0     0    lo0
192.168.11.255  ff:ff:ff:ff:ff:ff  UHLWbI      0     5    en0
ルーティング(tun0)も設定されています。


(7) [クライアント側作業] サーバへの接続確認

$ ping 10.8.0.1
PING 10.8.0.1 (10.8.0.1): 56 data bytes
64 bytes from 10.8.0.1: icmp_seq=0 ttl=64 time=14.487 ms
64 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=12.533 ms
64 bytes from 10.8.0.1: icmp_seq=2 ttl=64 time=13.144 ms
64 bytes from 10.8.0.1: icmp_seq=3 ttl=64 time=11.017 ms
64 bytes from 10.8.0.1: icmp_seq=4 ttl=64 time=12.979 ms
サーバ(10.8.0.1)に疎通できています。


(7) [サーバ側作業] クライアントへの接続確認

# ping 10.8.0.6
PING 10.8.0.6 (10.8.0.6) 56(84) bytes of data.
64 bytes from 10.8.0.6: icmp_seq=1 ttl=64 time=58.2 ms
64 bytes from 10.8.0.6: icmp_seq=2 ttl=64 time=80.5 ms
64 bytes from 10.8.0.6: icmp_seq=3 ttl=64 time=103 ms
64 bytes from 10.8.0.6: icmp_seq=4 ttl=64 time=10.9 ms
64 bytes from 10.8.0.6: icmp_seq=5 ttl=64 time=45.8 ms
クライアント(10.8.0.6)に疎通できています。

次はVPCに踏み込んでいきます。
--------
http://www.suz-lab.com

VPC上にOpenVPN(CentOS6)をインストール

スズキです。

OpenVPNは、たまに構築する機会があるのですが、頻度が少なすぎるため
前回の作業を全く忘れてしまい、いつも調べ直しているので、効率化のために
いったんブログにまとめておくことにしました。

(1) インストールと準備


# yum -y install openvpn
...
# cd /usr/share/doc/openvpn-2.2.2/easy-rsa/2.0/
# ln -s openssl-1.0.0.cnf openssl.cnf 
# ls -1 | grep -v "\.cnf" | grep -v Makefile | grep -v README | grep -v keys | xargs chmod a+x
# source vars 
NOTE: If you run ./clean-all, I will be doing a rm -rf on /usr/share/doc/openvpn-2.2.2/easy-rsa/2.0/keys
# ./clean-all
ポイントは"source vars"をエラーなく実行するために、openssl.confのシンボリックと、
各種スクリプトに実行権限を付与しているところです。

(2) CA(認証局)の鍵と証明書を作成


# ./build-ca 
Generating a 1024 bit RSA private key
........................++++++
.++++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [CA]:
Locality Name (eg, city) [SanFrancisco]:
Organization Name (eg, company) [Fort-Funston]:
Organizational Unit Name (eg, section) [changeme]:
Common Name (eg, your name or your server's hostname) [changeme]:
Name [changeme]:
Email Address [mail@host.domain]:
とりあえず、デフォルト設定のまま進めています。

すると下記のようなファイルが作成されます。
# ls -1 keys/
ca.crt
ca.key
index.txt
serial
鍵は"ca.key"で証明書は"ca.crt"です。

(3) サーバの鍵と証明書を作成


# ./build-key-server server
Generating a 1024 bit RSA private key
..............++++++
.......++++++
writing new private key to 'server.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [CA]:
Locality Name (eg, city) [SanFrancisco]:
Organization Name (eg, company) [Fort-Funston]:
Organizational Unit Name (eg, section) [changeme]:
Common Name (eg, your name or your server's hostname) [server]:
Name [changeme]:
Email Address [mail@host.domain]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /usr/share/doc/openvpn-2.2.2/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'CA'
localityName          :PRINTABLE:'SanFrancisco'
organizationName      :PRINTABLE:'Fort-Funston'
organizationalUnitName:PRINTABLE:'changeme'
commonName            :PRINTABLE:'server'
name                  :PRINTABLE:'changeme'
emailAddress          :IA5STRING:'mail@host.domain'
Certificate is to be certified until Sep 25 16:47:52 2022 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
こちらもデフォルト設定のまますすめています。

今度は、下記のようなファイルが追加されます。
# ls -1 keys/
01.pem
ca.crt
ca.key
index.txt
index.txt.attr
index.txt.old
serial
serial.old
server.crt
server.csr
server.key
鍵は"server.key"で証明書は"server.crt"となります。

(4) Diffie-Hellmanパラメータの作成


# ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
.................................................................+....+..................++*++*++*

"dh1024.pem"が作成されます。
# ls -1 keys/
01.pem
ca.crt
ca.key
dh1024.pem
index.txt
index.txt.attr
index.txt.old
serial
serial.old
server.crt
server.csr
server.key

(5) 設定ファイルの配置

# cp keys/ca.crt keys/server.crt keys/server.key keys/dh1024.pem /etc/openvpn/
上記で作成した鍵や証明書などを配置します。

# cp /usr/share/doc/openvpn-2.2.2/sample-config-files/server.conf /etc/openvpn/
OpenVPN自体の設定ファイルもコピーします。

(6) OpenVPNの起動

# /etc/init.d/openvpn start
openvpn を起動中:                                          [  OK  ]
起動スクリプトが用意されています。

# ifconfig tun0
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:10.8.0.1  P-t-P:10.8.0.2  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)   
トンネルインターフェース(tun0)が"10.8.0.1"で設定されていることがわかります。

# netstat -nr
Kernel IP routing table
Destination  Gateway   Genmask          Flags  MSS  Window  irtt  Iface
10.8.0.2     0.0.0.0   255.255.255.255  UH       0  0          0  tun0
10.0.0.0     0.0.0.0   255.255.255.0    U        0  0          0  eth0
10.8.0.0     10.8.0.2  255.255.255.0    UG       0  0          0  tun0
169.254.0.0  0.0.0.0   255.255.0.0      U        0  0          0  eth0
0.0.0.0      10.0.0.1  0.0.0.0          UG       0  0          0  eth0
ルーティング(10.8.0.0/24 → tun0)も設定されています。

# netstat -ulnp | grep openvpn
udp    0    0 0.0.0.0:1194    0.0.0.0:*    10487/openvpn
ポート(UDP 1194)もリッスンしています。

(7) UDPの1194ポートをセキュリティグループで許可



AWSコンソールから設定します。当然、このEC2がインターネットアクセスできる
必要があるため、EIPの付与と、所属するサブネットの0.0.0.0/0へのルーティングが、
インターネットゲートウェイに向いている必要があります。

次はクライアント(Mac)からVPN接続してみます。
--------
http://www.suz-lab.com

2012年9月27日木曜日

VPCのELBのサブネットを変更する

スズキです。

VPC上でELBを作成する場合は下記で紹介したとおり、サブネットを設定する必要があり、
そのサブネットは各AZで最大一個、複数指定することができます。
VPCのSubnetとELBの関係(Availability Zone編)
このELBに設定したサブネットは途中で変更することも可能です。

まず、ELBに下記のようなサブネット(10.0.0.0/24 Aゾーン)が指定されているとします。


この選択されているサブネットを、


下記のようなサブネット(10.0.2.0/24 Aゾーン)に変更してみますが、
エラーが出力され、変更できません。


エラーは下記のように出力されており、
In order to change the subnet attached to your load balancer, you need
to have at least two availability zones registered with the load balancer
ELBに設定されているサブネットを変更するには、
少なくても二つのAZがELBに設定されている必要があるようです。

ということで、別ゾーンのサブネット(10.0.1.0/24 Bゾーン)を設定(追加)すると、


今度は問題なく設定することができ、


再度、最初に設定しようとしたサブネット(10.0.2.0/24 Aゾーン)に変更してみると、


こちらも問題なく変更できました。


最後に、一時的につけた別ゾーンのサブネット(10.0.1.0/24 Bゾーン)を削除すると、


無事、サブネットの変更が完了します。


ちなみに、サブネットを変更すると、ELBのヘルスチェックは下記のように
10.0.0.86 - - [27/Sep/2012:17:18:04 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:18:08 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:18:11 +0900] "GET /phpinfo.php HTTP/1.1" 200 48239 "-" "ELBLatencyCheck-1.0"
10.0.0.86 - - [27/Sep/2012:17:18:11 +0900] "GET /phpinfo.php HTTP/1.1" 200 48233 "-" "ELBLatencyCheck-1.0"
10.0.0.86 - - [27/Sep/2012:17:18:14 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:18:20 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:18:26 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:18:32 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:18:38 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:18:44 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:18:50 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.2.224 - - [27/Sep/2012:17:18:54 +0900] "GET /phpinfo.php HTTP/1.1" 200 47680 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:18:56 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.2.224 - - [27/Sep/2012:17:18:59 +0900] "GET /phpinfo.php HTTP/1.1" 200 47680 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:19:01 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.2.224 - - [27/Sep/2012:17:19:05 +0900] "GET /phpinfo.php HTTP/1.1" 200 47680 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:19:07 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:19:09 +0900] "GET /phpinfo.php HTTP/1.1" 200 48239 "-" "ELBLatencyCheck-1.0"
10.0.2.224 - - [27/Sep/2012:17:19:11 +0900] "GET /phpinfo.php HTTP/1.1" 200 47680 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:19:12 +0900] "GET /phpinfo.php HTTP/1.1" 200 48233 "-" "ELBLatencyCheck-1.0"
10.0.0.86 - - [27/Sep/2012:17:19:13 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.2.224 - - [27/Sep/2012:17:19:17 +0900] "GET /phpinfo.php HTTP/1.1" 200 47680 "-" "ELB-HealthChecker/1.0"
10.0.0.86 - - [27/Sep/2012:17:19:19 +0900] "GET /phpinfo.php HTTP/1.1" 200 47673 "-" "ELB-HealthChecker/1.0"
10.0.2.224 - - [27/Sep/2012:17:19:23 +0900] "GET /phpinfo.php HTTP/1.1" 200 47680 "-" "ELB-HealthChecker/1.0"
だんだんと、変更前のIPアドレス(10.0.0.86)から変更後のIPアドレス(10.0.2.224)に
変更されていきます。

ELBは手強い...
--------
http://www.suz-lab.com

EC2のコマンドラインツールのインストールと起動時にホスト名をNameタグの値とする方法

スズキです。

下記で"Auto Scaling"でEC2を自動起動するときに、
EC2のNameタグもつけるように設定していましたが、
この場合、すべてのEC2で同じ値のタグになってしまいます。

EC2ごとに違う値にしたいときは、やはり起動時にAPIを用いて設定するしかありません。

ということで、設定するスクリプトを作成してみました。

まずは、EC2のコマンドラインツールのインストールです。
# cd /opt/
# curl -OL http://s3.amazonaws.com/ec2-downloads/ec2-api-tools.zip
# unzip ec2-api-tools.zip
# ln -s ec2-api-tools-1.6.3.1 ec2-api-tools
# rm -f ec2-api-tools.zip

コマンドラインツールが使えるように環境変数の設定です。
# export JAVA_HOME=/usr/lib/jvm/jre
# export EC2_HOME=/opt/ec2-api-tools
# export PATH=$PATH:$EC2_HOME/bin 
# export AWS_ACCESS_KEY=XXXXXXXX
# export AWS_SECRET_KEY=YYYYYYYY
# export EC2_URL=https://ec2.ap-northeast-1.amazonaws.com

下記コマンドが実行できれば、準備OKです。
# ec2-version 
1.6.3.1 2012-08-15

次にタグの設定ですが、EC2関係のコマンドが多すぎて探すのが大変だったので、
下記のようにして、対象のコマンド(ec2-create-tags)をみつけました。
# ls -1 $EC2_HOME/bin/ | grep -v cmd | grep tag
ec2-create-tags
ec2-delete-tags
ec2-describe-tags
ec2addtag
ec2deltag
ec2dtag
ec2tag

タグは下記のように実行してつけることができます。
# ec2-create-tags i-905bb493 \
> --tag Name=Suzuki
TAG instance i-905bb493 Name Suzuki

最後にスクリプト化です。(仕様は下記です)
  • メタデータから自分のインスタンスIDを取得してNameタグを設定する。
  • 設定するNameタグはEC2_PREFIXとIPアドレス(メタデータから)をつなげたもの
  • ついでに同じ値でホスト名も設定する
#!/bin/sh

# エラー発生時にNGと終了ステータスコードを出力
set -e
trap 'echo NG:$?' ERR

# コマンドラインツールを利用する環境変数を指定(環境に応じて!)
export JAVA_HOME=/usr/lib/jvm/jre
export EC2_HOME=/opt/ec2-api-tools
export PATH=$PATH:$EC2_HOME/bin
export AWS_ACCESS_KEY=XXXXXXXX
export AWS_SECRET_KEY=YYYYYYYY
export EC2_URL=https://ec2.ap-northeast-1.amazonaws.com

# "EC2"の情報を指定(環境に応じて!)
EC2_PREFIX="suzuki"

# メタ情報の取得(名前決定で必要なものを取得!)
INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
echo "INSTANCE ID: " $INSTANCE_ID
LOCAL_IPV4=`curl -s http://169.254.169.254/latest/meta-data/local-ipv4`
echo "LOCAL IPV4: " $LOCAL_IPV4

# 名前の設定(仕様に応じて!)
NAME=${EC2_PREFIX}-${LOCAL_IPV4}
echo "NAME: " ${NAME}

# ホスト名とNameタグの設定
hostname ${NAME}
ec2-create-tags ${INSTANCE_ID} --tag Name=${NAME}

# 正常終了
echo OK:0
exit 0
"rc.local"などで実行すれば、該当する値が起動時にホスト名とNameタグに設定されます。
ネーミングルールに従い、EC2_PREFIXやメタデータから取得する情報などを
変える必要があります。

コマンドラインツールを使ったスクリプトがたまってきた...
--------
http://www.suz-lab.com

"Auto Scaling Group"のタグの変更は"as-create-or-update-tags"を使う

スズキです。

"Auto Scaling Group"の設定の変更は下記で紹介したように
"as-update-auto-scaling-group"で行うのですが、
"Auto Scaling"で利用するAMIをアップデートしてみる
同様にタグも変更しようとしたら、エラーになってしまいました。

タグの変更は専用のコマンドが用意されており、"as-create-or-update-tags"で行います。

まずは、現状のタグを確認して、
# as-describe-tags 
TAG  vpc-ag-1  auto-scaling-group  Name  vpc-ec2-1  true
上記のコマンドでアップデートし、
# as-create-or-update-tags --tag "id=vpc-ag-1, t=auto-scaling-group, k=Name, v=vpc-ec2-2, p=true"
OK-Created/Updated tags
確認すると、
# as-describe-tags 
TAG  vpc-ag-1  auto-scaling-group  Name  vpc-ec2-2  true
タグが変更されていることがわかります。

オプション"--tag"で指定されている値は、
  • id = "Auto Scaling Group"の名前(resource-name)
  • t = "auto-scaling-group"固定(でいい?)(resource-type)
  • k = タグのキー(tag-key)
  • v = タグの値(tag-val)
  • p = "Auto Scaling"がEC2起動時に同じタグをつけるか?(propagate-at-launch flag)
といった感じです。

"propagate-at-launch flag"は、もう少し掘り下げておこう。
--------
http://www.suz-lab.com

2012年9月26日水曜日

ロードバランサー(ELB)経由でなくてもX-Forwarded-Forをつける

スズキです。

Webサーバをロードバランサー(ELB)経由にするときに、
Webサーバに設定されるリモートアドレスが、ユーザー(ブラウザ)のものから
ロードバランサーのものになってしまうことは有名な話だと思います。

その場合、ELBは(その他の多くのロードバランサーも)X-Forwarded-Forヘッダに、
ユーザー(ブラウザ)のIPアドレスを設定してくれるので、下記で紹介した方法などで
対応することが可能です。
ApacheでREMOTE_ADDRをELB経由でも...(CentOS)
そして(あまり無いとは思いますが)、ロードバランサー経由のWebサーバを
インターネットからの直接アクセスに戻す場合もあるかと思います。
(あるとしたらコスト削減や障害対応などでしょうか...)

もし、アプリケーションなどでX-Forwarded-Forヘッダを参照している場合、
当然、インターネットからの直接アクセスではX-Forwarded-Forヘッダは無いので、
この場合、アプリケーション側で問題が発生してしまうはずです。

アプリケーションを修正するのは、現実的では無い場合が多く、なんとか
Webサーバ(Apache)側で対応したいところです。

といっても単に、リモートアドレスと同じIPアドレスが設定された、
X-Forwarded-Forヘッダが設定されていれば、アプリケーション的にも
問題がなくなるはずです。

Apacheの場合は下記のように設定(httpd.conf)すれば、上記を実現することができます。
SetEnvIf X-Forwarded-For ".+" forwarded
RewriteEngine On
RewriteRule ^(.*) - [E=CLIENT_ADDR:%{REMOTE_ADDR},L]
RequestHeader set X-Forwarded-For "%{CLIENT_ADDR}e" env=!forwarded
※ロードバランサー(ELB)経由の場合は、そのままのX-Forwarded-Forを利用します。

実際に下記のPHPスクリプトで、ロードバランサー(ELB)経由と、
インターネットからの直接アクセスでの該当変数を確認すると、
<?php
print("REMOTE_ADDR="          . $_SERVER["REMOTE_ADDR"]);
print("forwarded="            . $_SERVER["forwarded"]);
print("CLIENT_ADDR="          . $_SERVER["CLIENT_ADDR"]);
print("HTTP_X_FORWARDED_FOR=" . $_SERVER["HTTP_X_FORWARDED_FOR"]);
?>
ロードバランサー(ELB)経由の場合は、X-Forwarded-Forが下記のように
ロードバランサーが設定したもののままとなり、


インターネットからの直接アクセスの場合は、X-Forwarded-Forに下記のように
リモートアドレスの値が設定されます。


SetEnvIfだけでできると思ったのに...
--------
http://www.suz-lab.com

2012年9月24日月曜日

"Auto Scaling"の"Metrics Collection"って?

スズキです。

"Auto Scaling"いじってて、ずっと気になっていた"Metrics Collection"、
そろそろ、気持ち悪さに限界がきたので、少し調べてみました。
(MetricsなのでCloudWatch関係でしょうか?)

まずは"as-describe-metric-collection-types"といったコマンドがあったので、
実行してみます。
# as-describe-metric-collection-types
METRIC-COLLECTION-TYPE  GroupMinSize
METRIC-COLLECTION-TYPE  GroupMaxSize
METRIC-COLLECTION-TYPE  GroupDesiredCapacity
METRIC-COLLECTION-TYPE  GroupInServiceInstances
METRIC-COLLECTION-TYPE  GroupPendingInstances
METRIC-COLLECTION-TYPE  GroupTerminatingInstances
METRIC-COLLECTION-TYPE  GroupTotalInstances
METRIC-GRANULARITY-TYPE  1Minute

"METRIC COLLECTION"と"METRIC GRANULARITY"の種類が表示されました...
(まだ何のことだかわかりません...)

そして"as-enable-metrics-collection"といった"Metrics Collection"を有効にする
コマンドがあったので、実行してみます。
# as-enable-metrics-collection vpc-ag-1 --granularity 1Minute
OK-Enabled metrics collection
"--granularity"は、上記のMETRIC-GRANULARITY-TYPEから(一種類しかありませんが)
"--metrics"には、METRIC-COLLECTION-TYPE(複数指定可)を指定します。
("--metrics"を省略した場合はすべてのMETRIC-COLLECTION-TYPEが指定されます)

で、何が起こったかというと...
下記のようにCloudWatchで、"Auto Scaling Group"ごとMETRIC-COLLECTION-TYPE
にあったメトリックが取得できるようになっていました。


ちょっと、すっきりした...
--------
http://www.suz-lab.com

2012年9月23日日曜日

"Auto Scaling"で利用するAMIをアップデートしてみる

スズキです。

CDPネタです。今回も「Scale Outパターン」ですが、運用っぽい話です。


このパターンの「注意点」に
EC2内のアップデートが必要な場合は、Auto Scalingで起動する
元となるAMIもアップデートする必要がある。
といった記載があります。

今回は、下記でインストールしたコマンドラインツールで、
"Auto Scaling"で利用するAMIを 差し替えてみます。
コマンドラインツール使ってVPCで"Auto Scaling"
そもそも、AMIの情報は"Launch Config"で指定されています。
なので、"Launch Config"のAMI情報をアップデートすればよいと思うのですが、
"Launch Config"の情報をアップデートすることはできません。
そのかわり、"Launch Config"を指定している"Auto Scaling Group"の情報は
アップデートできます。
よって、新しいAMIを指定した"Launch Config"を作成し、既存の
"Auto Scaling Group"の"Launch Config"を、新しく作成した"Launch Config"に
アップデートする形となります。

それでは、上記を実際にコマンドラインツールで試してみます。

まずは新しいAMIで、新規の"Launch Config"を作成します。
# as-create-launch-config vpc-lc-20120923 \
> --image-id ami-f8fc41f9 \
> --group sg-40a7b72c,sg-877c60eb \
> --instance-type m1.small
OK-Created launch config

次に既存の"Auto Scaling Group"に指定されている"Launch Config"を、
新しく作成したものにアップデートします。
# as-update-auto-scaling-group vpc-ag-1 \
> --launch-configuration vpc-lc-20120923
OK-Updated AutoScalingGroup

対象の"Auto Scaling Group"が複数("Auto Scaling Group"の名前が"vpc-ag*")の場合は
下記のようにすれば効率的です。
# as-describe-auto-scaling-groups \
> | grep AUTO-SCALING-GROUP \
> | grep vpc-ag \
> | awk '{print $2}' \
> | xargs -I{} as-update-auto-scaling-group {} \
>   --launch-configuration vpc-lc-20120923
OK-Updated AutoScalingGroup
OK-Updated AutoScalingGroup

差し替えられた古い"Launch Config"は削除しておきます。
# as-delete-launch-config vpc-lc-20120922 \
> --force
OK-Deleted launch configuration

削除対象の"Launch Config"が複数("Launch Config"の名前が"vpc-lc*")の場合は
下記のようにすれば効率的です。
# as-describe-launch-configs \
> | grep vpc-lc- \
> | grep -v vpc-lc-20120923 \
> | awk '{print $2}' \
> | xargs -I{} as-delete-launch-config {} \
>   --force
OK-Deleted launch configuration
OK-Deleted launch configuration
OK-Deleted launch configuration

以上の手順をスクリプト化してみました。
  • 引数は"AMI ID"を一つ指定し、"Auto Scaling"するEC2のAMIを、
    指定したIDのものに変更します。
  • 新規に作成する"Launch Config"の名前はLAUNCH_CONFIG_PREFIXに
    タイムスタンプをつけたものとなります。
  • 対象の"Auto Scaling Group"は、名前がAUTO_SCALING_GROUP_PREFIXで
    始まる(含む)ものです。
  • 新規に作成し差し替えられた"Launch Config"以外の古いものは削除されます。
    (対象は名前がLAUNCH_CONFIG_PREFIXで始まる(含む)ものです)
#!/bin/sh

# エラー発生時にNGと終了ステータスコードを出力
set -e
trap 'echo NG:$?' ERR

# コマンドラインツールを利用する環境変数を指定(環境に応じて!)
export JAVA_HOME=/usr/lib/jvm/jre
export AWS_AUTO_SCALING_HOME=/opt/AutoScaling
export AWS_CREDENTIAL_FILE=$AWS_AUTO_SCALING_HOME/credential-as.txt
export AWS_AUTO_SCALING_URL=https://autoscaling.ap-northeast-1.amazonaws.com
export PATH=$PATH:$AWS_AUTO_SCALING_HOME/bin

# "Auto Scaling"の情報を指定(環境に応じて!)
LAUNCH_CONFIG_PREFIX=vpc-lc
AUTO_SCALING_GROUP_PREFIX=vpc-ag
SECURITY_GROUPS=sg-40a7b72c,sg-877c60eb
INSTANCE_TYPE=m1.small

# 新規に作成する"Launch Config"の名前を作成
TIMESTAMP=`date +"%Y%m%d%H%M%S"`
LAUNCH_CONFIG_NAME=${LAUNCH_CONFIG_PREFIX}-${TIMESTAMP}

# "Launch Config"を作成
echo CREATING LAUNCH CONFIG NAME: ${LAUNCH_CONFIG_NAME}
as-create-launch-config ${LAUNCH_CONFIG_NAME} \
--image-id $1 \
--group ${SECURITY_GROUPS} \
--instance-type ${INSTANCE_TYPE}

# 対象の"Auto Scaling Group"の"Launch Config"をアップデート
as-describe-auto-scaling-groups \
| grep AUTO-SCALING-GROUP \
| grep ${AUTO_SCALING_GROUP_PREFIX} \
| awk '{print $2}' \
| while read auto_scaling_group_name; do
    echo UPDATING AUTO SCALING GROUP NAME: ${auto_scaling_group_name}
    as-update-auto-scaling-group ${auto_scaling_group_name} \
    --launch-configuration ${LAUNCH_CONFIG_NAME}
done

# 古い"Launch Config"を削除
as-describe-launch-configs \
| grep ${LAUNCH_CONFIG_PREFIX} \
| grep -v ${LAUNCH_CONFIG_NAME} \
| awk '{print $2}' \
| while read launch_config_name; do
    echo DELETING LAUNCH CONFIG NAME: ${launch_config_name}
    as-delete-launch-config  ${launch_config_name} \
    --force
done

# 正常終了
echo OK:0
exit 0

実際に実行してみると下記のようになるはずです。
# ./as-change-ami.sh ami-f8fc41f9
CREATING LAUNCH CONFIG NAME: vpc-lc-20120923195402
OK-Created launch config
UPDATING AUTO SCALING GROUP NAME: vpc-ag-1
OK-Updated AutoScalingGroup
UPDATING AUTO SCALING GROUP NAME: vpc-ag-2
OK-Updated AutoScalingGroup
DELETING LAUNCH CONFIG NAME: vpc-lc-20120923195131
OK-Deleted launch configuration
OK:0

AMI変えたら、起動中の古いAMIのEC2も変えないといけない...
--------
http://www.suz-lab.com

2012年9月21日金曜日

VPCのRDSをMulti-AZで作成しようとしたら"ap-northeast-1c"が足りないって言われた

スズキです。

VPC上でRDSをMulti-AZで作成しようとしたら、今まで作成できたはずが、
下記のようなエラーが作成できなくなってしまいました...


No subnet is in availability zone 'ap-northeast-1c', the subnets
in a subnet group should cover all availability zones.
つまり、
"ap-northeast-1c"のサブネットがありません。DBサブネットグループに登録する
サブネットは、すべてのAZをカバーするようにしなければなりません。
ってことです。
そういえば、最近、AZに"ap-northeast-1c"が追加されてたはずです...

たしかにDBサブネットグループを確認すると、下記のように、"ap-northeast-1a"と
"ap-northeast-1b"、それぞれで作成したサブネットのみが登録されています。


ということで、"ap-northeast-1c"に新規にサブネットを作成し、


そのサブネットをDBサブネットグループに登録して、


下記のように、すべてのAZをカバーするようにしておきます。


この状態で、再度、RDSを作成すると、無事、作成することができました。

運用中の"ap-northeast-1a"、ap-northeast-1b"のみのRDSは大丈夫なのかなー?
--------
http://www.suz-lab.com

"Auto Scaling"でのEC2の増減をSNSで通知

スズキです。

下記で、"Auto Scaling"の準備ができたので、実際に負荷をかけて
挙動を確認したいところですが、
その前に"Auto Scaling"のアクションをSNS(メール)で通知できるようにしておきます。

まずはSNSのトピック作成です。"Auto Scaling"のコマンドで通知先を設定するときに
このトピックを指定することになります。



次に作成したトピックに対して、サブスクリプションを設定します。
サブスクリプションはトピックに投げられたメッセージの通知先(メール)となります。



設定だけでは有効にならず、下記のメールが届くので本文中の確認用のリンクを
クリックする必要があります。
You have chosen to subscribe to the topic: 
arn:aws:sns:ap-northeast-1:811118151095:vpc-as

To confirm this subscription, click or visit the link below (If this was in error no action is necessary): 
Confirm subscription

Please do not reply directly to this e-mail. If you wish to remove yourself from receiving all future SNS subscription confirmation requests please send email to sns-opt-out


下記のように、トピックにサブスクリプションが設定されていることがわかります。


それでは、"Auto Scaling"のアクションの通知設定です。

通知できるアクションの種類は下記の通りです。
# as-describe-auto-scaling-notification-types
NOTIFICATION-TYPE  autoscaling:EC2_INSTANCE_LAUNCH
NOTIFICATION-TYPE  autoscaling:EC2_INSTANCE_LAUNCH_ERROR
NOTIFICATION-TYPE  autoscaling:EC2_INSTANCE_TERMINATE
NOTIFICATION-TYPE  autoscaling:EC2_INSTANCE_TERMINATE_ERROR
NOTIFICATION-TYPE  autoscaling:TEST_NOTIFICATION

すべてのアクションに対して通知するようにしました。
# as-put-notification-configuration vpc-ag \
> --notification-types autoscaling:EC2_INSTANCE_LAUNCH,autoscaling:EC2_INSTANCE_LAUNCH_ERROR,autoscaling:EC2_INSTANCE_TERMINATE,autoscaling:EC2_INSTANCE_TERMINATE_ERROR,autoscaling:TEST_NOTIFICATION  \
> --topic-arn arn:aws:sns:ap-northeast-1:811118151095:vpc-as
OK-Put Notification Configuration

通知の設定をすると、まずは"TEST_NOTIFICATION"が下記ように通知(メール)されます。
("--notification-types"に"TEST_NOTIFICATION"を設定して無ければ通知されません)
Auto Scaling: test notification for group "vpc-ag"
--------
Service: AWS Auto Scaling
Time: 2012-09-20T15:52:49.977Z
RequestId: 3ad41f27-033b-11e2-bfe2-dfc775ae5221
Event: autoscaling:TEST_NOTIFICATION
AccountId: 811118151095
AutoScalingGroupName: vpc-ag
AutoScalingGroupARN: arn:aws:autoscaling:ap-northeast-1:811118151095:autoScalingGroup:d6b54038-f82a-4890-b2bd-f4f4cefc3c73:autoScalingGroupName/vpc-ag

それでは、スケールアウトしてみます。
# as-execute-policy vpc-sp-out \
> --auto-scaling-group vpc-ag
OK-Executed Policy

下記ようにインスタンスの起動に対して通知(メール)されます。
Auto Scaling: launch for group "vpc-ag"
--------
Service: AWS Auto Scaling
Time: 2012-09-20T15:55:25.028Z
RequestId: 419a3f3f-37b9-43cf-9d40-d9a091381064
Event: autoscaling:EC2_INSTANCE_LAUNCH
AccountId: 811118151095
AutoScalingGroupName: vpc-ag
AutoScalingGroupARN: arn:aws:autoscaling:ap-northeast-1:811118151095:autoScalingGroup:d6b54038-f82a-4890-b2bd-f4f4cefc3c73:autoScalingGroupName/vpc-ag
ActivityId: 419a3f3f-37b9-43cf-9d40-d9a091381064
Description: Launching a new EC2 instance: i-74748877
Cause: At 2012-09-20T15:54:34Z a user request executed policy vpc-sp-out changing the desired capacity from 0 to 1.  At 2012-09-20T15:54:48Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 0 to 1.
StartTime: 2012-09-20T15:54:48.665Z
EndTime: 2012-09-20T15:55:25.028Z
StatusCode: InProgress
StatusMessage:
Progress: 50
EC2InstanceId: i-74748877
Details: {}

そして、スケールインです。
# as-execute-policy vpc-sp-in
> --auto-scaling-group vpc-ag
OK-Executed Policy

今度はインスタンスの終了に対して次のように通知(メール)されます。
Auto Scaling: termination for group "vpc-ag"
--------
Service: AWS Auto Scaling
Time: 2012-09-20T15:57:26.607Z
RequestId: 37a4d76b-1e9a-4b5b-8108-0a806397aab1
Event: autoscaling:EC2_INSTANCE_TERMINATE
AccountId: 811118151095
AutoScalingGroupName: vpc-ag
AutoScalingGroupARN: arn:aws:autoscaling:ap-northeast-1:811118151095:autoScalingGroup:d6b54038-f82a-4890-b2bd-f4f4cefc3c73:autoScalingGroupName/vpc-ag
ActivityId: 37a4d76b-1e9a-4b5b-8108-0a806397aab1
Description: Terminating EC2 instance: i-74748877
Cause: At 2012-09-20T15:56:15Z a user request executed policy vpc-sp-in changing the desired capacity from 1 to 0.  At 2012-09-20T15:56:20Z an instance was taken out of service in response to a difference between desired and actual capacity, shrinking the capacity from 1 to 0.  At 2012-09-20T15:56:20Z instance i-74748877 was selected for termination.
StartTime: 2012-09-20T15:56:21.013Z
EndTime: 2012-09-20T15:57:26.607Z
StatusCode: InProgress
StatusMessage:
Progress: 0
EC2InstanceId: i-74748877
Details: {}

Nagiosに統合したい...
--------
http://www.suz-lab.com

"Auto Scaling"の"Scaling Policy"を作成し"CloudWatch"と連携してみる

スズキです。

下記に引き続き、CDPの「Scale Outパターン」ネタです。
コマンドラインツール使ってVPCで"Auto Scaling"


今回は「実装」の部分の
  • EC2数を増減させるトリガーとなる条件(メトリクス)を定義する。
    EC2の平均CPU使用率、ネットワーク流量、セッション数、
    EBSのレイテンシーなどがよく使われる。
  • そのメトリクスをCloudWatchを使って監視し、
    一定の条件を満たすとアラームを出すように設定する。
  • アラームを受けた際、Auto ScalingがEC2数を増減するように設定する。
に関して、具体的に試してみます。
(前提として最初に紹介した記事の手順で"Auto Scaling Group"まで作成できているとします)

まずは"Scaling Policy"というものを作成します。これはEC2の増減に関するルールで、
下記のように作成することができます。
# as-put-scaling-policy vpc-sp-out \
> --auto-scaling-group vpc-ag \
> --adjustment 1 \
> --type ChangeInCapacity
arn:aws:autoscaling:ap-northeast-1:811118151095:scalingPolicy:f7340c54-284e-49db-a0cb-bb5019305719:autoScalingGroupName/vpc-ag:policyName/vpc-sp-out
"--adjustment"の値を、"--type"の方法で増減するようになっており、
上記は、1インスタンスずつ増やしていくポリシーとなります。

"--type"で指定できる値は下記で確認でき、
# as-describe-adjustment-types
ADJUSTMENT-TYPE  ChangeInCapacity
ADJUSTMENT-TYPE  ExactCapacity
ADJUSTMENT-TYPE  PercentChangeInCapacity
それぞれの値は次のような意味を持ちます。
  • ChangeInCapacity : 指定した値だけ既存の値から増減させる
  • ExactCapacity : 既存の値に関係なく指定した値にする
  • PercentChangeInCapacity : 指定した値を百分率とした割合で増減させる

ポリシーが作成できたら、試しにこのポリシーを下記のように手動で実行してみます。
# as-execute-policy vpc-sp-out \
> --auto-scaling-group vpc-ag
OK-Executed Policy
# as-execute-policy vpc-sp-out \
> --auto-scaling-group vpc-ag
OK-Executed Policy
# as-describe-auto-scaling-instances
INSTANCE  i-4cca364f  vpc-ag  ap-northeast-1a  Pending    HEALTHY  vpc-lc
INSTANCE  i-dcc935df  vpc-ag  ap-northeast-1b  InService  HEALTHY  vpc-lc
1インスタンスづつ増えていることがわかると思います。

増加の次は減少です。
# as-put-scaling-policy vpc-sp-in \
> --auto-scaling-group vpc-ag \
> --adjustment=-1 \
> --type ChangeInCapacity
arn:aws:autoscaling:ap-northeast-1:811118151095:scalingPolicy:31c85fff-fb50-42db-a888-8be6cd973bfd:autoScalingGroupName/vpc-ag:policyName/vpc-sp-in
減少は値をマイナスにするだけですが"--adjustment=-1"を指定しなければなりません。

手動で実行すると、
# as-execute-policy vpc-sp-in \
> --auto-scaling-group vpc-ag
OK-Executed Policy
# as-execute-policy vpc-sp-in \
> --auto-scaling-group vpc-ag
OK-Executed Policy
# as-describe-auto-scaling-instances
INSTANCE  i-22cb3721  vpc-ag  ap-northeast-1a  Terminating  HEALTHY  vpc-lc
INSTANCE  i-baca36b9  vpc-ag  ap-northeast-1b  Terminating  HEALTHY  vpc-lc
1インスタンスづつ減っていることがわかると思います。

ちなみに"Scaling Policy"の削除は次のとおりです。
# as-delete-policy vpc-sp \
> --auto-scaling-group vpc-ag
    Are you sure you want to delete this policy? [Ny]y
OK-Deleted Policy

"Scaling Policy"ができたら、CloudWatchにてELBのレイテンシーの値をトリガーにして
上記のポリシーが実行されるように設定します。(AWSコンソールでできます)


対象のメトリクス(ELBのLatency)を選択したら、
そこからアラームを作成(Create Alarm)します。


アラームはレイテンシーが3秒以上になったら発生するようにしています。


そして、そのアラームにアクションを定義します。


アラーム状態(レイテンシーが3秒以上)になったら、"Auto Scaling Group"が"vpc-ag"の
1インスタンスづつ増やすスケールアウトポリシー(vpc-sp-out)を自動で実行する、
といった感じです。


同様にレイテンシーが1秒以下になったらスケールインする設定もしておきます。


次はJMeterで負荷かけて挙動を確認してみますが、JMeterネタもあります...
--------
http://www.suz-lab.com

2012年9月19日水曜日

コマンドラインツール使ってVPCで"Auto Scaling"

スズキです。

CDPネタです。今回の対象は「Scale Outパターン」です。



このパターンの「実装」に
ロードバランサ―サービス「ELB」、モニタリングツール「CloudWatch」、
そして自動でスケールアウトする「Auto Scaling」の三つのサービスを
組み合わせることで、負荷に応じて自動でスケールアウトするシステムを
容易に構築できる。
といった記載があります。

コマンドラインツールでの"Auto Scaling"は以前、下記のように紹介しましたが
今回は、VPC環境で試してみました。

まずはインストールです。

下記のようにダウンロードして展開します。
# cd /opt
# curl -OL http://ec2-downloads.s3.amazonaws.com/AutoScaling-2011-01-01.zip
# unzip AutoScaling-2011-01-01.zip
# ln -s AutoScaling-1.0.61.1 AutoScaling

そして、キー情報をファイルに保存します。("IAM Role"も使えると思います)
# cd AutoScaling
# cp credential-file-path.template credential-as.txt
# cat credential-as.txt
AWSAccessKeyId=XXXXXXXX
AWSSecretKey=YYYYYYYY

環境変数も各種設定しておきます。
# export JAVA_HOME=/usr/lib/jvm/jre
# export AWS_AUTO_SCALING_HOME=/opt/AutoScaling
# export AWS_CREDENTIAL_FILE=$AWS_AUTO_SCALING_HOME/credential-as.txt
# export AWS_AUTO_SCALING_URL=https://autoscaling.ap-northeast-1.amazonaws.com
# export PATH=$PATH:$AWS_AUTO_SCALING_HOME/bin

コマンドが正常に実行できれば、OKです。
# as-version 
Amazon AutoScaling CLI version 1.0.61.1 (API 2011-01-01)

次にVPCでの"Auto Scaling"です。

最初に"Launch Config"の作成です。
# as-create-launch-config vpc-lc \
> --image-id ami-f8fc41f9 \
> --group sg-40a7b72c,sg-877c60eb \
> --instance-type m1.small
OK-Created launch config
注意点として、"--group"オプションで指定するセキュリティグループは、
VPCの場合、セキュリティグループ名ではなく、セキュリティグループIDとなります。

そして"AutoScaling Group"の作成です。
# as-create-auto-scaling-group vpc-ag \
> --launch-configuration vpc-lc \
> --tag "k=Name, v=VPC-AS, p=true" \
> --load-balancers test \
> --health-check-type ELB \
> --grace-period 60 \
> --availability-zones ap-northeast-1a,ap-northeast-1b \
> --min-size 0 \
> --max-size 4 \
> --desired-capacity 0 \
> --vpc-zone-identifier subnet-9bd939f2,subnet-1eda3a77
OK-Created AutoScalingGroup

注意点として、"--vpc-zone-identifier"オプションでは対象のサブネットを指定します。

また、直感的に分かりにくい部分として下記を挙げておきます。
  • --tag の p : "true"にすると新規に立ち上げたEC2インスタンスのみにタグをつけます。
  • --health-check-type : EC2とELBが選択できELBだとELBのヘルスチェックで
    "Auto Scaling"の死活監視を行います。(ELBの場合"--grace-period"も必要になります)
  • --grace-period : EC2インスタンスが立ち上がって"Auto Scaling"の死活監視が開始されるまでの時間です。 
これで"Auto Scaling"の設定は、いったん終了です。

"Desired Capacity"を増やすと、
# as-set-desired-capacity vpc-ag \
> --desired-capacity 4
OK-Desired Capacity Set

増やした値までEC2インスタンスが増加します。
# as-describe-auto-scaling-instances
INSTANCE  i-7058aa73  vpc-ag  ap-northeast-1b  InService  HEALTHY  vpc-lc
INSTANCE  i-7258aa71  vpc-ag  ap-northeast-1b  InService  HEALTHY  vpc-lc
INSTANCE  i-7858aa7b  vpc-ag  ap-northeast-1a  InService  HEALTHY  vpc-lc
INSTANCE  i-7a58aa79  vpc-ag  ap-northeast-1a  InService  HEALTHY  vpc-lc

最後に"Auto Scaling"の設定を削除します。

まずは"Desired Capacity"を0にして"、"AutoScaling Group"中の
EC2インスタンス数を0にします。
# as-set-desired-capacity vpc-ag \
> --desired-capacity 0
OK-Desired Capacity Set
# as-describe-auto-scaling-instances
No instances found

次に"AutoScaling Group"を削除します。
# as-delete-auto-scaling-group vpc-ag    
    Are you sure you want to delete this AutoScalingGroup? [Ny]y
OK-Deleted AutoScalingGroup

その後"Launch Config"も削除すれば、きれいになります。
# as-delete-launch-config vpc-lc
    Are you sure you want to delete this launch configuration? [Ny]y
OK-Deleted launch configuration

次はポリシー...
--------
http://www.suz-lab.com

"pssh"(Parallel ssh)を使ってみた

スズキです。

AWSでは容易にスケールアウトできるので、調子に乗って多くのインスタンスを
立ち上げがちですが、それだけ多いと、設定の検証作業などが大変です...

ということで、同一の複数サーバを効率よく相手にするために
"pssh"(Parallel SSH)を試してみました。

インストールは簡単で"rpmforge"から"yum"でインストールできます。
# yum -y install pssh

そして、接続先ホスト一覧ファイルを用意して、
# cat hosts.txt 
10.0.0.166
10.0.0.167

下記のように利用することができます。
pssh -h ホスト一覧ファイル -l ユーザー名 -A -i コマンド
※"-A"オプションはパスワードの入力を要求します。
実際にファイルを作成してみると下記となり、

# pssh -h hosts.txt -l suzuki -A -i touch test.txt
Warning: do not enter your password if anyone else has superuser
privileges or access to your account.
Password: 
[1] 12:52:17 [SUCCESS] 10.0.0.166
Stderr: Warning: Permanently added '10.0.0.166' (RSA) to the list of known hosts.
[2] 12:52:17 [SUCCESS] 10.0.0.167
Stderr: Warning: Permanently added '10.0.0.167' (RSA) to the list of known hosts.

ディレクトリを確認すると、次のようにファイルが作成されていることがわかります。

# pssh -h hosts.txt -l suzuki -A -i ls -la
Warning: do not enter your password if anyone else has superuser
privileges or access to your account.
Password: 
[1] 12:52:24 [SUCCESS] 10.0.0.167
合計 28
drwx------  3 suzuki suzuki 4096  9月 19 12:52 2012 .
drwxr-xr-x. 3 root   root   4096  9月 19 12:42 2012 ..
-rw-------  1 suzuki suzuki  260  9月 19 12:49 2012 .bash_history
-rw-r--r--  1 suzuki suzuki   18  5月 11 03:45 2012 .bash_logout
-rw-r--r--  1 suzuki suzuki  176  5月 11 03:45 2012 .bash_profile
-rw-r--r--  1 suzuki suzuki  124  5月 11 03:45 2012 .bashrc
drwx------  2 suzuki suzuki 4096  9月 19 12:47 2012 .ssh
-rw-rw-r--  1 suzuki suzuki    0  9月 19 12:52 2012 test.txt
Stderr: Warning: Permanently added '10.0.0.167' (RSA) to the list of known hosts.
[2] 12:52:24 [SUCCESS] 10.0.0.166
合計 20
drwx------  2 suzuki suzuki 4096  9月 19 12:52 2012 .
drwxr-xr-x. 3 root   root   4096  9月 19 12:45 2012 ..
-rw-r--r--  1 suzuki suzuki   18  5月 11 03:45 2012 .bash_logout
-rw-r--r--  1 suzuki suzuki  176  5月 11 03:45 2012 .bash_profile
-rw-r--r--  1 suzuki suzuki  124  5月 11 03:45 2012 .bashrc
-rw-rw-r--  1 suzuki suzuki    0  9月 19 12:52 2012 test.txt
Stderr: Warning: Permanently added '10.0.0.166' (RSA) to the list of known hosts.

"AWS API"と組み合わせれば、タグがついたインスタンスに対して
一斉にコマンドを実行することができそう...
--------
http://www.suz-lab.com

2012年9月17日月曜日

Windows & Ruby & AWS SDK for Ruby

スズキです。

WindowsにRubyをインストールして"AWS SDK for Ruby"を使ってみました。

Windows環境は下記のAMIからEC2を立ち上げて作成しています。
AMI ID: ami-f48e33f5
AMI Name: Windows_Server-2008-R2_SP1-Japanese-64Bit-Base-2012.08.15

"AWS SDK"で利用するアクセスキーやシークレットキーは、下記のように
EC2起動時に"IAM Role"を設定し、ソースなどに記載しなくても、SDKが
勝手にメタデータから取得してくれるようにします。


設定した"IAM Role"のパーミッションは下記の通りです。SDK利用時に必要な
パーミッションを適宜設定する必要があります。


それでは、Rubyのインストールです。

まずは、下記のサイトからインストーラーをダウンロードです。
RubyInstaller for Windows

今回は現状の最新版(1.9.3-p194)をダウンロードしました。


そしてインストーラーを実行です。


下記のようにライセンスに合意して、


"Add Ruby executables to your PATH"にチェックを入れて、


簡単にインストールすることができます。


下記のように確認できればOKです。
C:\Users\Administrator>ruby -v
ruby 1.9.3p194 (2012-04-20) [i386-mingw32]

C:\Users\Administrator>gem -v
1.8.23

そして、下記のようなSDKを利用した簡単なRubyスクリプトを用意して実行します。
require 'aws-sdk'

ec2 = AWS::EC2.new(:ec2_endpoint => 'ec2.ap-northeast-1.amazonaws.com')

ec2.instances.each {|instance|
  p instance.id
}

次のようにインスタンス一覧が出力されれば、SDKも("IAM Role"も)OKです。
C:\Users\Administrator\Desktop>ruby jmeter.rb
"i-71579171"
"i-cde3f7cd"
"i-905bb493"
"i-965bb495"
"i-d69b6bd5"
"i-baf606b9"

そろそろPHPからRubyにかえるか...
--------
http://www.suz-lab.com