简体   繁体   English

Route 53 是否指向实例而不是 IP 或 CNAME?

[英]Have Route 53 point to an instance instead of an IP or CNAME?

We're using Route 53 DNS to point to an EC2 instance.我们使用 Route 53 DNS 指向一个 EC2 实例。 Is there any way to get Route 53 to point to the instance directly, instead of to an Elastic IP or CNAME?有没有办法让 Route 53 直接指向实例,而不是 Elastic IP 或 CNAME?

I have multiple reasons for this:我有多种原因:

  1. I don't want to burn an IP.我不想烧掉 IP。

  2. CNAMEs are unreliable, because if an instance goes down and comes back up, the full name, ec2-XXXX.compute-1.amazonaws.com, will change. CNAME 是不可靠的,因为如果一个实例关闭并重新启动,全名 ec2-XXXX.compute-1.amazonaws.com 将会改变。

  3. In the future, I need to spin up instances programmatically and address them with a subdomain, and I see no easy way to do this with either elastic IPs or CNAMEs.将来,我需要以编程方式启动实例并使用子域对它们进行寻址,而且我认为使用弹性 IP 或 CNAME 都没有简单的方法可以做到这一点。

What's the best approach?最好的方法是什么?

I wrote my own solution to this problem since I was unhappy with other approaches that were presented here.我自己写了这个问题的解决方案,因为我对这里介绍的其他方法不满意。 Using Amazon CLI tools is nice, but they IMHO tend to be slower than direct API calls using other Amazon API libraries (Ruby for example).使用 Amazon CLI 工具很好,但恕我直言,它们往往比使用其他 Amazon API 库(例如 Ruby)的直接 API 调用慢。

Here's a link to my AWS Route53 DNS instance update Gist.这是我的AWS Route53 DNS 实例更新要点的链接。 It contains an IAM policy and a Ruby script.它包含一个 IAM 策略和一个 Ruby 脚本。 You should create a new user in IAM panel, update it with the attached policy (with your zone id in it) and set the credentials and parameters in the Ruby script.您应该在 IAM 面板中创建一个新用户,使用附加策略(其中包含您的区域 ID)更新它,并在 Ruby 脚本中设置凭据和参数。 First parameter is the hostname alias for your instance in your hosted zone.第一个参数是您的实例在托管区域中的主机名别名。 Instance's private hostname is aliased to <hostname>.<domain> and instance's public hostname is aliased to <hostname>-public.<domain>实例的私有主机名别名为<hostname>.<domain> ,实例的公共主机名别名为<hostname>-public.<domain>

UPDATE : Here's a link to AWS Route53 DNS instance update init.d script registering hostnames when instance boots.更新:这是指向AWS Route53 DNS 实例更新 init.d 脚本的链接,该脚本在实例启动时注册主机名。 Here's another one if want to use AWS Route53 DNS load-balancing in similar fashion.如果想以类似的方式使用AWS Route53 DNS 负载平衡,这是另一个。

If you stick to using route53, you can make a script that updates the CNAME record for that instance everytime it reboots.如果你坚持使用 route53,你可以制作一个脚本,在每次重启时更新该实例的 CNAME 记录。

see this -> http://cantina.co/automated-dns-for-aws-instances-using-route-53/ (disclosure, i did not create this, though i used it as a jumping point for a similar situation)看到这个 - > http://cantina.co/automated-dns-for-aws-instances-using-route-53/ (披露,我没有创建这个,虽然我用它作为类似情况的跳跃点)

better yet, because you mentioned being able to spin up instances programmatically, this approach should guide you to that end.更好的是,因为您提到能够以编程方式启动实例,所以这种方法应该会指导您实现这一目标。

see also -> http://docs.pythonboto.org/en/latest/index.html另见 -> http://docs.pythonboto.org/en/latest/index.html

Using a combination of Cloudwatch, Route53 and Lambda is also an option if you host at a least part of your dns in Route53.如果您至少将 dns 的一部分托管在 Route53 中,则使用 Cloudwatch、Route53 和 Lambda 的组合也是一种选择。 The advantage of this is that you don't need any applications running on the instance itself.这样做的好处是您不需要在实例本身上运行任何应用程序。

