Posted on :: 3018 Words :: Tags: , , , , ,

Cài Đặt Terraform

Xin chào lại các bạn! Ở Phần 1, mình đã cùng nhau tìm hiểu tại sao Infrastructure as Code lại quan trọng và vì sao Terraform trở thành công cụ phổ biến nhất. Giờ là lúc bắt tay vào việc thực sự—cài đặt và chạy nó lên thôi.

Sau khi đọc xong bài này, máy bạn sẽ có Terraform chạy mượt mà, credentials kết nối cloud đã được setup chuẩn chỉnh, và dự án đầu tiên sẵn sàng khởi tạo. Hết thời gian lý thuyết rồi, giờ làm thật luôn!

📦 Code Mẫu

Toàn bộ code mẫu trong series này mình đều để sẵn trên GitHub:

Repository: terraform-hcl-tutorial-series Phần này: Part 2 - Provider Setup Examples

Muốn thực hành ngay? Làm theo nhé:

git clone https://github.com/khuongdo/terraform-hcl-tutorial-series.git
cd terraform-hcl-tutorial-series
git checkout part-02

# Dùng AWS? Thử ngay:
cd examples/part-02-setup/aws/
terraform init
terraform plan

# Hoặc dùng GCP:
cd ../gcp/
terraform init
terraform plan

# Azure cũng có luôn:
cd ../azure/
terraform init
terraform plan

Các ví dụ này chỉ để test cấu hình provider, không tạo tài nguyên thật nên yên tâm không tốn tiền nhé.

Tại Sao Phải Setup Cẩn Thận?

Mình biết, bạn đang muốn nhảy vào deploy infrastructure ngay. Nhưng dành 20 phút setup chuẩn bây giờ, bạn sẽ tiết kiệm được cả chục giờ ngồi debug về sau đấy.

Những điều tệ hại khi setup vội vàng:

  • Dự án A cần Terraform 1.4, dự án B lại cần 1.7 → conflict tùm lum
  • Hardcode credentials vào file config → security check fail, lộ thông tin
  • Mất cả buổi chiều debug lỗi authentication chỉ vì PATH setup sai
  • Team member khác không chạy được code vì môi trường khác nhau

Setup đúng cách ngay từ đầu sẽ cho bạn:

  • Môi trường có thể tái tạo dễ dàng
  • Quản lý credentials an toàn
  • Cách ly version cho từng dự án
  • Audit trail rõ ràng

Đây không chỉ là làm Terraform chạy được—mà là làm cho nó chạy ổn định trong 3 năm tới.

Cài Đặt Terraform

Tin vui: Terraform chỉ là một file binary đơn giản thôi. Không cần runtime, không dependency phức tạp gì cả. Download về, bỏ vào PATH, xong.

Bước 1: Cài Đặt Trên macOS

Dùng macOS thì đơn giản nhất là Homebrew:

# Cài Terraform
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

# Kiểm tra xem đã chạy chưa
terraform version
# Sẽ hiện: Terraform v1.9.0 (hoặc version mới hơn)

Tại sao dùng Homebrew? Đơn giản vì khi update chỉ cần brew upgrade terraform là xong. Ez!

Không thích Homebrew? Cũng được:

# Download từ trang chính thức: https://releases.hashicorp.com/terraform/
wget https://releases.hashicorp.com/terraform/1.9.0/terraform_1.9.0_darwin_amd64.zip

# Giải nén và bỏ vào PATH
unzip terraform_1.9.0_darwin_amd64.zip
sudo mv terraform /usr/local/bin/

# Check thử
terraform version

Bước 1: Cài Đặt Trên Linux

Ubuntu/Debian, bạn thêm repo của HashiCorp vào:

# Thêm GPG key và repo của HashiCorp
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list

# Cài đặt luôn
sudo apt update && sudo apt install terraform

# Kiểm tra
terraform version

Hoặc cài thủ công cũng được:

wget https://releases.hashicorp.com/terraform/1.9.0/terraform_1.9.0_linux_amd64.zip
unzip terraform_1.9.0_linux_amd64.zip
sudo mv terraform /usr/local/bin/
terraform version

Bước 1: Cài Đặt Trên Windows

Dùng Chocolatey thì dễ nhất:

choco install terraform
terraform version

Không dùng Chocolatey? Download file ZIP từ trang releases của HashiCorp, giải nén vào C:\Program Files\Terraform\, rồi thêm folder đó vào PATH.

Cách thêm vào PATH: gõ "Environment Variables" trong menu Start → System Properties → Environment Variables → edit biến Path → thêm folder Terraform → Save → restart terminal.

Sau đó check thử:

terraform version

Bước 2: Kiểm Tra Cài Đặt

Cài xong rồi, giờ test thử:

terraform version

Bạn sẽ thấy version 1.7.0 trở lên. Muốn có tab completion (rất nên bật nhé), chạy thêm:

terraform -install-autocomplete

Restart terminal hoặc mở tab mới. Giờ gõ terraform rồi nhấn Tab sẽ có gợi ý lệnh luôn.

Lỗi thường gặp:

  • terraform version không chạy → kiểm tra PATH. Trên macOS/Linux dùng which terraform để xem đúng path chưa. Windows thì restart terminal sau khi sửa PATH
  • "Permission denied" trên Linux → chạy chmod +x /usr/local/bin/terraform

Authentication: Kết Nối Với Cloud

Terraform cần quyền truy cập cloud account của bạn để tạo tài nguyên. Mỗi cloud provider có cách riêng, nhưng nguyên tắc chung: bạn authentication ở local, Terraform tự động lấy credentials đó.

Điều TUYỆT ĐỐI KHÔNG được làm:

# ❌ ĐỪNG BAO GIỜ LÀM THẾ NÀY
provider "aws" {
  access_key = "AKIAIOSFODNN7EXAMPLE"
  secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}

Tại sao tệ đến vậy?

  • Commit vào Git → credentials ở trong history mãi mãi (xóa cũng vô ích, nó vẫn ở đó)
  • Lộ ra trong Terraform state files và plan outputs
  • Push nhầm lên public repo → người ta dùng account của bạn đào crypto, bill bay màu

Cách đúng: Dùng CLI tool của cloud provider để authentication. Terraform tự động lấy credentials từ môi trường. An toàn, gọn gàng.

Setup AWS

AWS có 3 cách authentication. Mình khuyên dùng theo thứ tự này.

Cách 1: AWS CLI (Bắt Đầu Từ Đây)

Chưa có AWS CLI? Cài ngay:

# macOS
brew install awscli

# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# Windows: tải MSI từ https://aws.amazon.com/cli/

Setup credentials:

aws configure

CLI sẽ hỏi 4 thứ:

  1. AWS Access Key ID - lấy từ AWS Console → Security Credentials → Access Keys
  2. AWS Secret Access Key - chỉ hiện 1 lần khi tạo key, copy ngay kẻo mất mãi mãi
  3. Default region - ví dụ us-west-2
  4. Output format - gõ json là đủ

Test thử xem chạy chưa:

aws sts get-caller-identity

Thấy AWS account ID và user ARN hiện ra là ok. Terraform sẽ tự động dùng credentials này.

Cách 2: Environment Variables (Cho CI/CD)

Chạy Terraform trong CI/CD pipeline? Dùng environment variables:

export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="us-west-2"

GitHub Actions và GitLab CI thường dùng cách này.

Cách 3: IAM Roles (Best Practice Production)

Chạy Terraform trên EC2 hoặc AWS CodeBuild? Dùng IAM roles, đừng dùng access keys. Lợi ích:

  • Không có credentials lưu lâu dài
  • Auto rotation
  • Scope permissions chuẩn chỉnh

Terraform tự động nhận diện:

provider "aws" {
  region = "us-west-2"
  # Không cần credentials block—dùng instance metadata
}

Đây là chuẩn vàng cho production. Không key để lộ.

Setup GCP

Google Cloud dùng Application Default Credentials thông qua gcloud CLI.

Cài gcloud

# macOS
brew install --cask google-cloud-sdk

