やること
- terraform で iam ロールをつくる
- terraform で ec2 インスタンスをつくる
- userdata を渡す
- s3 から shellscript をダウンロードして実行
- インスタンスに付与されている Name タグを hostname に設定する
- s3 から shellscript をダウンロードして実行
- userdata を渡す
これらを terraform apply
のみで完了させます。
環境
name | version |
---|---|
ec2 | amazon-linux 2015.09 |
terraform | 0.5.3 |
ローカル環境 | OSX 10.10.5 |
※ terraform の現在の最新は 0.6.6 のようです
前提
- subnet / routetable / security-group が作成済みであること
tf ファイルの作成
ec2 インスタンスの構成情報を記述します。作業ディレクトリは ~/terraform/test
とします。
aws アクセスキー
~/terraform/test/aws.tf
/*
aws settings
*/
provider "aws" {
access_key = "************"
secret_key = "********************"
region = "ap-northeast-1"
}
変数
今回は使いませんが、バケット名を書いたりすると便利そうです。
~/terraform/test/variables.tf
/*
variables
*/
variable "my-env" {
default = {
vpc_id = "vpc-****"
vpc_cidr = "10.0.0.0/16"
}
}
iam ロール
s3 へのアクセスと ec2 describe-instances
を許可します。
~/terraform/test/iam_role.tf
resource "aws_iam_role_policy" "test_policy" {
name = "test_policy"
role = "${aws_iam_role.test.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::my-bucket/*",
"arn:aws:s3:::my-bucket"
]
}
]
}
EOF
}
resource "aws_iam_role" "test_role" {
name = "test_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_instance_profile" "test_profile" {
name = "test_profile"
roles = ["${aws_iam_role.test_role.name}"]
}
一旦ここまでで terraform apply
して iam 設定を作成しておきます。
userdata
中身はこんな感じで、s3 からダウンロードしたスクリプトを実行するだけのものです。
userdata.sh
#!/bin/bash
# for userdata
aws="/usr/bin/aws --region ap-northeast-1"
work_dir="/tmp/userdata"
s3_url="s3://my-bucket/my-folder"
logger="logger -t $0"
${logger} "start scirpt."
mkdir -p "${work_dir}"
### download & run
${aws} s3 cp --recursive "${s3_url}" "${work_dir}"
ls "${work_dir}" | while read script
do
sh "${work_dir}"/"${script}"
done
${logger} "finished."
exit 0
これを base64
エンコードします。 mac だったら以下です。
$ cat userdata.sh | openssl enc -e -base64
IyEvYmluL2Jhc2gKIyBmb3IgdXNlcmRhdGEKCmF3cz0iL3Vzci9iaW4vYXdzIC0t
cmVnaW9uIGFwLW5vcnRoZWFzdC0xIgp3b3JrX2Rpcj0iL3RtcC91c2VyZGF0YSIK
czNfdXJsPSJzMzovL215LWJ1Y2tldC9teS1mb2xkZXIiCmxvZ2dlcj0ibG9nZ2Vy
IC10ICQwIgoKJHtsb2dnZXJ9ICJzdGFydCBzY2lycHQuIgpta2RpciAtcCAiJHt3
b3JrX2Rpcn0iCgojIyMgZG93bmxvYWQgJiBydW4KJHthd3N9IHMzIGNwIC0tcmVj
dXJzaXZlICIke3MzX3VybH0iICIke3dvcmtfZGlyfSIKbHMgIiR7d29ya19kaXJ9
IiB8IHdoaWxlIHJlYWQgc2NyaXB0CmRvCiAgc2ggIiR7d29ya19kaXJ9Ii8iJHtz
Y3JpcHR9Igpkb25lCgoke2xvZ2dlcn0gImZpbmlzaGVkLiIKZXhpdCAw
これを次の tf ファイルに貼り付けます。
ec2 インスタンス
~/terraform/test/instance.tf
resource "aws_instance" "test-001" {
ami = "ami-*****"
instance_type = "t2.micro"
subnet_id = "subnet-*****"
private_ip = "10.0.0.5"
user_data = <<EOF
IyEvYmluL2Jhc2gKIyBmb3IgdXNlcmRhdGEKCmF3cz0iL3Vzci9iaW4vYXdzIC0t
cmVnaW9uIGFwLW5vcnRoZWFzdC0xIgp3b3JrX2Rpcj0iL3RtcC91c2VyZGF0YSIK
czNfdXJsPSJzMzovL215LWJ1Y2tldC9teS1mb2xkZXIiCmxvZ2dlcj0ibG9nZ2Vy
IC10ICQwIgoKJHtsb2dnZXJ9ICJzdGFydCBzY2lycHQuIgpta2RpciAtcCAiJHt3
b3JrX2Rpcn0iCgojIyMgZG93bmxvYWQgJiBydW4KJHthd3N9IHMzIGNwIC0tcmVj
dXJzaXZlICIke3MzX3VybH0iICIke3dvcmtfZGlyfSIKbHMgIiR7d29ya19kaXJ9
IiB8IHdoaWxlIHJlYWQgc2NyaXB0CmRvCiAgc2ggIiR7d29ya19kaXJ9Ii8iJHtz
Y3JpcHR9Igpkb25lCgoke2xvZ2dlcn0gImZpbmlzaGVkLiIKZXhpdCAw
EOF
iam_instance_profile = "${aws_iam_instance_profile.test_profile.name}"
security_groups = [
"sg-*******"
]
ebs_block_device = {
device_name = "/dev/xvdba"
volume_type = "standard"
volume_size = "15"
encrypted = "true"
delete_on_termination = "true"
}
ebs_block_device = {
device_name = "/dev/xvdbb"
volume_type = "standard"
volume_size = "15"
encrypted = "true"
delete_on_termination = "true"
}
tags {
Name = "test-001"
}
}
ホスト名をつけるスクリプト
s3 にアップロードしておくスクリプトです。
set_hostname.sh
#!/bin/bash
# set_hostname.sh
# require awscli and ec2 read access on iam role
set -e
aws="/usr/bin/aws --region ap-northeast-1"
logger="logger -t $0"
get_instance_id()
{
instance_id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
}
get_tag_name()
{
tag_name=$(${aws} ec2 describe-instances \
--instance-id ${instance_id} \
--query 'Reservations[].Instances[].Tags[?Key==`Name`].Value' \
--output text)
}
set_hostname()
{
hostname "${tag_name}"
local res=$(grep "HOSTNAME=${tag_name}" /etc/sysconfig/network)
if [ -z "${res}" ]; then
sed -i -e '/HOSTNAME/d' /etc/sysconfig/network
echo "HOSTNAME=${tag_name}" >> /etc/sysconfig/network
fi
}
get_instance_id
get_tag_name
set_hostname
${logger} "finished $0"
exit 0
terraform 実行
$ terraform apply
~略~
ebs_block_device.66500966.delete_on_termination: "" => "1"
ebs_block_device.66500966.device_name: "" => "/dev/xvdba"
ebs_block_device.66500966.encrypted: "" => "1"
ebs_block_device.66500966.iops: "" => "<computed>"
ebs_block_device.66500966.snapshot_id: "" => "<computed>"
ebs_block_device.66500966.volume_size: "" => "15"
ebs_block_device.66500966.volume_type: "" => "standard"
ebs_block_device.7499016.delete_on_termination: "" => "1"
ebs_block_device.7499016.device_name: "" => "/dev/xvdbb"
ebs_block_device.7499016.encrypted: "" => "1"
ebs_block_device.7499016.iops: "" => "<computed>"
ebs_block_device.7499016.snapshot_id: "" => "<computed>"
ebs_block_device.7499016.volume_size: "" => "15"
ebs_block_device.7499016.volume_type: "" => "standard"
ephemeral_block_device.#: "" => "<computed>"
iam_instance_profile: "" => "test_profile"
instance_type: "" => "t2.medium"
key_name: "" => "<computed>"
placement_group: "" => "<computed>"
private_dns: "" => "<computed>"
private_ip: "" => "10.0.0.5"
public_dns: "" => "<computed>"
public_ip: "" => "<computed>"
root_block_device.#: "" => "<computed>"
security_groups.#: "" => "1"
security_groups.2820007362: "" => "sg-******"
subnet_id: "" => "subnet-******"
tags.#: "" => "1"
tags.Name: "" => "test-001"
tenancy: "" => "<computed>"
user_data: "" => "53f8ca1523019339fffee792e0210ded15b39f5a"
vpc_security_group_ids.#: "" => "<computed>"
aws_instance.test-001: Creation complete
Apply complete! Resources: 1 added, 1 changed, 1 destroyed.
ssh -i key ec2-user@10.0.0.5
でログインし、 prompt が変わっていることが確認できました。
[ec2-user@test-001 ~]$
とっても便利ですね!