Artykul

Managing Infrastructure as Code (IaC):

Najlepsze darmowe i komercyjne narzędzia, które realnie ułatwiają życie administratorowi

12.06.2025 7 min czytania import
Zarzadzanie infrastruktura jako kod

🌙

Managing Infrastructure as Code (IaC): A Practical Guide with Terraform and Ansible

How to define, maintain, and integrate infrastructure with system configuration in CI/CD pipelines.

Table of Contents

1. Introduction to IaC

In today’s dynamic IT world, where infrastructure is increasingly complex and distributed, managing it manually becomes inefficient, error-prone, and hard to scale. This is where the concept of Infrastructure as Code (IaC) comes into play. IaC is an approach that involves managing and provisioning infrastructure (networks, virtual machines, databases, load balancers, etc.) using code rather than manual processes or graphical interfaces.

Why implement IaC?

  • Consistency and repeatability: Infrastructure is always created in the same way, eliminating human errors and “configuration drift.”
  • Automation: The processes of creating, updating, and destroying infrastructure are automated, accelerating deployment and management.
  • Versioning: Infrastructure code can be stored in version control systems (e.g., Git), allowing you to track changes, roll back to previous versions, and collaborate as a team.
  • Faster deployments: The ability to quickly provision entire environments (dev, test, prod) shortens the time needed to roll out new applications.
  • Security and compliance: Easier to audit and enforce security policies through code inspection.

i IaC is the foundation of DevOps practices, enabling fast and secure software delivery.

2. Terraform Basics

Terraform is one of the most popular IaC tools, created by HashiCorp. It is a declarative tool, meaning you describe the desired state of your infrastructure, and Terraform ensures that state is achieved.

2.1. Installation and Project Initialization

Installing Terraform is straightforward: download the binary from HashiCorp’s website and place it in your system PATH. After installation, run in your project directory:

terraform init

This command initializes the working directory, downloads the necessary plugins (called providers) for the declared cloud (or local) services, and prepares Terraform to work.

2.2. Providers

Providers are plugins that allow Terraform to communicate with different platforms and services. Examples of popular providers include:

  • AWS: Managing resources in Amazon Web Services.
  • Azure: Managing resources in Microsoft Azure.
  • Google Cloud Platform (GCP): Managing resources in Google Cloud.
  • DigitalOcean: Managing resources in DigitalOcean.
  • VMware vSphere: Managing VMware virtual infrastructure.
  • local/remote-exec: Running scripts locally or remotely on machines.

Provider definition in main.tf:

terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } provider "aws" { region = "eu-central-1" # Example AWS region }

2.3. Your First main.tf – VM, Network, Storage Resources

In main.tf, you define your infrastructure resources. Below is an example of creating a simple virtual machine (EC2) in AWS, a VPC network, and an S3 bucket:

# Create VPC resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" tags = { Name = "my-iac-vpc" } } # Create Subnet resource "aws_subnet" "main" { vpc_id = aws_vpc.main.id cidr_block = "10.0.1.0/24" availability_zone = "eu-central-1a" tags = { Name = "my-iac-subnet" } } # Create EC2 Instance (Virtual Machine) resource "aws_instance" "web_server" { ami = "ami-0abcdef1234567890" # Replace with a current AMI for your region and OS instance_type = "t2.micro" subnet_id = aws_subnet.main.id tags = { Name = "web-server-iac" } } # Create S3 Bucket resource "aws_s3_bucket" "my_bucket" { bucket = "my-unique-iac-bucket-2025" # Bucket name must be globally unique acl = "private" tags = { Environment = "Dev" Project = "IaC-Guide" } }

After defining your resources, run:

terraform plan

terraform plan shows what changes will be made to your infrastructure before they are applied. This is a key step for verification. Then, to apply the changes:

terraform apply

Terraform will ask for confirmation and then proceed to create the resources.

3. Modules and State Management

3.1. Organizing Code into Modules

As your infrastructure grows in complexity, keeping all resources in a single main.tf file becomes impractical. Terraform offers modules, which allow you to group related resources into logical, reusable blocks.

Directory structure with modules:

. ├── main.tf ├── variables.tf ├── outputs.tf └── modules/ ├── vpc/ │ ├── main.tf │ ├── variables.tf │ └── outputs.tf └── ec2-instance/ ├── main.tf ├── variables.tf └── outputs.tf

Using a module in main.tf:

module "my_vpc" { source = "./modules/vpc" vpc_cidr_block = "10.0.0.0/16" } module "my_web_server" { source = "./modules/ec2-instance" ami_id = "ami-0abcdef1234567890" instance_type = "t2.micro" subnet_id = module.my_vpc.subnet_id }

3.2. Remote Backend (S3, Consul)

Terraform stores its state in the terraform.tfstate file. This file maps your Terraform configuration to the real-world resources. In team environments, local state management is risky because it can lead to overwritten changes and errors. Therefore, remote backends are used:

  • Amazon S3: The most common choice, often combined with DynamoDB for state locking.
  • HashiCorp Consul: A service discovery and configuration store solution.
  • Terraform Cloud/Enterprise: A managed service by HashiCorp with built-in state management and workflows.

S3 backend configuration in main.tf:

terraform { backend "s3" { bucket = "my-iac-tfstate-bucket" key = "dev/network/terraform.tfstate" region = "eu-central-1" encrypt = true dynamodb_table = "terraform-lock-table" # For state locking } }

3.3. Practical Tips on State Locking

State locking prevents simultaneous operations on the same Terraform state file, which is crucial for team collaboration. With S3, you use a DynamoDB table for locking. Always ensure your backend supports state locking and that it is enabled.

Tip Always use a remote backend for Terraform state in production environments.

4. Ansible as a Configuration Layer

While Terraform focuses on provisioning infrastructure, Ansible is a powerful tool for configuration management—installing software, configuring services, managing users, etc. Ansible is agentless (no agent required on managed machines), communicating over SSH.

4.1. Playbooks, Roles, Inventory

  • Inventory: A file (usually YAML or INI) listing the hosts Ansible manages, along with groups and variables.
  • Playbooks: YAML files defining sets of tasks to run on specified hosts.
  • Roles: A structured way to organize playbooks, variables, templates, and files, promoting code reuse.

Example inventory file (inventory.ini):

[webservers] web_server_1 ansible_host=10.0.1.10 web_server_2 ansible_host=10.0.1.11 [databases] db_server_1 ansible_host=10.0.1.20

Example simple playbook (install_nginx.yml):

---

  • name: Install Nginx web server
  • hosts: webservers become: true # Run tasks with root privileges tasks:

  • name: Update apt cache
  • apt: update_cache: yes

  • name: Install Nginx
  • apt: name: nginx state: present

  • name: Start Nginx service
  • service: name: nginx state: started enabled: yes

4.2. Example Web/DB Server Configuration

Running the playbook:

ansible-playbook -i inventory.ini install_nginx.yml

5. Terraform ↔ Ansible Integration

After provisioning infrastructure with Terraform, you need Ansible to configure the newly created machines. The key is dynamically passing IP addresses or hostnames from Terraform into Ansible’s inventory.

5.1. Generating a Dynamic Inventory

You can use Terraform outputs to generate an Ansible inventory file. Below is an example of producing a JSON (or INI) dynamic inventory:

# output.tf in the Terraform root directory output "ansible_inventory" { value = { _meta = { hostvars = { } } webservers = { hosts = [for instance in aws_instance.web_server : instance.public_ip] # Assuming public IPs } } sensitive = true # May contain sensitive data }

Then, after terraform apply, run:

terraform output -json ansible_inventory > inventory.json

and use this file with Ansible.

5.2. Calling Playbooks with local-exec/remote-exec

Terraform lets you run local (local-exec) or remote (remote-exec) commands as part of a resource’s lifecycle. This is often used to trigger Ansible playbooks.

resource "aws_instance" "web_server" { # ... instance configuration ... provisioner "remote-exec" { inline = [ "sudo apt update", "sudo apt install -y python3", # Ansible requires Python ] connection { type = "ssh" user = "ubuntu" private_key = file("~/.ssh/id_rsa") host = self.public_ip } } provisioner "local-exec" { command =

Wroc do bloga