Terraform实战11:完整三层架构——VPC + EKS + RDS
·
Terraform实战11:完整三层架构——VPC + EKS + RDS

本篇目标
将前面所有知识串联,用一套Terraform代码构建完整的生产级三层架构。这是面试时最有说服力的Terraform项目。
学完本篇你将掌握:
- 完整三层架构的设计思路(网络层 + 计算层 + 数据层)
- 多个模块的组合编排
- 层与层之间的安全隔离(安全组链)
- 65个资源的依赖管理
- 生产级基础设施的全貌
前置条件
- 已完成第8-10篇(EKS、ALB、RDS单独练习)
架构设计
┌─────────────────────────────────────────────────────────────────┐
│ VPC (10.0.0.0/16) │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌───────────────┐ │
│ │ 公有子网 (2 AZ) │ │ 私有子网 (2 AZ) │ │ DB子网 (2 AZ) │ │
│ │ 10.0.1-2.0/24 │ │ 10.0.10-11.0/24│ │ 10.0.20-21/24│ │
│ │ │ │ │ │ │ │
│ │ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐│ │
│ │ │NAT Gateway│ │ │ │EKS Nodes │ │ │ │RDS MySQL ││ │
│ │ └───────────┘ │ │ │(t3.micro) │ │ │ │(db.t3.micro)│ │
│ │ │ │ └─────┬─────┘ │ │ └─────┬─────┘│ │
│ └─────────────────┘ └───────┼─────────┘ └───────┼───────┘ │
│ │ │ │
│ │ 安全组:只允许 │ │
│ │ EKS节点 → 3306 │ │
│ └─────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ EKS Control Plane (AWS托管) │ │
│ │ API: https://xxx.eks.amazonaws.com │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────┐
│ Secrets Manager │ ← 存储RDS密码
└─────────────────────┘
三层职责
| 层 | 子网 | 资源 | 职责 |
|---|---|---|---|
| 网络层 | 公有子网 | NAT Gateway、未来的ALB | 对外通信出入口 |
| 计算层 | 私有子网 | EKS节点 | 运行业务容器 |
| 数据层 | 数据库子网 | RDS MySQL | 持久化数据 |
安全隔离设计
外网 → 公有子网(NAT/ALB)
↓ 只允许特定端口
EKS节点(私有子网)
↓ 安全组限制:只允许EKS节点安全组访问3306
RDS(数据库子网)
目录结构
11-full-architecture/
├── main.tf # 三层架构所有资源
├── variables.tf # 变量
└── outputs.tf # 三层输出
完整代码
main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.0"
}
}
required_version = ">= 1.0"
}
provider "aws" {
region = var.region
}
locals {
name_prefix = "${var.project_name}-${var.environment}"
cluster_name = "${local.name_prefix}-eks"
common_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
}
}
# ============================================
# 第一层:网络
# 6个子网:2公有 + 2私有 + 2数据库
# ============================================
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.16.0"
name = "${local.name_prefix}-vpc"
cidr = "10.0.0.0/16"
azs = ["${var.region}a", "${var.region}b"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.10.0/24", "10.0.11.0/24"]
database_subnets = ["10.0.20.0/24", "10.0.21.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
enable_dns_support = true
create_database_subnet_group = true
database_subnet_group_name = "${local.name_prefix}-db-subnet-group"
# EKS所需子网标签
public_subnet_tags = {
"kubernetes.io/role/elb" = 1
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
}
private_subnet_tags = {
"kubernetes.io/role/internal-elb" = 1
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
}
tags = local.common_tags
}
# ============================================
# 第二层:计算(EKS)
# ============================================
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "20.31.6"
cluster_name = local.cluster_name
cluster_version = "1.31"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
cluster_endpoint_public_access = true
eks_managed_node_groups = {
default = {
name = "default-node-group"
instance_types = ["t3.micro"]
min_size = 1
max_size = 2
desired_size = 1
labels = { Environment = var.environment }
tags = local.common_tags
}
}
tags = local.common_tags
}
# ============================================
# 第三层:数据(RDS + Secrets Manager)
# ============================================
resource "random_password" "db_password" {
length = 16
special = true
override_special = "!#$%&*()-_=+[]{}<>:?"
}
resource "aws_secretsmanager_secret" "db_credentials" {
name = "${local.name_prefix}-db-credentials"
recovery_window_in_days = 0
tags = local.common_tags
}
resource "aws_secretsmanager_secret_version" "db_credentials" {
secret_id = aws_secretsmanager_secret.db_credentials.id
secret_string = jsonencode({
username = var.db_username
password = random_password.db_password.result
dbname = var.db_name
host = aws_db_instance.mysql.endpoint
port = 3306
engine = "mysql"
})
}
# 【关键】RDS安全组:只允许EKS节点安全组访问
resource "aws_security_group" "rds" {
name = "${local.name_prefix}-rds-sg"
vpc_id = module.vpc.vpc_id
ingress {
description = "MySQL from EKS nodes"
from_port = 3306
to_port = 3306
protocol = "tcp"
security_groups = [module.eks.node_security_group_id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(local.common_tags, { Name = "${local.name_prefix}-rds-sg" })
}
resource "aws_db_instance" "mysql" {
identifier = "${local.name_prefix}-mysql"
engine = "mysql"
engine_version = "8.0"
instance_class = "db.t3.micro"
allocated_storage = 20
max_allocated_storage = 50
storage_type = "gp3"
storage_encrypted = true
db_name = var.db_name
username = var.db_username
password = random_password.db_password.result
db_subnet_group_name = module.vpc.database_subnet_group_name
vpc_security_group_ids = [aws_security_group.rds.id]
publicly_accessible = false
backup_retention_period = 1
skip_final_snapshot = true
multi_az = false
deletion_protection = false
tags = merge(local.common_tags, { Name = "${local.name_prefix}-mysql" })
}
层与层之间的安全隔离
这是本篇最重要的设计点——每层只能访问它该访问的资源:
| 来源 | 目标 | 允许方式 |
|---|---|---|
| 外网 | EKS节点 | ❌ 不允许直接访问 |
| 外网 | RDS | ❌ 不允许(publicly_accessible=false) |
| EKS节点 | RDS:3306 | ✅ 安全组引用节点SG |
| EKS节点 | 外网 | ✅ 通过NAT Gateway |
# RDS安全组的ingress:只允许EKS节点安全组
security_groups = [module.eks.node_security_group_id]
这比用 cidr_blocks = ["10.0.0.0/16"] 更精确——只有EKS节点能访问数据库,同VPC内其他资源不能。
操作步骤与实际输出
Plan
terraform plan
# Plan: 65 to add, 0 to change, 0 to destroy.
65个资源 = 网络层(约20) + EKS(约35) + RDS+Secrets(约10)
Apply(约15-20分钟)
terraform apply -auto-approve
关键耗时:
NAT Gateway: 2m0s
RDS MySQL: 6m39s
EKS Control Plane: 10m24s ← 最慢
EKS Node Group: 1m51s
Apply complete! Resources: 65 added
输出
=== 网络层 ===
VPC: vpc-0f5d11f137a3423a9
公有子网: 2个
私有子网: 2个
数据库子网: 2个
=== 计算层 ===
EKS集群: tf-practice-dev-eks
K8s版本: 1.31
API端点: https://xxx.eks.amazonaws.com
=== 数据层 ===
RDS端点: tf-practice-dev-mysql.xxx.rds.amazonaws.com:3306
Secret名: tf-practice-dev-db-credentials
控制台验证
EKS集群:

RDS实例:

VPC 6个子网:

RDS安全组(只允许EKS节点):

Destroy
terraform destroy -auto-approve
# Destroy complete! Resources: 65 destroyed.
延伸思考:面试怎么讲这个项目
面试开场:
“我用Terraform搭建过完整的三层架构:网络层用VPC社区模块创建6个子网(公有+私有+数据库),计算层用EKS跑业务容器,数据层用RDS MySQL配合Secrets Manager管理密码。安全设计上,RDS的安全组只允许EKS节点安全组访问,不允许公网直连。整个架构65个资源,一套代码管理。”
面试追问和回答:
| 追问 | 回答 |
|---|---|
| 为什么分三种子网? | 公有放NAT/ALB,私有放计算节点,数据库子网放RDS,职责隔离 |
| RDS怎么保证安全? | 不可公网访问 + 安全组只允许EKS节点 + 存储加密 + 密码不在代码中 |
| EKS节点怎么访问RDS? | 同VPC内通过私网连接,安全组放行节点SG到3306 |
| 密码怎么管理? | random_password生成 + Secrets Manager存储,Pod通过API获取 |
| 这套架构有什么不足? | 单NAT单AZ是单点,生产应multi-AZ NAT + RDS multi_az |
费用说明
| 资源 | 费用 |
|---|---|
| EKS控制面 | $0.10/小时 |
| NAT Gateway | $0.045/小时 |
| EC2节点 t3.micro | $0.0104/小时 |
| RDS db.t3.micro | $0.017/小时 |
| 其他(VPC/SG/Secret等) | 免费或极低 |
| 总计 | ~$0.17/小时 |
本次练习(约35分钟):约$0.10
小结
本篇核心收获:
- 三层架构是生产环境的标准设计(网络/计算/数据分离)
- 65个资源通过模块组合,一套代码管理
- 安全组链实现层与层之间的精确访问控制
- 6个子网各有职责(公有/私有/数据库)
- 这就是你简历上的Terraform项目——面试时能完整讲出来
下一篇预告
Terraform实战12:CI/CD集成——GitLab CI + Terraform自动化
下一篇进入进阶阶段:
- 把Terraform集成到GitLab CI pipeline
- 自动plan(MR时预览变更)
- 手动approve后apply
- 状态锁和并发控制
参考链接
更多推荐
所有评论(0)