Cloud – Fullstack Station https://fullstackstation.com Hướng dẫn lập trình, thiết kế, lập trình web, thiết kế web, lập trình javascript, lập trình fullstack từ cơ bản đến nâng cao Sat, 07 Feb 2026 03:19:06 +0000 vi hourly 1 https://wordpress.org/?v=6.8.3 https://fullstackstation.com/wp-content/uploads/2019/08/favicon.ico Cloud – Fullstack Station https://fullstackstation.com 32 32 Terraform 2025: HCP Terraform và OpenTofu https://fullstackstation.com/terraform-2025-hcp-opentofu/ https://fullstackstation.com/terraform-2025-hcp-opentofu/#respond Wed, 16 Apr 2025 08:30:00 +0000 https://fullstackstation.com/terraform-2025-hcp-opentofu/ Thế giới Terraform đã có nhiều biến động lớn trong năm 2024-2025: HashiCorp bị Broadcom mua lại, việc đổi giấy phép BSL gây tranh cãi, và OpenTofu ra đời như một nhánh mã nguồn mở. Bài viết này cập nhật tình hình và đưa ra gợi ý cho năm 2025. Dòng thời gian các sự […]

The post Terraform 2025: HCP Terraform và OpenTofu appeared first on Fullstack Station.

]]>
Thế giới Terraform đã có nhiều biến động lớn trong năm 2024-2025: HashiCorp bị Broadcom mua lại, việc đổi giấy phép BSL gây tranh cãi, và OpenTofu ra đời như một nhánh mã nguồn mở. Bài viết này cập nhật tình hình và đưa ra gợi ý cho năm 2025.

Dòng thời gian các sự kiện quan trọng

  • Tháng 8/2023: HashiCorp đổi giấy phép sang BSL (không còn mã nguồn mở hoàn toàn)
  • Tháng 9/2023: Cộng đồng công bố dự án OpenTofu
  • Tháng 1/2024: OpenTofu phiên bản 1.6 ổn định
  • Tháng 4/2024: Broadcom đàm phán mua HashiCorp
  • Tháng 11/2024: Broadcom hoàn tất thương vụ
  • 2025: Tương lai còn nhiều điều chưa rõ ràng

HCP Terraform (trước đây là Terraform Cloud)

HashiCorp đã đổi tên Terraform Cloud thành HCP Terraform:

// Cấu hình kết nối với HCP Terraform
terraform {
  cloud {
    organization = "cong-ty-cua-toi"
    workspaces {
      name = "moi-truong-san-pham"
    }
  }
}

Tính năng mới

  • Quản lý trạng thái tốt hơn
  • Tích hợp tốt hơn với HCP Vault
  • Chính sách dưới dạng mã (Sentinel)
  • Kho module riêng tư
  • Tích hợp với quy trình CI/CD

Lo ngại về giá cả

Sau khi Broadcom tiếp quản, nhiều người lo ngại:

  • Gói miễn phí có thể bị cắt giảm
  • Giá doanh nghiệp có thể tăng
  • Bị phụ thuộc vào một nhà cung cấp

OpenTofu – Nhánh mã nguồn mở

OpenTofu là phiên bản do cộng đồng phát triển, giữ giấy phép MPL mã nguồn mở:

# Chuyển đổi từ Terraform sang OpenTofu
# 1. Cài đặt OpenTofu
brew install opentofu

# 2. Thay thế lệnh (cú pháp giống hệt)
tofu init      # thay vì terraform init
tofu plan      # thay vì terraform plan  
tofu apply     # thay vì terraform apply

# 3. Tệp trạng thái tương thích hoàn toàn
# terraform.tfstate hoạt động bình thường!

Tính năng riêng của OpenTofu (2025)

# Mã hóa trạng thái (chỉ có ở OpenTofu)
terraform {
  encryption {
    key_provider "pbkdf2" "mat_khau" {
      passphrase = var.mat_khau_trang_thai
    }
    
    method "aes_gcm" "mac_dinh" {
      key_provider = key_provider.pbkdf2.mat_khau
    }
    
    state {
      method = method.aes_gcm.mac_dinh
    }
  }
}

