diff --git a/iac-template/terraform-hcl-standard/vultr-vps/README.md b/iac-template/terraform-hcl-standard/vultr-vps/README.md new file mode 100644 index 0000000..80e44ea --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/README.md @@ -0,0 +1,36 @@ +# Vultr VPS Terraform Standard + +此目录在保持 AWS 模板目录结构的同时,提供 Vultr VPS 的等效实现,方便在 Vultr 上快速落地基础设施。模板包含引导阶段(bootstrap)、环境示例(envs)与模块库(modules),与 `aws-cloud`/`gcp-cloud` 目录一一对应。 + +## AWS → Vultr 资源映射 +- **VPC (aws_vpc)** → `vultr_vpc`:创建私网并自定义 IPv4 段。 +- **EC2 (aws_instance)** → `vultr_instance`:创建 VPS/计算实例,支持自定义镜像与云初始化脚本。 +- **S3 (aws_s3_bucket)** → `vultr_object_storage`:提供 S3 兼容对象存储,可用于远端状态与应用资产。 +- **IAM (aws_iam_user/role + aws_key_pair)** → `vultr_user` + `vultr_ssh_key`:管理子账号权限与 SSH 公钥分发。 +- **RDS (aws_db_instance)** → `vultr_database`:托管数据库(MySQL/PostgreSQL/Redis),支持自动备份与高可用套餐。 + +## 目录结构 +- `bootstrap-object-storage/`:初始化 Vultr 对象存储集群与访问密钥,可作为 Terraform 远端状态桶。 +- `bootstrap-iam/`:创建子账号与 SSH Key,实现最小权限访问与实例登录。 +- `config/`:包含通用的 `backend.tf` 与 `provider.tf`,用于配置 S3 兼容后端与 Vultr Provider。 +- `modules/`:核心模块实现(vpc、compute、storage、iam、data_store),接口与 AWS 模块命名保持一致。 +- `envs/`:示例环境(`dev`)展示如何组合模块。 + +## 使用方式 +1. 在 `config/backend.tf` 中填写 Vultr 对象存储的 endpoint、bucket、访问密钥;在 `config/provider.tf` 设置 `vultr_api_key` 与默认 region。 +2. 使用引导模板创建状态桶与基础身份: + ```bash + terraform -chdir=bootstrap-object-storage init + terraform -chdir=bootstrap-object-storage apply + + terraform -chdir=bootstrap-iam init + terraform -chdir=bootstrap-iam apply + ``` +3. 根据需要复制 `envs/dev`,调整变量后运行: + ```bash + terraform -chdir=envs/dev init + terraform -chdir=envs/dev apply + ``` +4. 模块可单独在 `envs` 下拆分(如 `dev-vpc`, `dev-compute`),以匹配 AWS 目录的分环境实践。 + +> 本目录只新增 Vultr 代码,不改动既有 AWS/GCP 模板。 diff --git a/iac-template/terraform-hcl-standard/vultr-vps/bootstrap-iam/main.tf b/iac-template/terraform-hcl-standard/vultr-vps/bootstrap-iam/main.tf new file mode 100644 index 0000000..abf5d21 --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/bootstrap-iam/main.tf @@ -0,0 +1,70 @@ +terraform { + required_version = ">= 1.5" + + required_providers { + vultr = { + source = "vultr/vultr" + version = "~> 2.19" + } + } +} + +provider "vultr" { + api_key = var.vultr_api_key +} + +resource "vultr_user" "readonly" { + email = var.user_email + api_enabled = true + acls = var.acls + password = var.user_password +} + +resource "vultr_ssh_key" "bootstrap" { + name = var.ssh_key_name + ssh_key = var.public_key +} + +output "user_id" { + value = vultr_user.readonly.id + description = "最小权限 API 子账号 ID" +} + +output "ssh_key_id" { + value = vultr_ssh_key.bootstrap.id + description = "上传到 Vultr 的 SSH 公钥 ID" +} + +variable "vultr_api_key" { + description = "管理账号 API Key" + type = string + sensitive = true +} + +variable "user_email" { + description = "子账号邮箱" + type = string +} + +variable "user_password" { + description = "子账号初始密码" + type = string + sensitive = true +} + +variable "acls" { + description = "授予子账号的权限集合,例如 [\"subscriptions\", \"support\"]" + type = list(string) + default = ["subscriptions", "support", "billing"] +} + +variable "ssh_key_name" { + description = "SSH Key 的名称标签" + type = string + default = "bootstrap-key" +} + +variable "public_key" { + description = "SSH 公钥内容" + type = string +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/bootstrap-object-storage/main.tf b/iac-template/terraform-hcl-standard/vultr-vps/bootstrap-object-storage/main.tf new file mode 100644 index 0000000..0b150cc --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/bootstrap-object-storage/main.tf @@ -0,0 +1,85 @@ +terraform { + required_version = ">= 1.5" + + required_providers { + vultr = { + source = "vultr/vultr" + version = "~> 2.19" + } + } +} + +provider "vultr" { + api_key = var.vultr_api_key +} + +resource "vultr_object_storage" "state" { + region = var.region + cluster_id = var.cluster_id + label = var.name + smtp_enabled = false + minio_access = true + minio_secret = var.seed_secret + bucket_name = var.bucket +} + +resource "vultr_object_storage_key" "state" { + object_storage_id = vultr_object_storage.state.id + description = "terraform-state" +} + +output "bucket" { + description = "对象存储桶名称" + value = vultr_object_storage.state.bucket_name +} + +output "endpoint" { + description = "S3 兼容 Endpoint" + value = vultr_object_storage.state.s3_hostname +} + +output "access_key" { + description = "访问密钥 Access Key" + value = vultr_object_storage_key.state.access_key + sensitive = true +} + +output "secret_key" { + description = "访问密钥 Secret Key" + value = vultr_object_storage_key.state.secret_key + sensitive = true +} + +variable "vultr_api_key" { + description = "Vultr API Key" + type = string + sensitive = true +} + +variable "region" { + description = "Vultr 区域代码" + type = string +} + +variable "cluster_id" { + description = "对象存储集群 ID(例如 ewr1)" + type = string +} + +variable "bucket" { + description = "对象存储桶名称" + type = string +} + +variable "name" { + description = "资源标签" + type = string + default = "terraform-state" +} + +variable "seed_secret" { + description = "可选的初始密钥种子,确保生成的 secret 可追踪" + type = string + default = "" + sensitive = true +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/config/backend.tf b/iac-template/terraform-hcl-standard/vultr-vps/config/backend.tf new file mode 100644 index 0000000..a3ffc7d --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/config/backend.tf @@ -0,0 +1,46 @@ +terraform { + backend "s3" { + endpoint = var.object_storage_endpoint + bucket = var.state_bucket + key = var.state_key + region = var.region + access_key = var.access_key + secret_key = var.secret_key + skip_credentials_validation = true + skip_region_validation = true + skip_requesting_account_id = true + force_path_style = true + } +} + +variable "object_storage_endpoint" { + description = "Vultr 对象存储的 S3 兼容 Endpoint (例如 https://ewr1.vultrobjects.com)" + type = string +} + +variable "state_bucket" { + description = "用于存储 Terraform state 的对象存储桶" + type = string +} + +variable "state_key" { + description = "state 文件路径,例如 vpc/dev/terraform.tfstate" + type = string +} + +variable "region" { + description = "Vultr 区域代码,例如 ewr、sgp、fra" + type = string +} + +variable "access_key" { + description = "对象存储访问密钥 Access Key" + type = string + sensitive = true +} + +variable "secret_key" { + description = "对象存储访问密钥 Secret Key" + type = string + sensitive = true +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/config/provider.tf b/iac-template/terraform-hcl-standard/vultr-vps/config/provider.tf new file mode 100644 index 0000000..d195873 --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/config/provider.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.5" + + required_providers { + vultr = { + source = "vultr/vultr" + version = "~> 2.19" + } + } +} + +provider "vultr" { + api_key = var.vultr_api_key + rate_limit = 700 +} + +variable "vultr_api_key" { + description = "Vultr API Key,建议通过环境变量 VULTR_API_KEY 提供" + type = string + sensitive = true +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/envs/dev/cloud-init.yaml b/iac-template/terraform-hcl-standard/vultr-vps/envs/dev/cloud-init.yaml new file mode 100644 index 0000000..2a68a60 --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/envs/dev/cloud-init.yaml @@ -0,0 +1,6 @@ +#cloud-config +package_update: true +package_upgrade: true +runcmd: + - echo "Hello from Vultr dev environment" > /etc/motd + - systemctl enable ssh diff --git a/iac-template/terraform-hcl-standard/vultr-vps/envs/dev/main.tf b/iac-template/terraform-hcl-standard/vultr-vps/envs/dev/main.tf new file mode 100644 index 0000000..03014d5 --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/envs/dev/main.tf @@ -0,0 +1,80 @@ +terraform { + required_version = ">= 1.5" + + required_providers { + vultr = { + source = "vultr/vultr" + version = "~> 2.19" + } + } +} + +provider "vultr" { + api_key = var.vultr_api_key +} + +module "vpc" { + source = "../modules/vpc" + region = var.region + description = var.vpc_description + v4_subnet = var.v4_subnet + v4_subnet_size = var.v4_subnet_size +} + +module "iam" { + source = "../modules/iam" + users = var.users + ssh_keys = var.ssh_keys +} + +module "storage" { + source = "../modules/storage" + region = var.region + cluster_id = var.cluster_id + object_bucket = var.object_bucket + enable_block = var.enable_block + block_size_gb = var.block_size_gb + label = "${var.name_prefix}-storage" +} + +module "compute" { + source = "../modules/compute" + label = "${var.name_prefix}-vm" + region = var.region + plan = var.plan + os_id = var.os_id + enable_ipv6 = true + backups = true + tags = [var.name_prefix, "dev"] + vpc_id = module.vpc.vpc_id + ssh_key_ids = values(module.iam.ssh_key_ids) + user_data = file(var.user_data_file) +} + +module "data_store" { + source = "../modules/data_store" + label = "${var.name_prefix}-db" + region = var.region + engine = var.db_engine + plan = var.db_plan + dbname = var.dbname + username = var.db_username + password = var.db_password + ha = var.db_ha +} + +output "vpc_id" { + value = module.vpc.vpc_id +} + +output "instance_ip" { + value = module.compute.main_ip +} + +output "bucket" { + value = module.storage.bucket_name +} + +output "database_dsn" { + value = module.data_store.dsn +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/envs/dev/variables.tf b/iac-template/terraform-hcl-standard/vultr-vps/envs/dev/variables.tf new file mode 100644 index 0000000..7646c49 --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/envs/dev/variables.tf @@ -0,0 +1,144 @@ +variable "vultr_api_key" { + description = "Vultr API Key" + type = string + sensitive = true +} + +variable "region" { + description = "部署区域" + type = string + default = "ewr" +} + +variable "vpc_description" { + description = "VPC 描述" + type = string + default = "dev-vpc" +} + +variable "v4_subnet" { + description = "VPC IPv4 段" + type = string + default = "10.20.0.0" +} + +variable "v4_subnet_size" { + description = "掩码位数" + type = number + default = 22 +} + +variable "cluster_id" { + description = "对象存储集群 ID" + type = string + default = "ewr1" +} + +variable "object_bucket" { + description = "对象存储桶名称" + type = string + default = "dev-app-bucket" +} + +variable "enable_block" { + description = "是否创建块存储" + type = bool + default = true +} + +variable "block_size_gb" { + description = "块存储大小" + type = number + default = 100 +} + +variable "name_prefix" { + description = "资源名前缀" + type = string + default = "demo" +} + +variable "plan" { + description = "实例套餐" + type = string + default = "vc2-1c-1gb" +} + +variable "os_id" { + description = "操作系统 ID" + type = number + default = 215 +} + +variable "users" { + description = "子账号配置" + type = list(object({ + email = string + password = string + acls = list(string) + })) + default = [ + { + email = "devops@example.com" + password = "ChangeMe123!" + acls = ["subscriptions", "support"] + } + ] +} + +variable "ssh_keys" { + description = "SSH 公钥列表" + type = list(object({ + name = string + public = string + })) + default = [ + { + name = "dev-key" + public = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKexamplegenerated dev@example" + } + ] +} + +variable "user_data_file" { + description = "cloud-init 脚本路径" + type = string + default = "cloud-init.yaml" +} + +variable "db_engine" { + description = "数据库引擎" + type = string + default = "pg" +} + +variable "db_plan" { + description = "数据库套餐" + type = string + default = "vultr-dbaas-startup-cc-1-7-5" +} + +variable "dbname" { + description = "数据库名称" + type = string + default = "app" +} + +variable "db_username" { + description = "数据库用户名" + type = string + default = "app" +} + +variable "db_password" { + description = "数据库密码" + type = string + sensitive = true + default = "ChangeMeP@ssw0rd" +} + +variable "db_ha" { + description = "启用数据库高可用" + type = bool + default = false +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/modules/compute/main.tf b/iac-template/terraform-hcl-standard/vultr-vps/modules/compute/main.tf new file mode 100644 index 0000000..0d453da --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/modules/compute/main.tf @@ -0,0 +1,84 @@ +variable "label" { + description = "实例名称" + type = string +} + +variable "region" { + description = "Vultr 区域代码" + type = string +} + +variable "plan" { + description = "Vultr 计费套餐 (例如 vc2-1c-1gb)" + type = string +} + +variable "os_id" { + description = "操作系统 ID,参考 Vultr 文档 (例:215 为 Ubuntu 22.04)" + type = number +} + +variable "enable_ipv6" { + description = "是否启用 IPv6" + type = bool + default = true +} + +variable "backups" { + description = "启用自动备份" + type = bool + default = false +} + +variable "tags" { + description = "实例标签列表" + type = list(string) + default = [] +} + +variable "vpc_id" { + description = "可选的 VPC ID,将实例加入私网" + type = string + default = null +} + +variable "ssh_key_ids" { + description = "已上传的 SSH Key ID 列表" + type = list(string) + default = [] +} + +variable "user_data" { + description = "cloud-init 用户数据" + type = string + default = "" +} + +resource "vultr_instance" "this" { + label = var.label + region = var.region + plan = var.plan + os_id = var.os_id + enable_ipv6 = var.enable_ipv6 + backups = var.backups + tags = var.tags + vpc_ids = var.vpc_id == null ? [] : [var.vpc_id] + ssh_key_ids = var.ssh_key_ids + user_data = var.user_data +} + +output "instance_id" { + value = vultr_instance.this.id + description = "实例 ID" +} + +output "main_ip" { + value = vultr_instance.this.main_ip + description = "主公网 IP" +} + +output "default_password" { + value = vultr_instance.this.default_password + description = "系统生成密码(如未使用 SSH Key 时)" + sensitive = true +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/modules/data_store/main.tf b/iac-template/terraform-hcl-standard/vultr-vps/modules/data_store/main.tf new file mode 100644 index 0000000..7756e17 --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/modules/data_store/main.tf @@ -0,0 +1,72 @@ +variable "label" { + description = "数据库实例标签" + type = string + default = "app-db" +} + +variable "region" { + description = "Vultr 区域代码" + type = string +} + +variable "engine" { + description = "数据库引擎 (mysql, pg, redis)" + type = string +} + +variable "plan" { + description = "数据库套餐代号(如 vultr-dbaas-startup-cc-1-7-5)" + type = string +} + +variable "dbname" { + description = "数据库名称" + type = string + default = "app" +} + +variable "username" { + description = "数据库用户名" + type = string + default = "app" +} + +variable "password" { + description = "数据库密码" + type = string + sensitive = true +} + +variable "ha" { + description = "启用高可用" + type = bool + default = false +} + +resource "vultr_database" "this" { + label = var.label + region = var.region + plan = var.plan + engine = var.engine + replicas = var.ha ? 1 : 0 + + database = var.dbname + username = var.username + password = var.password +} + +output "dsn" { + description = "标准连接串(host:port/database)" + value = "${vultr_database.this.hostname}:${vultr_database.this.port}/${vultr_database.this.database}" +} + +output "username" { + value = vultr_database.this.username + description = "数据库用户名" +} + +output "password" { + value = vultr_database.this.password + sensitive = true + description = "数据库密码" +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/modules/iam/main.tf b/iac-template/terraform-hcl-standard/vultr-vps/modules/iam/main.tf new file mode 100644 index 0000000..8ab8c19 --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/modules/iam/main.tf @@ -0,0 +1,42 @@ +variable "users" { + description = "需要创建的子账号列表" + type = list(object({ + email = string + password = string + acls = list(string) + })) + default = [] +} + +variable "ssh_keys" { + description = "需要上传的 SSH 公钥列表" + type = list(object({ + name = string + public = string + })) + default = [] +} + +resource "vultr_user" "this" { + for_each = { for u in var.users : u.email => u } + email = each.value.email + password = each.value.password + api_enabled = true + acls = each.value.acls +} + +resource "vultr_ssh_key" "this" { + for_each = { for k in var.ssh_keys : k.name => k } + name = each.value.name + ssh_key = each.value.public +} + +output "user_ids" { + value = { for k, v in vultr_user.this : k => v.id } + description = "创建的子账号 ID 映射" +} + +output "ssh_key_ids" { + value = { for k, v in vultr_ssh_key.this : k => v.id } + description = "上传的 SSH Key ID 映射" +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/modules/storage/main.tf b/iac-template/terraform-hcl-standard/vultr-vps/modules/storage/main.tf new file mode 100644 index 0000000..c4de958 --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/modules/storage/main.tf @@ -0,0 +1,80 @@ +variable "region" { + description = "Vultr 区域代码" + type = string +} + +variable "object_bucket" { + description = "对象存储桶名称" + type = string +} + +variable "cluster_id" { + description = "对象存储集群 ID (如 ewr1)" + type = string +} + +variable "enable_block" { + description = "是否同时创建块存储卷" + type = bool + default = false +} + +variable "block_size_gb" { + description = "块存储大小 (GB)" + type = number + default = 100 +} + +variable "label" { + description = "资源标签" + type = string + default = "app-storage" +} + +resource "vultr_object_storage" "bucket" { + region = var.region + cluster_id = var.cluster_id + label = var.label + bucket_name = var.object_bucket + minio_access = true +} + +resource "vultr_object_storage_key" "bucket" { + object_storage_id = vultr_object_storage.bucket.id + description = "app-storage" +} + +resource "vultr_block_storage" "volume" { + count = var.enable_block ? 1 : 0 + region = var.region + label = "${var.label}-block" + size_gb = var.block_size_gb + block_type = "storage_opt" +} + +output "bucket_name" { + value = vultr_object_storage.bucket.bucket_name + description = "创建的对象存储桶" +} + +output "bucket_endpoint" { + value = vultr_object_storage.bucket.s3_hostname + description = "S3 兼容 Endpoint" +} + +output "access_key" { + value = vultr_object_storage_key.bucket.access_key + sensitive = true + description = "对象存储 Access Key" +} + +output "secret_key" { + value = vultr_object_storage_key.bucket.secret_key + sensitive = true + description = "对象存储 Secret Key" +} + +output "block_volume_id" { + value = try(vultr_block_storage.volume[0].id, null) + description = "可选块存储卷 ID" +} diff --git a/iac-template/terraform-hcl-standard/vultr-vps/modules/vpc/main.tf b/iac-template/terraform-hcl-standard/vultr-vps/modules/vpc/main.tf new file mode 100644 index 0000000..3f02058 --- /dev/null +++ b/iac-template/terraform-hcl-standard/vultr-vps/modules/vpc/main.tf @@ -0,0 +1,32 @@ +variable "region" { + description = "Vultr 区域代码" + type = string +} + +variable "description" { + description = "VPC 描述标签" + type = string + default = "app-vpc" +} + +variable "v4_subnet" { + description = "VPC 的 IPv4 子网,例如 10.10.0.0/22" + type = string +} + +variable "v4_subnet_size" { + description = "子网掩码位数,Vultr 需要单独传递" + type = number +} + +resource "vultr_vpc" "this" { + region = var.region + description = var.description + v4_subnet = var.v4_subnet + v4_subnet_size = var.v4_subnet_size +} + +output "vpc_id" { + value = vultr_vpc.this.id + description = "创建的 VPC ID" +}