Warm tip: This article is reproduced from serverfault.com, please click

amazon web services-AWS RDS代理不可用

(amazon web services - AWS RDS Proxy unavailalbe)

发布于 2020-11-30 11:03:20

我已经使用Terraform创建了RDS代理。但是,它似乎不起作用。

我的应用程序代码无法连接到代理(超时),并aws rds describe-db-proxy-targets提供以下信息:

{
    "Targets": [
        {
            "Endpoint": "mydb.aaaaaaaaaaaa.eu-west-2.rds.amazonaws.com",
            "RdsResourceId": "mydb",
            "Port": 5432,
            "Type": "RDS_INSTANCE",
            "TargetHealth": {
                "State": "UNAVAILABLE",
                "Description": "DBProxy Target unavailable due to an internal error"
            }
        }
    ]
}

我该如何调试呢?

这是代理的Terraform脚本。RDS实例在其他地方进行了描述,但是正在运行。

data "aws_subnet" "mydb_rds" {
  filter {
    name   = "availability-zone"
    values = [ aws_db_instance.mydb.availability_zone ]
  }
}

resource "aws_secretsmanager_secret" "mydb_rds_proxy" {
  name = "mydb-rds-proxy"
}

resource "aws_secretsmanager_secret_version" "mydb_rds_proxy" {
  secret_id     = aws_secretsmanager_secret.mydb_rds_proxy.id
  secret_string = var.db_password
}

resource "aws_iam_role" "mydb_rds_proxy" {
  name = "mydb-rds-proxy"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Action": "sts:AssumeRole",
      "Effect": "Allow",
      "Principal": {
        "Service": "rds.amazonaws.com"
      }
    }
  ]
}
EOF
}

resource "aws_iam_policy" "mydb_rds_proxy_policy" {
  name = "mydb-rds-proxy"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "GetSecretValue",
      "Action": [
        "secretsmanager:GetSecretValue"
      ],
      "Effect": "Allow",
      "Resource": [
        "${aws_secretsmanager_secret.mydb_rds_proxy.arn}"
      ]
    },
    {
      "Sid": "DecryptSecretValue",
      "Action": [
        "kms:Decrypt"
      ],
      "Effect": "Allow",
      "Resource": [
        "${aws_secretsmanager_secret.mydb_rds_proxy.arn}"
      ]
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "mydb_rds_proxy_policy_attachment" {
  role       = aws_iam_role.mydb_rds_proxy.name
  policy_arn = aws_iam_policy.mydb_rds_proxy_policy.arn
}

resource "aws_db_proxy" "mydb" {
  name                   = "mydb-rds-proxy"
  debug_logging          = false
  engine_family          = "POSTGRESQL"
  idle_client_timeout    = 1800
  require_tls            = true
  role_arn               = aws_iam_role.mydb_rds_proxy.arn
  vpc_security_group_ids = [ aws_security_group.mydb_rds.id ]
  vpc_subnet_ids         = [
    data.aws_subnet.mydb_rds.id,
    aws_default_subnet.subnet_a.id,
    aws_default_subnet.subnet_b.id
  ]

  auth {
    auth_scheme = "SECRETS"
    iam_auth    = "DISABLED"
    secret_arn  = aws_secretsmanager_secret.mydb_rds_proxy.arn
  }
}

resource "aws_db_proxy_default_target_group" "mydb" {
  db_proxy_name = aws_db_proxy.mydb.name

  connection_pool_config {
    connection_borrow_timeout    = 120
    max_connections_percent      = 100
    max_idle_connections_percent = 50
  }
}

resource "aws_db_proxy_target" "mydb" {
  db_instance_identifier = aws_db_instance.mydb.id
  db_proxy_name          = aws_db_proxy.mydb.name
  target_group_name      = aws_db_proxy_default_target_group.mydb.name
}

locals {
  proxied_pg_connection_string = "postgres://${aws_db_instance.mydb.username}:${var.db_password}@${aws_db_proxy.mydb.endpoint}:5432/postgres?client_encoding=UTF8"
}
Questioner
sdgfsdh
Viewed
11
sdgfsdh 2020-12-02 00:01:30

要使此功能正常运行,你需要执行以下几项操作:

  • 用户名/密码存储在机密中
  • Lambda中的安全组规则-> RDS代理
  • 来自RDS代理-> RDS的安全组规则
  • 同一VPC中的RDS代理,Lambda和RDS
  • RDS代理角色可以访问机密

一个有用的调试查询是:

aws rds describe-db-proxy-targets --db-proxy-name <proxy-name>

要了解它返回的错误消息,请参阅此页面

用户名/密码是最难发现的,因为Terraform尚不支持它。你需要做的是在Terraform中构造一个与RDS代理可以理解的JSON字符串匹配的字符串:

resource "aws_secretsmanager_secret_version" "my_db_proxy" {
  secret_id     = aws_secretsmanager_secret.my_db_proxy.id
  secret_string = jsonencode({
    "username"             = aws_db_instance.my_db.username
    "password"             = var.db_password
    "engine"               = "postgres"
    "host"                 = aws_db_instance.my_db.address
    "port"                 = 5432
    "dbInstanceIdentifier" = aws_db_instance.my_db.id
  })
}

然后,你需要确保存在以下安全组规则,以允许端口上的TCP流量5432(对于Postgres)存在:

  • ingress Lambda到RDS代理
  • ingress RDS代理到RDS
  • egress RDS代理到 "0.0.0.0/0"

RDS代理角色应具有以下策略:

resource "aws_iam_policy" "my_rds_proxy_policy" {
  name = "my-rds-proxy"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Action": [
        "rds:*"
      ],
      "Effect": "Allow",
      "Resource": [
        "${aws_db_instance.my_db.arn}"
      ]
    },
    {
      "Sid": "GetSecretValue",
      "Action": [
        "secretsmanager:GetSecretValue"
      ],
      "Effect": "Allow",
      "Resource": [
        "${aws_secretsmanager_secret.my_rds_proxy.arn}"
      ]
    },
    {
      "Sid": "DecryptSecretValue",
      "Action": [
        "kms:Decrypt"
      ],
      "Effect": "Allow",
      "Resource": [
        "*"
      ]
    },
    {
      "Sid": "DecryptKms",
      "Effect": "Allow",
      "Action": "kms:Decrypt",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "kms:ViaService": "secretsmanager.${var.aws_region}.amazonaws.com"
        }
      }
    }
  ]
}
EOF
}

祝你好运!