So sánh hai công cụ

Tiêu chí Terraform OpenTofu
Giấy phép BSL 1.1 (hạn chế) MPL 2.0 (mã nguồn mở)
Mã hóa trạng thái Chỉ bản Cloud Có sẵn
Kho provider registry.terraform.io Tương thích
Hỗ trợ doanh nghiệp HashiCorp Cộng đồng/Đối tác
Phát triển bởi HashiCorp Linux Foundation

Chọn công cụ nào trong năm 2025?

Nên tiếp tục dùng Terraform khi:

  • Cần hỗ trợ kỹ thuật từ nhà cung cấp
  • Đang dùng Terraform Cloud/Enterprise
  • Ưu tiên sự ổn định
  • Tổ chức không muốn rủi ro
  • Đã có hợp đồng với HashiCorp

Nên xem xét OpenTofu khi:

  • Quan trọng việc mã nguồn mở
  • Lo ngại về Broadcom làm chủ sở hữu
  • Cần tính năng mã hóa trạng thái
  • Muốn công cụ do cộng đồng phát triển
  • Bắt đầu dự án mới

Các thực hành tốt cho năm 2025

# 1. Giới hạn phiên bản rõ ràng
terraform {
  required_version = ">= 1.5.0, < 2.0.0"
  
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# 2. Lưu trữ trạng thái từ xa với mã hóa
terraform {
  backend "s3" {
    bucket         = "trang-thai-terraform"
    key            = "san-pham/terraform.tfstate"
    region         = "ap-northeast-1"
    encrypt        = true
    dynamodb_table = "khoa-terraform"
  }
}

# 3. Dùng workspace cho các môi trường
terraform workspace new staging
terraform workspace new production

# 4. Dùng module để tái sử dụng
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"
}

Cách chuyển đổi

Từ Terraform sang OpenTofu

# 1. Thử nghiệm ở môi trường phát triển trước
cd moi-truong-dev
tofu init
tofu plan  # Nên thấy không có thay đổi

# 2. Cập nhật quy trình CI/CD
# Thay 'terraform' bằng 'tofu'

# 3. Cập nhật tài liệu

# 4. Triển khai dần đến môi trường sản phẩm

Giữ linh hoạt cho cả hai

#!/bin/bash
# Script bọc để dùng cả hai công cụ

if command -v tofu &> /dev/null; then
    tofu "$@"
else
    terraform "$@"
fi

Các lựa chọn khác đáng theo dõi

  • Pulumi: Dùng ngôn ngữ lập trình thay vì HCL
  • Crossplane: Quản lý hạ tầng trên Kubernetes
  • AWS CDK: CloudFormation với mã lập trình
  • CDKTF: CDK cho Terraform

Lời khuyên từ Fullstack Station

Gợi ý cho năm 2025:

  • Đang dùng Terraform: Tiếp tục dùng, theo dõi tiến độ OpenTofu
  • Dự án mới: Xem xét OpenTofu để đảm bảo tương lai
  • Doanh nghiệp: Chờ xem chiến lược của Broadcom rõ ràng hơn
  • Học cả hai: Cú pháp gần như giống nhau, dễ chuyển đổi
  • Tránh bị khóa: Dùng tính năng Terraform cơ bản, tránh tính năng riêng của Cloud

Năm 2025 sẽ là năm quan trọng để xem Broadcom định hướng thế nào. Hãy giữ các lựa chọn mở!

Tham khảo

The post Terraform 2025: HCP Terraform và OpenTofu appeared first on Fullstack Station.

]]>
https://fullstackstation.com/terraform-2025-hcp-opentofu/feed/ 0
Terraform vs Pulumi: So sánh hai công cụ IaC hàng đầu https://fullstackstation.com/terraform-vs-pulumi-so-sanh/ https://fullstackstation.com/terraform-vs-pulumi-so-sanh/#respond Wed, 22 Jan 2025 04:45:00 +0000 https://fullstackstation.com/terraform-vs-pulumi-so-sanh/ Terraform và Pulumi là hai công cụ Hạ tầng dưới dạng Mã (IaC) hàng đầu. Terraform sử dụng HCL, trong khi Pulumi cho phép dùng ngôn ngữ lập trình như Python, TypeScript. Bài viết này so sánh chi tiết để giúp bạn chọn đúng công cụ. Tổng quan Terraform (HashiCorp) Ngôn ngữ: HCL (Ngôn ngữ […]

