Cloud Native 24 min read

Mastering IaC with Terraform: From Basics to Multi‑Environment Deployments

This article explains the fundamentals of Infrastructure as Code (IaC), its relationship with AIOps, and why Terraform is the preferred tool, then walks through Terraform architecture, core commands, state management, remote backends, project layout, and a complete multi‑environment deployment example on Alibaba Cloud.

Ops Development Stories
Ops Development Stories
Ops Development Stories
Mastering IaC with Terraform: From Basics to Multi‑Environment Deployments

Overview

When discussing AIOps, it is essential to introduce Infrastructure as Code (IaC) because IaC provides the automated foundation on which AIOps operates, enabling resource waste detection, optimal instance recommendation, and root‑cause analysis for failed deployments.

What is IaC?

IaC means defining, managing, and deploying IT infrastructure using code instead of manual clicks, turning manual configuration into programmable scripts.

Why Terraform?

Terraform is an open‑source IaC tool from HashiCorp that can provision, manage, and destroy resources across clouds. It uses the declarative HCL language, which is easy to read and write.

Key advantages of Terraform include repeatability, versioning, automation integration with CI/CD, easy environment replication, and strong maintainability.

Terraform Architecture

Terraform Config – HCL files describing the desired state.

Terraform Core – the engine that plans and applies changes.

Terraform Provider – plugins that translate HCL into cloud provider API calls.

Terraform State – a file that records the real infrastructure state.

Core Commands

terraform init

– initialize the working directory and download providers. terraform plan – preview the actions without applying. terraform apply – execute the plan and create resources. terraform destroy – remove all managed resources.

State Management Commands

terraform state list

– list resources in the state. terraform state show <resource> – show details of a resource. terraform state rm <resource> – remove a resource from state without destroying it. terraform state pull / terraform state push – sync state with remote storage. terraform refresh – update state from real infrastructure. terraform import <resource> <id> – import existing resources.

Query and Debug Commands

terraform show

– display state file contents. terraform output – show defined outputs. terraform graph – generate a dependency graph. terraform validate – check configuration syntax.

Other Useful Commands

terraform fmt

– format .tf files. terraform taint <resource> – mark a resource for recreation. terraform workspace – manage multiple environments (dev, staging, prod).

Terraform State

The state file (default terraform.tfstate) stores all metadata of real resources. Terraform uses this state to plan changes and ensure consistency. Local state files are unsuitable for team collaboration because they lack shared access, locking, and encryption.

Remote state storage (e.g., Alibaba Cloud OSS) provides automatic syncing, locking, and better security.

terraform {
  backend "oss" {
    bucket = "bucket-for-terraform-state"
    prefix = "path/mystate"
    key    = "version-1.tfstate"
    region = "cn-beijing"
    tablestore_endpoint = "https://terraform-remote.cn-hangzhou.ots.aliyuncs.com"
    tablestore_table = "statelock"
  }
}

Project Layout

A recommended Terraform project layout splits files into four main parts:

main.tf – primary business logic.

outputs.tf – defined outputs.

variables.tf – input variables.

versions.tf – provider and Terraform version constraints.

Complex projects can further organize modules and environment directories.

# Example directory structure
project-root/
├── environments/
│   ├── dev/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── staging/
│   └── prod/
├── modules/
│   ├── vpc/
│   └── rds/
├── versions.tf
└── backend.tf

Terraform Hands‑On Example (Alibaba Cloud)

The example demonstrates a modular, multi‑environment Terraform project that creates a VPC, an ECS instance, installs Kubernetes (v1.32.1) via kubeadm, and deploys an Nginx application.

VPC Module

# modules/vpc/variables.tf
variable "vpc_name" { type = string }
variable "cidr_block" { type = string default = "10.0.0.0/16" }
variable "subnet_cidr" { type = string default = "10.0.1.0/24" }
variable "zone_id" { type = string }

# modules/vpc/main.tf
resource "alicloud_vpc" "main" { vpc_name = var.vpc_name cidr_block = var.cidr_block }
resource "alicloud_vswitch" "main" { vswitch_name = "${var.vpc_name}-vsw" cidr_block = var.subnet_cidr vpc_id = alicloud_vpc.main.id zone_id = var.zone_id }

ECS Module

# modules/ecs/variables.tf
variable "instance_name" { type = string }
variable "image_id" { type = string }
variable "instance_type" { type = string }
variable "vpc_id" { type = string }
variable "vswitch_id" { type = string }
variable "zone_id" { type = string }
variable "root_password" { type = string }