To use this this approach you configure a Cloudwatch rule to trigger a Lambda function whenever the status of an EC2 instance changes to running.要使用此方法,您需要配置一个 Cloudwatch 规则,以在 EC2 实例的状态更改为运行时触发 Lambda function。 The Lambda function can then retrieve the public ip address of the instance and update the dns record in Route53.然后 Lambda function 可以检索实例的公共 ip 地址并更新 Route53 中的 dns 记录。

The Lambda could look something like this (using Node.js runtime): 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);
        });
    });
}

You will need to execute the Lambda with a role that has permissions to describe EC2 instances and update records in Route53.您将需要使用有权描述 EC2 实例和更新 Route53 中的记录的角色来执行 Lambda。

With Route 53 you can create alias records that map to an Elastic Load Balancer (ELB):使用 Route 53,您可以创建 map 到弹性负载均衡器 (ELB) 的别名记录:

http://docs.amazonwebservices.com/Route53/latest/DeveloperGuide/HowToAliasRRS.html http://docs.amazonwebservices.com/Route53/latest/DeveloperGuide/HowToAliasRRS.html

I've not tried on aws EC2 instance but it should work too.我没有尝试过 aws EC2 实例,但它也应该可以工作。 I've written a small Java program that detect the public IP of the machine and update a certain record on aws route 53.我写了一个小的 Java 程序来检测机器的公共 IP 并更新 aws 路由 53 上的特定记录。

The only requirement is that you need Java installed on your EC2 instance.唯一的要求是您需要在 EC2 实例上安装 Java。

The project is hosted on https://github.com/renatodelgaudio/awsroute53 and you are also free to modify it in case you need it项目托管在https://github.com/renatodelgaudio/awsroute53也可以自由修改以备不时之需

You could configure it to run at boot time or as a crontab job so that your record get updated with the new public IP following instructions similar to these Linux manual installation steps您可以将其配置为在启动时运行或作为 crontab 作业运行,以便按照类似于这些Linux 手动安装步骤的说明使用新的公共 IP 更新您的记录

I used this cli53 tool to let an EC2 instance create an A record for itself during startup.我使用这个 cli53 工具让 EC2 实例在启动期间为自己创建一个 A 记录。

https://github.com/barnybug/cli53 https://github.com/barnybug/cli53

I added file following lines to my rc.local (please check your linux calls this script during startup):我将以下几行文件添加到我的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

It creates an A record play.example.com pointing to the current public IP of the EC2 instance.它创建了一条A记录play.example.com指向EC2实例当前的public IP。

You need to assign a IAM role to EC2 instance, which allows the instance to manipulate Route 53. In the simplest case just create a IAM role using a predefined policy AmazonRoute53FullAccess .您需要为 EC2 实例分配一个 IAM 角色,这允许该实例操作 Route 53。在最简单的情况下,只需使用预定义策略AmazonRoute53FullAccess创建一个 IAM 角色。 Then assign this role to the EC2 instance.然后将此角色分配给 EC2 实例。

Assuming the EC2 instance has the aws command configured with proper permissions, the following shell script does it:假设 EC2 实例为aws命令配置了适当的权限,以下 shell 脚本会执行此操作:

#!/bin/bash
IP=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
PROFILE="dnsuserprofile"
ZONE="XXXXXXXXXXXXXXXXXXXXX"
DOMAIN="my.domain.name"
TMPFILE="/tmp/updateip.json"
cat << EOF > $TMPFILE
{
  "Comment": "Updating instance IP address",
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "$DOMAIN",
        "Type": "A",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": "$IP"
          }
        ]
      }
    }
  ]
}
EOF
aws route53 change-resource-record-sets --profile $PROFILE --hosted-zone-id $ZONE --change-batch file://$TMPFILE > /dev/null && \
rm $TMPFILE

Set that script to run on reboot, for example in cron:将该脚本设置为在重新启动时运行,例如在 cron 中:

@reboot /home/ec2-user/bin/updateip

The IAM policy can be as narrow as: IAM 政策可以缩小到:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "route53:ChangeResourceRecordSets",
            "Resource": "arn:aws:route53:::hostedzone/XXXXXXXXXXXXXXXXXXXXX"
        }
    ]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM