2012/11/13

Amazon EC2上で、内部IP(Private IP)をベースにhostsファイルを作成するスクリプト。

Amazon EC2インスタンスでは、標準でPublic DNS名と、Private DNS名が割り当てられる。

自分が作ったノード同士は出来れば固定したホスト名でやりとりしたいが、Public DNS名もPrivate DNS名もインスタンスをstopしてstartした場合は付け直されてしまうため、何かと困ってしまう状況が発生する。

そういう場合に、インスタンスに設定したタグ:Nameに基づいて、各ノード上で動的に/etc/hostsファイルを生成するスクリプトを書いてみた。

☆ec2-describe-instancesコマンドでは、自分のアカウントに紐付くインスタンス情報が全て出てきてしまうので、各ノードに設定しているタグ:GroupNameが同じものだけhostsに出てくるようにしている。

==== create_hosts.sh ====

#!/bin/sh

# 必要な環境変数の定義
export PATH=${PATH}:/opt/aws/bin/
export EC2_HOME=/opt/aws/apitools/ec2
export JAVA_HOME=/usr/lib/jvm/jre

cd /tmp

# AWS Access Key, Secret Access Keyを設定しておく
export AWS_ACCESS_KEY=XXXXXXXXXXXXXXXX
export AWS_SECRET_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# 自分のインスタンスを求めるために内部IPを求める
MY_LOCAL_ADDR=`curl -s http://169.254.169.254/latest/meta-data/local-ipv4` >/dev/null 2>&1
MY_PUBLIC_ADDR=`curl -s http://169.254.169.254/latest/meta-data/public-ipv4` >/dev/null 2>&1

EC2_INSTANCES_FILENAME=instances.$$
ec2-describe-instances > ${EC2_INSTANCES_FILENAME}

# 内部IPに基づいて、インスタンスIDを見つける
MY_INSTANCE_ID=`grep ${MY_LOCAL_ADDR} ${EC2_INSTANCES_FILENAME} | grep -w ^INSTANCE | awk '{print $2;}'`
# インスタンスIDに紐付いているタグGroupNameの値を引っ張る
MY_GROUPNAME=`grep ${MY_INSTANCE_ID} ${EC2_INSTANCES_FILENAME} | grep -w ^TAG | grep -w GroupName | awk '{print $5;}'`

# タグGroupNameが同じインスタンスの一覧を取得する
EC2_GROUP_INSTANCES_FILENAME=group_instances.$$
ec2-describe-instances -F tag:GroupName=${MY_GROUPNAME} > ${EC2_GROUP_INSTANCES_FILENAME}

# インスタンス一覧から、インスタンスID・内部IP・名前(tag:Name)の紐付けを作成する
EC2_GROUP_IPADDRS_FILENAME=group_ipaddr.$$
grep -w ^INSTANCE ${EC2_GROUP_INSTANCES_FILENAME} | awk '{print $2,$15;}' | sort > ${EC2_GROUP_IPADDRS_FILENAME}
EC2_GROUP_HOSTNAME_FILENAME=group_hosts.$$
grep -w ^TAG ${EC2_GROUP_INSTANCES_FILENAME} | grep -w Name | awk '{print $3,$5;}' | sort > ${EC2_GROUP_HOSTNAME_FILENAME}

# 内部IP・名前から/etc/hostsを作成し上書きする
EC2_GROUP_HOSTS=hosts.$$
echo "127.0.0.1   localhost localhost.localdomain" > ${EC2_GROUP_HOSTS}
join -j1 1 -j2 1 ${EC2_GROUP_IPADDRS_FILENAME} ${EC2_GROUP_HOSTNAME_FILENAME} | awk '{print $2,$3;}' >> ${EC2_GROUP_HOSTS}

cat ${EC2_GROUP_HOSTS} > /etc/hosts

# 一時作業ファイルを削除する
rm ${EC2_INSTANCES_FILENAME} ${EC2_GROUP_INSTANCES_FILENAME} ${EC2_GROUP_IPADDRS_FILENAME} ${EC2_GROUP_HOSTNAME_FILENAME}
rm ${EC2_GROUP_HOSTS}
==== end. ====

とりあえずこれでタグ:GroupNameが同じもの同士は、/etc/hostsに書き出されるようになったので、crontabなどで定期的に実行されるように設定しておく。


<追記>
スクリプトだけだと何をやってるのか分かりにくかったので、コマンド例を。

※インスタンスのインスタンスID($2)と内部IP($15)を拾ってくる。

[root@ip-10-145-150-102 shell]# ec2-describe-instances | grep -w ^INSTANCE | awk '{print $2,$15}'
i-56aa7a1b 10.123.102.108
i-54ab7ab1 10.123.148.222

※インスタンスのインスタンスID($3)とタグ名・設定値($4,$5)を拾ってくる。

[root@ip-10-145-150-102 shell]# ec2-describe-instances | grep -w ^TAG | awk '{print $3,$4,$5;}'
i-56aa7a1b Name CDHMGR01
i-56aa7a1b GroupName Cloudera
i-54ab7ab1 Name CDHMGR02
i-54ab7ab1 GroupName Cloudera

↓これらをUNIXのjoinコマンドでつなげてやると、

i-56aa7a1b 10.123.102.108 CDHMGR01
i-54ab7ab1 10.123.148.222 CDHMGR02

となるので、あとは頭のいらない部分を捨てた上で、hostsに追記している。

0 件のコメント:

コメントを投稿