# Linux (Debian/Ubuntu)
sudo apt-get install apt-transport-https ca-certificates gnupg
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt-get update && sudo apt-get install google-cloud-sdk

# Windows: tải từ https://cloud.google.com/sdk/docs/install

Authentication

gcloud init
gcloud config set project YOUR_PROJECT_ID
gcloud auth application-default login

Lệnh cuối sẽ mở browser để OAuth login. Sau khi xác thực, credentials lưu vào ~/.config/gcloud/application_default_credentials.json. Terraform tự đọc file này.

Kiểm tra xem ok chưa:

gcloud projects list

Thấy danh sách GCP projects là thành công.

Service Account Keys (Chỉ Cho CI/CD)

Local development thì dùng Application Default Credentials. Nhưng CI/CD cần service account key thì làm thế này:

gcloud iam service-accounts create terraform-sa --display-name "Terraform Service Account"

gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
  --member="serviceAccount:terraform-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/editor"

gcloud iam service-accounts keys create ~/terraform-key.json \
  --iam-account=terraform-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com

export GOOGLE_APPLICATION_CREDENTIALS="$HOME/terraform-key.json"

Chú ý quan trọng: Service account key là credential lâu dài. Ai lấy được file JSON này = full access GCP project của bạn. Coi như password, đừng commit vào Git. Chỉ dùng khi thực sự cần.

Setup Azure

Azure dùng Azure CLI để authentication.

Cài Azure CLI

# macOS
brew install azure-cli

# Linux (Ubuntu/Debian)
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

# Windows: tải từ https://aka.ms/installazurecliwindows

Login

az login

Browser sẽ mở lên. Đăng nhập, CLI sẽ lưu credentials.

Có nhiều subscriptions? Chọn cái cần dùng:

az account list --output table
az account set --subscription "YOUR_SUBSCRIPTION_ID"

Kiểm tra subscription đang active:

az account show

Thấy subscription ID và email là ok.

Service Principal (Cho CI/CD)

CI/CD pipeline cần service principal:

az ad sp create-for-rbac --name "terraform-sp" --role Contributor

Lệnh này sẽ output ra appId, password, và tenant ID. Lưu lại cẩn thận rồi set environment variables:

export ARM_CLIENT_ID="appId từ output"
export ARM_CLIENT_SECRET="password từ output"
export ARM_SUBSCRIPTION_ID="your-subscription-id"
export ARM_TENANT_ID="tenant từ output"

Hiểu Về Terraform Providers

Authentication xong rồi, giờ nói về providers.

Provider = plugin dịch config Terraform thành API calls. Bạn viết resource "aws_s3_bucket", AWS provider chuyển thành AWS SDK calls. GCP và Azure cũng vậy.

Tư duy đơn giản: Provider giống như database driver. Bạn không giao tiếp trực tiếp với PostgreSQL mà dùng driver. Providers cũng thế—nó nói chuyện với cloud APIs thay bạn.

Cấu hình provider trông như này:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-west-2"
}

Phân tích từng phần:

Block terraform khai báo provider nào cần dùng. source = nơi download—hashicorp/aws tức là registry.terraform.io/hashicorp/aws. version khóa vào version 5.x, không lên 6.0.

Tại sao version lại quan trọng? 6 tháng sau, AWS provider 8.0 release với breaking changes. Không có version constraint → code vỡ bất ngờ. Với ~> 5.0, bạn ở 5.x cho đến khi chủ động upgrade.

Version constraint phổ biến:

  • ~> 5.0 = "version 5.x bất kỳ, không lên 6.0" (khuyên dùng)
  • = 5.31.0 = "chính xác version này" (quá strict)
  • >= 5.0, < 6.0 = "range rõ ràng" (cũng ok)

Block provider cấu hình provider. Với AWS thường chỉ cần region. Credentials lấy từ môi trường (AWS CLI, env vars, hoặc IAM role), không cần ghi ở đây.

Dùng nhiều providers trong 1 project? Hoàn toàn được:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-west-2"
}

provider "google" {
  project = "my-gcp-project"
  region  = "us-central1"
}

