Skip to content

Instantly share code, notes, and snippets.

@sasajib
Last active October 18, 2023 19:10
Show Gist options
  • Save sasajib/fb9e4ab44a42c9345e500925841cdb4d to your computer and use it in GitHub Desktop.
Save sasajib/fb9e4ab44a42c9345e500925841cdb4d to your computer and use it in GitHub Desktop.

terraform illustration

Introduction

Terraform is primarily known and used as an "infrastructure as code" (IaC) tool, and it excels in that specific domain. Its role and usage can be broken down into several key areas:

  1. Infrastructure Provisioning: Terraform's main strength is provisioning infrastructure. This means using code to create, modify, and destroy the physical (e.g., servers, networks) or virtual (e.g., VMs) resources that your applications need to run. It can do this across cloud providers (like AWS, Google Cloud, Azure) or on-premises (via VMware, OpenStack).

  2. Platform Agnostic: One of Terraform's major benefits is that it allows you to manage infrastructure across different cloud providers, using the same language and similar concepts. This prevents vendor lock-in and promotes reusable practices.

  3. State Management: Terraform tracks the current state of the infrastructure it manages (using a file known as the state file), allowing it to create plans to adjust infrastructure from its current state to the desired state. This is key in understanding the impact of a change before applying it, avoiding costly mistakes.

  4. Declarative Configuration: You describe your desired infrastructure setup, and Terraform figures out how to get there. This is the essence of declarative programming: you specify what you want, and the tool determines the series of steps needed to achieve that state.

  5. Modularity and Reusability: Terraform configurations can be modularized, allowing the reuse of your configurations or the establishment of standards for infrastructures. These modules can be used across different projects but maintain the same level of configuration.

  6. Collaboration and Sharing: With features that integrate with HashiCorp's Terraform Cloud, teams can collaborate on infrastructure updates and maintain versioning of infrastructure changes using VCS (Version Control Systems) integrations. It helps maintain consistency and control in team environments.

While Terraform handles the provisioning of infrastructure very well, it's not designed to manage the configuration of individual machines or the software on those machines. That's where configuration management tools like Ansible, Chef, or Puppet come in. They are designed to install software, manage configurations, and ensure the internal state of servers remains consistent over time.

In a typical use case, you might use Terraform to provision a new cloud environment (like an AWS EC2 instance) and then use Ansible to configure the servers (installing required software, setting up files, etc.). By combining these tools, you can create a robust system for managing both the infrastructure itself and the software/configuration state of the servers within that infrastructure.

Examples

Let's walk through a basic example, where we will create an AWS S3 bucket. (Note: You'll need an AWS account and AWS Access Credentials).

Credential Setup

  • Set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables with your credentials.
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"

OR

provider "aws" {
  region     = "us-west-2"
  access_key = "your-access-key"
  secret_key = "your-secret-key"
}

Example 1

  1. Set up Terraform configuration file: Create a file named main.tf and add the following configuration:
provider "aws" {
  region = "us-west-2"
  ...
}

resource "aws_s3_bucket" "my_bucket" {
  bucket = "my-unique-s3-bucketname"
  acl    = "private"
}

In this example, we're setting up an AWS provider and creating a new S3 bucket resource. Replace "my-unique-s3-bucketname" with a unique bucket name.

  1. Initialize Terraform: Run the command terraform init. Terraform will initialize the working directory and install the necessary plugins.

  2. Plan the deployment: Run terraform plan. Terraform will perform a dry run to show you what changes it will make to your infrastructure.

  3. Apply the changes: Run terraform apply. Terraform will prompt you to confirm that you want to perform the actions described in your plan. Type yes to confirm and proceed.

  4. Clean up resources: Once you no longer need the resources, you can run terraform destroy to remove the infrastructure you set up. This step is especially important if you're working in a cloud environment to avoid incurring unnecessary charges.

Example2

Another basic example, where we will configuring Docker and Docker Compose on a remote server. Using Terraform involves several steps. Terraform will help you provision the remote server but doesn't directly install software on it. For that, you'll need to use a provisioner that can run commands on the remote machine after it's created.

Here's how you can achieve it:

1. Prerequisites:

  • Terraform installed on your local machine.
  • SSH access to your server (1.2.3.4).
  • Your server running an OS that supports Docker (e.g., Ubuntu).
  • Necessary permissions to execute scripts and install packages on the server.

2. Set Up Terraform Configuration:

  • Create a new directory for your Terraform configuration and navigate into it.
  • Create a new file named main.tf and open it in a text editor.

3. Configure Terraform to use SSH: We will use Terraform’s connection block to specify SSH connection details, and a provisioner block to specify the actions (commands) we want to execute on the remote resource.

Here’s how you can set it up in your main.tf:

