AWS RDS Proxy를 활용한 Aurora Failover 구현하기
개요
AWS RDS Proxy은 "DB Connection Pool Management" 또는 "Automatic Failover를 위한 Proxy" 기능을 제공합니다.
결국, AWS RDS Proxy를 사용하는 이유는 HA(High Availability)를 구현하기 위함입니다.
Solution을 사용하기 앞서서, HA(High Availability)를 위한 Multi-AZ(Multi Availability Zone) 개념을 시작으로 이야기를 풀어가보겠습니다.
RDS는 HA(High Availability)를 위해서 Multi-AZ(Multi Availability Zone)를 권장합니다. Downtime 없는 DB Instance를 사용하기 위함입니다.
Multi-AZ를 통한 DB 구성과 Application에서 활용하는 방식은 다음과 같습니다.
여기서 AZ(Availability Zone)의 개념은 물리적으로 구분된 IDC라고 생각하시면 됩니다.
예를 들면, Zone A는 Seoul, Zone B는 Daegu, Zone C는 Busan과 같이 보통 지역으로 분리해놓습니다.
Multi-AZ를 구성하고, 어느 하나의 AZ 또는 DB Instance에 장애가 발생하였을 때 장점은 다음과 같습니다.
- Enhanced durability: 장애가 발생한 Workload를 안전하게 보장해서 DB에 반영해줍니다.
- Increased availability: Aurora는 1분 이내, MariaDB는 30초 이내, 다른 DB Engine은 1~2분 이내로 Automatic failover를 통해서 정상화시킵니다. 그리고 maintenance 또는 backup이 발생했을 때도 DB에 반영할 Workload를 보장해줍니다.
- Protection of your database performance: MySQL, MariaDB, Oracle, PostgreSQL Engine에서 Backup이 발생하였을 때, I/O workload를 지속적으로 보장해줍니다. Aurora를 사용하고 있는 경우에도 마찬가지로 I/O workload를 보장하고, 장애가 발생하여도 Automatic Failover과 Read Replica를 통해서 Performance를 유지시켜줍니다.
- Automatic failover: Primary DB가 있는 AZ에서 Downtime이 발생했을 때, Failover를 통해서 짧은 시간 안에 Secondary DB를 승격시켜서 DB를 정상화시킵니다. 마찬가지로 Secondary DB에서 Downtime이 발생했을 때, 다른 정상적인 AZ로 Workload를 넘겨줍니다.
또한, AWS Multi-AZ 구성은 다음 아래와 같은 내용을 보장합니다.
Amazon RDS Service Level Agreement Multi-AZ configurations for MySQL, MariaDB, Oracle, and PostgreSQL are covered by the Amazon RDS Service Level Agreement ("SLA"). The RDS SLA affirms that AWS will use commercially reasonable efforts to make Multi-AZ instances of Amazon RDS available with a Monthly Uptime Percentage of at least 99.95% during any monthly billing cycle. In the event Amazon RDS does not meet the Monthly Uptime Percentage commitment, affected customers will be eligible to receive a service credit.
요약한 내용은 다음과 같습니다.
- 한 달의 Billing Cycle 동안 99.95% 이상의 서비스 시간 보장 (30일*24시간*60분 * 0.0005 = 21.6분 이하의 Downtime 보장)
- 99.95%이상 SLA 보장을 못 받은 사용자에게는 그만큼의 Service Credit 제공
하지만 Multi-AZ가 장점이 많음에도 비용이 증가하는 단점이 있기 때문에, 웬만한 소규모 상용 서비스들은 보통 1개 DB Instance로 Multi-AZ를 구현하지 않고 사용합니다.
"서비스의 초반에는 굳이 Multi-AZ까지 필요할까?"라는 말엔 공감합니다. 그러나 서비스가 성장하고, 24시간 쉼 없이 사용자들에게 서비스를 제공하게 되면서, DB의 HA(High Availability)가 중요해집니다.
결국, Multi-AZ가 필요한 시점이 옵니다.
그러면 Multi-AZ를 어떻게 사용할까요? 내부 Architecture는 비슷하지만, Engine에 따라서 구성하는 방식은 조금 다릅니다.
- MySQL, MariaDB, Oracle, PostgreSQL Engine: DB를 생성할 때, Multi-AZ를 선택할 수 있습니다. 생성 후에 적용도 가능합니다.
- Aurora: Read Replica를 생성하면 자동으로 Multi-AZ가 구성이 됩니다.
MySQL, MariaDB, Oracle, PostgreSQL Engine은 장애가 발생하였을 때, 동일한 endpoint를 통해서 요청해도 Automatic Failover를 통해서 DB를 전환시켜주기 때문에 그대로 endpoint를 사용하시면 HA(High Availability)를 구성할 수 있습니다.
이 글에선 더 다양한 기능과 확장성을 제공하는 Aurora를 기준으로 Proxy를 활용해서 Automatic Failover를 구현하고, HA(High Availability)를 가능하게 만들어보겠습니다.
AWS Aurora Automatic Failover 테스트를 진행하기 위한 구성은 다음과 같습니다.
- RDS Aurora Instance Cluster 1(Primary Instance 1, Replica Instance 1)
- RDS Proxy 1(Secrets Manager "Secret", IAM "Policy", IAM "Role")
- EC2 Instance 1
// RDS Aurora Instance Cluster 1(Primary Instance 1, Replica Instance 1)는 이미 생성되어있다고 가정합니다. 이 글에서 사용하는 DB Instance Name은 test입니다.
목차
- RDS Proxy에 사용할 Secrets Manager "secret" 생성하기
- RDS Proxy에 사용할 IAM "policy" 생성하기
- RDS Proxy에 사용할 IAM "role" 생성하기
- RDS Proxy를 생성하고, Aurora cluster에 연결하기
- RDS Proxy Endpoint를 사용해서, "Automatic Failover" 테스트하기
1. RDS Proxy에 사용할 Secrets Manager "secret" 생성하기
: RDS Proxy를 이용하기 위해서는 Proxy가 어디로 어떤 정보를 이용해서 DB에 접속해야 하는 지를 정보를 저장해야 합니다. Proxy는 그 정보의 단위를 Secrets Manager "secret"를 생성해서 관리하고 사용합니다.
- Secret type: "Credentials for RDS database"
- User name: 접속할 DB의 username
- Password: 접속할 DB의 password
- Encryption key: DefaultEncryptionKey
- RDS database this secret will access: "secret"을 사용하여 Proxy를 사용할 DB
Next~
- Secret name: "secret" 구분하기 위한 이름. 보통 {Environment}/{Object}/{DBtype}로 만듭니다.
Next~
- automatic rotation은 "secret"의 rotation 사용 전략입니다. 여기서는 일단, "Disable automatic rotation"을 선택하겠습니다.
Next~
- 최종적으로 설정한 부분을 확인합니다.
Store~
- 최종적으로 생성된 "secret"을 볼 수 있습니다. 생성된 "secret"은 RDS Proxy를 생성하는데 쓰이게 됩니다.
- 아래 단계로 넘어가기 앞서서 생성된 "secret"으로 들어가면 생성된 "Secret ARN"을 볼 수 있습니다. 복사해둡니다.
2. RDS Proxy에 사용할 IAM "policy" 생성하기
: RDS Proxy를 생성하는 데에 IAM "policy"를 생성하는 이유는 결국, IAM "role"을 Proxy가 가지기 위함입니다.
그러면 IAM "role"을 생성하는 이유는 RDS Proxy가 다른 서비스 자원을 이용하기 위한 권한을 획득하는 단위이기 때문입니다.
풀어보면, "secret" 리소스를 제어할 수 있는 "policy"를 만들어서, IAM "role"을 생성해서, RDS Proxy에게 권한을 넘겨주기 위함입니다.
- AWS IAM으로 들어갑니다. IAM policy를 생성하기 위해서 Access management => Policies => "Create policy"를 선택합니다.
- "JSON" 탭으로 이동합니다. 그리고 Policy의 JSON을 넣습니다.
- "secret" Resource를 사용할 수 있게 허용하기 위해서 "your_secret_ARN"에 secret 생성 시에 얻었던 "Secret ARN"로 변경해줍니다.
Policy의 JSON은 다음과 같습니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"secretsmanager:GetRandomPassword",
"secretsmanager:CreateSecret",
"secretsmanager:ListSecrets"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "secretsmanager:*",
"Resource": [
"your_secret_ARN"
]
}
]
}
- Policy JSON을 반영했으면, "Review policy"를 선택해줍니다.
- Name을 적어주고 나서, "Create policy"를 눌러줍니다.
이제 AWS IAM "role"을 생성하기 위한 "policy" 생성이 되었습니다.
3. RDS Proxy에 사용할 IAM "role" 생성하기
: 위 단계에서 만들어진 IAM "policy"를 이용해서, 다음 단계에서 만들게 될 RDS Proxy가 사용할 리소스의 권한을 얻기 위한 IAM "role"을 만들어보겠습니다.
- "role"을 생성하기 위해서, 다음 순서로 들어가 줍니다.
- IAM => Roles 탭 => "Create role"
- AWS Service에서 RDS Proxy의 role을 만들어주기 위해서 "RDS"를 선택하고, role을 추가합니다.
- "AWS Service" => "RDS" => "RDS - Add Role to Database" => "Next: Permissions"
- 위 단계에서 RDS Proxy IAM "role"위해서 만들었던, IAM policy "test-rds-proxy"를 IAM "role"에 붙여줍니다.
- "test-rds-proxy" 검색 => "Next: Tags"
- 그냥 넘어가도 되는 부분입니다. tag를 붙여서 가독성을 주고 싶다면, Key: Name , Value: "원하는 이름"으로 넣어주시고, 넘어가 줍니다.
- "Next: Review"
- 최종적으로 설정한 IAM "role"의 내용을 보고, 맞다면 생성해줍니다.
- "Role name" 입력 => "Create role"
- 생성된 IAM "role"을 확인하고 선택해서 들어가 줍니다.
- 하나 남은 작업이 있습니다. RDS와의 신뢰 정책을 편집해서 보다 안전하게 리소스 간에 신뢰를 구성하기 위해서입니다.
- "Trust relationships" => "Edit trust relationship"
- Trust Policy를 넣어주고 "Update Trust Policy"를 눌러 갱신해줍니다.
Trust Relationship을 위한 Policy JSON은 다음과 같습니다.
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal":{
"Service":"rds.amazonaws.com"
},
"Action":"sts:AssumeRole"
}
]
}
이렇게 RDS Proxy가 RDS Aurora DB cluster와 연결되어 제 기능을 할 수 있게 하는 IAM "role", "policy"의 생성을 마쳤습니다.
4. RDS Proxy를 생성하고, Aurora cluster에 연결하기
: 여기서는 RDS Proxy를 생성하고, RDS Aurora DB cluster와 연결해보겠습니다. 연결을 마치게 되면, RDS Proxy에서 제공하는 기능들을 사용할 수 있습니다.
RDS Proxy가 제공하는 기능은 DB의 HA(High Availability)를 구현하기 위함이고, 특징적인 기능은 다음과 같습니다.
- DB Connection Pool Management
- Automatic Failover
- Proxy identifier 입력 => Proxy가 사용될 DB Engine 선택 => TLS 연결이 필요하면 선택 => "Idle client connection timeout" 시간 선택
- Proxy는 자체적으로 Connection Pool을 관리해주기 때문에 서비스의 Idel time이 적다면 "Idle client connection timeout"을 원하는 만큼 늘리면 됩니다.
- "Database": Proxy와 연결할 RDS Database를 골라줍니다. 여기서는 미리 생성해두었던 RDS Database "test"를 선택해줍니다.
- "Connection pool maximum connections": 생성한 Database "test"의 설정되어 있는 옵션 "max_connections"의 percent 만큼만 RDS Proxy에서 할당받아서 연결합니다.
- "Secrets Manager secret(s)": "1. RDS Proxy에 사용할 Secrets Manager "secret" 생성하기"에서 생성한 secret을 적용해줍니다.
- "IAM role": "RDS Proxy에 사용할 IAM "policy" 생성하기"와 "RDS Proxy에 사용할 IAM "role" 생성하기"에서 생성하였던 IAM role인 "test-rds-proxy"를 넣어줍니다.
- "IAM authentication": 여기서는 1) IAM을 통한 사용자 접근 제어 방법과 2) 기존의 DB 접속 방식 이 있습니다. 여기서는 2) 번으로 사용할 것이기 때문에 Disabled를 사용합니다.
- "Subnets": VPC로 사용한 곳에서 Database가 사용할 Subnet의 범위를 결정합니다. 2개 이상을 선택해주는 것이 필수입니다.
- "VPC security group": 은 "Create new"로 생성해도 되고, 기존에 VPC가 있는 경우에는 "Choose existing"으로 선택해줍니다. VPC를 선택해주시는 경우에는 꼭 VPC에 "Internet Gateway"를 장착해주시길 바랍니다.
- "Enhanced logging": CloudWatch에서 커스텀하게 Logging을 관리하길 원하시면, "Enable enhanced logging"을 선택해줍니다.
- 아직은 Preview 상태로 정식 제품이 아니기 때문에 상용에는 사용하지 마시길 바랍니다. 그리고 인지하였음을 선택해줍니다.
- "Create proxy" 생성 완료!
- 몇 분 정도 기다리면, Proxy가 생성됩니다.
- "test-proxy"를 선택해서 들어가 줍니다.
- 생성된 proxy의 정보를 확인할 수 있습니다.
- "Proxy ARN"은 이제 DB의 host endpoint처럼 사용할 수 있습니다.
- 중요한 점은 RDS Proxy는 AWS 내부 환경에서만 사용할 수 있습니다. Tool을 사용하여 접속하려고 하면 접속이 불가능합니다.
그래서 테스트 환경을 구성해서 Test를 진행하기 위해서, 다음 단계로 넘어가겠습니다.
5. RDS Proxy Endpoint를 사용해서, "Automatic Failover" 테스트하기
: 이제 필요한 모든 Resource를 생성했습니다. 마지막으로 테스트 환경을 구성해서 과연 RDS Proxy를 사용해서 Primary DB(Writer)가 장애(failure)가 발생하였을 때, Automatic Failover가 반영이 되는지 확인해보겠습니다.
AWS Aurora Automatic Failover 테스트를 진행하기 위한 구성은 다음과 같습니다.
- RDS Aurora Instance Cluster 1(Primary Instance 1, Replica Instance 1)
- RDS Proxy 1(Secrets Manager "Secret", IAM "Policy", IAM "Role")
- EC2 Instance 1
- EC2 Instance를 생성하기 위해서, "EC2" => "Instances" => "Launch Instance" 선택합니다.
- 테스트를 위한 MySQL을 패키지로 제공하는 "Amazon Linux AMI"를 사용했습니다.
- 물론 다른 OS를 선택하시고, MySQL을 설치해주어도 됩니다.
- 원하는 EC2 Type을 선택하면 됩니다. 여기서는 t2.micro를 사용했습니다.
- "Next: Configure Instance Details"를 선택
- 여기서 테스트를 위한 설정으로 중요한 부분은 VPC 설정입니다.
- VPC는 테스트에 사용되는 RDS Aurora Cluster와 같은 VPC를 사용하시면 됩니다. 서로 다른 VPC 접근은 허용하게 설계되었다면, VPC가 달라도 무관합니다.
- 테스트를 위해서 방화벽인 Security Group의 Inbound Rule은 All traffic을 허용해두겠습니다.
- 마지막으로 설정된 정보를 확인하고, "Launch"를 눌러서 EC2 Instance를 생성합니다.
- EC2 Instance를 생성하기 위해서는 접근을 위한, ".pem" 파일을 생성하거나, 기존의 ".pem"파일을 사용하셔도 됩니다.
- 여기에서는 기존의 ".pem"파일을 사용하겠습니다.
- 생성된 EC2를 확인할 수 있습니다.
- 이제 직접 접속하기 위해서 "Connect"를 선택해줍니다.
- 여기에서 EC2 Instance에 접속하기 위해서 Example의 CLI 명령어를 복사합니다.
- 터미널로 와서 위에서 복사한 CLI 명령어를 붙여 넣어서 접속합니다.
접속하고 나면, 일단 필요한 MySQL 패키지를 설치하기 위해서 다음 명령어를 실행해줍니다.
sudo yum update -y
sudo yum install mysql-server -y
테스트를 하기 위한 Database: "test"와 Table: "user"를 생성하기 위해서 다음 명령어를 실행해줍니다.
mysql -s -N --host=test.cluster-test1290393.ap-northeast-1.rds.amazonaws.com --user=admin --password=testdb1234! --port=3306 -e "create database test;use test;create table user (id BIGINT(20) UNSIGNED not null auto_increment, name varchar(255), age varchar(255), created_at datetime(6) not null, modified_at datetime(6) not null, primary key (id)) engine=InnoDB;";
- 테스트를 위해서 이전에 만들었던, RDS Proxy endpoint을 복사합니다.
- RDS Proxy endpoint 접근은 AWS 내부에서 접근이 가능합니다. 외부에서는 접근이 불가능합니다. 혹시 DB tool로 사용하신다면, 접속이 안되실 겁니다.
- RDS Proxy가 생성되었다고 해서, Aurora Cluster의 Endpoint를 사용하지 못하진 않습니다.
- 하단에 보이는 "Writer", "Reader" cluster endpoint 도 여전히 사용 가능합니다.
- 테스트를 위한 Insert 쿼리 하나, Select 쿼리 하나를 1초 간격으로 반복문으로 실행시켜놓습니다. (테스트가 끝났을 때는 control + C로 종료해줍니다.)
while true; do mysql -s -N --host=test.cluster-test1290393.ap-northeast-1.rds.amazonaws.com --user=admin --password=testdb1234! --port=3306 --database=test -e "insert into user(name, age, created_at, modified_at) values('name', 'age', now(), now());select now();"; sleep 1; done
- RDS는 Instance를 수동으로 DB를 Failover 시킬 수 있게 기능을 제공합니다.
- Failover 테스트를 위해서, RDS Databases => Writer DB Instance 선택 => "Actions" => Failover 선택 OK
- 쿼리를 반복문으로 실행하였던, 터미널로 돌아갑니다.
- RDS Aurora를 이용한 Primary DB 장애 발생 시, Failover를 위한 RDS Proxy 테스트가 완료되었습니다.
- 기본적으로 RDS는 Engine에 따라서 Failover 되어 보통은 30초 이내 시간을 보장합니다.
- 다시 한번 말씀드리면, RDS Proxy는 현재 Preview 이기 때문에 상용 DB에 쓰는 것을 아직 권하지 않습니다.
결론
- 메인 DB가 장애가 오거나, 유지 보수하는 경우에는 Failover를 구현하는 것은 상당히 중요합니다.
- Downtime을 짧게 하고, DB에 요청된 쿼리를 안전하게 무효화시키는 것도 중요합니다.
- RDS Aurora를 사용하시는 분이라면, 추후에 RDS Proxy가 서비스 정식 런칭이 되면, 사용하시길 추천합니다.
- 추천하는 이유가 한 가지 더 있는데요. DB connection pool을 관리시켜줘서, 중복되거나 유휴된 Connection을 관리하여, 적은 Connection을 가지고, Connection 최적화를 이룰 수 있습니다.
참고자료