The post Terraform vs Pulumi: So sánh hai công cụ IaC hàng đầu appeared first on Fullstack Station.

]]>
Terraform và Pulumi là hai công cụ Hạ tầng dưới dạng Mã (IaC) hàng đầu. Terraform sử dụng HCL, trong khi Pulumi cho phép dùng ngôn ngữ lập trình như Python, TypeScript. Bài viết này so sánh chi tiết để giúp bạn chọn đúng công cụ.

Tổng quan

Terraform (HashiCorp)

  • Ngôn ngữ: HCL (Ngôn ngữ cấu hình HashiCorp)
  • Ra mắt: 2014
  • Giấy phép: BSL (từ 2023, trước là MPL)
  • Cách tiếp cận: Cấu hình khai báo

Pulumi

  • Ngôn ngữ: Python, TypeScript, Go, C#, Java
  • Ra mắt: 2018
  • Giấy phép: Apache 2.0
  • Cách tiếp cận: Lập trình mệnh lệnh

So sánh cú pháp

Tạo máy chủ EC2

Terraform (HCL):

resource "aws_instance" "may_chu_web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  
  tags = {
    Name = "may-chu-web"
  }
}

output "dia_chi_ip" {
  value = aws_instance.may_chu_web.public_ip
}

Pulumi (Python):

import pulumi
import pulumi_aws as aws

may_chu_web = aws.ec2.Instance("may_chu_web",
    ami="ami-0c55b159cbfafe1f0",
    instance_type="t3.micro",
    tags={"Name": "may-chu-web"}
)

pulumi.export("dia_chi_ip", may_chu_web.public_ip)

Pulumi (TypeScript):

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const mayChuWeb = new aws.ec2.Instance("may-chu-web", {
    ami: "ami-0c55b159cbfafe1f0",
    instanceType: "t3.micro",
    tags: { Name: "may-chu-web" }
});

export const diaChiIp = mayChuWeb.publicIp;

Điểm mạnh của Terraform

1. Hệ sinh thái trưởng thành

# Hàng nghìn nhà cung cấp
terraform {
  required_providers {
    aws     = { source = "hashicorp/aws" }
    google  = { source = "hashicorp/google" }
    azure   = { source = "hashicorp/azurerm" }
    k8s     = { source = "hashicorp/kubernetes" }
    # ... hơn 3000 nhà cung cấp
  }
}

2. Dễ học

HCL dễ đọc, không cần biết lập trình:

# Người không phải lập trình viên cũng hiểu được
resource "aws_s3_bucket" "tinh" {
  bucket = "trang-web-tinh-cua-toi"
}

resource "aws_s3_bucket_website_configuration" "tinh" {
  bucket = aws_s3_bucket.tinh.id
  index_document { suffix = "index.html" }
}

3. Quản lý trạng thái đã được chứng minh

# Trạng thái từ xa với S3
terraform {
  backend "s3" {
    bucket = "trang-thai-terraform"
    key    = "san-pham/terraform.tfstate"
    region = "ap-northeast-1"
    encrypt = true
    dynamodb_table = "khoa-terraform"
  }
}

4. Terraform Cloud/Enterprise

  • Quản lý trạng thái
  • Quy trình làm việc nhóm
  • Chính sách dưới dạng mã (Sentinel)
  • Kho module riêng

Điểm mạnh của Pulumi

1. Ngôn ngữ lập trình thực

# Python với vòng lặp, điều kiện, hàm
import pulumi_aws as aws

# Tạo tài nguyên động
for i in range(3):
    aws.ec2.Instance(f"web-{i}",
        ami="ami-xxx",
        instance_type="t3.micro" if i < 2 else "t3.small"
    )

# Hàm có thể tái sử dụng
def tao_vpc(ten: str, cidr: str):
    vpc = aws.ec2.Vpc(ten, cidr_block=cidr)
    return vpc

