RDS ProxyをCloudformationで作る時Stackが終わらない問題


先日Aurora RDS ProxyをAWS Cloudformationで作成する時に、いくつの問題に遭遇したため、それをどうやって解消したかを紹介いたします。


## まず問題紹介

RDS ProxyをCloudformation作成する際に、長期間にProxyTargetGroupの作成過程で止まっている現象がありました。ずっと待っていてもCompleteにならなかったです。一方でGUIでProxyの状態を見ると、Availableになっていて、余計戸惑いました。そこでAWS Supportに問い合わせをして、裏側のログを確認していただきまして、原因が解明しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457921/5f61add2-de59-aef0-6a6b-dbd45799342f.png)


もし皆さんがこの問題にあったらどうやってTroubleShootingするか考えて見てください。問題解明や解決策を最後に掲載します。

## 再現します

### 1. まずAurora Postgresを1つ作成します。

方法はいくつかがありますが、AWS CloudformationやTerraformなどのIacはもちろん、GUIベースの操作ももちろん可能です。


### 2. AWS RDS ProxyをCloudformation作成していきます

ここでエラーになるCloudformationを提供いたします。
AWS RDS Proxyのcloudformationの詳細を以下の公式ページから確認可能です。

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxy.html


```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFormation template to create an RDS Proxy with optional read endpoint

Parameters:
  DBProxyName:
    Type: String
    Description: Name of the RDS Proxy

  AuthSecretArn:
    Type: String
    Description: The ARN of the AWS Secrets Manager secret

  VpcSubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
    Description: List of VPC Subnet IDs

  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: VPC ID

  DBClusterIdentifier:
    Type: String
    Description: The identifier of the RDS cluster

Resources:
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for the RDS Proxy
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - CidrIp: 127.0.0.1/32
          Description: Allow self access
          IpProtocol: tcp
          FromPort: 5432
          ToPort: 5432

  DBProxy:
    Type: AWS::RDS::DBProxy
    Properties:
      DBProxyName: !Ref DBProxyName
      EngineFamily: POSTGRESQL
      RoleArn: !GetAtt ProxyRole.Arn
      Auth:
        - AuthScheme: SECRETS
          IAMAuth: DISABLED
          SecretArn: !Ref AuthSecretArn
      VpcSubnetIds: !Ref VpcSubnetIds
      RequireTLS: true
      IdleClientTimeout: 1800
      DebugLogging: true
      VpcSecurityGroupIds:
        - !Ref SecurityGroup

  ProxyTargetGroup:
    Type: AWS::RDS::DBProxyTargetGroup
    Properties:
      DBProxyName: !Ref DBProxy
      TargetGroupName: default
      DBClusterIdentifiers:
        - !Ref DBClusterIdentifier

  ProxyRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: rds.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: DBProxyPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - secretsmanager:GetSecretValue
                  - kms:Decrypt
                Resource: !Sub 'arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*'

Outputs:
  DBProxyEndpoint:
    Description: "The endpoint of the RDS Proxy"
    Value: !GetAtt DBProxy.Endpoint

```

### 3. 問題発生

上記のTemplateを利用して、DB作成された際にできた情報を入力して作成すると再現できます。


## 問題解明

AWS Supportを原因究明をして、ProxyTargetGroupの完了条件が2つあることが知りました。

1. RDS Proxyから該当DB Clusterへのアクセス疎通性がOKであること
2. RDS ProxyにつけているIAM RoleがAttachされたSecretsに読む権限を持ちかつSecretsのResources Policyではそのロールからアクセス可能な状態にしないと行けない

どちらか1つでも成功でないと、裏ではエラーにならずに、ずっとConnectの再実行を繰り返すことになり、結果としてProxyTargetGroupの作成でStopして、Stackが永遠に終わらない現象になりました。


## 解決案

実際の解決案はCase By Caseですが、Ideaとして以下の方向から試すことが良いかと思います。

### 1. RDS Proxyから該当DB Clusterへのアクセス疎通性問題の場合

以下のCommandを打って疎通性に問題ないかを確認することが可能です。

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

もし以下で`UNAVAILABLE`などがありましたら、多分どこかで問題は発生していますね。

```json
{
    "Targets": [
        {
            "RdsResourceId": "database-1",
            "Port": 5432,
            "Type": "TRACKED_CLUSTER"　
        },
        {
            "Endpoint": "database-1-instance-1.cn0ckck8wgix.us-east-1.rds.amazonaws.com",
            "TrackedClusterId": "database-1",
            "RdsResourceId": "database-1-instance-1",
            "Port": 5432,
            "Type": "RDS_INSTANCE",
            "Role": "UNKNOWN",
            "TargetHealth": {
                "State": "UNAVAILABLE",　＜ーーーここ注目
                "Reason": "PENDING_PROXY_CAPACITY",
                "Description": "DBProxy Target is waiting for proxy to scale to desired capacity"
            }
        }
    ]
}
```


こちらが割とシンプルで、RDS ProxyにつけているSecurity GroupのOutboundルールをTarget Databaseに設定する必要があります。

例えば、`nslookup`を利用して、AuroraのEndpointを調査してアドレスを確認したり、Subnetを確認したりすることでOutboundに設定する内容を大凡に把握することが可能です。

### 2. IAM RoleのResource Policy問題の場合

RDSに付けようとしたSecretsにあるResource Policyを再度確認したほうが良さそうです。

```bash
aws secretsmanager get-resource-policy --secret-id <secret-id>
```


## さいごに

Aurora RDS Proxyはまだまだ罠がありますので、実際AWSドキュメントが間違うところもありましたので、本当に困った時はAWS Supportに聞いて、バックエンドのエラーを調査しても早く問題解決につながるかもしれません。

もちろん、以下のページの中にもたくさん良い情報が載せているので、問題解決に参照したほうが良いと思います。

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.troubleshooting.html