Terraform实战10:RDS + Secrets Manager——数据库与密钥管理
Terraform实战10RDS Secrets Manager——数据库与密钥管理本篇目标用Terraform创建RDS MySQL数据库配合Secrets Manager安全管理数据库密码。理解数据库子网组、安全访问控制和密钥管理最佳实践。学完本篇你将掌握RDS数据库的创建和配置数据库子网组DB Subnet GroupSecrets Manager存储和管理密码random_password生成安全密码数据库安全组设计只允许应用层访问前置条件已完成前九篇练习理解VPC公私网和安全组为什么需要Secrets Manager之前的练习中密码可以写在变量里但生产环境这样做很危险方式问题密码写在代码里推到Git后所有人都能看到密码写在tfvars里tfvars可能被提交或本地泄露密码写在环境变量里不方便管理和轮转Secrets Manager加密存储、API获取、支持自动轮转、有审计日志架构图┌─────────────────────────────────────────────────────────┐ │ VPC (10.0.0.0/16) │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌───────────┐ │ │ │ 公有子网(2个) │ │ 私有子网(2个) │ │DB子网(2个)│ │ │ │ 10.0.1-2.0/24│ │ 10.0.10-11/24│ │10.0.20-21 │ │ │ └───────────────┘ └───────────────┘ └─────┬─────┘ │ │ │ │ │ ┌──────┴──────┐ │ │ │ RDS MySQL │ │ │ │ db.t3.micro│ │ │ │ port:3306 │ │ │ └─────────────┘ │ │ ↑ │ │ 安全组 │ │ 只允许VPC内部3306 │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────┐ │ Secrets Manager │ │ 存储DB用户名/密码 │ ← 应用通过API获取密码 └─────────────────────┘目录结构10-rds-secrets/ ├── main.tf # VPC RDS Secrets Manager 安全组 ├── variables.tf # 变量DB规格、库名、用户名 └── outputs.tf # 输出端点地址、Secret名称完整代码main.tfterraform { 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} common_tags { Project var.project_name Environment var.environment ManagedBy terraform } } # VPC注意多了database_subnets 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] # 【新增】数据库专用子网 # 社区模块自动创建数据库子网组 create_database_subnet_group true database_subnet_group_name ${local.name_prefix}-db-subnet-group enable_nat_gateway false enable_dns_hostnames true enable_dns_support true tags local.common_tags } # 【新资源】随机密码不把密码写在代码里 resource random_password db_password { length 16 special true override_special !#$%*()-_[]{}:? } # 【新资源】Secrets Manager - 密钥存储 resource aws_secretsmanager_secret db_credentials { name ${local.name_prefix}-db-credentials description RDS database credentials recovery_window_in_days 0 # 练习用生产用7-30天 tags local.common_tags } # Secret的值JSON格式 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 }) } # 安全组 - 只允许VPC内部访问3306 resource aws_security_group rds { name ${local.name_prefix}-rds-sg vpc_id module.vpc.vpc_id ingress { description MySQL from VPC from_port 3306 to_port 3306 protocol tcp cidr_blocks [module.vpc.vpc_cidr_block] } 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 }) } # 【新资源】RDS MySQL resource aws_db_instance mysql { identifier ${local.name_prefix}-mysql # 引擎 engine mysql engine_version 8.0 instance_class var.db_instance_class # 存储 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 }) }variables.tfvariable region { default us-east-1 } variable project_name { default tf-practice } variable environment { default dev } variable db_instance_class { description RDS实例规格 default db.t3.micro } variable db_name { description 数据库名称 default myapp } variable db_username { description 数据库管理员用户名 default admin }outputs.tfoutput rds_endpoint { description RDS连接地址 value aws_db_instance.mysql.endpoint } output rds_port { value aws_db_instance.mysql.port } output rds_database_name { value aws_db_instance.mysql.db_name } output secret_name { description Secrets Manager中的密钥名称 value aws_secretsmanager_secret.db_credentials.name } output secret_arn { description Secret ARN value aws_secretsmanager_secret.db_credentials.arn } # 不输出密码明文通过API获取 output how_to_get_password { value aws secretsmanager get-secret-value --secret-id ${aws_secretsmanager_secret.db_credentials.name} --query SecretString --output text }新增资源说明RDS关键字段字段含义示例值identifierRDS实例标识控制台显示的名称“tf-practice-dev-mysql”engine/engine_version数据库引擎和版本“mysql” / “8.0”instance_class实例规格“db.t3.micro”allocated_storage初始存储(GB)20max_allocated_storage存储自动扩展上限(GB)50storage_type存储类型“gp3”性价比最高storage_encrypted是否加密存储truedb_subnet_group_name数据库子网组跨2个AZpublicly_accessible是否允许公网访问false必须multi_az是否多AZ高可用生产true练习falsebackup_retention_period备份保留天数生产7-30练习1skip_final_snapshot删除时是否跳过最终快照生产false练习truedeletion_protection防止误删生产true练习falseSecrets Manager关键字段字段含义name密钥名称全局唯一recovery_window_in_days删除后保留天数0立即删生产用7-30secret_string密钥值通常是JSON格式random_passwordresource random_password db_password { length 16 # 密码长度 special true # 包含特殊字符 override_special !#$%*()... # 指定允许的特殊字符 } # 引用random_password.db_password.resultdatabase_subnetsVPC模块新参数module vpc { # ... database_subnets [10.0.20.0/24, 10.0.21.0/24] # 数据库专用子网 create_database_subnet_group true # 自动创建子网组 database_subnet_group_name xxx-db-subnet-group # 子网组名称 }RDS要求至少2个AZ的子网才能创建子网组。社区VPC模块支持直接传database_subnets参数自动处理。操作步骤与实际输出ApplyRDS创建约6-7分钟terraform apply -auto-approvemodule.vpc.aws_db_subnet_group.database[0]: Creation complete after 3s aws_security_group.rds: Creation complete after 7s aws_db_instance.mysql: Still creating... [6m0s elapsed] aws_db_instance.mysql: Creation complete after 6m30s Apply complete! Resources: 27 added, 0 changed, 0 destroyed. Outputs: rds_endpoint tf-practice-dev-mysql.cqnyouc4a558.us-east-1.rds.amazonaws.com:3306 rds_database_name myapp secret_name tf-practice-dev-db-credentials how_to_get_password aws secretsmanager get-secret-value --secret-id tf-practice-dev-db-credentials --query SecretString --output text获取密码通过API而非明文输出aws secretsmanager get-secret-value\--secret-id tf-practice-dev-db-credentials\--querySecretString--outputtext返回JSON{username:admin,password:随机生成的16位密码,dbname:myapp,host:tf-practice-dev-mysql.xxx.rds.amazonaws.com:3306,port:3306,engine:mysql}控制台验证RDS实例详情引擎MySQL 8.0规格db.t3.micro状态Available连接与安全公网访问NoVPC和子网组Secrets Manager密钥已创建数据库子网组跨2个AZDestroyterraform destroy -auto-approve# Destroy complete! Resources: 27 destroyed.安全最佳实践实践本篇演示生产环境建议密码不写在代码里✅ random_password生成✅密码存在Secrets Manager✅✅ 开启自动轮转RDS不可公网访问✅ publicly_accessiblefalse✅安全组限制来源✅ 只允许VPC内部进一步限制到应用安全组存储加密✅ storage_encryptedtrue✅ 用自定义KMS key多AZ高可用❌ 省钱关闭✅ multi_aztrue删除保护❌ 练习关闭✅ deletion_protectiontrue备份保留1天7-30天延伸思考面试常见问题面试问题答案要点RDS密码怎么管理random_password生成 Secrets Manager存储不在代码中明文为什么RDS要放私有子网不暴露公网只允许VPC内部应用访问DB Subnet Group是什么告诉RDS可以在哪些子网创建实例至少跨2个AZmulti_az有什么用主从自动切换主实例挂了自动failover到备用AZ应用怎么获取数据库密码通过Secrets Manager API获取不写死在配置文件里gp3和gp2的区别gp3性价比更高基准性能更好可独立调整IOPS费用说明资源费用RDS db.t3.micro~$0.017/小时Secrets Manager~$0.40/月按比例VPC / 子网 / 安全组免费总计~$0.02/小时本次练习约15分钟约$0.01小结本篇核心收获RDS放私有子网publicly_accessiblefalse是安全标配random_password生成密码 Secrets Manager存储 安全的密码管理DB Subnet Group需要至少2个AZ的子网VPC模块可自动创建不输出密码明文通过Secrets Manager API获取生产环境要开multi_az、deletion_protection、更长的备份保留下一篇预告Terraform实战11完整三层架构VPC ALB EKS RDS下一篇将串联前面所有知识构建一个完整的生产级架构VPC网络层ALB负载均衡层EKS计算层RDS数据层所有组件通过模块组合参考链接本系列配套代码GitHubTerraform aws_db_instance文档Terraform aws_secretsmanager_secret文档AWS RDS最佳实践AWS Secrets Manager文档Terraform random_password文档