2. Kiểm thử tốt hơn

import unittest
import pulumi

class KiemTraHaTang(unittest.TestCase):
    @pulumi.runtime.test
    def kiem_tra_instance_co_the(self):
        def kiem_tra_the(args):
            the = args[0]
            self.assertIn("Name", the)
        
        pulumi.Output.all(instance.tags).apply(kiem_tra_the)

3. An toàn kiểu (TypeScript)

// Tự động hoàn thành IDE, lỗi lúc biên dịch
const instance = new aws.ec2.Instance("web", {
    ami: "ami-xxx",
    instanceType: "t3.micro",  // Kiểm tra kiểu
    // lỗi chính tả: instnceType - lỗi biên dịch!
});

4. Trừu tượng component

class VpcComponent(pulumi.ComponentResource):
    def __init__(self, ten: str, cidr: str, opts=None):
        super().__init__("tuy_chinh:VpcComponent", ten, opts)
        
        self.vpc = aws.ec2.Vpc(f"{ten}-vpc",
            cidr_block=cidr,
            opts=pulumi.ResourceOptions(parent=self)
        )
        
        self.mang_con = []
        for i, az in enumerate(["a", "b"]):
            mang = aws.ec2.Subnet(f"{ten}-mang-{az}",
                vpc_id=self.vpc.id,
                cidr_block=f"10.0.{i}.0/24",
                availability_zone=f"ap-northeast-1{az}",
                opts=pulumi.ResourceOptions(parent=self)
            )
            self.mang_con.append(mang)

So sánh chi tiết

Tiêu chí Terraform Pulumi
Độ khó học Thấp (HCL đơn giản) Cao (cần lập trình)
Linh hoạt Bị giới hạn bởi HCL Sức mạnh lập trình đầy đủ
Kiểm thử Hạn chế (terratest) Kiểm thử đơn vị gốc
Cộng đồng Lớn hơn Đang phát triển
Nhà cung cấp Hơn 3000 Hơn 100 (bọc Terraform)
Quản lý trạng thái Trưởng thành Tương đương
Doanh nghiệp Terraform Cloud Pulumi Cloud
Giấy phép BSL (gây tranh cãi) Apache 2.0

Khi nào dùng Terraform

  • Nhóm hỗn hợp (có người không phải lập trình viên)
  • Hạ tầng đơn giản
  • Cần hệ sinh thái lớn
  • Đã đầu tư vào Terraform
  • Doanh nghiệp với hỗ trợ HashiCorp

Khi nào dùng Pulumi

  • Nhóm lập trình viên
  • Logic phức tạp (vòng lặp, điều kiện)
  • Cần kiểm thử đơn vị
  • Thích ngôn ngữ lập trình thực
  • Ưu tiên mã nguồn mở (sau Terraform BSL)

OpenTofu - Lựa chọn thay thế

Sau khi HashiCorp đổi giấy phép sang BSL, cộng đồng tạo nhánh OpenTofu:

# Thay thế trực tiếp
# Thay terraform bằng tofu
tofu init
tofu plan
tofu apply

Lời khuyên từ Fullstack Station

Cả hai đều là công cụ tốt. Gợi ý của mình:

  • Mới bắt đầu: Terraform - tài liệu học nhiều hơn
  • Nhóm lập trình viên: Pulumi - tận dụng kỹ năng lập trình
  • Doanh nghiệp: Terraform Cloud hoặc Pulumi Cloud
  • Ưu tiên mã nguồn mở: OpenTofu (nhánh Terraform)

Xu hướng 2025: Pulumi đang phát triển nhanh, đặc biệt trong các nhóm lập trình viên. Terraform vẫn chiếm ưu thế nhưng giấy phép BSL gây lo ngại.

Tham khảo

