name: aws-rds-database description: 部署和管理关系数据库使用RDS,支持多可用区、只读副本、备份和加密。适用于PostgreSQL、MySQL、MariaDB和Oracle。
AWS RDS 数据库
概览
Amazon RDS简化了关系数据库的部署和操作。支持多种数据库引擎,具有自动备份、复制、加密和通过多可用区部署实现的高可用性。
使用场景
- PostgreSQL和MySQL应用程序
- 事务数据库和OLTP
- Oracle和Microsoft SQL Server工作负载
- 读密集型应用程序和副本
- 开发和测试环境
- 需要ACID合规性的数据
- 需要自动备份的应用程序
- 灾难恢复场景
实施示例
1. 使用AWS CLI创建RDS实例
# 创建数据库子网组
aws rds create-db-subnet-group \
--db-subnet-group-name app-db-subnet \
--db-subnet-group-description "应用数据库子网" \
--subnet-ids subnet-12345 subnet-67890
# 创建RDS安全组
aws ec2 create-security-group \
--group-name rds-sg \
--description "RDS安全组" \
--vpc-id vpc-12345
# 允许入站PostgreSQL
aws ec2 authorize-security-group-ingress \
--group-id sg-rds123 \
--protocol tcp \
--port 5432 \
--source-security-group-id sg-app123
# 创建RDS实例
aws rds create-db-instance \
--db-instance-identifier myapp-db \
--db-instance-class db.t3.micro \
--engine postgres \
--engine-version 15.2 \
--master-username admin \
--master-user-password MySecurePassword123! \
--allocated-storage 100 \
--storage-type gp3 \
--db-subnet-group-name app-db-subnet \
--vpc-security-group-ids sg-rds123 \
--multi-az \
--storage-encrypted \
--kms-key-id arn:aws:kms:region:account:key/id \
--backup-retention-period 30 \
--preferred-backup-window "03:00-04:00" \
--preferred-maintenance-window "mon:04:00-mon:05:00" \
--enable-cloudwatch-logs-exports postgresql \
--enable-iam-database-authentication
# 创建只读副本
aws rds create-db-instance-read-replica \
--db-instance-identifier myapp-db-read \
--source-db-instance-identifier myapp-db
# 手动快照
aws rds create-db-snapshot \
--db-snapshot-identifier myapp-db-backup-2024 \
--db-instance-identifier myapp-db
# 描述RDS实例
aws rds describe-db-instances \
--db-instance-identifier myapp-db \
--query 'DBInstances[0].[DBInstanceIdentifier,DBInstanceStatus,Endpoint.Address]'
2. Terraform RDS配置
# rds.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
# DB子网组
resource "aws_db_subnet_group" "app" {
name = "app-db-subnet"
subnet_ids = [aws_subnet.private1.id, aws_subnet.private2.id]
tags = { Name = "app-db-subnet" }
}
# 安全组
resource "aws_security_group" "rds" {
name_prefix = "rds-"
vpc_id = aws_vpc.main.id
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# KMS加密密钥
resource "aws_kms_key" "rds" {
description = "RDS加密密钥"
deletion_window_in_days = 10
enable_key_rotation = true
}
resource "aws_kms_alias" "rds" {
name = "alias/rds-key"
target_key_id = aws_kms_key.rds.key_id
}
# RDS实例
resource "aws_db_instance" "app" {
identifier = "myapp-db"
engine = "postgres"
engine_version = "15.2"
instance_class = "db.t3.micro"
allocated_storage = 100
storage_type = "gp3"
storage_encrypted = true
kms_key_id = aws_kms_key.rds.arn
db_name = "appdb"
username = "admin"
password = random_password.db_password.result
db_subnet_group_name = aws_db_subnet_group.app.name
vpc_security_group_ids = [aws_security_group.rds.id]
multi_az = true
publicly_accessible = false
backup_retention_period = 30
backup_window = "03:00-04:00"
maintenance_window = "mon:04:00-mon:05:00"
copy_tags_to_snapshot = true
enabled_cloudwatch_logs_exports = ["postgresql"]
enable_iam_database_authentication = true
deletion_protection = true
skip_final_snapshot = false
final_snapshot_identifier = "myapp-db-final-snapshot-${formatdate("YYYY-MM-DD-hhmm", timestamp())}"
tags = {
Name = "myapp-db"
}
}
# 生成随机密码
resource "random_password" "db_password" {
length = 16
special = true
}
# 在Secrets Manager中存储密码
resource "aws_secretsmanager_secret" "db_password" {
name_prefix = "rds/myapp/"
recovery_window_in_days = 7
}
resource "aws_secretsmanager_secret_version" "db_password" {
secret_id = aws_secretsmanager_secret.db_password.id
secret_string = jsonencode({
username = aws_db_instance.app.username
password = random_password.db_password.result
engine = "postgres"
host = aws_db_instance.app.address
port = aws_db_instance.app.port
dbname = aws_db_instance.app.db_name
})
}
# 只读副本
resource "aws_db_instance" "read_replica" {
identifier = "myapp-db-read"
replicate_source_db = aws_db_instance.app.identifier
instance_class = "db.t3.micro"
publicly_accessible = false
tags = {
Name = "myapp-db-read"
}
}
# 增强监控角色
resource "aws_iam_role" "rds_monitoring" {
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "monitoring.rds.amazonaws.com"
}
}]
})
}
resource "aws_iam_role_policy_attachment" "rds_monitoring" {
role = aws_iam_role.rds_monitoring.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
}
# CloudWatch报警
resource "aws_cloudwatch_metric_alarm" "db_cpu" {
alarm_name = "rds-high-cpu"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/RDS"
period = 300
statistic = "Average"
threshold = 80
alarm_description = "当RDS CPU超过80%时报警"
dimensions = {
DBInstanceIdentifier = aws_db_instance.app.id
}
}
resource "aws_cloudwatch_metric_alarm" "db_connections" {
alarm_name = "rds-high-connections"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "DatabaseConnections"
namespace = "AWS/RDS"
period = 300
statistic = "Average"
threshold = 80
alarm_description = "当数据库连接超过80时报警"
dimensions = {
DBInstanceIdentifier = aws_db_instance.app.id
}
}
# 输出
output "db_endpoint" {
value = aws_db_instance.app.endpoint
description = "RDS端点地址"
}
output "db_password_secret" {
value = aws_secretsmanager_secret.db_password.arn
description = "数据库凭据的Secret Manager ARN"
}
3. 数据库连接和配置
# 连接到RDS实例
psql -h myapp-db.xxxx.us-east-1.rds.amazonaws.com \
-U admin \
-d appdb \
-p 5432
# 使用IAM认证创建数据库用户
psql -h myapp-db.xxxx.us-east-1.rds.amazonaws.com \
-U admin \
-d appdb << EOF
CREATE USER app_user;
GRANT CONNECT ON DATABASE appdb TO app_user;
GRANT USAGE ON SCHEMA public TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
ALTER ROLE app_user WITH PASSWORD 'MySecurePassword123!';
EOF
# 导出数据库
pg_dump -h myapp-db.xxxx.us-east-1.rds.amazonaws.com \
-U admin \
appdb > backup.sql
# 导入数据库
psql -h myapp-db.xxxx.us-east-1.rds.amazonaws.com \
-U admin \
appdb < backup.sql
最佳实践
✅ DO
- 生产环境使用多可用区
- 启用自动备份
- 使用静态和传输中的加密
- 实施IAM数据库认证
- 创建只读副本以扩展
- 监控性能指标
- 设置CloudWatch报警
- 在Secrets Manager中存储凭据
- 使用参数组进行配置
❌ DON’T
- 在代码中存储密码
- 禁用加密
- 在生产中使用公共可访问性
- 忽略备份保留
- 跳过自动备份
- 无多可用区创建数据库
监控
- CloudWatch指标(CPU、连接、存储)
- 增强监控与OS指标
- RDS性能洞察
- AWS CloudTrail用于API日志记录
- 来自应用程序的自定义CloudWatch日志