2

Java 8 using the AWS Java SDK here. I have a private hosted zone (PHZ) of, say, myapp.example.com and I have an A record in that zone called db.myapp.example.com which points to an RDS instance.

I am now writing a Lambda (Java) that will create a new RDS instance, and update the db.myapp.example.com zone record to point to the new RDS instance.

So far the gist of my code looks like this:

CreateDBInstanceRequest createDbRequest = getSomehow();
DBInstance rdsInstance = amazonRDS.createDBInstance(createDbRequest);

ListHostedZonesResult hostedZonesResult = amazonRoute53.listHostedZones();
Optional<HostedZone> hostedZoneOpt = hostedZonesResult.getHostedZones().stream()
    .filter(zone -> "db.myapp.example.com".equals(zone.getName())).findFirst();
if (hostedZoneOpt.isPresent()) {

    // TODO: how to update the record so that it points to 'rdsInstance'?
    ResourceRecordSet alias = new ResourceRecordSet(aliasName, "A");
    
    Change updateAlias = new Change(ChangeAction.UPSERT, alias);
    List<Change> changes = Collections.singletonList(updateAlias);
    ChangeBatch changeBatch = new ChangeBatch(changes);

    ChangeResourceRecordSetsRequest changeRecordRequest =
        new ChangeResourceRecordSetsRequest(hostedZoneOpt.get().getId(), changeBatch);
    amazonRoute53.changeResourceRecordSets(changeRecordRequest);
    
} else {
  // handle
}

I think this is correct for the most part. However, after scouring the Route53 SDK API docs I cannot for the life of me figure out how/where I configure the alias : ResourceRecordSet instance with the new RDS (rdsInstance) info so that db.myapp.example.com now points to it.

Any ideas? Thanks in advance!

Update

I see there is the concept of TrafficPolicy in Route53 and apparently I can send a JSON document to AWS and configure a traffic policy for my A record, so maybe this is the correct way to go. But looking at the Traffic Policy document definition, I need to be able to specify an IP address in its Value field, and I don't believe the AWS SDK exposes IP addresses anywhere!

hotmeatballsoup
  • 385
  • 6
  • 58
  • 136
  • Looks like you can `new` up a `ResourceRecordSet`, then call [`setAliasTarget`](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/route53/model/ResourceRecordSet.html#setAliasTarget-com.amazonaws.services.route53.model.AliasTarget-) to point it to the DNS name of your RDS instance. Does that work? – DylanSp Mar 08 '21 at 18:08
  • Actually, looking more closely at the docs for Route 53 aliasing, I'm not sure if you can create an alias for RDS instances. Where do you see that you can do that (vs. just creating a CNAME that points to the RDS instance's domain name)? – DylanSp Mar 08 '21 at 18:11
  • Hi @DylanSp, thanks. I'm trying to create a DNS endpoint that won't change so that I can _switch out_ RDS instances underneath it, without forcing applications (that use the DB) to update their connection strings. My inspiration for taking this route is from [this answer](https://stackoverflow.com/a/66502128/5235665). Its possible I misunderstood that answer, or that it was wrong, but thats the motivation for me going this method. Thanks again! – hotmeatballsoup Mar 08 '21 at 18:21
  • I think a CNAME will do the trick for you. Writing up an answer now. – DylanSp Mar 08 '21 at 18:28

2 Answers2

2

Per the AWS docs on alias routing, you can't create an alias DNS record pointing to an RDS instance. What you can do, however, is create a regular CNAME record in Route 53, pointing to the RDS instance's domain name. Your record would have type CNAME, Name db.myapp.example.com, and the Value would be the RDS instance's domain name, i.e. some-instance.cxu5ec943k5u.us-east-1.rds.amazonaws.com. You can get this from rdsInstance.getEndpoint().getAddress().

DylanSp
  • 1,379
  • 13
  • 27
  • Thanks again @Dylan (+1), but here's the scary question, how could I (using the SDK) find the "`some-instance.cxu5ec943k5u.us-east-1.rds.amazonaws.com`" instance name? – hotmeatballsoup Mar 08 '21 at 18:44
  • The only thing available via `DBInstance` is `getInstanceIdentifier()` which does not return domain info, it returns a string that you can optionally set when creating the instance. – hotmeatballsoup Mar 08 '21 at 18:45
  • 1
    Edited info on that into the answer, see the last line. – DylanSp Mar 08 '21 at 19:07
  • Thank you @DylanSp (+1) -- i will absolutely reward you with the green check and bounty as soon as SO allows me to! In the meantime, can I ask, why the CNAME would work and not an A record? – hotmeatballsoup Mar 08 '21 at 19:54
  • Glad it works! As the other answer states, A records in general only point to IP addresses; AWS extends this to aliasing certain resources, like ALBs and S3 buckets, but not RDS instances. – DylanSp Mar 08 '21 at 20:09
2

Generally speaking, DNS A records can only point to IP addresses (or in the case of Route 53, to AWS aliases for certain AWS resources - not including RDS). CNAME records can point to other subdomains (including RDS instance's domain name).

johnmgn
  • 52
  • 1