The post Terraform vs Pulumi: So sánh hai công cụ IaC hàng đầu appeared first on Fullstack Station.

]]>
https://fullstackstation.com/terraform-vs-pulumi-so-sanh/feed/ 0
Terraform Modules: Tái sử dụng infrastructure code hiệu quả https://fullstackstation.com/terraform-modules-tai-su-dung-code/ https://fullstackstation.com/terraform-modules-tai-su-dung-code/#respond Wed, 09 Oct 2024 07:30:00 +0000 https://fullstackstation.com/terraform-modules-tai-su-dung-code/ Tiếp tục series Terraform, bài này hướng dẫn về Modules – cách tổ chức và tái sử dụng Terraform code hiệu quả cho production. Terraform Modules là gì? Module là container cho nhiều resources được sử dụng cùng nhau. Thay vì copy-paste code, bạn đóng gói thành module và tái sử dụng. Cấu trúc Module […]

The post Terraform Modules: Tái sử dụng infrastructure code hiệu quả appeared first on Fullstack Station.

]]>
Tiếp tục series Terraform, bài này hướng dẫn về Modules – cách tổ chức và tái sử dụng Terraform code hiệu quả cho production.

Terraform Modules là gì?

Module là container cho nhiều resources được sử dụng cùng nhau. Thay vì copy-paste code, bạn đóng gói thành module và tái sử dụng.

Cấu trúc Module

modules/
└── vpc/
    ├── main.tf       # Resources
    ├── variables.tf  # Input variables
    ├── outputs.tf    # Output values
    └── README.md     # Documentation

Tạo Module VPC

modules/vpc/variables.tf

variable "name" {
  description = "VPC name prefix"
  type        = string
}

variable "cidr" {
  description = "VPC CIDR block"
  type        = string
  default     = "10.0.0.0/16"
}

variable "azs" {
  description = "Availability zones"
  type        = list(string)
}

variable "enable_nat" {
  description = "Enable NAT gateway"
  type        = bool
  default     = true
}

modules/vpc/main.tf

resource "aws_vpc" "this" {
  cidr_block           = var.cidr
  enable_dns_hostnames = true
  
  tags = { Name = "${var.name}-vpc" }
}

resource "aws_subnet" "public" {
  count             = length(var.azs)
  vpc_id            = aws_vpc.this.id
  cidr_block        = cidrsubnet(var.cidr, 8, count.index)
  availability_zone = var.azs[count.index]
  
  tags = { Name = "${var.name}-public-${count.index + 1}" }
}

resource "aws_subnet" "private" {
  count             = length(var.azs)
  vpc_id            = aws_vpc.this.id
  cidr_block        = cidrsubnet(var.cidr, 8, count.index + 10)
  availability_zone = var.azs[count.index]
  
  tags = { Name = "${var.name}-private-${count.index + 1}" }
}

resource "aws_internet_gateway" "this" {
  vpc_id = aws_vpc.this.id
}

resource "aws_nat_gateway" "this" {
  count         = var.enable_nat ? 1 : 0
  allocation_id = aws_eip.nat[0].id
  subnet_id     = aws_subnet.public[0].id
}

resource "aws_eip" "nat" {
  count  = var.enable_nat ? 1 : 0
  domain = "vpc"
}

modules/vpc/outputs.tf

output "vpc_id" {
  value = aws_vpc.this.id
}

output "public_subnet_ids" {
  value = aws_subnet.public[*].id
}

output "private_subnet_ids" {
  value = aws_subnet.private[*].id
}

Sử dụng Module

# main.tf
module "vpc_prod" {
  source = "./modules/vpc"
  
  name       = "prod"
  cidr       = "10.0.0.0/16"
  azs        = ["ap-northeast-1a", "ap-northeast-1c"]
  enable_nat = true
}

module "vpc_staging" {
  source = "./modules/vpc"
  
  name       = "staging"
  cidr       = "10.1.0.0/16"
  azs        = ["ap-northeast-1a"]
  enable_nat = false  # Tiết kiệm chi phí
}

# Sử dụng outputs
resource "aws_instance" "web" {
  subnet_id = module.vpc_prod.public_subnet_ids[0]
  # ...
}

Module từ Terraform Registry

# Sử dụng module public
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"

  name = "my-vpc"
  cidr = "10.0.0.0/16"

  azs             = ["ap-northeast-1a", "ap-northeast-1c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24"]

  enable_nat_gateway = true
}

