Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to alias a domain name to an Elastic Beanstalk Environment using CloudFormation?

What is the correct Route 53 CloudFormation configuration to alias sub-domain names to an Elastic Beanstalk Environment ELBs?

I have copied the HostedZoneIds from the Amazon Route 53 Hosted Zone ID table to mappings:

"Beanstalk2Route53HostedZoneId" : {
  "us-east-1"      : { "HostedZoneId": "Z117KPS5GTRQ2G" },
  "us-west-1"      : { "HostedZoneId": "Z1LQECGX5PH1X" },
  "us-west-2"      : { "HostedZoneId": "Z38NKT9BP95V3O" },
  "eu-west-1"      : { "HostedZoneId": "Z2NYPWQ7DFZAZH" },
  "eu-central-1"   : { "HostedZoneId": "Z1FRNW7UH4DEZJ" },
  "ap-northeast-1" : { "HostedZoneId": "Z1R25G3KIG2GBW" },
  "ap-northeast-2" : { "HostedZoneId": "Z3JE5OI70TWKCP" },
  "ap-southeast-1" : { "HostedZoneId": "Z16FZ9L249IFLT" },
  "ap-southeast-2" : { "HostedZoneId": "Z2PCDNR3VC2G1N" },
  "sa-east-1"      : { "HostedZoneId": "Z10X7K2B4QSOFV" }
}

My resources have two Beanstalk Environments:

"MyBeanstalkConfig": {
  "Type": "AWS::ElasticBeanstalk::ConfigurationTemplate",
  "Properties": {
    "OptionSettings": {
      { "Namespace": "aws:elb:listener:80", "OptionName": "ListenerEnabled", "Value" : "false" },
      { "Namespace": "aws:elb:listener:443", "OptionName": "ListenerEnabled", "Value" : "true" },
      { "Namespace": "aws:elb:listener:443", "OptionName": "InstancePort", "Value" : "8081" },
      { "Namespace": "aws:elb:listener:443", "OptionName": "ListenerProtocol", "Value" : "HTTPS" },
      { "Namespace": "aws:elb:listener:443", "OptionName": "SSLCertificateId", "Value" : "arn:aws:iam::[accountNbr]:server-certificate/example-cert-name" },
      [...]
    }
  }
},

"MyStageBeanstalkEnv": {
  "Type": "AWS::ElasticBeanstalk::Environment",
  "Properties": {
    "Description": "Stage Environment",
    "TemplateName": { "Ref": "MyBeanstalkConfig" },
    [...]
  }
},

"MyProdBeanstalkEnv": {
  "Type": "AWS::ElasticBeanstalk::Environment",
  "Properties": {
    "Description": "Production Environment",
    "TemplateName": { "Ref": "MyBeanstalkConfig" },
    [...]
  }
},

Outputs:

"StageEndpoint" : {
  "Description" : "endpoint of the stage environment",
  "Value" : { "Fn::GetAtt" : [ "MyStageBeanstalkEnv", "EndpointURL" ] }
},
"ProdEndpoint" : {
  "Description" : "endpoint of the production environment",
  "Value" : { "Fn::GetAtt" : [ "MyProdBeanstalkEnv", "EndpointURL" ] }
}

Both the stage and the prod Beanstalk Environments are working, i.e. they respond to calls to MyStageBeanstalkEnv.eu-west-1.elasticbeanstalk.com as well as the endpoints returned by { "Fn::GetAtt" : [ "MyStageBeanstalkEnv", "EndpointURL" ] } (which look like awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com). Unsurprisingly, the cert is not valid since it expects the domain name to be either stage.example.com or prod.example.com.


Now I attempt to add Route 53 configuration:

"ExampleDomainHostedZone": {
  "Type" : "AWS::Route53::HostedZone",
  "Properties" : {
    "Name" : "example.com"
  }
},

"ExampleDomainRecordSetGroup" : {
  "Type" : "AWS::Route53::RecordSetGroup",
  "Properties" : {
    "HostedZoneId" : { "Ref": "ExampleDomainHostedZone" },
    "RecordSets" : [{
      "AliasTarget" : {
        "DNSName" : { "Fn::GetAtt" : ["MyStageBeanstalkEnv", "EndpointURL"] },
        "EvaluateTargetHealth" : false,
        "HostedZoneId" : { "Fn::FindInMap" : [ "Beanstalk2Route53HostedZoneId", {"Ref" : "AWS::Region"}, "HostedZoneId" ]}
      },
      "Name" : "stage.example.com",
      "Type": "A"
    },
    {
      "AliasTarget" : {
        "DNSName" : { "Fn::GetAtt" : ["MyProdBeanstalkEnv", "EndpointURL"] },
        "EvaluateTargetHealth" : false,
        "HostedZoneId" : { "Fn::FindInMap" : [ "Beanstalk2Route53HostedZoneId", {"Ref" : "AWS::Region"}, "HostedZoneId" ]}
      },
      "Name" : "prod.example.com",
      "Type": "A"
    }]
  }
},

