摘要:通过本系列文章,你学会了在VPC中使用定制DNS服务器来发布一个拥有定制私有域名的EMR集群。只要你能够解析集群中的所有节点,你可以使用任何方法来发布一个EMR集群。
在第一部分,我们学习了 Amazon EMR如何使用 Amazon VPC
,DNS主机名称和DHCP设置来满足Hadoop需求。而在实际应用中,在 DHCP选项集中将域名修改成定制互联网域名的操作非常普遍,本篇博文将介绍如成功地给EMR配置不同的DNS服务,比如BIND、Dnsmasq以及
Amazon Route 544。通常情况下,我们需要执行下述多个操作:
1. 为VPC进行BIND服务器配置。
2. 修改已有VPC来使用一个定制域名和DNS服务器。
3. 为定制化域名安装和配置Dnsmasq来解析域名查询。
4. 配置Route 53来托管私有域。
如上篇博文所述,我们将发布一个简单的测试集群来保证一切可以正常的启动和运行。
DNS相关
为了自动地生成DNS主机名称记录,我们需要一个DHCP服务器。然而,在VPC中并不存在这个DHCP选项,因此用户必须为每个发布集群的子网手动地列出所有IP地址记录。此外,为了满足Hadoop
DNS的查找需求,正反向查找都需要被成功地设置。这就意味着用户需要为hostname A记录设置一个正向域,同时也要为IP
PTR记录设置一个反向查找域。在本文中,我们将使用一个小的子网(11条可用主机记录),实际操作中,子网和集群封装大小根据实际情况制定。基于这些需求,如果VPC
DNS服务不能解析DHCP选项集(除非默认region.compute.internal域名和Route
53中托管的域名,其他的不能被解析)中的域名,那么必须要存在工具对其解析。下面言归正传。
建立一个BIND服务器配置
如果已经拥有一个DNS服务器,简单的必要主机和IP地址记录配置已不可行。这一节我们将展示如何配置一个BIND服务器。基于BIND服务器设置的复杂性,这里不会一步一步的进行安装。这里假设已经存在一个现有的BIND服务器,它已经被配置和运行一些名称解析服务。
如果你在BIND的设置上还是个新手,需要注意的是它对域文件错误非常敏感。当然,如果你真的一点基础都没有的话,
Setting up a DNS Server in Amazon EC2 一文可以帮助到你,或者这个通过Ubuntu一步一步设置一个私有的
DNS服务器 。否则,你可以直接跳到下面的学习设置Dnsmasq一节。同样,尽管展示用例使用的是BIND服务器,用户也可以使用任何其他DNS服务器。
这个示例BIND服务器被配置用来监听查询,不管是本地回调地址,亦或是私有互联网IP地址:
listen-on port 53 { 127.0.0.1; 10.20.30.5; }; |
在VPC中,所有IP地址都允许做递归查询以发现未知主机。需要注意的是,确保这些设置已足够严格来阻止DNS重放攻击:
recursion yes; allow-recursive { 10.20.30.0/24; }; allow-query { 10.20.30.0/24; }; |
这里需要配置两个域文件:“hadoop.local”和“30.20.10.in-addr.arpa”。
// // named.conf // // Provided by Red Hat bind package to configure the ISC BIND named(8) DNS // server as a caching-only nameserver (as a localhost DNS resolver only). // // See /usr/share/doc/bind*/sample/ for example named configuration files. // options { listen-on port 53 { 127.0.0.1; 10.20.30.5; }; // listen-on-v6 port 53 { ::1; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; allow-query { 10.20.30.0/24; }; recursion yes; allow-recursion { 10.20.30.0/24; }; dnssec-enable no; dnssec-validation no; // dnssec-lookaside auto;
/* Path to ISC DLV key */
bindkeys-file "/etc/named.iscdlv.key";
managed-keys-directory "/var/named/dynamic";
};
logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};
};
zone "." IN {
type hint;
file "named.ca";
};
zone "hadoop.local" IN {
type master;
file "hadoop.zone";
};
zone "30.20.10.in-addr.arpa" IN {
type master;
file "reverse.zone";
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key"; |
正向域hadoop.local,包含了所有回到10.20.30.5 BIND服务器NS记录;所有可能的主机名称都被定义如下文A记录:
$TTL 5M @ IN SOA ns.hadoop.local. root.hadoop.local. ( 0 ; serial 1D ; refresh 1H ; retry 1W ; expire 3H ) ; minimum IN NS ns.hadoop.local. ;host records
ns IN A 10.20.30.5
ip-10-20-30-6 IN A 10.20.30.6
ip-10-20-30-7 IN A 10.20.30.7
ip-10-20-30-8 IN A 10.20.30.8
ip-10-20-30-9 IN A 10.20.30.9
ip-10-20-30-10 IN A 10.20.30.10
ip-10-20-30-11 IN A 10.20.30.11
ip-10-20-30-12 IN A 10.20.30.12
ip-10-20-30-13 IN A 10.20.30.13
ip-10-20-30-14 IN A 10.20.30.14
;Alias for nameserver
ip-10-20-30-5 IN CNAME ns |
上述情况也适用于反向域30.20.10.in-addr.arpa。所有子网中可能的IP地址被映射回 hadoop.local域下的主机A记录。
$TTL 5M @ IN SOA ns.hadoop.local. root.hadoop.local. ( 0 ; serial 1D ; refresh 1H ; retry 1W ; expire 3H ) ; minimum IN NS ns.hadoop.local. ;ptr records 5 IN PTR ip-10-20-30-5.hadoop.local. 6 IN PTR ip-10-20-30-6.hadoop.local. 7 IN PTR ip-10-20-30-7.hadoop.local. 8 IN PTR ip-10-20-30-8.hadoop.local. 9 IN PTR ip-10-20-30-9.hadoop.local. 10 IN PTR ip-10-20-30-10.hadoop.local. 11 IN PTR ip-10-20-30-11.hadoop.local. 12 IN PTR ip-10-20-30-12.hadoop.local. 13 IN PTR ip-10-20-30-13.hadoop.local. 14 IN PTR ip-10-20-30-14.hadoop.local. |
修改VPC以使用一个定制化域名和DNS服务器
上篇博文展示了如何建立和使用一个VPC,下一个步骤则是通过DHCP选项集修改域名和DNS服务器,并建立一个解析hadoop.local域的DNS服务器。DHCP选项集将使用一个位于子网内首个可用IP地址的定制化DNS服务器。注意:AWS会保存任何子网的前四个和最后一个地址,因此你的可用地址应该从.5开始。
首先发布一个Amazon EC2实例,并为其配置一个10.20.30.5的私有IP地址。请确保已经为SSH访问填入一个键值对。在这个例子中,我们将展示使用俄勒冈州最新的Linux
HVM EBS-backed AMI。你可以通过以下代码为region获得AMI ID:
aws ec2 run-instances --image-id ami-dfc39aef --count 1 --key-name
--instance-type t2.micro --subnet-id subnet-907af9f5 --private-ip-address 10.20.30.5 --associate-public-ip-address |
通过下述代码建立一个域名为“hadoop.local”的DHCP选项集,并且将DNS服务器设置为“10.20.30.5,
AmazonProvidedDNS'”:
$ aws ec2 create-dhcp-options --dhcp-configurations Key=domain-name,Values=hadoop.local Key=domain-name-servers,Values=10.20.30.5,AmazonProvidedDNS |
{ "DhcpOptions": { "DhcpConfigurations": [ { "Values": [ { "Value": "hadoop.local" } ], "Key": "domain-name" }, { "Values": [ { "Value": "10.20.30.5" }, { "Value": "AmazonProvidedDNS" } ], "Key": "domain-name-servers" } ], "DhcpOptionsId": "dopt-793fdf1c" } } |
现在,为VPC设置DHCP选项集和VPC-id值,主机名称在:
{ "DhcpOptions": { "DhcpConfigurations": [ { "Values": [ { "Value": "hadoop.local" } ], "Key": "domain-name" }, { "Values": [ { "Value": "10.20.30.5" }, { "Value": "AmazonProvidedDNS" } ], "Key": "domain-name-servers" } ], "DhcpOptionsId": "dopt-793fdf1c" } } |
修改实例所在的安全组以允许从VPC CIDR 中实例流入的DNS查询。如果你没有为run-instances命令提供一个子网组ID,那么它将是VPC中的默认安全组:
aws ec2 authorize-security-group-ingress --group-id sg-08bf9b6d --protocol udp --port 53 --cidr 10.20.30.0/24 |
安装和配置Dnsmasq来解析域名查询
如果你在VPC中没有运行一个DNS服务器,并且想在无附加措施的情况下运行一个EMR集群,一个类似Dnsmasq这样的组件非常适合。在资源有限的情况下,Dnsmasq可以提供名称缓存并转发服务。在2.6.7版本中,Dnsmasq引入了synth-domain功能,它可以为你选择的任何IP/hostname范围提供定制的A/PTR。
--synth-domain=<domain>,<address range>[,<prefix>] |
通过这个特性,你不再需要单独地指定,或者限制到一个已经定义了域记录的单一子网,它允许你响应任何可能的IP地址或者hostname查询。amazon-linux
yum repo只提供了2.4.8版本,因此为了使用这个功能,你必须允许外部版本库或者从源代码编译。
使用SSH去连接新建立的服务器,并通过以下命令来建立开发工具(包括一个编译器):
[ec2-user ~]$ sudo yum –y groupinstall "Development Tools" |
将下述命令复制和粘贴到终端以下载一个最新的Dnsmasq源代码,untar、build并link回期望系统的sbin路径。
wget <a href="http://www.thekelleys.org.uk/dnsmasq/dnsmasq-2.72.tar.gz">
http://www.thekelleys.org.uk/dnsmasq/dnsmasq-2.72.tar.gz</a>gunzip dnsmasq-*.gz tar -xf dnsmasq-*.tar cd dnsmasq-2.72 sudo make install sudo ln -s /usr/local/sbin/dnsmasq /usr/sbin/dnsmasq |
使用命令行在监听器端口上开启一个DNS服务器,这个命令提供了整个VPC CIDR范围的解析。你的VPC
CIDR范围是10.20.30.0/24(这个在第一篇博文中获得)。服务器参数会转发那些不可以被默认AWS
DNS服务器解析的查询,详见 DHCP Options Sets一文。
sudo dnsmasq --interface=eth0 --listen-address=127.0.0.1 --synth-domain=hadoop.local,10.20.30.0/24,ip- --server=10.20.30.2 |
在VPC中一个独立的实例上测试到这个服务器上的查询将得到正确的返回。使用ip-hostname值对虚构实例发布一个nslookup查询。
现在,对这个地址发布相同的查找:
[ec2-user@ip-10-20-30-6 ~]$ nslookup ip-10-20-30-40.hadoop.local 10.20.30.5 Server: 10.20.30.5 Address: 10.20.30.5#53
Name: ip-10-20-30-40.hadoop.local
Address: 10.20.30.40 |
[ec2-user@ip-10-20-30-6 ~]$ nslookup 10.20.30.40 10.20.30.5 Server: 10.20.30.5 Address: 10.20.30.5#53
40.30.20.10.in-addr.arpa name = ip-10-20-30-40.hadoop.local |
两个都可以正常解析;现在需要测试的只有一个事情了。保证你可以为s3.amazonaws.com解析一个IP地址;对于解析公共DNS目录,这是一个不错的测试,特别是服务器端点。
[ec2-user@ip-10-20-30-6 ~]$ nslookup s3.amazonaws.com 10.20.30.5 Server: 10.20.30.5 Address: 10.20.30.5#53 Non-authoritative answer: s3.amazonaws.com canonical name = s3.a-geo.amazonaws.com. s3.a-geo.amazonaws.com canonical name = s3-2.amazonaws.com. Name: s3-2.amazonaws.com Address: 54.231.244.4 |
当下一切就绪,开启另一个wordcount作业测试。
aws emr create-cluster --bootstrap-actions Path= s3://support.elasticmapreduce/bootstrap-actions/other/sethostforvpc.sh --steps Type=STREAMING,Name='Streaming Program',ActionOnFailure=CONTINUE,Args=[-files,
s3://elasticmapreduce/samples/wordcount/wordSplitter.py,-mapper,wordSplitter.py,-reducer,aggregate,
-input,s3://elasticmapreduce/samples/wordcount/input,-output,
s3:///wordcount/output/] --ami-version 3.6.0 --instance-groups InstanceGroupType=MASTER,
InstanceCount=1,InstanceType=m3.xlarge InstanceGroupType=CORE,
InstanceCount=2,InstanceType=m3.xlarge --auto-terminate |
如果一切设置正确,你就可以在数分钟内成功的拥有一个集群。如果你的终止原因是“Steps completed”,一切都会如预期般的工作。
aws emr describe-cluster --cluster-id --query Cluster.Status.StateChangeReason.Message "Steps completed" |
如果你计划使用Route 53来解析主机记录,在这里你可以成功的终止一个DNSmasq;你不再需要任何其他操作。
aws ec2 terminate-instances --instance-ids i-22d6792f |
配置Route 53到你的私有域
本系列的最后一个教程是使用Route 53私有DNS域来支撑正方向域记录。如之前所述,在已存DNS服务器中会发生类似的问题;在未使用DHCP服务器情况下,我们无法填充host/address记录。为了让示例更加简单,我们使用了一个小的子网,并定义任何可能的地址。同时,我们使用了示例中介绍的BIND域,并让输入直接通往Route
53。
Route 53需求开启Dns Hostnames参数,如果在之前没有开启,你可以通过下述命令完成:
aws ec2 modify-vpc-attribute --vpc-id vpc-055ef660 --enable-dns-hostnames |
建立两个域,分别拥有正反向查找,同时确保为每个请求支持unique-caller-reference
值。
aws route53 create-hosted-zone --name hadoop.local --vpc VPCRegion=us-west-2,
VPCId=vpc-055ef660 --caller-reference Support01 |
记下返回的主机域ID。
"Id": "/hostedzone/Z34WMQP8SCULM7 " |
通过以下代码连接Route 53私有DNS域和VPC。
aws route53 associate-vpc-with-hosted-zone
--hosted-zone-id /hostedzone/Z34WMQP8SCULM7 --vpc VPCRegion=us-west-2,VPCId=vpc-055ef660 |
在反向域中执行相同的操作。
aws route53 associate-vpc-with-hosted-zone
--hosted-zone-id /hostedzone/Z1KTAQQMOLRO1Z --vpc VPCRegion=us-west-2,VPCId=vpc-055ef660 |
现在,从上述示例BIND服务器中导入域记录。在Route 53控制台,选择hadoop.local域,选择
Go to Record Sets、Import Zone File,随后粘贴域文件内容到Zone File。选择屏幕下方的Import。在30.20.10.in-addr.arpa域中执行相同的操作。
建立一个新的DHCP选项集,并将DNS服务器hadoop.local指向AmazonProvidedDNS,随后移除Dnsmasq示例使用的DNS服务器。
aws ec2 create-dhcp-options --dhcp-configurations Key=domain-name,Values=hadoop.local Key=domain-name-servers,Values=AmazonProvidedDNS |
记下新DHCP选项集ID。
{ "DhcpOptions": { "DhcpConfigurations": [ { "Values": [ { "Value": "hadoop.local" } ], "Key": "domain-name" }, { "Values": [ { "Value": "AmazonProvidedDNS" } ], "Key": "domain-name-servers" } ], "DhcpOptionsId": "dopt-936484f6" } } |
连接新选项集和VPC。
aws ec2 associate-dhcp-options --dhcp-options-id dopt-936484f6 --vpc-id vpc-055ef660 |
随后发布最终集群,并验证所做的工作。
确保你已经使用你自己的值替换了示例中使用的值,并且使用了你自己的输出地址,否则操作将失败。
aws emr create-cluster --bootstrap-actions Path= s3://support.elasticmapreduce/bootstrap-actions/other/sethostforvpc.sh --steps Type=STREAMING,Name='Streaming Program',ActionOnFailure=CONTINUE,Args=[-files,
s3://elasticmapreduce/samples/wordcount/wordSplitter.py,-mapper,wordSplitter.py,
-reducer,aggregate,-input,s3://elasticmapreduce/samples/wordcount/input,-output,
s3:///wordcount/output/] --ami-version 3.6.0 --instance-groups InstanceGroupType=MASTER,
InstanceCount=1,InstanceType=m3.xlarge InstanceGroupType=CORE,InstanceCount=2,
InstanceType=m3.xlarge --auto-terminate |
等待几分钟,并检查最终状态的变化原因:
aws emr describe-cluster --cluster-id j-2TEFHMDR3LXWD --query Cluster.Status.StateChangeReason.Message "Steps completed" |
注意:如果你期望避免所有DNS管理操作,你可以利用 bootstrap actions将集群主机名称改回默认值,并允许AWS服务管理所有事情。将下面的定制bootstrap
action加入集群:
s3://support.elasticmapreduce/bootstrap-actions/other/sethostforvpc.sh |
|