mingming

Terraform 으로 Aurora cluster 및 RDS Proxy 구현하기 본문

Terraform

Terraform 으로 Aurora cluster 및 RDS Proxy 구현하기

mingming_96 2023. 8. 13. 03:07

실제 팀 프로젝트 당시 데이터베이스 파트를 테라폼 코드로 구현하는 과정에서 겪었던 것들을 기록해보려고 합니다.

 

먼저 Terraform Docs 를 참조하시는걸 추천드립니다. provider 버전 별로 어떤 인수값을 지원하는지 어떤 출력값을 지원하

 

는지 확인하실 수 있습니다. 

 

Architecture

Provider

provider "aws" {
  region = "ap-northeast-2"
  version = "~> 5.7"
}

provider는 aws 버전은 5.7 로 설정했습니다. 버전 별로 지원하는 인수값이 다르니 꼭 기술문서를 참조하시길 바랍니다.

 

datasource

data "aws_iam_role" "RDS_Proxy_iam" {
  name = "rds-proxy-role9" # 본인 rds proxy iam 으로 교체
}

data "aws_secretsmanager_secret_version" "rds_secret" { 
  secret_id = "secretmanager arn"
}

미리 콘솔에서 생성해둔 rds proxy 에 부착할 iam role 과 rds 데이터베이스 자격증명 정보를 담은 secret manager를 

datasource로 참조했습니다. 

rds proxy iam role 에는 secret manager에 접근할 수 있는 iam policy가 부착되어 있어야 합니다.

 

terraform_remote_state

data "terraform_remote_state" "terraform_state" {
  backend = "s3"

  config = {
    bucket = "terraform-state-interface"
    key    = "Seoul-terraform.tfstate"
    region = "ap-northeast-2"
  }
}

실제 프로젝트 당시 베이스 인프라를 배포 후 필요한 subnet, vpc 정보를 outputs로 내보내 참조하였습니다.

테라폼은 기본적으로 상태저장 파일이 로컬에 저장되지만 backend 설정을 통해 s3버켓에 저장하도록 했습니다. 

또한 저장한 상태저장 파일을 datasource로 불러와 참조할 수 도 있습니다. 

 

aws_rds_cluster

resource "aws_rds_cluster" "Seoul_aurora_cluster" {
  apply_immediately       = true
  cluster_identifier      = "aurora-cluster-seoul"
  engine                  = "aurora-mysql"
  engine_version          = "5.7.mysql_aurora.2.11.3"
  db_subnet_group_name    = aws_db_subnet_group.aws_aurora_subnet_group.name
  vpc_security_group_ids = [ data.terraform_remote_state.terraform_state.outputs.aws_security_group_Aurora_Seoul ]
  database_name           = var.db_name
  master_username         = jsondecode(data.aws_secretsmanager_secret_version.rds_secret.secret_string)["username"] 
  master_password         = jsondecode(data.aws_secretsmanager_secret_version.rds_secret.secret_string)["password"] 
  backup_retention_period = 5
  skip_final_snapshot = true
  db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.rds_cluster_Seoul.name
  preferred_backup_window = "07:00-09:00"
}

jsondecode를 통해 미리 생성해둔 secret manager의 username과 password를 참조했습니다.  

  manage_master_user_password = true
  master_user_secret_kms_key_id = data.aws_kms_key.rds_master_key.key_id

해당 블록을 통해 cluster 생성시 자동으로 secretmanger가 생성되도록 할 수도있습니다.  

 

aws_rds_cluster_instance

resource "aws_rds_cluster_instance" "primary" {
  cluster_identifier    = aws_rds_cluster.Seoul_aurora_cluster.id
  identifier            = "seoul-database-2"
  engine                = "aurora-mysql"
  instance_class        = "db.t3.small"  
  publicly_accessible   = false
}

resource "aws_rds_cluster_instance" "secondary" {
  cluster_identifier    = aws_rds_cluster.Seoul_aurora_cluster.id
  identifier            = "seoul-database-3"
  engine                = "aurora-mysql"
  instance_class        = "db.t3.small"  
  publicly_accessible   = false
}

rds instance는 총 두대를 생성했습니다. 

 

aws_rds_cluster_parameter_group

