2012年12月1日土曜日

Amazon Linux で起動時にホスト名を設定する

Amazon Linux で起動時にホスト名を設定したいと思い、調べてみたところ CloudInit というものがあることが分かりました。

CloudInit とは、cloud-platform(EC2 や Openstack など)の Ubuntu でインスタンスの初期化を扱うためのものです。Amazon Linux では、CloudInit が使用可能になっているんですね。

サンプルを参考に、以下の内容をインスタンス起動時に渡してみましたが、うまくいきません。

cloudinit: /doc/examples/cloud-config.txt
$ cat cloud-config.txt
--------------------------------------
#cloud-config
hostname: myhostname
--------------------------------------
$ ec2-run-instances ami-4e6cd34f -g [GROUP] -k [KEYPAIR] -t [INSTANCE_TYPE] -f cloud-config.txt

Ubuntu の AMI を使用すると、うまくホスト名が設定できるので もう少し調べてみたところ、このフォーラムにたどり着きました。

Amazon AMI w/ #cloud-config - struggling with the basics
For your question as to why setting the hostname isn't working, it is because the version of cloud-init found in the Amazon Linux AMI does not currently support those options.

今の Amazon Linux では、hostname のオプションは使えないそう。フォーラムには、別の方法での設定例があって、以下の方法でも実現できるんですね。
#cloud-config
runcmd:
 - [ echo, 'Setting custom hostname' ]
 - [ sed, -i, 's/^HOSTNAME=[a-zA-Z0-9\.\-]*$/HOSTNAME=MyName/g', /etc/sysconfig/network ]
 - [ hostname, 'MyName' ]

2012年9月9日日曜日

Amazon S3 上の Web サイトへのアクセス制限

Amazon S3 上のバケットは、Web サイトとして設定することができます。

Hosting Websites on Amazon S3

また、Bucket Policies を使用することで、アクセスの制限をすることも可能です。例えば、特定のIPアドレスからのみアクセスを許可・拒否したい場合は、以下のように設定します。