Best Practices

  • Version modules – Dùng git tags hoặc semantic versioning
  • Documentation – README.md với examples
  • Validation – Dùng variable validation
  • Testing – Terratest cho automated testing
# Variable validation
variable "environment" {
  type = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be dev, staging, or prod."
  }
}

Module Composition

# Kết hợp nhiều modules
module "vpc" {
  source = "./modules/vpc"
  # ...
}

module "eks" {
  source     = "./modules/eks"
  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnet_ids
}

module "rds" {
  source     = "./modules/rds"
  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnet_ids
}

Fullstack Station Tips

Modules là cách organize Terraform code cho teams:

  • Bắt đầu với modules nhỏ, đơn giản
  • Dùng modules từ Registry khi phù hợp – đã được test kỹ
  • Pin versions để tránh breaking changes
  • Document inputs/outputs rõ ràng

Tham khảo

The post Terraform Modules: Tái sử dụng infrastructure code hiệu quả appeared first on Fullstack Station.

]]>
https://fullstackstation.com/terraform-modules-tai-su-dung-code/feed/ 0
Terraform với AWS: Hướng dẫn xây dựng infrastructure thực tế https://fullstackstation.com/terraform-aws-infrastructure-thuc-te/ https://fullstackstation.com/terraform-aws-infrastructure-thuc-te/#respond Thu, 01 Aug 2024 07:00:00 +0000 https://fullstackstation.com/terraform-aws-infrastructure-thuc-te/ Sau bài giới thiệu Terraform cơ bản, hôm nay chúng ta sẽ đi sâu vào thực hành với AWS – cloud provider phổ biến nhất. Bài viết này hướng dẫn tạo một infrastructure hoàn chỉnh bao gồm VPC, EC2, RDS và ALB. Chuẩn bị AWS Credentials # Cấu hình AWS CLI aws configure # AWS […]

The post Terraform với AWS: Hướng dẫn xây dựng infrastructure thực tế appeared first on Fullstack Station.

]]>
Sau bài giới thiệu Terraform cơ bản, hôm nay chúng ta sẽ đi sâu vào thực hành với AWS – cloud provider phổ biến nhất. Bài viết này hướng dẫn tạo một infrastructure hoàn chỉnh bao gồm VPC, EC2, RDS và ALB.

Chuẩn bị

AWS Credentials

# Cấu hình AWS CLI
aws configure
# AWS Access Key ID: AKIAXXXXXXXX
# AWS Secret Access Key: xxxxxxxxxxxxx
# Default region: ap-northeast-1
# Default output format: json

Project Structure

aws-infrastructure/
├── main.tf
├── variables.tf
├── outputs.tf
├── vpc.tf
├── ec2.tf
├── rds.tf
├── alb.tf
└── security-groups.tf

VPC và Networking (vpc.tf)

# VPC
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "${var.project_name}-vpc"
  }
}

# Internet Gateway
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
}

# Public Subnets
resource "aws_subnet" "public" {
  count                   = 2
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.${count.index + 1}.0/24"
  availability_zone       = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.project_name}-public-${count.index + 1}"
  }
}

# Private Subnets
resource "aws_subnet" "private" {
  count             = 2
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.${count.index + 10}.0/24"
  availability_zone = data.aws_availability_zones.available.names[count.index]

  tags = {
    Name = "${var.project_name}-private-${count.index + 1}"
  }
}

# NAT Gateway
resource "aws_eip" "nat" {
  domain = "vpc"
}

resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public[0].id
}

# Route Tables
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main.id
  }
}

Security Groups (security-groups.tf)

# ALB Security Group
resource "aws_security_group" "alb" {
  name        = "${var.project_name}-alb-sg"
  description = "Security group for ALB"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# EC2 Security Group
resource "aws_security_group" "ec2" {
  name        = "${var.project_name}-ec2-sg"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port       = 80
    to_port         = 80
    protocol        = "tcp"
    security_groups = [aws_security_group.alb.id]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = [var.allowed_ssh_cidr]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# RDS Security Group
resource "aws_security_group" "rds" {
  name   = "${var.project_name}-rds-sg"
  vpc_id = aws_vpc.main.id

  ingress {
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    security_groups = [aws_security_group.ec2.id]
  }
}

EC2 Instance (ec2.tf)

resource "aws_instance" "web" {
  count                  = 2
  ami                    = data.aws_ami.amazon_linux.id
  instance_type          = var.instance_type
  subnet_id              = aws_subnet.private[count.index].id
  vpc_security_group_ids = [aws_security_group.ec2.id]
  key_name               = var.key_pair_name

  user_data = <<-EOF
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    systemctl enable httpd
    echo "Hello from $(hostname)" > /var/www/html/index.html
  EOF

  tags = {
    Name = "${var.project_name}-web-${count.index + 1}"
  }
}

RDS Database (rds.tf)

resource "aws_db_subnet_group" "main" {
  name       = "${var.project_name}-db-subnet"
  subnet_ids = aws_subnet.private[*].id
}

resource "aws_db_instance" "main" {
  identifier             = "${var.project_name}-db"
  engine                 = "mysql"
  engine_version         = "8.0"
  instance_class         = "db.t3.micro"
  allocated_storage      = 20
  storage_type           = "gp2"
  db_name                = var.db_name
  username               = var.db_username
  password               = var.db_password
  db_subnet_group_name   = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.rds.id]
  skip_final_snapshot    = true
  multi_az               = false

  tags = {
    Name = "${var.project_name}-db"
  }
}

Application Load Balancer (alb.tf)

resource "aws_lb" "main" {
  name               = "${var.project_name}-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = aws_subnet.public[*].id
}

resource "aws_lb_target_group" "main" {
  name     = "${var.project_name}-tg"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.main.id

  health_check {
    path                = "/"
    healthy_threshold   = 2
    unhealthy_threshold = 10
  }
}

resource "aws_lb_target_group_attachment" "main" {
  count            = 2
  target_group_arn = aws_lb_target_group.main.arn
  target_id        = aws_instance.web[count.index].id
  port             = 80
}

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.main.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.main.arn
  }
}

Deploy

# Khởi tạo và download providers
terraform init

# Xem kế hoạch
terraform plan

# Apply
terraform apply

# Output
terraform output alb_dns_name

Chi phí ước tính

  • 2x t3.micro EC2: ~$15/tháng
  • 1x db.t3.micro RDS: ~$13/tháng
  • ALB: ~$16/tháng + data transfer
  • NAT Gateway: ~$32/tháng
  • Tổng: ~$76/tháng

Fullstack Station Tips

Infrastructure này là nền tảng tốt cho production workloads nhỏ. Một số cải tiến có thể làm:

  • Thêm Auto Scaling Group cho EC2
  • Bật Multi-AZ cho RDS
  • Thêm CloudFront cho static assets
  • Sử dụng Secrets Manager cho credentials

Trong bài tiếp theo, mình sẽ hướng dẫn về Terraform Modules để tái sử dụng code hiệu quả hơn.

Tham khảo

The post Terraform với AWS: Hướng dẫn xây dựng infrastructure thực tế appeared first on Fullstack Station.

]]>
https://fullstackstation.com/terraform-aws-infrastructure-thuc-te/feed/ 0
Terraform cơ bản: Bắt đầu với Infrastructure as Code https://fullstackstation.com/terraform-co-ban-infrastructure-as-code/ https://fullstackstation.com/terraform-co-ban-infrastructure-as-code/#respond Wed, 05 Jun 2024 03:30:00 +0000 https://fullstackstation.com/terraform-co-ban-infrastructure-as-code/ Infrastructure as Code (IaC) đã trở thành tiêu chuẩn trong DevOps hiện đại, và Terraform của HashiCorp là công cụ phổ biến nhất trong lĩnh vực này. Bài viết này sẽ giúp bạn bắt đầu với Terraform từ những khái niệm cơ bản nhất. Terraform là gì? Terraform là công cụ IaC cho phép bạn […]

The post Terraform cơ bản: Bắt đầu với Infrastructure as Code appeared first on Fullstack Station.

]]>
Infrastructure as Code (IaC) đã trở thành tiêu chuẩn trong DevOps hiện đại, và Terraform của HashiCorp là công cụ phổ biến nhất trong lĩnh vực này. Bài viết này sẽ giúp bạn bắt đầu với Terraform từ những khái niệm cơ bản nhất.

Terraform là gì?

Terraform là công cụ IaC cho phép bạn định nghĩa và quản lý infrastructure bằng code. Thay vì click chuột trên console AWS/GCP/Azure, bạn viết file cấu hình và Terraform sẽ tự động tạo, sửa, xóa resources.

Ưu điểm của Terraform:

  • Multi-cloud – Hỗ trợ AWS, GCP, Azure, và hàng trăm providers khác
  • Declarative – Mô tả trạng thái mong muốn, Terraform tự tìm cách đạt được
  • Version control – Infrastructure được quản lý như code, có thể review, rollback
  • Reusable – Modules cho phép tái sử dụng code

Cài đặt Terraform

macOS

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

Ubuntu/Debian

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
sudo apt update && sudo apt install terraform

Kiểm tra cài đặt

terraform version
# Terraform v1.8.x

Cấu trúc project Terraform

Một project Terraform cơ bản gồm các file:

my-infrastructure/
├── main.tf          # Resources chính
├── variables.tf     # Khai báo biến
├── outputs.tf       # Output values
├── terraform.tfvars # Giá trị biến (không commit lên git)
└── providers.tf     # Cấu hình providers

Ví dụ: Tạo EC2 instance trên AWS

1. Cấu hình Provider (providers.tf)

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

provider "aws" {
  region = "ap-northeast-1"  # Tokyo
}

2. Khai báo biến (variables.tf)

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t3.micro"
}

variable "instance_name" {
  description = "Name tag for the instance"
  type        = string
  default     = "my-terraform-instance"
}

3. Định nghĩa Resource (main.tf)

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = var.instance_type

  tags = {
    Name = var.instance_name
  }
}

resource "aws_security_group" "web_sg" {
  name        = "web-sg"
  description = "Allow HTTP and SSH"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

4. Output (outputs.tf)

output "instance_public_ip" {
  description = "Public IP of EC2 instance"
  value       = aws_instance.web.public_ip
}

output "instance_id" {
  description = "ID of EC2 instance"
  value       = aws_instance.web.id
}

Các lệnh Terraform cơ bản

# Khởi tạo project, download providers
terraform init

# Xem những thay đổi sẽ được thực hiện
terraform plan

# Áp dụng thay đổi (tạo/sửa/xóa resources)
terraform apply

# Xem state hiện tại
terraform show

# Xóa toàn bộ resources
terraform destroy

# Format code
terraform fmt

# Validate cấu hình
terraform validate

State Management

Terraform lưu trạng thái infrastructure trong file terraform.tfstate. Khi làm việc nhóm, nên dùng remote backend:

terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "prod/terraform.tfstate"
    region = "ap-northeast-1"
    
    # Optional: State locking với DynamoDB
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Best Practices

  • Không commit terraform.tfvars – Chứa secrets, credentials
  • Sử dụng remote backend – Cho team collaboration
  • Tách môi trường – dev/, staging/, prod/ riêng biệt
  • Dùng modules – Tái sử dụng code
  • Pin provider versions – Tránh breaking changes
  • Chạy terraform plan trước apply – Review changes

Fullstack Station Tips

Terraform là kỹ năng quan trọng cho bất kỳ developer nào làm việc với cloud. Mình khuyên bạn:

  • Bắt đầu với AWS Free Tier để thực hành không tốn phí
  • Đọc documentation của provider bạn dùng – rất chi tiết
  • Học Terraform Cloud/Enterprise cho production
  • Kết hợp với CI/CD (GitHub Actions, GitLab CI) để tự động hóa

Trong bài tiếp theo, mình sẽ hướng dẫn chi tiết hơn về Terraform với AWS, bao gồm VPC, RDS, và các services phức tạp hơn.

Tham khảo

The post Terraform cơ bản: Bắt đầu với Infrastructure as Code appeared first on Fullstack Station.

]]>
https://fullstackstation.com/terraform-co-ban-infrastructure-as-code/feed/ 0