resource "aws_rds_cluster_parameter_group" "rds_cluster_Seoul" {
  name        = "rds-cluster-seoul"
  family      = "aurora-mysql5.7"
  description = "RDS default cluster parameter group"

  parameter {
    name  = "character_set_server"
    value = "utf8"
  }

  parameter {
    name  = "character_set_client"
    value = "utf8"
  }

  parameter {
    name  = "binlog_format"
    value = "ROW"
    apply_method = "pending-reboot"
  }  
}

server와 client의 인코딩설정 및 이진로그 설정

 

aws_db_proxy

resource "aws_db_proxy" "RDS_Proxy" {
  depends_on = [ aws_rds_cluster.Seoul_aurora_cluster ]
  name                   = "rds-proxy"
  debug_logging          = false
  engine_family          = "MYSQL"
  idle_client_timeout    = 1800
  require_tls            = false
  role_arn               = data.aws_iam_role.RDS_Proxy_iam.arn       
  vpc_security_group_ids = [ data.terraform_remote_state.terraform_state.outputs.aws_security_group_Aurora_Seoul ]
  vpc_subnet_ids         = aws_db_subnet_group.aws_aurora_subnet_group.subnet_ids

  auth {
    auth_scheme = "SECRETS"
    iam_auth    = "DISABLED"
    secret_arn  =  data.aws_secretsmanager_secret_version.rds_secret.arn

  }

  tags = {
    Name = "Seoul-RDS-Proxy"
    Key  = "value"
  }
}

resource "aws_db_proxy_default_target_group" "RDS_Proxy_target_group" {
  db_proxy_name = aws_db_proxy.RDS_Proxy.name

  connection_pool_config {
    connection_borrow_timeout    = 120
    max_connections_percent      = 100
    max_idle_connections_percent = 50
    session_pinning_filters      = ["EXCLUDE_VARIABLE_SETS"]
  }
}

resource "aws_db_proxy_target" "RDS_Proxy_target" {
  db_cluster_identifier  = aws_rds_cluster.Seoul_aurora_cluster.cluster_identifier
  db_proxy_name          = aws_db_proxy.RDS_Proxy.name
  target_group_name      = aws_db_proxy_default_target_group.RDS_Proxy_target_group.name
}

resource "aws_db_proxy_endpoint" "read_only_EP" {
  db_proxy_name          = aws_db_proxy.RDS_Proxy.name
  db_proxy_endpoint_name = "readonly"
  vpc_subnet_ids         = [aws_subnet.Seoul-PriSN3.id, aws_subnet.Seoul-PriSN4.id]
  target_role            = "READ_ONLY"
}

rds proxy 생성시 타겟그룹과 타겟을 생성해줍니다. 기본적으로 읽기/쓰기 엔드포인트가 생성되지만

읽기전용 엔드포인트를 추가로 생성해주었습니다.

 

글을 마치며.

현재는 secret manager를 따로 생성해 username과 password를 수동으로 참조해주었지만 원래 처음 시나리오는 위에 기술한 것처럼  aws에서 제공하는 마스터 암호 관리 기능을 사용하려 했었습니다. 한 가지 문제가 있었는데요, 

실제 프로젝트에선 dms 과정이  들어갑니다. 이때 source와 target endpoint를 설정하게 되는데 각각 데이터베이스의 연결 세부정보를 입력해야 합니다. 

연결 세부정보엔 실제 데이터베이스 엔드포인트와, 접속포트, username, password 네가지의 값이 필요하지만, 마스터 암호 관리 기능을 활성화 후 aurora cluster 생성하게 되면 username과 password 두 가지 값만 생성되어 실제 dms 과정에 이용할 수 없었습니다. 

 

만약 마스터 암호 관리 기능을 이용하시려면 aurora cluster 프로비저닝 과정에서 생성된 secretmanager의 arn 값을 참조해야 합니다. ( 해당 값은 rds proxy 생성시 자격증명 정보에 이용됩니다. )

 

실제 terraform apply 하게되면 상태저장 파일에 리스트 딕셔너리 값으로 구성되어 있습니다. 

"master_user_secret": [
  {
    "kms_key_id": "kmskey_arn",
    "secret_arn": "sercret_arn",
    "secret_status": "active
  }
]

 

rds proxy 생성 시 이런 형태로 참조할 수 있습니다. 

  auth {
    auth_scheme = "SECRETS"
    iam_auth    = "DISABLED"
    secret_arn  =  aws_rds_cluster.Seoul_aurora_cluster.master_user_secret[0]["secret_arn"]

  }

 

 

'Terraform' 카테고리의 다른 글

Terraform 이란?  (2) 2023.08.11