Infrastructure as Code
Terraform, Ansible and CloudFormation side by side: the commands and the file shapes you use again and again.
Terraform workflow
terraform initDownload providers and set up the backend (once per folder, and after changes to them)
terraform fmt -recursive && terraform validateTidy the formatting and check the syntax
terraform plan -out=tfplanShow what would change, and save that plan
terraform apply tfplanMake exactly that plan happen
terraform destroyDelete everything this configuration manages
terraform output | terraform output -raw nameShow the output values
Terraform language
variable "env" { type = string default = "dev" validation { condition = contains(["dev", "prod"], var.env) error_message = "env must be dev or prod." } }An input with a type, a default and a rule
variable "db_password" { type = string sensitive = true }A secret input: no default, hidden in output
locals { name = "${var.env}-app" }A named value computed once (use local.name)
resource "aws_s3_bucket" "assets" { bucket = local.name }A resource: type, local name and arguments
output "bucket" { value = aws_s3_bucket.assets.bucket }A value to show after apply
terraform apply -var="env=prod" | -var-file=prod.tfvarsSet inputs on the command line or from a file
Terraform: loops, modules, state
for_each = toset(["a", "b"]) bucket = "${var.env}-${each.key}"One resource per item; keys keep their identity when the list changes
count = var.enabled ? 1 : 0Create a resource only when a condition holds
module "site" { source = "./modules/bucket" name = "docs" }Reuse a folder of configuration as a module
lifecycle { prevent_destroy = true ignore_changes = [tags] }Protect a resource, or ignore changes made elsewhere
moved { from = aws_s3_bucket.old to = aws_s3_bucket.assets }Rename in code without destroying and recreating
terraform state list | terraform state show aws_s3_bucket.assetsSee what Terraform tracks, and one resource in detail
terraform import aws_s3_bucket.assets my-existing-bucketBring an existing resource under Terraform
.gitignore: .terraform/ *.tfstate *.tfstate.*Keep state and caches out of Git (use a remote backend for state)
Ansible: inventory and commands
[web] web1 ansible_host=10.0.0.11 web2 ansible_host=10.0.0.12 [prod:children] web [web:vars] ansible_user=deployAn INI inventory with a group of groups and group variables
ansible all -i inventory.ini -m pingCan Ansible log in to every host?
ansible web -i inventory.ini -m command -a "uptime"Run one command on a group
ansible-inventory -i inventory.ini --graphSee how hosts and groups fit together
ansible-playbook -i inventory.ini site.yml --check --diffA dry run that shows the differences
ansible-playbook -i inventory.ini site.yml --limit web1 --tags configRun only part of a playbook, or only some hosts
Ansible: playbooks and roles
- name: Web servers hosts: web become: true tasks: - name: Install nginx ansible.builtin.package: name: nginx state: presentA play with a task
- name: Config ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/conf.d/app.conf notify: restart nginxFill a template, and notify a handler when the file changed
handlers: - name: restart nginx ansible.builtin.service: name: nginx state: restartedA handler runs once, only if notified
loop: [git, curl] when: ansible_os_family == "Debian"Repeat a task, and run it only under a condition
- name: Init database ansible.builtin.command: /usr/local/bin/init-db.sh args: creates: /var/lib/app/.initializedKeep a command idempotent with creates
roles/web/{tasks,handlers,defaults,templates}/main.ymlThe folders of a role; roles: [web] in a play uses it
ansible-vault encrypt_string "s3cret" --name db_passwordEncrypt one value to keep in a variables file
CloudFormation
aws cloudformation deploy --template-file template.yaml --stack-name app --parameter-overrides Env=prodCreate the stack, or update it if it exists
aws cloudformation describe-stacks --stack-name app --query "Stacks[0].Outputs"Read the outputs of a stack
aws cloudformation list-stack-resources --stack-name appWhat the stack created
aws cloudformation validate-template --template-body file://template.yamlCheck a template
aws cloudformation delete-stack --stack-name appDelete the stack and what it created
Parameters: Env: { Type: String, Default: dev } Resources: Assets: Type: AWS::S3::Bucket Properties: BucketName: !Sub "debo-${Env}-assets" Outputs: Bucket: Value: !Ref AssetsA template with a parameter, a bucket and an output
!Ref Name !Sub "text-${Name}" !GetAtt Res.Arn !Join ["-", [a, b]]The intrinsic functions you use most
Nothing matches that search.
Cheatsheet for the Infrastructure as Code path · Deboistech · All cheatsheets