相关新闻

Maixcam2 IMU低零飘姿态解算:从校准到互补滤波的工程实践

Maixcam2 IMU低零飘姿态解算:从校准到互补滤波的工程实践

这次我们来看一个针对 Maixcam2 开发板的实用项目:如何利用其板载的 IMU(惯性测量单元)实现低零飘的姿态解算。对于嵌入式开发者和机器人爱好者来说,IMU 的零飘(零点漂移)是影响姿态角(如俯仰角…

2026/10/13 11:54:40 阅读更多 →
Python量化分析:从复权因子到前复权与后复权价格计算全解析

Python量化分析:从复权因子到前复权与后复权价格计算全解析

1. 从一次数据回测的“乌龙”说起 前段时间,我帮一个做量化策略的朋友看他的回测代码,发现了一个很有意思的问题。他的策略是基于历史股价的均线系统,但回测结果和他在专业软件(比如同花顺)上手动计算的结果总是对不上…

2026/10/13 11:54:53 阅读更多 →
Android存储权限演进与Operation not permitted异常全解析

Android存储权限演进与Operation not permitted异常全解析

1. 项目概述:一个困扰安卓开发者多年的“顽疾” 如果你是一名安卓开发者,并且你的应用需要访问设备的外部存储(也就是我们常说的SD卡),那么你大概率遇到过这个令人头疼的异常: java.io.IOException: Opera…

2026/10/13 11:54:57 阅读更多 →

最新新闻

Service层命名规范:从见名知意到代码可维护性

Service层命名规范:从见名知意到代码可维护性

接手一个业务系统,我最怕看到的不是复杂算法,而是那种一打开就让人头晕的 Service 实现类。2000 行起步,方法名字从 process 到 handle 再到 doSomething,翻遍整个类也猜不出某个方法是干嘛的。命名这种事,看起来不影响…

2026/10/13 17:55:28 阅读更多 →
Windows内核模块枚举与隐藏原理深度解析

Windows内核模块枚举与隐藏原理深度解析

1. 这不是“找模块”,而是在内核内存里做一次精准外科手术“枚举和隐藏内核模块”——这八个字在安全研究、驱动开发或系统调试场景中,绝不是一句轻飘飘的技术术语。它背后是一整套对Windows内核运行时状态的深度观测与主动干预能力。我第一次在某高校实…

2026/10/13 17:55:28 阅读更多 →
Hibernate二级缓存Provider详解:从原理到选型与排坑

Hibernate二级缓存Provider详解:从原理到选型与排坑

被人突然问起“Hibernate的caching provider是什么”,我第一反应是:能问出这个词的人,多半已经看到配置文件里那一堆以hibernate.cache开头的键,但又没搞懂这些键到底在切换什么。这篇文章就把这个词拆开讲清楚,重点解…

2026/10/13 17:55:28 阅读更多 →
电能质量复合扰动识别:混沌集成决策树实战解析

电能质量复合扰动识别:混沌集成决策树实战解析

简介:这是一份面向电能质量复合扰动识别研究的MATLAB完整源程序包,对应知网论文《基于混沌集成决策树的电能质量复合扰动识别》,可作为电气工程、信号处理及机器学习方向的毕业设计或课题研究参考,帮助复现算法并开展对比实验。程…

2026/10/13 17:55:28 阅读更多 →
CentOS局域网DNS搭建:BIND9多域名权威解析实战

CentOS局域网DNS搭建:BIND9多域名权威解析实战

1. 为什么在CentOS上自建局域网DNS不是“多此一举”,而是刚需落地的第一步很多人看到“CentOS搭建局域网DNS”第一反应是:不就是改个/etc/resolv.conf?内网查个主机名用/etc/hosts不就完事了?我试过——在某高校实验室的物联网教学…

2026/10/13 17:55:28 阅读更多 →
ActiveMQ consumerCount精准获取与实战调优指南

ActiveMQ consumerCount精准获取与实战调优指南

1. 项目概述:为什么“获取消费者数量”是 ActiveMQ 运维与调优的黄金指标在某公司消息中间件团队的实际运维中,我接手的第一个紧急故障就和consumerCount直接相关——一个订单履约服务突然延迟飙升,下游库存扣减平均耗时从200ms暴涨到8秒。排…

2026/10/13 17:54:25 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →