我们使用 Route 53 DNS 指向 EC2 实例。有没有办法让 Route 53 直接指向实例,而不是指向弹性 IP 或 CNAME?
我有多个原因:
我不想烧一个IP。
CNAME 是不可靠的,因为如果一个实例宕机又恢复,全名 ec2-XXXX.compute-1.amazonaws.com 将会改变。
将来,我需要以编程方式启动实例并使用子域对其进行寻址,而且我认为使用弹性 IP 或 CNAME 都没有简单的方法来做到这一点。
最好的方法是什么?
我们使用 Route 53 DNS 指向 EC2 实例。有没有办法让 Route 53 直接指向实例,而不是指向弹性 IP 或 CNAME?
我有多个原因:
我不想烧一个IP。
CNAME 是不可靠的,因为如果一个实例宕机又恢复,全名 ec2-XXXX.compute-1.amazonaws.com 将会改变。
将来,我需要以编程方式启动实例并使用子域对其进行寻址,而且我认为使用弹性 IP 或 CNAME 都没有简单的方法来做到这一点。
最好的方法是什么?
我为这个问题编写了自己的解决方案,因为我对这里介绍的其他方法不满意。使用 Amazon CLI 工具很好,但恕我直言,它们往往比使用其他 Amazon API 库(例如 Ruby)的直接 API 调用慢。
这是我的AWS Route53 DNS 实例更新要点的链接。它包含一个 IAM 策略和一个 Ruby 脚本。您应该在 IAM 面板中创建一个新用户,使用附加的策略(其中包含您的区域 ID)对其进行更新,并在 Ruby 脚本中设置凭证和参数。第一个参数是托管区域中实例的主机名别名。实例的私有主机名别名为<hostname>.<domain>
,实例的公有主机名别名为<hostname>-public.<domain>
更新:这是AWS Route53 DNS 实例更新 init.d 脚本在实例启动时注册主机名的链接。如果想以类似的方式使用AWS Route53 DNS 负载平衡,这是另一个。
如果您坚持使用 route53,您可以编写一个脚本,在该实例每次重新启动时更新该实例的 CNAME 记录。
看到这个-> http://cantina.co/automated-dns-for-aws-instances-using-route-53/(披露,我没有创建这个,虽然我用它作为类似情况的跳跃点)
更好的是,因为您提到能够以编程方式启动实例,所以这种方法应该可以指导您实现这一目标。
如果您在 Route53 中托管至少部分 dns,则还可以选择结合使用 Cloudwatch、Route53 和 Lambda。这样做的好处是您不需要在实例本身上运行任何应用程序。
要使用此方法,您需要配置一条 Cloudwatch 规则,以便在 EC2 实例的状态更改为运行时触发 Lambda 函数。然后,Lambda 函数可以检索实例的公共 IP 地址并更新 Route53 中的 dns 记录。
Lambda 可能看起来像这样(使用 Node.js 运行时):
var AWS = require('aws-sdk');
var ZONE_ID = 'Z1L432432423';
var RECORD_NAME = 'testaws.domain.tld';
var INSTANCE_ID = 'i-423423ccqq';
exports.handler = (event, context, callback) => {
var retrieveIpAddressOfEc2Instance = function(instanceId, ipAddressCallback) {
var ec2 = new AWS.EC2();
var params = {
InstanceIds: [instanceId]
};
ec2.describeInstances(params, function(err, data) {
if (err) {
callback(err);
} else {
ipAddressCallback(data.Reservations[0].Instances[0].PublicIpAddress);
}
});
}
var updateARecord = function(zoneId, name, ip, updateARecordCallback) {
var route53 = new AWS.Route53();
var dnsParams = {
ChangeBatch: {
Changes: [
{
Action: "UPSERT",
ResourceRecordSet: {
Name: name,
ResourceRecords: [
{
Value: ip
}
],
TTL: 60,
Type: "A"
}
}
],
Comment: "updated by lambda"
},
HostedZoneId: zoneId
};
route53.changeResourceRecordSets(dnsParams, function(err, data) {
if (err) {
callback(err, data);
} else {
updateARecordCallback();
}
});
}
retrieveIpAddressOfEc2Instance(INSTANCE_ID, function(ip) {
updateARecord(ZONE_ID, RECORD_NAME, ip, function() {
callback(null, 'record updated with: ' + ip);
});
});
}
您将需要使用有权描述 EC2 实例和更新 Route53 中的记录的角色来执行 Lambda。
使用 Route 53,您可以创建映射到弹性负载均衡器 (ELB) 的别名记录:
http://docs.amazonwebservices.com/Route53/latest/DeveloperGuide/HowToAliasRRS.html
我没有尝试过 aws EC2 实例,但它也应该可以工作。我编写了一个小型 Java 程序,用于检测机器的公共 IP 并更新 aws route 53 上的某个记录。
唯一的要求是您需要在 EC2 实例上安装 Java。
该项目托管在https://github.com/renatodelgaudio/awsroute53上,如果需要,您也可以自由修改它
您可以将其配置为在启动时运行或作为 crontab 作业运行,以便按照类似于这些 Linux 手动安装步骤的说明使用新的公共 IP 更新您的记录
我使用这个 cli53 工具让 EC2 实例在启动期间为自己创建一条 A 记录。
https://github.com/barnybug/cli53
我在我的文件中添加了以下几行rc.local
(请检查您的 linux 在启动期间调用此脚本):
IP=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
/usr/local/bin/cli53 rrcreate example.com "play 30 A $IP" --wait --replace
它创建一个play.example.com
指向 EC2 实例当前公共 IP 的 A 记录。
您需要为 EC2 实例分配一个 IAM 角色,这允许该实例操作 Route 53。在最简单的情况下,只需使用预定义的策略创建一个 IAM 角色AmazonRoute53FullAccess
。然后将此角色分配给 EC2 实例。