Terraform

Terraform#

With Terraform, you can describe your infrastructure using a special declarative language.

The Terraform can manipulate different pieces of software with an API. Each piece of software managed by the Terraform is called a provider. A provider could be:

  • IaaS: AWS/Azure/GCP.

  • PaaS: K8s.

  • Specific software: Docker.

CLI#

To manipulate the terraform use special CLI. The basic commands are:

  • terraform init: to init the terraform directory.

  • terraform validate: to check if there are syntax mistakes in your terrform configuration.

  • terraform apply: to apply the configuration.

  • terraform destroy: to unroll the infrastructure.

For more details check the Terraform CLI Documentation.


The following cell defines a simple Terraform configuration that deploys an nginx image in the Docker runtime.

rm -rf /tmp/terraform
mkdir /tmp/terraform
cat << EOF > /tmp/terraform/main.tf
terraform {
  required_providers {
    docker = {
      source = "kreuzwerker/docker"
      version = "~> 3.0.1"
    }
  }
}

provider "docker" {}

resource "docker_image" "nginx" {
  name         = "nginx:latest"
  keep_locally = false
}

resource "docker_container" "nginx" {
  image = docker_image.nginx.image_id
  name  = "terraform_example"
  ports {
    internal = 80
    external = 8000
  }
}
EOF
cd /tmp/terraform

The following cell show the terrafrom initialisation outputs:

terraform init
Initializing the backend...
Initializing provider plugins...
- Finding kreuzwerker/docker versions matching "~> 3.0.1"...
- Installing kreuzwerker/docker v3.0.2...
- Installed kreuzwerker/docker v3.0.2 (self-signed, key ID BD080C4571C6104C)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://developer.hashicorp.com/terraform/cli/plugins/signing
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Special folders are created in the terraform directory:

ls -la
total 56
drwxrwxr-x  3 user user  4096 paź 29 07:44 .
drwxrwxrwt 22 root root 36864 paź 29 07:44 ..
-rw-rw-r--  1 user user   400 paź 29 07:44 main.tf
drwxr-xr-x  3 user user  4096 paź 29 07:44 .terraform
-rw-r--r--  1 user user  1337 paź 29 07:44 .terraform.lock.hcl

The validation:

terraform validate
Success! The configuration is valid.

The following code applies the configuration. The -auto-approve flag removes the terraform prompts to confirm that you want to apply the changes.

terraform apply -auto-approve &> /dev/null

The specified nginx container appeared in the docker runtime.

docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                  NAMES
4b2945deff80   9d0e6f6199dc   "/docker-entrypoint.…"   2 seconds ago   Up 2 seconds   0.0.0.0:8000->80/tcp   terraform_example

The following cell shows that after terraform destroy the container deployed by terraform disappered:

terraform destroy -auto-approve &> /dev/null
docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Configuration language#

Terraform configuration language operates with blocks. Generall block syntax is following:

<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
  # Block body
  <IDENTIFIER> = <EXPRESSION> # Argument
}

The most usefull block types are:

Block

Description

terraform

Configures settings related to the Terraform itself (e.g., backend, required providers, version).

provider

Defines the provider (e.g., AWS, GCP, Azure) and its configuration parameters.

resource

Declares infrastructure objects to be created or managed by Terraform.

data

Reads information from existing infrastructure or external sources.

variable

Defines input variables to parameterize configurations.

output

Exposes information about resources after deployment.

locals

Declares local variables for reuse within the configuration.

module

Reuses a set of Terraform configurations from local paths or remote sources.

backend

Defines where Terraform stores its state file (inside the terraform block).

provisioner

Runs scripts or commands on a resource after it is created or destroyed.

depends_on

Explicitly defines dependencies between resources or modules.

For more details check:

Providers#

Provider is a piece of software that allows the terraform to interact with some tools. Check the list of official providres.

The following table list the most popular terraform providers:

Provider

Description

aws

Manages resources on Amazon Web Services (EC2, S3, RDS, IAM, etc.).

azurerm

Manages Microsoft Azure resources (VMs, Storage, Networking, etc.).

google

Manages Google Cloud Platform resources (Compute, Storage, IAM, etc.).

kubernetes

Manages Kubernetes clusters and resources (Pods, Deployments, Services, etc.).

helm

Manages Helm charts within Kubernetes clusters.

docker

Manages Docker images, containers, and networks.

vault

Manages HashiCorp Vault secrets and policies.

github

Manages GitHub repositories, teams, and workflows.

gitlab

Manages GitLab projects, users, and CI/CD pipelines.

cloudflare

Manages Cloudflare DNS, firewall, and CDN configurations.

datadog

Manages Datadog monitors, dashboards, and integrations.

newrelic

Manages New Relic alerts, dashboards, and integrations.

postgresql

Manages PostgreSQL databases, roles, and permissions.

random

Generates random strings, IDs, or numbers for use in Terraform configs.

null

Provides null resources for running local scripts or defining dependencies.