Posted at

Route53 と roadworker を使って VPC 環境の内部DNSを構築する

More than 1 year has passed since last update.


概要

AWS の VPC 環境の内部DNSに Route53 を利用するように設定して、Codenize.tools の roadworker を使って EC2 インスタンスの tag.Name で ssh したりできるようにしてみたのでその時の環境構築の時のメモです


構築環境


  • Amazon Linux AMI release 2017.09

  • ruby 2.3.5p376 (2017-09-14 revision 59905) [x86_64-linux-gnu]

  • roadwork 0.5.9.beta5


Route53 で VPC の内部DNSを構築

参考: https://cloudpack.media/9573


VPC でプライベートホストゾーンを有効化

http://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/hosted-zones-private.html

aws ec2 modify-vpc-attribute \

--vpc-id vpc-XXXXXXXX \
--enable-dns-hostnames '{"Value":true}'

aws ec2 modify-vpc-attribute \
--vpc-id vpc-XXXXXXXX \
--enable-dns-support '{"Value":true}'


Route53 でプライベートホストゾーンを作成

aws route53 create-hosted-zone \

--name my-sample-private-hosted-zone.internal \
--vpc 'VPCRegion="ap-northeast-1",VPCId="vpc-XXXXXXXX"' \
--caller-reference 2017-12-14-00:00 \
--hosted-zone-config 'PrivateZone="true"'


DHCP オプションを作成して VPC に関連付け

aws ec2 create-dhcp-options --dhcp-configuration '[

{
"Key": "domain-name-servers",
"Values": ["AmazonProvidedDNS"]
},
{
"Key": "domain-name",
"Values": ["my-sample-private-hosted-zone.internal"]
}
]'
aws ec2 associate-dhcp-options --dhcp-options-id dopt-XXXXXXXX --vpc-id vpc-XXXXXXXX # --dhcp-options-id は aws ec2 create-dhcp-options の返り値の "DhcpOptionsId" の値


roadworker で EC2 インスタンスの tag.Name を自動で Route53 のレコードに追加できるようにする

試してみたら結構便利だったので Codenize.toolsroadworker を使って EC2 インスタンスの tag.Name を自動で Route53 のレコードに追加するようにしてみました


roadworker 用 EC2 インスタンスを作成

aws ec2 run-instances \

--image-id ami-da9e2cbc \
--security-group-ids sg-XXXXXX \
--subnet-id subnet-XXXXXX \
--count 1 \
--instance-type m4.medium \
--key-name sample-keyname

(事前に上記のインスタンスに ssh できるようにしておく必要があります)


対象インスタンスへ Route53 と EC2 のアクセス権を付与する IAM ポリシーを付与

aws iam create-role --role-name roadworker --assume-role-policy-document '{

"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}
}'
{
"Role": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": {
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
}
}
},
"RoleId": "XXXXXXXXXXXXXXXXXXXX",
"CreateDate": "2017-12-14T00:00:00.000Z",
"RoleName": "roadworker",
"Path": "/",
"Arn": "arn:aws:iam::XXXXXXXXXXXX:role/roadworker"
}
}

aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonRoute53FullAccess --role-name roadworker
aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess --role-name roadworker
aws iam create-instance-profile --instance-profile-name roadworker
aws iam add-role-to-instance-profile --role-name roadworker --instance-profile-name roadworker
aws ec2 associate-iam-instance-profile --instance-id i-XXXXXXXXXXXXXXXXX --iam-instance-profile Name="roadworker"

--instance-id i-XXXXXXXXXXXXXXXXX は作成したインスタンスの ID となります


ruby バージョンアップ & 関連 yum install

サーバに ssh して

$ sudo su -

$ yum install -y ruby23-devel gcc libpcap-devel
$ alternatives --config ruby

There are 2 programs which provide 'ruby'.

Selection Command
-----------------------------------------------
*+ 1 /usr/bin/ruby2.0
2 /usr/bin/ruby2.3

Enter to keep the current selection[+], or type selection number: 2

$ gem install bundler
$ bundle exec ruby -v
ruby 2.3.5p376 (2017-09-14 revision 59905) [x86_64-linux-gnu]


roadworker インストール

$ mkdir /usr/local/roadworker

$ cd /usr/local/roadworker
$ bundle init
$ echo "gem 'roadworker', '0.5.9.beta5'" >> Gemfile
$ echo "gem 'json'" >> Gemfile # https://github.com/tdiary/tdiary-core/issues/510 の問題が発生するため
$ bundle install
$ vi Routefile # ↓の内容で Routefile を書く

Routefile

require 'aws-sdk'

region = "ap-northeast-1"
vpc_id = "vpc-XXXXXXXX"
domain = "my-sample-private-hosted-zone.internal."

hosted_zone "my-sample-private-hosted-zone.internal." do
vpc region, vpc_id

resp = Aws::EC2::Client.new(region: region).describe_instances(filters:[{ name: 'vpc-id', values: [vpc_id] }])
instances = resp.reservations.each_with_object({}) do |reservation, reservations|
reservations.merge!(reservation.instances.each_with_object({}) do |instance, instances|
instances[instance.private_ip_address] = instance.tags.find {|tag| tag['key'] == 'Name' }['value']
end)
end

instances.each {|private_ip_address, tagName|
rrset "#{tagName}.#{domain}", "A" do
ttl 60
resource_records private_ip_address
end
}
end

作成した Routefile を適用

$ bundle exec roadwork -a --dry-run --target-zone 'my-sample-private-hosted-zone\.internal' # dry-run

$ bundle exec roadwork -a --target-zone 'my-sample-private-hosted-zone\.internal'


EC2 の tag.Name の値で対象サーバにアクセスできることを確認

数分待ってから DNS が引けることを確認

(↓は roadworker 用 EC2 インスタンスの tag.Name を roadworker-exec-server としていた場合)

$ roadworker-exec-server.my-sample-private-hosted-zone.internal | grep -A 1 'ANSWER SECTION'

;; ANSWER SECTION:
roadworker-exec-server.my-sample-private-hosted-zone.internal. 55 IN A 10.0.0.60

$ ssh roadworker-exec-server

Last login: Thu Dec 14 00:00:00 2017 from XXX.XXX.XXX.XXX

__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2017.09-release-notes/
[ec2-user@ip-10-0-0-60 ~]$

ssh できるところまで確認できたので、あとは roadwork を cron とかで定期的にで実行するようにしておけばインスタンスが追加されても tag.Name を使って ssh とかできるようになりそうです

注意点としては今回作成した Routefile だと tag.Name が重複する場合は IP が上書きされたりと行ったことがあるので tag.Name で ssh したいインスタンスの tag.Name は重複しないようにする必要があります


感想

環境構築で微妙にハマるところがあったけれど Codenize.tools(roadworker) 便利でした