When I attempt to update the CloudFormation stack I get the following error in the AWS console:

16:12:00 UTC+0200 CREATE_FAILED AWS::Route53::RecordSetGroup ExampleDomainRecordSetGroup Tried to create an alias that targets awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com., type A in zone Z2NYPWQ7DFZAZH, but the alias target name does not lie within the target zone

In this context, awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com is the same URL as provided by the Beanstalk ELB.


Comments:

  • I have successfully managed to setup Route 53 alias resource record to the same Beanstalk Environments in the AWS console following the description To add an alias resource record set in Amazon Route 53, so it is "just" a question about transferring these configuration steps to the CloudFormation template.
  • The stack is deployed in eu-west-1.
  • Instead of using the AWS::Route53::RecordSetGroup resource I have also tried to create two separate AWS::Route53::RecordSet resources, but the stack update failed with the same error.
like image 568
matsev Avatar asked May 03 '16 15:05

matsev


People also ask

How do Elastic Beanstalk and CloudFormation work together?

Elastic Beanstalk automatically handles the deployment, from capacity provisioning, load balancing, auto-scaling to application health monitoring based on the code you upload to it, where as CloudFormation is an automated provisioning engine designed to deploy entire cloud environments via a JSON script.

Does Elastic Beanstalk use CloudFormation?

CloudFormation supports Elastic Beanstalk application environments. This allows you, for example, to create and manage an AWS Elastic Beanstalk–hosted application along with an RDS database to store the application data.

How do I change my environment name on Elastic Beanstalk?

Open the Elastic Beanstalk console , and in the Regions list, select your AWS Region. In the navigation pane, choose Environments, and then choose the name of your environment from the list.


2 Answers

Some Googling hinted that (1, 2) the Amazon Route 53 Hosted Zone ID cannot be used when configuring alias. It is stated that eu-west-1 has the Hosted Zone ID Z2NYPWQ7DFZAZH for the elasticbeanstalk.eu-west-1.amazonaws.com endpoint. However, when double-checking the ELB configuration of what Beanstalk actually generated by using the AWS CLI I found that:

$ aws elb describe-load-balancers --region eu-west-1
{
    "LoadBalancerDescriptions": [
        {
            [...]
            "CanonicalHostedZoneNameID": "Z3NF1Z3NOM5OY2",
            "CanonicalHostedZoneName": "awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com",
        }
    ]
}

In other words, the hosted zone name id is different. Moreover, the CanonicalHostedZoneName is equal to the DNSName in the AliasTarget, i.e. awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com, which is not the same endpoint as elasticbeanstalk.eu-west-1.amazonaws.com used in Amazon Route 53 Hosted Zone ID. Consequently, I changed the mappings to include the CanonicalHostedZoneNameID provided from the CLI output:

"Beanstalk2Route53HostedZoneId" : {
  "eu-west-1" : { "HostedZoneId": "Z3NF1Z3NOM5OY2" }
}

Now the stack could be updated successfully. Regrettably only for eu-west-1, but the procedure can be updated if / when I deploy the stack to other regions.

After the stack was updated, there was still no response from the DNS names (stable.example.com and unstable.example.com). Updating Your Registrar's Name Servers solved that problem.

like image 169
matsev Avatar answered Sep 23 '22 11:09

matsev


I had same problem with Route53 Alias for CloudFront. I build HostedZOneId mapping but it never worked for me, by searching AWS documentation I find this:

The hosted zone ID.

For load balancers, use the canonical hosted zone ID of the load balancer.

For Amazon S3, use the hosted zone ID for your bucket's website endpoint.

For CloudFront, use Z2FDTNDATAQYW2.

For a list of hosted zone IDs of other services, see the relevant service in the AWS Regions and Endpoints.

So I just hard-coded it:

"AliasTarget": {
    "HostedZoneId": "Z2FDTNDATAQYW2",
    "DNSName": {
        "Fn::GetAtt": ["MyCloudFrontDistribution", "DomainName"]
    }
}

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html

like image 33
ADV-IT Avatar answered Sep 19 '22 11:09

ADV-IT