# modules/ecs/main.tf
resource "alicloud_security_group" "k8s-node" { name = "k8s-node-sg" vpc_id = var.vpc_id }
resource "alicloud_instance" "k8s-master" {
  instance_name = var.instance_name
  image_id = var.image_id
  instance_type = var.instance_type
  availability_zone = var.zone_id
  system_disk_category = "cloud_efficiency"
  system_disk_size = 40
  vswitch_id = var.vswitch_id
  security_groups = [alicloud_security_group.k8s-node.id]
  internet_max_bandwidth_out = 100
  password = var.root_password
}

Kubernetes Installation Module

# modules/k8s-install/install-k8s.sh
#!/bin/bash
# Install Docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
systemctl start docker && systemctl enable docker
# Install kubelet, kubeadm, kubectl 1.32.1
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kube*
EOF

yum install -y kubelet-1.32.1 kubeadm-1.32.1 kubectl-1.32.1
systemctl enable kubelet && systemctl start kubelet
# Initialize cluster
kubeadm init --pod-network-cidr=10.244.0.0/16
# Configure kubectl
mkdir -p $HOME/.kube
cp /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# Install Flannel CNI
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
EOF

# modules/k8s-install/variables.tf
variable "ecs_public_ip" { type = string }
variable "root_password" { type = string }

# modules/k8s-install/main.tf
resource "null_resource" "install_k8s" {
  connection {
    type = "ssh"
    user = "root"
    password = var.root_password
    host = var.ecs_public_ip
  }
  provisioner "file" {
    source = "${path.module}/install-k8s.sh"
    destination = "/root/install-k8s.sh"
  }
  provisioner "remote-exec" {
    inline = ["chmod +x /root/install-k8s.sh", "/root/install-k8s.sh"]
  }
}

Nginx Deployment Module

# modules/k8s-deploy-nginx/nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: NodePort

# modules/k8s-deploy-nginx/variables.tf
variable "ecs_public_ip" { type = string }
variable "root_password" { type = string }

# modules/k8s-deploy-nginx/main.tf
resource "null_resource" "deploy_nginx" {
  depends_on = [module.k8s-install]
  connection {
    type = "ssh"
    user = "root"
    password = var.root_password
    host = var.ecs_public_ip
  }
  provisioner "file" {
    source = "${path.module}/nginx-deployment.yaml"
    destination = "/root/nginx-deployment.yaml"
  }
  provisioner "remote-exec" {
    inline = ["kubectl apply -f /root/nginx-deployment.yaml"]
  }
}

Development Environment (dev) Main Logic

# environments/dev/main.tf
module "vpc" {
  source = "../../modules/vpc"
  vpc_name = "dev-vpc"
  cidr_block = "10.0.0.0/16"
  subnet_cidr = "10.0.1.0/24"
  zone_id = "cn-beijing-a"
}

module "ecs" {
  source = "../../modules/ecs"
  instance_name = "k8s-master"
  image_id = "centos_7_9_x64_20G_alibase_20220310.vhd"
  instance_type = "ecs.n4.small"
  vpc_id = module.vpc.vpc_id
  vswitch_id = module.vpc.vswitch_id
  zone_id = "cn-beijing-a"
  root_password = "your-root-password-123"
}

module "k8s-install" {
  source = "../../modules/k8s-install"
  ecs_public_ip = module.ecs.ecs_public_ip
  root_password = "your-root-password-123"
  depends_on = [module.ecs]
}

module "deploy-nginx" {
  source = "../../modules/k8s-deploy-nginx"
  ecs_public_ip = module.ecs.ecs_public_ip
  root_password = "your-root-password-123"
  depends_on = [module.k8s-install]
}

Outputs

# environments/dev/outputs.tf
output "vpc_id" { value = module.vpc.vpc_id }
output "ecs_public_ip" { value = module.ecs.ecs_public_ip }
output "k8s_config" { value = "/root/.kube/config" }

Deployment Workflow

# Switch to dev directory
cd environments/dev
# Create dev workspace
terraform workspace new dev
# Initialize providers
terraform init
# Preview changes
terraform plan
# Apply deployment
terraform apply

Conclusion

The article systematically explains the core concepts of Infrastructure as Code (IaC), its connection to AIOps, and the advantages of using IaC tools. It then dives deep into Terraform—its architecture, essential commands, state handling, and project organization—followed by a complete hands‑on case that provisions VPC, ECS, Kubernetes, and Nginx on Alibaba Cloud, demonstrating how IaC enables efficient, repeatable, and secure infrastructure management.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

cloud nativedevopsiacTerraformInfrastructure as Code
Ops Development Stories
Written by

Ops Development Stories

Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.