- LZ - Landing Zone
- CLZ - Cloud Landing Zone
- AWS - Amazon Web Services
Deploy a CLZ using Terraform.
I'll quote Wikipedia here, when they define a LZ as:
A landing zone (LZ) is an area where aircraft can land.
If we translate this to the IT we could rewrite it as:
A landing zone is IT infrastructure to deploy applications.
A CLZ helps users to setup an initial secure and scalable baseline environment using cloud providers design best practices. That environment allow user to quickly get started with a multi-account architecture, identity and access management, governance, data security, network design, and logging.
This solution was designed with simplicity and code cleanliness in mind. Because of that is good to have some knowledge on how is the code structured and what is the content code files type.
Is also very important to mention that this LZ approach is opinionated and is enforcing all CLZ deployed with it to follow those best practices, governance and security. Nevertheless at the end code is just code and everybody should feel free to customise it :)
Code is structured around two concepts Module
and Composition
:
A module is a group of connected resources inherently related to the CLZ. Each Module:
- Glue different Terraform resources (could be one or multiple)
- Abstract complexity
- Do one single task
- Is not executed by Terraform commands but called from a Composition
Composition is a collection of modules that describes a logical part of the CLZ product. Each composition is:
- Either global or region specific
- Executed once in case of the global or multiple times in case of regional
- Requires at least a persistent variables file in case of global based compositions and an additional region specific variables for regional compositions
Below there is a brief description of common files content separated by domain:
-
Environments
- prod (production)
- stg (staging)
- dev (development)
-
Composition
data.tf
:resources.tf
providers.tf
variables.tf
-
Module
resources.tf
outputs.tf
variables.tf
This solution is assuming that the new free Terraform Cloud Remote State Management service provided by Hashicorp is used. This is not mandatory by is strongly suggested to use remote state files and never keep it locally.
An additional solution using AWS S3 and Dynamo DB is also possible and will be added.
Following Hashicorp's best practices are following the rule of:
One Workspace Per Environment Per Terraform Configuration
Which translates to use a workspace name that reflects component
and environment
name.
i.e.: shared-services-dev, shared-services-stg, shared-services-prod
Naming convention is one of the main pillars of code consistency in Terraform, using the following rules will make Terraform code clean, consistent and easy to read as well as the final infrastructure objects easily identifiable.
The previously mentioned structure is used as main directory tree. We will differentiate what provider is used in every case as well as creating an additional organization layer for modules:
├── composition
│ └── <PROVIDER_NAME>
│ └── <COMPOSITION_NAME>
└── module
└── <PROVIDER_NAME>
└── <PRODUCT_NAME>
└── <PROVIDER_NAME>
Here's a directory example based on AWS only solution:
├── composition
│ └── aws
| ├── backup_solution
| ├── shared_services
│ └── 2_tier_app
└── module
└── aws
├── compute
│ ├── ec2
| └── lambda
├── database
| ├── rds
| └── dynamodb
└── identity
├── iam
└── certificate_manager
Here is the list of services for the three major Cloud providers:
Filesystem files are following the next rules:
- Directories are named singular
- Files are named plural
- Only use lower case letters and numbers
- Use the underscore symbol (_) in between words
- File names should be descriptive, such as:
data.tf
to define data sourceslocals.tf
to define local variablesmodules.tf
to define modulesresources.tf
to define resourcesvariables.tf
to define variablesproviders.tf
to define providersoutputs.tf
to define outputsvalues.tfvars
environment variables values
-
Variables should always have
type
anddescription
defined but never defaults, their values should be either explicitly specified or computed -
Do not repeat resource type in resource name:
resource "aws_vpc" "vpc" <- WRONG
instead use a domain descriptive name such as
public
,private
orthis
resource "aws_vpc" "this" <- RIGHT
-
Use singular names for resources
-
tags
is always present at the bottom of the resource definition -
count
andfor_each
are always located at the beginning of the resource definition. -
Use the same variable names, description and default as defined in "Argument Reference" section from the official documentation for the resource you are working on.
Before using Terraform please make sure you have the following installed and set up:
terraform init -backend-config=backend.config
terraform plan -var-file=values.local.tfvars
Terraform settings AWS Provider
MIT License
Copyright (c) 2019 Sergi Barroso
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.