resource "null_resource" "install_docker" {
  # Changes to any instance of the cluster requires re-provisioning
  triggers = {
    cluster_instance_ids = "1.2.3.4"
  }

  connection {
    type        = "ssh"
    host        = "1.2.3.4" # Your server's IP
    user        = "your-ssh-username"
    private_key = file("/path/to/your/private/key.pem")
    # Alternatively, use the password parameter if you use a password to SSH
    # password = "your-ssh-password"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common",
      "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -",
      "sudo add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\"",
      "sudo apt-get update",
      "sudo apt-get install -y docker-ce",
      "sudo systemctl status docker --no-pager", # Optional: Check Docker status
      "sudo curl -L \"https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)\" -o /usr/local/bin/docker-compose", # Download Docker Compose. Note: Check the release page for the latest version.
      "sudo chmod +x /usr/local/bin/docker-compose",
      "docker-compose --version" # Optional: Verify the installed Docker Compose version
    ]
  }
}

4. Initialize Terraform: Run terraform init in your terminal. Terraform will initialize the working directory.

5. Apply the Configuration:

  • Run terraform apply. Terraform will show an execution plan. Review it.
  • Confirm the actions by typing yes. Terraform will establish an SSH connection to the server and run the specified commands.

Note: The null_resource is a special type of resource used to execute arbitrary commands. It's useful for actions that don't fit into standard Terraform resources. The provisioner section includes the commands to install Docker and Docker Compose. These commands are specific to Ubuntu, so you might need to adjust them for other operating systems.

Remember, this approach directly executes shell commands on your server, which might not be the most secure or reliable method for production environments. For a more resilient setup, consider using a configuration management tool like Ansible, Chef, or Puppet in combination with Terraform to handle software installation and configuration.

Differences

Terraform, Ansible, Chef, and Puppet serve different (though sometimes overlapping) roles in infrastructure management and configuration. Here's a comparative look at them across various dimensions:

Criterion Terraform Ansible Chef Puppet
Primary Function Infrastructure as Code (IaC) tool primarily used for provisioning and managing cloud infrastructure. Configuration management tool designed for deploying and updating applications alongside systems orchestration. Configuration management tool focused on automating infrastructure deployment and maintaining consistency. Configuration management tool specializing in declarative automation and enforcing the desired system configuration.
Management Style Declarative: You define the desired state, and Terraform creates a plan to reach that state. Imperative (though it supports declarative status): You define tasks in playbooks, and Ansible executes the commands. Declarative: You define the desired state with "recipes," and Chef ensures the system reaches that state. Declarative: You declare configurations in "manifests," and Puppet applies the necessary changes to achieve the desired state.
Language HashiCorp Configuration Language (HCL) YAML for playbooks (task definitions), Jinja2 for templating. Ruby for writing configurations (recipes). Puppet's custom declarative language, and Ruby for more complex tasks.
Agent Agentless: It directly interacts with the APIs of service providers. Agentless: It connects via SSH or WinRM and doesn’t require agents on remote systems. Requires an agent (Chef-client) installed on each managed node. Requires an agent (Puppet agent) installed on each node, communicating with the Puppet master.
Master Server Not necessary: Terraform runs on your local machine and communicates directly with the cloud provider. Not necessary: Ansible pushes configurations from a control machine. Chef-server is necessary for storing your cookbooks and the overall state of your network. Puppet master server is required, acting as a central control point and source of configuration data.
Setup Complexity Relatively simple setup, especially for cloud-based setups. Terraform files are straightforward to understand and use. Minimal setup complexity. Easy to get started, especially for ad-hoc commands and small-scale configurations. Somewhat complex, particularly with setting up the Chef-server and attaching nodes. Requires understanding of Ruby. More complex initial setup, especially with master-agent architecture. Requires understanding of Puppet's DSL for complex configurations.
Use Case Scenarios Best for building, changing, and versioning infrastructure safely and efficiently. Ideal for multi-cloud scenarios due to its provider-agnostic design. Suited for multi-tier deployments, on-the-fly configurations, and system orchestration tasks. Can be used for cloud provisioning but isn’t its primary strength. Ideal for organizations looking for robust management, particularly those with strong coding capabilities as it allows for greater control. Perfect for enforcing and ensuring system configuration across many systems and ensuring they remain in their desired state.
Community & Ecosystem Strong community support with a multitude of providers for different platforms. Very strong community support with a large variety of roles/playbooks available. Strong community with a significant number of cookbooks available. Has enterprise support. Established community with a wide array of modules. Known for its longevity in the industry and enterprise-level environment support.

Each of these tools has its strengths and is better suited to specific tasks, environments, or team preferences. Terraform is unrivaled for cloud infrastructure provisioning, Ansible is great for its easy-to-understand approach and orchestration capabilities, Chef is excellent for detailed control over configuration, and Puppet is a veteran tool known for system configuration and enforcing compliance. The best tool often depends on your specific needs, existing tools, and environment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment