How to get Availability Zones in AWS CDK

avatar

Borislav Hadzhiev

Sat Apr 24 20214 min read

Updated on Sat Apr 24 2021

Getting the Availability Zones in CDK #

Every AWS Region consists of multiple Availability Zones. Usually when we provision resources we have to specify the region, and sometimes the availability zones, i.e. for an EC2 or RDS instances.

We provision resources in multiple availability zones to avoid for unexpected downtime in case of Availability Zone outages.

The code for this article is available on GitHub

In order to get the Availability Zones in CDK we have to use the availabilityZones property on the core Stack construct.

lib/cdk-starter-stack.ts
import * as cdk from '@aws-cdk/core'; export class MyCdkStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props: cdk.StackProps) { super(scope, id, props); // ๐Ÿ‘‡ get Availability Zones, Region, Account console.log('availability zones ๐Ÿ‘‰', cdk.Stack.of(this).availabilityZones); console.log('region ๐Ÿ‘‰', cdk.Stack.of(this).region); console.log('accountId ๐Ÿ‘‰', cdk.Stack.of(this).account); } } const app = new cdk.App(); new MyCdkStack(app, 'my-cdk-stack', { stackName: 'my-cdk-stack', // ๐Ÿ‘‡ Set the environment for the stack env: { region: process.env.CDK_DEFAULT_REGION, account: process.env.CDK_DEFAULT_ACCOUNT, }, });

In the code snippet:

  1. We have used the availabilityZones property on the Stack construct in order to get access to the availability zones of the region our CDK application is configured for

  2. We've set the env property when instantiating our CDK stack. This sets the environment (account, region), where our CDK stack will be deployed.

I'll run the synth command to execute my CDK code and print the values for the Availability Zones and region:

shell
npx cdk synth

The output shows all of the Availability Zones for my default region - eu-central-1:

azs region

However, there are a couple of caveats with setting environments in CDK.

Availability Zones Resolution in CDK #

Every CDK stack we deploy belongs to a specific region and account. If we don't explicitly set the region and account using the env property when instantiating the stack, the stack is considered environment agnostic:

To better illustrate this scenario I'll comment out the env prop I've passed to the stack upon instantiation:

lib/cdk-starter-stack.ts
import * as cdk from '@aws-cdk/core'; export class MyCdkStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props: cdk.StackProps) { super(scope, id, props); // ๐Ÿ‘‡ accessing the same values console.log('availability zones ๐Ÿ‘‰', cdk.Stack.of(this).availabilityZones); console.log('region ๐Ÿ‘‰', cdk.Stack.of(this).region); console.log('accountId ๐Ÿ‘‰', cdk.Stack.of(this).account); } } const app = new cdk.App(); new MyCdkStack(app, 'my-cdk-stack', { stackName: 'my-cdk-stack', // โŒ๏ธ NOT setting env // env: { // region: process.env.CDK_DEFAULT_REGION, // account: process.env.CDK_DEFAULT_ACCOUNT, // }, });

I'll now run the synth command to execute my CDK code and print the outputs:

shell
npx cdk synth

The result shows the values as Tokens:

token values

Tokens in CDK are encoded values that get resolved at deployment time by CloudFormation. This means we can't access the resolved version of these values in our CDK code, i.e. in conditional statements.

Environment-Agnostic Stacks #

The reason we're getting token values back is because we haven't set the env property upon stack instantiation, which makes our stack environment-agnostic.

Environment-agnostic stacks resolve the values of region, account and availability zones at deployment time, rather than synthesis time. Which means that we don't have access to the resolved values in our CDK code.

In the screenshot we can see only 2 Availability Zones, the reason being - there are AWS regions that only provide 2 availability zones and CDK doesn't know if we'll be deploying to one of them. The safe bet on CDK's part is to just allow us to use 2 Availability Zones.

The account and region in an environment-agnostic stack get resolved to the account and region of the profile we've set using the --profile flag, for example:

shell
npx cdk deploy --profile my-profile

If we don't explicitly set the --profile flag the account and region values are resolved to the default AWS CLI profile's account and region:

shell
npx cdk deploy

Best Practice - Explicitly set Env #

In order to get access to all of the Availability Zones of a region, the best practice is to explicitly specify the env property when instantiating a stack:

bin/cdk-starter.ts
const app = new cdk.App(); new MyCdkStack(app, 'my-cdk-stack', { stackName: 'my-cdk-stack', // ๐Ÿ‘‡ explicitly set Env env: { region: 'us-east-1', account: '123456789', }, });

By doing that we are able to set a consistent environment for our stack deployments, regardless of the machine we're deploying from.

Now we can access get access to all of the Availability Zones for the region our stack is configured for.

An alternative approach is to use the environment variables that CDK provides for us, i.e.:

bin/cdk-starter.ts
const app = new cdk.App(); new MyCdkStack(app, 'my-cdk-stack', { stackName: 'my-cdk-stack', // ๐Ÿ‘‡ Implicitly set env env: { region: process.env.CDK_DEFAULT_REGION, account: process.env.CDK_DEFAULT_ACCOUNT, }, });

The CDK_DEFAULT_REGION and CDK_DEFAULT_ACCOUNT environment variables are made available for us in the CDK environment. They resolve at synthesis time, which means we are able to access all of the Availability Zones for the region.

However, they rely on behavior specific to local machine configuration:

  • if we don't pass a --profile flag when issuing the deploy command these environment variables resolve at synthesis time, to our default AWS Profile's account and region.

  • if we provide the --profile flag, when deploying, the environment variables are set to the profile's account and region at synthesis time.

The problem with this behavior, is that local profile configuration may vary between your machine and the machines of other developers on your team, which might lead to deploying the cdk Stack to multiple accounts and regions.

Summary #

In order to access the availability zones of an AWS region we have to:

  • Set the env property when instantiating the CDK stack
  • use the availabilityZones property on the core Stack construct

Further Reading #

Add me on LinkedIn

I'm a Web Developer with TypeScript, React.js, Node.js and AWS experience.

Let's connect on LinkedIn

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee