Infrastructure as Code with Terraform
Complete guide for managing SBM CRM Platform infrastructure using Terraform on Huawei Cloud.
Prerequisites
- Terraform >= 1.0
- Huawei Cloud account
- Access key and secret key
- Basic knowledge of Terraform
Terraform Configuration
Provider Configuration
Create providers.tf:
terraform {
required_version = ">= 1.0"
required_providers {
huaweicloud = {
source = "huaweicloud/huaweicloud"
version = "~> 1.40"
}
}
backend "s3" {
# Use OBS for state storage
bucket = "sbmcrm-terraform-state"
key = "terraform.tfstate"
region = "ap-southeast-1"
}
}
provider "huaweicloud" {
region = var.region
access_key = var.access_key
secret_key = var.secret_key
}
Variables
Create variables.tf:
variable "region" {
description = "Huawei Cloud region"
type = string
default = "ap-southeast-1"
}
variable "access_key" {
description = "Huawei Cloud access key"
type = string
sensitive = true
}
variable "secret_key" {
description = "Huawei Cloud secret key"
type = string
sensitive = true
}
variable "project_name" {
description = "Project name"
type = string
default = "sbmcrm"
}
variable "environment" {
description = "Environment (production, staging, development)"
type = string
default = "production"
}
variable "vpc_cidr" {
description = "VPC CIDR block"
type = string
default = "10.0.0.0/16"
}
variable "availability_zones" {
description = "Availability zones"
type = list(string)
default = ["ap-southeast-1a", "ap-southeast-1b"]
}
VPC and Networking
Create network.tf:
# VPC
resource "huaweicloud_vpc" "main" {
name = "${var.project_name}-vpc"
cidr = var.vpc_cidr
}
# Public Subnet A
resource "huaweicloud_vpc_subnet" "public_a" {
name = "${var.project_name}-public-subnet-a"
cidr = "10.0.1.0/24"
gateway_ip = "10.0.1.1"
vpc_id = huaweicloud_vpc.main.id
availability_zone = var.availability_zones[0]
dns_list = [
"100.125.1.250",
"100.125.129.250"
]
}
# Public Subnet B
resource "huaweicloud_vpc_subnet" "public_b" {
name = "${var.project_name}-public-subnet-b"
cidr = "10.0.2.0/24"
gateway_ip = "10.0.2.1"
vpc_id = huaweicloud_vpc.main.id
availability_zone = var.availability_zones[1]
dns_list = [
"100.125.1.250",
"100.125.129.250"
]
}
# Private Subnet A
resource "huaweicloud_vpc_subnet" "private_a" {
name = "${var.project_name}-private-subnet-a"
cidr = "10.0.10.0/24"
gateway_ip = "10.0.10.1"
vpc_id = huaweicloud_vpc.main.id
availability_zone = var.availability_zones[0]
dns_list = [
"100.125.1.250",
"100.125.129.250"
]
}
# Private Subnet B
resource "huaweicloud_vpc_subnet" "private_b" {
name = "${var.project_name}-private-subnet-b"
cidr = "10.0.11.0/24"
gateway_ip = "10.0.11.1"
vpc_id = huaweicloud_vpc.main.id
availability_zone = var.availability_zones[1]
dns_list = [
"100.125.1.250",
"100.125.129.250"
]
}
Security Groups
Create security_groups.tf:
# Application Security Group
resource "huaweicloud_networking_secgroup" "app" {
name = "${var.project_name}-app-sg"
description = "Security group for application servers"
}
resource "huaweicloud_networking_secgroup_rule" "app_http" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 80
port_range_max = 80
remote_group_id = huaweicloud_networking_secgroup.elb.id
security_group_id = huaweicloud_networking_secgroup.app.id
}
resource "huaweicloud_networking_secgroup_rule" "app_https" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 443
port_range_max = 443
remote_group_id = huaweicloud_networking_secgroup.elb.id
security_group_id = huaweicloud_networking_secgroup.app.id
}
resource "huaweicloud_networking_secgroup_rule" "app_ssh" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = "203.0.113.0/24" # Management IPs
security_group_id = huaweicloud_networking_secgroup.app.id
}
# Database Security Group
resource "huaweicloud_networking_secgroup" "db" {
name = "${var.project_name}-db-sg"
description = "Security group for database"
}
resource "huaweicloud_networking_secgroup_rule" "db_postgres" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 5432
port_range_max = 5432
remote_group_id = huaweicloud_networking_secgroup.app.id
security_group_id = huaweicloud_networking_secgroup.db.id
}
# Cache Security Group
resource "huaweicloud_networking_secgroup" "cache" {
name = "${var.project_name}-cache-sg"
description = "Security group for Redis cache"
}
resource "huaweicloud_networking_secgroup_rule" "cache_redis" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 6379
port_range_max = 6379
remote_group_id = huaweicloud_networking_secgroup.app.id
security_group_id = huaweicloud_networking_secgroup.cache.id
}
ECS Instances
Create ecs.tf:
# Key Pair
resource "huaweicloud_kps_keypair" "main" {
name = "${var.project_name}-keypair"
}
# ECS Instance 1
resource "huaweicloud_compute_instance" "api_01" {
name = "${var.project_name}-api-01"
image_id = "ubuntu_20_04_64bit"
flavor_id = "s6.xlarge.2"
availability_zone = var.availability_zones[0]
key_pair = huaweicloud_kps_keypair.main.name
network {
uuid = huaweicloud_vpc_subnet.public_a.id
}
security_groups = [
huaweicloud_networking_secgroup.app.id
]
system_disk_type = "SSD"
system_disk_size = 100
user_data = <<-EOF
#!/bin/bash
apt-get update
apt-get install -y docker.io docker-compose
systemctl enable docker
systemctl start docker
EOF
tags = {
Environment = var.environment
Role = "api-server"
}
}
# ECS Instance 2
resource "huaweicloud_compute_instance" "api_02" {
name = "${var.project_name}-api-02"
image_id = "ubuntu_20_04_64bit"
flavor_id = "s6.xlarge.2"
availability_zone = var.availability_zones[1]
key_pair = huaweicloud_kps_keypair.main.name
network {
uuid = huaweicloud_vpc_subnet.public_b.id
}
security_groups = [
huaweicloud_networking_secgroup.app.id
]
system_disk_type = "SSD"
system_disk_size = 100
user_data = <<-EOF
#!/bin/bash
apt-get update
apt-get install -y docker.io docker-compose
systemctl enable docker
systemctl start docker
EOF
tags = {
Environment = var.environment
Role = "api-server"
}
}
RDS Database
Create rds.tf:
resource "huaweicloud_rds_instance" "postgresql" {
name = "${var.project_name}-postgresql"
flavor = "rds.pg.c2.xlarge"
ha_replication_mode = "async"
vpc_id = huaweicloud_vpc.main.id
subnet_id = huaweicloud_vpc_subnet.private_a.id
security_group_id = huaweicloud_networking_secgroup.db.id
availability_zone = [
var.availability_zones[0],
var.availability_zones[1]
]
db {
type = "PostgreSQL"
version = "13"
password = var.db_password
port = 5432
}
volume {
type = "ULTRAHIGH"
size = 500
}
backup_strategy {
start_time = "02:00-03:00"
keep_days = 30
}
tags = {
Environment = var.environment
}
}
resource "huaweicloud_rds_database" "main" {
instance_id = huaweicloud_rds_instance.postgresql.id
name = "sbmcrm_production"
character_set = "UTF8"
}
resource "huaweicloud_rds_account" "main" {
instance_id = huaweicloud_rds_instance.postgresql.id
name = "sbmcrm"
password = var.db_user_password
}
Redis Cache
Create redis.tf:
resource "huaweicloud_dcs_instance" "redis" {
name = "${var.project_name}-redis"
engine_version = "6.0"
password = var.redis_password
capacity = 8
vpc_id = huaweicloud_vpc.main.id
subnet_id = huaweicloud_vpc_subnet.private_a.id
security_group_id = huaweicloud_networking_secgroup.cache.id
availability_zones = [var.availability_zones[0]]
backup_policy {
save_days = 7
backup_type = "auto"
period_type = "weekly"
begin_at = "00:00-01:00"
backup_at = [1, 2, 3, 4, 5, 6, 7]
}
tags = {
Environment = var.environment
}
}
ELB Load Balancer
Create elb.tf:
resource "huaweicloud_elb_loadbalancer" "main" {
name = "${var.project_name}-elb"
vpc_id = huaweicloud_vpc.main.id
ipv4_subnet_id = huaweicloud_vpc_subnet.public_a.id
ipv6_subnet_id = huaweicloud_vpc_subnet.public_b.id
l4_flavor_id = "elb.s2.medium"
l7_flavor_id = "elb.s2.medium"
availability_zone = var.availability_zones
}
resource "huaweicloud_elb_listener" "https" {
name = "${var.project_name}-https-listener"
protocol = "HTTPS"
protocol_port = 443
loadbalancer_id = huaweicloud_elb_loadbalancer.main.id
server_certificate_id = var.ssl_certificate_id
default_pool_id = huaweicloud_elb_pool.main.id
}
resource "huaweicloud_elb_pool" "main" {
name = "${var.project_name}-backend-pool"
protocol = "HTTP"
lb_method = "ROUND_ROBIN"
listener_id = huaweicloud_elb_listener.https.id
persistence {
type = "APP_COOKIE"
cookie_name = "JSESSIONID"
}
health_check {
protocol = "HTTP"
delay = 30
timeout = 5
max_retries = 3
url_path = "/health"
}
}
resource "huaweicloud_elb_member" "api_01" {
address = huaweicloud_compute_instance.api_01.access_ip_v4
protocol_port = 3000
pool_id = huaweicloud_elb_pool.main.id
subnet_id = huaweicloud_vpc_subnet.public_a.id
}
resource "huaweicloud_elb_member" "api_02" {
address = huaweicloud_compute_instance.api_02.access_ip_v4
protocol_port = 3000
pool_id = huaweicloud_elb_pool.main.id
subnet_id = huaweicloud_vpc_subnet.public_b.id
}
Outputs
Create outputs.tf:
output "vpc_id" {
value = huaweicloud_vpc.main.id
}
output "elb_ip" {
value = huaweicloud_elb_loadbalancer.main.ipv4_address
}
output "ecs_instance_ips" {
value = [
huaweicloud_compute_instance.api_01.access_ip_v4,
huaweicloud_compute_instance.api_02.access_ip_v4
]
}
output "rds_endpoint" {
value = huaweicloud_rds_instance.postgresql.private_ips[0]
}
output "redis_endpoint" {
value = huaweicloud_dcs_instance.redis.ip
}
Usage
Initialize Terraform
terraform init
Plan Changes
terraform plan -var-file=production.tfvars
Apply Configuration
terraform apply -var-file=production.tfvars
Destroy Infrastructure
terraform destroy -var-file=production.tfvars
Environment-Specific Configurations
production.tfvars
environment = "production"
region = "ap-southeast-1"
vpc_cidr = "10.0.0.0/16"
staging.tfvars
environment = "staging"
region = "ap-southeast-1"
vpc_cidr = "10.1.0.0/16"
Best Practices
- State Management: Use remote state (OBS) for team collaboration
- Variables: Use
.tfvarsfiles for environment-specific values - Modules: Create reusable modules for common patterns
- Versioning: Pin provider versions
- Secrets: Use environment variables or secret management for sensitive data
- Documentation: Document all resources and their purposes
- Testing: Test changes in staging before production
Next Steps
- Review Cloud Architecture for manual setup
- Configure Networking for network details
- Set up High Availability configuration