CloudFormation
- AWS에서 제공하는 IaC 도구 입니다.
- CloudFormation 템플릿으로 리소스들을 작성할 수 있습니다. 템플릿은 JSON, YAML로 작성할 수 있습니다.
- 템플릿으로 생성된 결과물을 ‘스택’ 이라 칭합니다.
- 생성된 스택은 롤백하거나 업데이트 할 수 있고, 스택을 중첩시켜서 여러 스택관의 의존관계를 나타내는 것도 가능합니다.
CloudFormation 템플릿의 기본 구조
Parameters: Tag: Type: "String" Resources: VPC: Type: "AWS::EC2::VPC" Properties: CidrBlock: "10.0.0.0/16" Tags: - Key: "Name" Value: !Ref "Tag" SubnetA: Type: "AWS::EC2::Subnet" Properties: AvailabilityZone: !Select - 0 - !GetAZs Ref: 'AWS::Region' VpcId: !Ref "VPC" CidrBlock: "10.0.0.0/24" Outputs: VpcId: Description: The VPC ID Value: !Ref VPC
- Parameter
- Template 으로 넘겨주는 입력 값
- 예를 들면, DB의 Username과 Password를 설정해야한다고 가정해봅시다.
- 계정 정보를 소스코드내 명시하는 건 좋지 않습니다.
- 따라서 Template 으로 생성하는 단계에 입력 받아서 넘겨주는 역할을 수행해야하는데 이런 경우에 사용할 수 있습니다.
- Resources
- 실제로 생성될 AWS의 리소스를 나타냅니다.
- 거의 모든 AWS 리소스에 대한 정보를 AWS 공식문서에서 확인할 수 있습니다.
- Outputs
- 템플릿으로 스택을 생성한 이후 나오는 출력 값을 정의합니다.
- 주로 스택에서 생성한 어떤 리소스의 ARN이나 이름 값을 가져다 다른 스택의 Input Parameter 값으로 넘겨주거나 할 때 쓰이곤 합니다.
CloudFormation 실행하기/검증하기
작성한 CloudFormation의 구문 오류, 조건 검증하기. 단, 값 자체에 대한 유효성 검증은 하지 않기에, 생성시 오류가 나는 부분까지 잡아주진 않습니다.
Template 검증하기
aws cloudformation validate-template --template-body file:://./file.yaml
AWS CLI 로 실행하기
aws cloudformation create-stack --stack-name [StackName] --template-body file:://./file.yaml --parameters ParameterKey=dbUserName,ParameterValue=root ParameterKey=dbUserPassword,ParameterValue=1234
AWS 콘솔에서 실행하기
CloudFormation → 스택 생성 → 새 리소스 사용
RDS를 생성하려면 어떤 리소스가 필요한가?
AWS::RDS::DBInstance
(필수)
AWS::EC2::SecurityGroup
(필수)
AWS::RDS::DBSubnetGroup
(선택)
AWS::RDS::DBCluster
(선택)
AWS::RDS::DBClusterParameterGroup
(선택)
RDS를 CloudFormation으로 생성시 주의 할점
- 콘솔에서 생성시에는 당연히 여기다가 제약이 없는 IaC 환경에서 실행하다보면 잦은 오류를 볼 수 있습니다.
- DB 엔진 값은 아래는 Engine에 대한 리스트를 참조해서 맞는 DB를 넣읍시다. CloudFormation 뿐 아니라, Terraform 으로 생성할 때도 참고할 수 있습니다.
aurora-mysql (for Aurora MySQL DB instances) aurora-postgresql (for Aurora PostgreSQL DB instances) custom-oracle-ee (for RDS Custom for Oracle DB instances) custom-oracle-ee-cdb (for RDS Custom for Oracle DB instances) custom-sqlserver-ee (for RDS Custom for SQL Server DB instances) custom-sqlserver-se (for RDS Custom for SQL Server DB instances) custom-sqlserver-web (for RDS Custom for SQL Server DB instances) db2-ae db2-se mariadb mysql oracle-ee oracle-ee-cdb oracle-se2 oracle-se2-cdb postgres sqlserver-ee sqlserver-se sqlserver-ex sqlserver-web
- 해당 DB에 대한 사용가능한 version은 CLI에서 확인할 수 있습니다.
aws rds describe-db-engine-versions --engine <db_engine>
- 이 때 일부 DB의 경우 지원하는 인스턴스 클래스가 맞지 않을 수 있습니다. 예를 들면, aurora-mysql이나 aurora-postgresql은 생성가능한 인스턴스 클래스가 t3.medium 이상만 지원합니다. 그 미만의 인스턴스는 생성 불가합니다.
DBInstance
로 단일 구동하는 게 아닌DBCluster
를 구동하는 경우에도 마찬가지로 제약이 있습니다.
DBCluster
를 생성하는 경우에DBInstance
에는 DBName, MasterUserName, MasterPassword, VPCSecurityGroups, StorageSize,AllocatedStorage
등등 속성이 들어가면 안됩니다.DBInstance
가 아닌DBCluster
내 들어가야할 정확히는 아래 속성들이 포함됩니다.
AllocatedStorage AutoMinorVersionUpgrade AvailabilityZone BackupRetentionPeriod CharacterSetName DBInstanceClass DBName DBParameterGroupName DBSecurityGroups DBSubnetGroupName Engine EngineVersion Iops LicenseModel MasterUsername MasterUserPassword MultiAZ OptionGroupName PreferredBackupWindow PreferredMaintenanceWindow
DBInstance
속성 중에는 지원하거나 권장되지 않는 설정들이 존재합니다. 실행시 ‘해당 리전에서는 지원하지 않는다’ 는 오류가 뜹니다. 주로 더 이상 사용 되지 않거나 Deprecated 된 속성들이 존재합니다.- DBSecurityGroups
DeletionPolicy
를 SnapShot으로 설정하는 것이 좋습니다. CloudFormation 으로 생성한 리소스의 경우 해당 스택을 삭제해버리면, DB의 데이터 역시 날아갑니다. 이 때 DeletionPolicy를 SnapShot으로 설정하면 스택 삭제전에 자동으로 스냅샷을 생성합니다.- 업데이트 하는 경우 역시 기존 데이터베이스 스냅샷을 가져와서 업데이트 할 수 있습니다.
DBSnapshotIdentifier
속성을 지정하면 업데이트 할 때 기존 데이터베이스의 데이터를 그대로 가져올 수 있습니다. 그렇지 않으면, 데이터가 날라갑니다.
아래는 Cluster 1개와 Instance 1개인 RDS를 구성하는 예시입니다. 서브넷과 VPC는 이미 생성된 리소스를 참조하는 것을 가정했습니다.
AWSTemplateFormatVersion: 2010-09-09 Description: Set up rds dbUserPassword: NoEcho: true Type: String dbUserName: NoEcho: true Type: String DbSize: Type: String Default: db.t4g.medium DbStorageSize: Type: String Default: "20" DbName: Type: String Default: "my_database" Resources: EC2SecurityGroupForDatabase: Type: "AWS::EC2::SecurityGroup" Properties: GroupName: "my-rds-sg" GroupDescription: "security group for rds" VpcId: "vpc-09c07451beabe29da" SecurityGroupEgress: - IpProtocol: -1 FromPort: -1 ToPort: -1 CidrIp: 0.0.0.0/0 SecurityGroupIngress: - IpProtocol: tcp FromPort: 5432 ToPort: 5432 CidrIp: 0.0.0.0/0 PublicDatabaseSubnetGroup: Type: "AWS::RDS::DBSubnetGroup" Properties: DBSubnetGroupDescription: Subnet for rds DBSubnetGroupName: rds-subnet-group SubnetIds: - subnet-0a78a3b6a6e420b40 - subnet-01078402d182b8615 DatabaseCluster: Type: "AWS::RDS::DBCluster" Properties: MasterUsername: !Ref dbUserName MasterUserPassword: !Ref dbUserPassword AllocatedStorage: !Ref DbStorageSize Engine: postgres EngineVersion: 14.9 DBSubnetGroupName: !Ref PublicDatabaseSubnetGroup VpcSecurityGroupIds: - Ref: "EC2SecurityGroupForDatabase" DatabasePrimaryInstance: Type: "AWS::RDS::DBInstance" Properties: Engine: postgres EngineVersion: 14.9 DBClusterIdentifier: !Ref "DatabaseCluster" DBInstanceClass: !Ref DbSize PubliclyAccessible: false DeletionPolicy: Snapshot
서버리스 v2로 생성하려는 경우 DatabaseCluster로 생성해줘야 합니다.
AWSTemplateFormatVersion: 2010-09-09 Description: ServerlessV2 Cluster Parameters: MasterUsername: Type: String MasterUserPassword: Type: String NoEcho: true DBClusterIdentifier: Type: String EngineVersion: Type: String MinCapacity: Type: String MaxCapacity: Type: String Resources: RDSDBCluster: Type: 'AWS::RDS::DBCluster' Properties: Engine: aurora-mysql DBClusterIdentifier: !Ref DBClusterIdentifier EngineVersion: !Ref EngineVersion MasterUsername: !Ref MasterUsername MasterUserPassword: !Ref MasterUserPassword ServerlessV2ScalingConfiguration: MinCapacity: !Ref MinCapacity MaxCapacity: !Ref MaxCapacity RDSDBInstance: Type: 'AWS::RDS::DBInstance' Properties: Engine: aurora-mysql DBInstanceClass: db.serverless DBClusterIdentifier: !Ref RDSDBCluster
요약
요약: ??