Create Atmos Stacks
In the previous step, we've configured the Terraform components and described how they can be vendored into the repository.
Next step is to create and configure Atmos stacks.
Create Catalog for Components
Atmos supports the Catalog pattern to configure default settings for Atmos components.
All the common default settings for each Atmos component should be in a separate file in the stacks/catalog directory.
The file then gets imported into the parent Atmos stacks.
This makes the stack configurations DRY by reusing the component's config that is common for all environments.
Refer to Stack Imports for more details on Atmos imports.
In the stacks/catalog/vpc-flow-logs-bucket/defaults.yaml file, add the following manifest for the vpc-flow-logs-bucket Atmos component:
stacks/catalog/vpc-flow-logs-bucket/defaults.yaml
In the stacks/catalog/vpc/defaults.yaml file, add the following manifest for the vpc Atmos component:
stacks/catalog/vpc.yaml
In the stacks/catalog/vpc/ue2.yaml file, add the following manifest for the vpc Atmos component:
stacks/catalog/vpc/ue2.yaml
In the stacks/catalog/vpc/uw2.yaml file, add the following manifest for the vpc Atmos component:
stacks/catalog/vpc/uw2.yaml
In the stacks/catalog/vpc/dev.yaml file, add the following manifest for the vpc Atmos component:
stacks/catalog/vpc/dev.yaml
In the stacks/catalog/vpc/staging.yaml file, add the following manifest for the vpc Atmos component:
stacks/catalog/vpc/staging.yaml
In the stacks/catalog/vpc/prod.yaml file, add the following manifest for the vpc Atmos component:
stacks/catalog/vpc/prod.yaml
These Atmos component manifests will be imported into the top-level Atmos stacks. The default variables (in the vars sections)
can be overridden in the derived Atmos components by using Atmos Component Inheritance.
Atmos Top-level Stacks
When executing the CLI commands, Atmos does not use the stack file names and their filesystem locations to search for the stack
where the component is defined. Instead, Atmos uses the context variables (namespace, tenant, environment, stage) to search for the stack. The
stack config file names (stack manifest names) can be anything, and they can be in any folder in any sub-folder in the stacks directory.
For example, when executing the atmos terraform apply vpc -s plat-ue2-dev
command, the Atmos stack plat-ue2-dev is specified by the -s flag. By looking at name_pattern: "{tenant}-{environment}-{stage}"
(see Configure CLI) and processing the tokens, Atmos knows that the first part of the stack name is tenant, the second
part is environment, and the third part is stage. Then Atmos searches for the top-level stack manifest (in the stacks directory)
where tenant: plat, environment: ue2 and stage: dev are defined (inline or via imports).
Atmos top-level stacks can be configured using a Basic Layout or a Hierarchical Layout.
The Basic Layout can be used when you have a very simple configuration using just a few accounts and regions. The Hierarchical Layout should be used when you have a very complex organization, for example, with many AWS Organizational Units (which Atmos refers to as tenants) and dozens of AWS accounts and regions.
Basic Layout
A basic form of stack organization is to follow the pattern of naming where each $environment-$stage.yaml is a file. This works well until you have
so many environments and stages.
For example, $environment might be ue2 (for us-east-2) and $stage might be prod which would result in stacks/ue2-prod.yaml
Some resources, however, are global in scope. For example, Route53 and IAM might not make sense to tie to a region. These are what we call "global
resources". You might want to put these into a file like stacks/global-region.yaml to connote that they are not tied to any particular region.
In our example, the filesystem layout for the stacks Basic Layout using dev, staging and prod accounts and us-east-2 and us-west-2 regions
would look like this:
infra-live/
Hierarchical Layout
We recommend using a hierarchical layout that follows the way AWS thinks about infrastructure. This works very well when you may have dozens or hundreds of accounts and regions that you operate in.
Create Top-level Stacks
Although in this Quick Start guide we use just a few Terraform components which we want to provision into three AWS accounts in just two AWS regions (which could be considered basic), we will use the Hierarchical Layout to show how the Atmos stacks can be configured for very complex organizations and infrastructures.
We will assume we are using just one Organization acme and just one AWS Organizational Unit (OU) plat. But as you will notice, the layout
can be easily extended to support many AWS Organizations and Organizational Units.
Create the following filesystem layout (which will be the final layout for this Quick Start guide):
infra-live/
Configure Region and Stage Mixins
Mixins are a special kind of "import". It's simply a convention we recommend to distribute reusable snippets of configuration that alter the behavior in some deliberate way. Mixins are not handled in any special way. They are technically identical to all other imports.
In stacks/mixins/tenant/core.yaml, add the following config:
stacks/mixins/tenant/core.yaml
In stacks/mixins/tenant/plat.yaml, add the following config:
stacks/mixins/tenant/plat.yaml
In stacks/mixins/region/us-east-2.yaml, add the following config:
stacks/mixins/region/us-east-2.yaml
In stacks/mixins/region/us-west-2.yaml, add the following config:
stacks/mixins/region/us-west-2.yaml
In stacks/mixins/stage/dev.yaml, add the following config:
stacks/mixins/stage/dev.yaml
In stacks/mixins/stage/prod.yaml, add the following config:
stacks/mixins/stage/prod.yaml
In stacks/mixins/stage/staging.yaml, add the following config:
stacks/mixins/stage/staging.yaml
As we can see, in the tenant, region and stage mixins, besides some other common variables, we are defining the global context
variables tenant, environment and stage, which Atmos uses when searching for a component in a stack. These mixins then get imported into the
parent Atmos stacks without defining the context variables in each top-level stack, making the configuration DRY.
Configure Defaults for Organization, OU and accounts
The _defaults.yaml stack manifests contain the default settings for the Organization(s), Organizational Units, and accounts.
The _defaults.yaml stack manifests are not imported into other Atmos manifests automatically.
You need to explicitly import them using imports.
In stacks/orgs/acme/_defaults.yaml, add the following config:
stacks/orgs/acme/_defaults.yaml
The file defines the context variable namespace for the entire acme Organization.
In stacks/orgs/acme/core/_defaults.yaml, add the following config for the core OU (tenant):
stacks/orgs/acme/core/_defaults.yaml
In stacks/orgs/acme/plat/_defaults.yaml, add the following config for the plat OU (tenant):
stacks/orgs/acme/plat/_defaults.yaml
In the stacks/orgs/acme/plat/_defaults.yaml file, we import the defaults for the Organization and for the plat tenant (which
corresponds to the plat Organizational Unit). When Atmos processes this stack config, it will import and deep-merge all the variables defined in the
imported files and inline. All imports are processed in the order they are defined.
In stacks/orgs/acme/plat/dev/_defaults.yaml, add the following config for the dev account:
stacks/orgs/acme/plat/dev/_defaults.yaml
In the file, we import the mixin for the plat tenant (which, as was described above, imports the defaults for the Organization), and then the mixin
for the dev account (which defines stage: dev variable). After processing all these imports, Atmos determines the values for the three context
variables namespace, tenant and stage, which it then sends to the Terraform components as Terraform variables. We are using hierarchical imports
here.
Similar to the dev account, add the following configs for the prod and staging accounts:
stacks/orgs/acme/plat/prod/_defaults.yaml
stacks/orgs/acme/plat/staging/_defaults.yaml
Configure Top-level Stacks
After we've configured the catalog for the components, the mixins for the tenants, regions and stages, and the defaults for the Organization, OU and accounts, the final step is to configure the Atmos root (top-level) stacks and the Atmos components in the stacks.
In stacks/orgs/acme/plat/dev/us-east-2.yaml, add the following config:
stacks/orgs/acme/plat/dev/us-east-2.yaml
In the file, we import the region mixin and the defaults for the Organization, OU and account (using hierarchical imports).
Similarly, create the top-level Atmos stack for the dev account in us-west-2 region:
stacks/orgs/acme/plat/dev/us-west-2.yaml
In stacks/orgs/acme/plat/staging/us-east-2.yaml, add the following config:
stacks/orgs/acme/plat/staging/us-east-2.yaml
Similarly, create the top-level Atmos stack for the staging account in us-west-2 region:
stacks/orgs/acme/plat/staging/us-west-2.yaml
In stacks/orgs/acme/plat/prod/us-east-2.yaml, add the following config:
stacks/orgs/acme/plat/prod/us-east-2.yaml
In the file, we import the region mixin and the defaults for the Organization, OU and account (using hierarchical imports).
Similarly, create the top-level Atmos stack for the prod account in us-west-2 region: