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


小结

本篇核心收获:

  1. 三层架构是生产环境的标准设计(网络/计算/数据分离)
  2. 65个资源通过模块组合,一套代码管理
  3. 安全组链实现层与层之间的精确访问控制
  4. 6个子网各有职责(公有/私有/数据库)
  5. 这就是你简历上的Terraform项目——面试时能完整讲出来

下一篇预告

Terraform实战12:CI/CD集成——GitLab CI + Terraform自动化

下一篇进入进阶阶段:

  • 把Terraform集成到GitLab CI pipeline
  • 自动plan(MR时预览变更)
  • 手动approve后apply
  • 状态锁和并发控制

参考链接

更多推荐