Giờ bạn có thể tạo resources cả AWS lẫn GCP trong cùng 1 codebase Terraform.

Dự Án Terraform Đầu Tiên

Đến lúc thực hành thật rồi!

Bước 3: Tạo Cấu Trúc Dự Án

Tạo folder:

mkdir ~/terraform-getting-started
cd ~/terraform-getting-started

Cấu trúc file mình khuyên dùng:

terraform-getting-started/
├── main.tf          # Resources chính
├── variables.tf     # Input variables
├── outputs.tf       # Outputs
└── terraform.tfvars # Giá trị variables (đừng commit secrets vào đây)

Chưa cần tất cả ngay, nhưng đây là best practice nên biết trước.

Bước 4: Viết Config Đầu Tiên (AWS)

Tạo file main.tf:

terraform {
  required_version = ">= 1.7.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

resource "aws_s3_bucket" "learning_bucket" {
  bucket = "terraform-learning-${var.environment}-${random_id.bucket_suffix.hex}"

  tags = {
    Name        = "Terraform Learning Bucket"
    Environment = var.environment
    ManagedBy   = "Terraform"
  }
}

resource "random_id" "bucket_suffix" {
  byte_length = 4
}

Tạo variables.tf:

variable "aws_region" {
  description = "AWS region for resources"
  type        = string
  default     = "us-west-2"
}

variable "environment" {
  description = "Environment name (dev, staging, prod)"
  type        = string
  default     = "dev"

  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be dev, staging, or prod."
  }
}

Tạo outputs.tf:

output "bucket_name" {
  description = "Name of the created S3 bucket"
  value       = aws_s3_bucket.learning_bucket.id
}

output "bucket_arn" {
  description = "ARN of the S3 bucket"
  value       = aws_s3_bucket.learning_bucket.arn
}

Hoặc Sử Dụng GCP

Nếu bạn thích Google Cloud, thay thế main.tf bằng:

terraform {
  required_version = ">= 1.7.0"

  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = var.gcp_project_id
  region  = var.gcp_region
}

resource "google_storage_bucket" "learning_bucket" {
  name     = "terraform-learning-${var.environment}-${random_id.bucket_suffix.hex}"
  location = var.gcp_region

  labels = {
    environment = var.environment
    managed_by  = "terraform"
  }
}

resource "random_id" "bucket_suffix" {
  byte_length = 4
}

Và cập nhật variables.tf:

variable "gcp_project_id" {
  description = "GCP project ID"
  type        = string
}

variable "gcp_region" {
  description = "GCP region for resources"
  type        = string
  default     = "us-central1"
}

variable "environment" {
  description = "Environment name"
  type        = string
  default     = "dev"
}

Hoặc Azure

Cho Azure:

