26

I have a cloudformation script that attempts to create a VPC, with one subnet per AZ.

When I run:

aws ec2 describe-availablity-zones

I get 4 zones returned:

"AvailabilityZones": [
    {
        "State": "available", 
        "RegionName": "us-east-1", 
        "Messages": [], 
        "ZoneName": "us-east-1a"
    }, 
    {
        "State": "available", 
        "RegionName": "us-east-1", 
        "Messages": [], 
        "ZoneName": "us-east-1b"
    }, 
    {
        "State": "available", 
        "RegionName": "us-east-1", 
        "Messages": [], 
        "ZoneName": "us-east-1c"
    }, 
    {
        "State": "available", 
        "RegionName": "us-east-1", 
        "Messages": [], 
        "ZoneName": "us-east-1d"
    }
 ]

However, when I try to create my stack, I get an error:

  "ResourceStatusReason": "Value (us-east-1a) for parameter availabilityZone
   is invalid. Subnets can currently only be created in the following 
   availability zones: us-east-1c, us-east-1b, us-east-1d.", 

I am specifying the AZ with

      "AvailabilityZone" : {
        "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]
      },

Is there a way to check to see if the AZ is really available for the creation of a subnet?

chris
  • 36,094
  • 53
  • 157
  • 237

4 Answers4

9

This may not be helpful for the CLI Approach or your exact scenario - but with AWS Management Console this works smooth.

With the recent updates with the CloudFormation Parameters, you would be able pin-point the AZs pertaining to the specified AZs.

This would be much convenient during the DR / DR Drills and making the CFN template Region Independent.

enter image description here

"Parameters": {
    "SubnetAZ": {
      "Description": "Availability Zone of the Subnet",
      "Type": "AWS::EC2::AvailabilityZone::Name"
    }
}

More Information About the CloudFormation Parameters

Naveen Vijay
  • 15,928
  • 7
  • 71
  • 92
  • 3
    Fn::GetAZs will provide the available and usable availability zones as long as you have a default vpc with a subnet in each AZ! which by the way all new aws accounts have as long as you don't delete them manually. – hellomichibye Nov 17 '16 at 15:07
  • @Naveen I think in your snippet you meant : `List` instead of `AWS::EC2::AvailabilityZone::Name` – Souad Feb 15 '17 at 13:43
6

Unfortunately I had the same problem. There is no method in CloudFormation to do this and the zones can be different per AWS account. This is a limitation of VPC infrastructure and it is likely not going to change. Your only option will be to hardcode the zones that you have found in your CloudFOrmation template instead of Fn::Select, for example:

"AvailabilityZone" : "us-east-1b"

Alternatively if you leave AvailabilityZone blank, the default behavior would be AWS will automatically pick one for you.

Arya
  • 2,135
  • 15
  • 13
  • Can't leave them blank because we are creating a VPC with subnets in each AZ - the problem is not every AZ that is returned allows subnets! – chris Jan 29 '14 at 22:11
  • So if one zone does not allow VPC subnets, what is the point of using it it you are hosting in VPC? Simply ignore that zone and deal with the 3 zones that support it. – Arya Jan 31 '14 at 14:03
  • That is a manual process - If I create subnets based on Fn::Select with index 0, 1 and 2 it will sometimes fail because there are actually 4 AZs, but not every one of them allows subnets – chris Jan 31 '14 at 20:02
  • You can supply it with the list of AZs instead of using Fn::GetAZs. If you want to make 3 different subnets, then define 3 distinct stack resources each referencing specific zone. – Arya Feb 03 '14 at 19:19
  • I actually tried that, but moving between accounts can cause it to fail - for example, we have a test account that has shown 1b, 1c and 1d, and when I run it in prod we have 1a, 1b and 1d. It's frustrating. – chris Feb 04 '14 at 21:57
  • agreed. I have the same problem. I maintain 3 copies, 1 for each account, for these kinds of things. I made the recommendation to CloudFormation team during a call, hopefully at some point they will implement it, but until then, I don't see another option for doing this with cfn. – Arya Feb 06 '14 at 02:13
  • 2
    The "solution" I have implemented is to use a Mapping for each of the accounts, with the truly available AZs as one of the values in the mapping. – scientastic Mar 17 '14 at 20:58
  • I have done something pretty similar to the above comment also. You could always do some logic prior to stack launch and inject params into the template. That seems a little bit bulky though. – David Dec 03 '15 at 11:33
  • You can also pick a previously automatically selected AZs with `{ "Fn::GetAtt" : [ "subnetPublicSubnetDefinition", "AvailabilityZone" ] }` ( [official documentation](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html)) – herve Mar 08 '16 at 14:18
  • Fn::GetAZs will provide the available and usable availability zones as long as you have a default vpc with a subnet in each AZ! which by the way all new aws accounts have as long as you don't delete them manually. – hellomichibye Nov 17 '16 at 15:07
5

Fn::GetAZs will provide the available and usable availability zones as long as you have a default vpc with a subnet in each AZ! which by the way all new aws accounts have as long as you don't delete them manually.

hellomichibye
  • 4,112
  • 2
  • 23
  • 23
-3

I get around the limitation by avoiding json as the medium of expression. I use troposphere to compose my cloudformation templates.(https://github.com/cloudtools/troposphere)

You would however would have to deploy some sort of tooling around the deployment of cloudformation templates to individual regions.