Example Cases for Amazon S3 Bucket Policies
{
    "Version": "2008-10-17",
    "Id": "S3PolicyId1",
    "Statement": [
        {
            "Sid": "IPAllow",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::bucket/*",
            "Condition" : {
                "IpAddress" : {
                    "aws:SourceIp": "192.168.143.0/24"
                },
                "NotIpAddress" : {
                    "aws:SourceIp": "192.168.143.188/32"
                }
            }
        }
    ]
}
この例では、192.168.143.* からのアクセスを許可しますが、例外として 192.168.143.188 からの アクセスは拒否されます。

各要素の説明は、Element Descriptions に記載されています。

2012年9月1日土曜日

Auto Scaling から起動するインスタンスに Security Group を設定する

Auto Scaling を使ってインスタンスを起動する場合、Security Group を指定しないと default が設定されます。

Security Group を指定したい場合は、Launch Configuration を作成する時に group を設定します。
$ as-create-launch-config --help
…
   --group VALUE1,VALUE2,VALUE3...
       Security groups with which to associate the Amazon EC2 instances. Note
       that Amazon VPC security groups and Amazon EC2 security groups are
       mutually exclusive and can't be used together. Either all group names or
       all group ids are acceptable, but not both.

Auto Scaling Developer Guide には詳しく書いてなくて、色々調べた後に、コマンドのヘルプに書いてあることを知った。最初にココを見るべきだった。

command line tool のオプションは API と対応しているから、API Reference を参照して、まずオプションの有無を調べてみるのもいいかもしれない。

Auto Scaling API Reference - CreateLaunchConfiguration
SecurityGroups.member.N

The names of the security groups with which to associate Amazon EC2 or Amazon VPC instances. Specify Amazon EC2 security groups using security group names, such as websrv. Specify Amazon VPC security groups using security group IDs, such as sg-12345678. 

2012年8月26日日曜日

Amazon ELB からのみアクセスを許可する Security Group の設定

ELB の配下に設置しているインスタンスは、セキュリティを考慮すると ELB からのみアクセスを許可するようにしたいですね(管理用のアクセスは別として)。

ELB に用意されている特別な Security Group を使って、これを実現できます。

まず最初に ELB の API Tools を使用して、Source Security Group の名前を確認します。
$ elb-describe-lbs [LoadBalancerName] --show-long --headers
... ,"{owner-alias=example-elb,group-name=example-elb-sg}", ...
次に ELB 配下のインスタンスが所属する Security Group に、確認した名前を設定します。
$ ec2-authorize [group_name] -u example-elb -o example-elb-sg
もし、より制限の低いルールが設定されていた場合は、そのルールを削除します。
(以下の例は、tcp 80番へのアクセスを全て許可するルールが設定されていた場合)
$ ec2-revoke [group_name] -P tcp -p 80 -s 0.0.0.0/0

2012年8月5日日曜日

boto を使って Amazon S3 へのアップロード

boto を使って S3 へアップロードする時、東京リージョンなど、US Standard 以外のリージョンのバケットへのアップロードが失敗するという事象に遭遇しました。エラー内容は Broken pipe 。
>>> from boto.s3.connection import S3Connection
>>> conn = S3Connection()
>>> bucket = conn.get_bucket('mybucket')
>>> k = Key(bucket)
>>> k.set_contents_from_filename('myfile')
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
...
    857             raise BotoServerError(response.status, response.reason, body)
    858         elif e:
--> 859             raise e
    860         else:
    861             msg = 'Please report this exception as a Boto Issue!'

error: [Errno 32] Broken pipe
しかも、50KBぐらいのファイルだと問題ないのに、500KBくらいになるとダメ。東京リージョンのサーバから実行してるから、US の方が距離的に遠いし、時間がかかってタイムアウトとは考えにくい。しかも、500KBってそんなに大きいサイズではないし。 

同じ事象で困っている人がいて、以下のページが参考になりました。

 broken pipe error, non US-Standard region

解決方法としては、Connection を作成する時に、host を指定すること。
>>> from boto.s3.connection import S3Connection
>>> conn = S3Connection(host='s3-ap-northeast-1.amazonaws.com')

指定するエンドポイントは、ここから参照できます。

Amazon Web Services Glossary - Regions and Endpoints

2012年6月23日土曜日

Amazon EC2 の AMI の種類

Amazon EC2 の AMI には、EBS-backed と instance store-backed の2種類あります。それぞれの違いについてあらためて整理してみる。

・root device のサイズ制限
EBS-backed は 1TBまで。instance store-backed は 10GBまで。 Windows などは サイズが大きいので、多くは EBS-backed になる。

・停止時の動作の違い
EBS-backed だと停止時の動作に stop を選択できる。stopped のインスタンスは EBS上に保持され、restart することが可能。EBS は永続性のあるストレージのため、restart 後もデータは保持される。

instance store-backed は、terminate のみ。terminate したインスタンスはデータが失われる。また、意図的でない停止(インスタンスの障害など)でも同様にデータが失われる。

すなわち EBS は、EC2のインスタンスとは独立してデータを保持するが、instance store は EC2のインスタンス起動時のみデータが保持される。

・起動にかかる時間
EBS-backed AMI は instance store-backed AMI よりも起動時間が短い。目安としては、EBS-backed で1分以内、instance store-backed で 5分以内。

・AMI の作成方法
instance store-backed の Linux/Unix OS でAMIを作成する場合、インスタンス自身の上でイメージを作成する必要があり、API が用意されていない。EBS-backed であれば ec2-create-image コマンドで作成が可能。

・課金方法
instance store-backed は、AMI ストレージである S3 の料金 と インスタンス使用量 に対して料金がかかる。EBS-backed は AMI ストレージである EBS snapshot の料金(= S3 の料金) と インスタンス使用量に加えて、EBS の 割当量と入出力量 に対して料金がかかる。

また、instance store-backed は、AMI をカスタマイズして新しく作成した際、全体が S3 に保存されるのに対し、EBS-backed では変更部分のみ保存される。そのため、次に保存する AMI のサイズは小さくなり AMI ストレージ の料金は instance store-backed に比べて低くなる。


こうやって見ていると EBS-backed の方が管理しやすいように思えますね。

2012年5月19日土曜日

iptables による ポートのリダイレクト

あるポートから違うポートへリダイレクトさせたい時があります。

例えば、下記ページの例のように「8080 ポートで待ち受けをしている Tomcat に対して、http://anyhost.com:8080 ではなく http://anyhost.com でアクセスさせたい」などです。

Firewalls-local-port-redirection

色々な方法がありますが、その1つとして iptables の REDIRECT ターゲット を使用する方法があります。この場合、リダイレクトする対象として、以下のパターンが考えられます。

1. 外から入ってきたパケットをリダイレクトする
2. ローカルで生成したパケットをリダイレクトする

サーバーに設定するのであれば、1 のパターンがメインになりますね。2 のパターンはテストをする時などでしょうか。

1 のパターンの場合の設定は以下になります。
(-dst の値は環境にあわせて変更)
# iptables -t nat -I PREROUTING --src 0/0 --dst 127.0.0.1 \
-p tcp --dport 80 -j REDIRECT --to-ports 8080
設定の意味が理解しやすいルールですね。ただ、2のパターンのルールを見たとき、ピンときませんでした。
# iptables -t nat -I OUTPUT --src 0/0 --dst 127.0.0.1 \
-p tcp --dport 80 -j REDIRECT --to-ports 8080

理由は、OUTPUT チェインが外に出て行く時に適用されると勘違いしていたから。あらためて man の TABLES の部分を見てみると「ローカルで生成したパケットをルーティング前に変更する」とハッキリ書いてますね!
nat: This table is consulted when a packet that creates a 
new connection is encountered. 〜 OUTPUT (for altering 
locally-generated packets before routing)
下記のページの図も参考になります。
NAT(Network Address Translation) の概要

設定を削除する場合は以下。(テーブルを指定しない場合のデフォルトは "filter" なので、"nat" テーブルを削除する場合には、明示的に指定する必要がある)
# iptables -t nat -F
また、個別にルールを削除したい場合は、以下のようにします。
# iptables -t nat -n -L --line-numbers
-------------------------------------------------
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination      
1    REDIRECT   tcp  --  0.0.0.0/0            127.0.0.1 ...

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination      


Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination      
1    REDIRECT   tcp  --  0.0.0.0/0            127.0.0.1 ...
-------------------------------------------------

削除したいルールのチェインと行番号を指定する
# iptables -t nat -D PREROUTING 1

2012年5月4日金曜日

Amazon Linux の yum リポジトリ

Amazon Linux AMI のインスタンスで Python をソースからコンパイルしたかったのですが、いつもコンパイル時にインストールしていた tk-devel パッケージが見つからない。

Amazon Linux では、amzn-main という独自のリポジトリが設定されている模様。
$ ls /etc/yum.repos.d/
---------------------------------
amzn-nosrc.repo    amzn-updates.repo  epel.repo
amzn-main.repo     amzn-preview.repo  epel-testing.repo
---------------------------------

Amazon Linux に含まれている EPEL リポジトリのバージョンが 6 に設定されていたので、AWSのフォーラムを参考に、CentOS 6 のリポジトリを追加してインストールを試みた。
$ cd /etc/yum.repos.d
$ sudo vim CentOS-Base.repo
--------------------------------------------
[base]
name=CentOS-6 - Base
mirrorlist=http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os
enabled=0
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
--------------------------------------------
$ sudo yum install --enablerepo=base tk-devel

$ rpm -qa | grep tk-devel
tk-devel-8.5.7-5.el6.x86_64

うまくインストールされ、Python のコンパイルも成功。