terraform {
  required_version = ">= 1.7.0"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "learning" {
  name     = "rg-terraform-learning-${var.environment}"
  location = var.azure_region
}

resource "azurerm_storage_account" "learning" {
  name                     = "tflearn${var.environment}${random_id.suffix.hex}"
  resource_group_name      = azurerm_resource_group.learning.name
  location                 = azurerm_resource_group.learning.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  tags = {
    environment = var.environment
    managed_by  = "terraform"
  }
}

resource "random_id" "suffix" {
  byte_length = 4
}

variables.tf:

variable "azure_region" {
  description = "Azure region for resources"
  type        = string
  default     = "East US"
}

variable "environment" {
  description = "Environment name"
  type        = string
  default     = "dev"
}

Bước 5: Chạy terraform init

Giờ đến bước quyết định:

terraform init

Lệnh này làm 4 việc:

  1. Download provider plugins bạn đã khai báo (AWS, GCP, hoặc Azure)
  2. Khởi tạo backend (mặc định là local, production dùng remote)
  3. Tạo folder .terraform/ chứa provider binaries
  4. Tạo .terraform.lock.hcl để lock provider versions

Output sẽ trông như này:

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.31.0...
- Installed hashicorp/aws v5.31.0 (signed by HashiCorp)

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!

Check xem đã tạo gì:

ls -la

Bạn sẽ thấy:

  • .terraform/ - provider binaries, ĐỪNG commit vào Git
  • .terraform.lock.hcl - version lock file, NÊN commit
  • main.tf, variables.tf, outputs.tf - config của bạn

Lock File Là Gì?

Mở file .terraform.lock.hcl ra xem:

provider "registry.terraform.io/hashicorp/aws" {
  version     = "5.31.0"
  constraints = "~> 5.0"
  hashes = [
    "h1:...",
    "zh:...",
  ]
}

File này lock chính xác provider version. Bạn khai báo ~> 5.0, Terraform chọn version 5.31.0 và ghi lại ở đây. Lần sau bạn hoặc team member chạy terraform init, sẽ dùng đúng version này.

Các hashes để verify integrity—Terraform check provider bạn download không bị tamper.

Có nên commit file này không? CÓ. Thêm vào Git để cả team dùng đúng provider versions.

Troubleshooting

Lỗi thường gặp:

  • "Failed to query available provider packages" → check internet, Terraform cần download từ registry.terraform.io
  • "Required version constraint not satisfied" → Terraform version cũ quá, chạy terraform version rồi upgrade qua Homebrew hoặc tải lại
  • "Error configuring the backend" → check cú pháp main.tf, chạy terraform validate để bắt lỗi

Bước 6: Những Gì Nên Commit Vào Git

Tạo file .gitignore trong project:

# Local .terraform directories
**/.terraform/*

# State files - chứa resource IDs và có thể có secrets
*.tfstate
*.tfstate.*

# Crash logs
crash.log
crash.*.log

# Variable files có secrets
*.tfvars
!example.tfvars

# CLI config - có thể chứa credentials
.terraformrc
terraform.rc

# Override files
override.tf
override.tf.json
*_override.tf
*_override.tf.json

NÊN commit:

  • Các file *.tf - toàn bộ Terraform code
  • .terraform.lock.hcl - provider version lock
  • README.md - documentation
  • example.tfvars - template không có giá trị thật

KHÔNG BAO GIỜ commit:

  • *.tfstate - chứa resource IDs, có thể có secrets
  • .terraform/ - provider binaries, tải lại được
  • terraform.tfvars nếu có credentials/API keys

Tự Kiểm Tra

Trước khi sang Phần 3, check xem bạn đã nắm chưa:

1. Ba cách authentication AWS là gì? → AWS CLI credentials, environment variables, IAM roles

2. terraform init làm gì? → Download providers, khởi tạo backend, tạo folder .terraform/, tạo lock file

3. Tại sao dùng version constraint ~> 5.0? → Tránh breaking changes khi provider auto-update, nhưng vẫn nhận minor updates

4. Có nên commit .terraform.lock.hcl không? → CÓ. Đảm bảo cả team dùng đúng provider versions

5. Tại sao không hardcode credentials vào provider blocks? → Lộ trong Git history, Terraform state, và plan outputs. Dùng CLI tools hoặc env vars

Trả lời được hết? Bạn đã sẵn sàng Phần 3 rồi đấy!

Tiếp Theo

Ở Phần 3, chúng ta sẽ thực sự deploy thứ gì đó lên cloud. Bạn sẽ chạy:

  • terraform plan - xem trước những thay đổi
  • terraform apply - tạo cloud resources thật
  • terraform destroy - dọn dẹp khi xong

Đây là lúc Terraform từ lý thuyết trở thành thực tế. Bạn sẽ tạo infrastructure thật trên AWS/GCP/Azure, hiểu cách Terraform track state, và học cách modify resources mà không làm vỡ mọi thứ.

Sẵn sàng chưa? Tiếp tục Phần 3 → (sắp có)


Tài Liệu Tham Khảo

Docs Chính Thức:

Authentication Guides:

Điều hướng series:

Có thắc mắc? Comment bên dưới nhé. Mình trả lời hết và sẽ tích hợp feedback vào các bài sau.


Phần của series "Terraform from Fundamentals to Production". Theo dõi để làm chủ Infrastructure as Code!