인프라
험난했던 CloudFormation으로 인프라 구성하기
김도리개발자
2023. 4. 11. 01:54
13번의 시도 동안 어떤 에러였는지 어떻게 해결했는지 써보겠다!
1. dory-test
- 대상 : AWS::EC2::EIPAssociation
- 에러 메시지 : The networkInterface ID 'eni-0b76d551207121168' does not exist (Service: AmazonEC2; Status Code: 400; Error Code: InvalidNetworkInterfaceID.NotFound; Request ID: 5ec40d3a-ccb6-42ce-a75c-f3049cfdd437; Proxy: null)
- 문제 : networkInterfaceId를 입력하는데 networkInterface는 EIP가 생성되고 나서 나오기때문에 지정하는 것이 불가능함
- 솔루션 : networkInterfaceId에 EC2 인스턴스를 Ref로 넣어줌
(스포를 하자면 잘못된 해결 방식이었고 밑에서 올바른 해결법이 나옴)
2. dory-test-2
- 대상 : AWS::ElasticLoadBalancingV2::LoadBalancer
- 에러 메시지 : 1 validation error detected: Value 'Internet-facing' at 'scheme' failed to satisfy constraint: Member must satisfy enum value set: [internet-facing, internal] (Service: AmazonElasticLoadBalancing; Status Code: 400; Error Code: ValidationError; Request ID: a84e9a53-bc93-4ba1-aaf5-fe6ff3ecd25e; Proxy: null)
- 문제 : scheme 값의 value "internet-facing"의 "i" "I" 대소문자 잘못 입력으로 인한 오류
- 솔루션 : "I"를 "i"로 바꾸기
3. dory-test-3
- 대상 : AWS::EC2::Instance
- 에러 메시지 : The subnet ID 'subnet-0b81102228ea3ee85' does not exist (Service: AmazonEC2; Status Code: 400; Error Code: InvalidSubnetID.NotFound; Request ID: c87299f4-1cd1-4d71-bab3-a563174986ef; Proxy: null)
- 문제 : EC2 인스턴스에 subnet id로 "subnet-oooooooooo~~" 이런식으로 입력함
- 솔루션 : subnet id로 Ref로 앞으로 만들어질 subnet을 지정
4. dory-test-4
- 대상 : AWS::EC2::KeyPair, AWS::EC2::Instance
- 에러 메시지 : The key pair '[prod] gridge bastion host' does not exist (Service: AmazonEC2; Status Code: 400; Error Code: InvalidKeyPair.NotFound; Request ID: 8a17627e-3107-432b-ad80-3fce8bd5d6c8; Proxy: null)
- 문제 : KeyPair에서 정의한 KeyName과 의 Instance에서 지정한 KeyName을 다르게 입력함
- 솔루션 : KeyName을 동일하게 잘 입력함
5. dory-test-5, dory-test-6, dory-test-7
- 대상 : AWS::EC2::EIPAssociation
- 에러 메시지 : Invalid id: "i-0b9febe9c7baa6a37" (expecting "eni-...") (Service: AmazonEC2; Status Code: 400; Error Code: InvalidNetworkInterfaceId.Malformed; Request ID: 64a53572-1a9d-4119-b6ab-e5cd92b4f838; Proxy: null)
- 문제 : networkInterfaceId는 "eni-"로 시작해야 하는데 인스턴스의 id는 "i-"로 시작함
- 솔루션 : dory-test와 엮인 상황
- Sub 사용해서 id 앞에 "en"을 붙여줌 (ㅇㅇ틀린 방법임)
- !Sub "en${EC2Instance}" 이런식으루
- 에러 메시지 : The networkInterface ID 'eni-09ce3f806a427eb3a' does not exist (Service: AmazonEC2; Status Code: 400; Error Code: InvalidNetworkInterfaceID.NotFound; Request ID: 80a00740-e4b8-48c1-a105-4e8871e99088; Proxy: null)
- 문제 : 존재하지 않는 네트워크 인터페이스 id라고 함
- 솔루션
- 다른 예시의 네트워크 인터페이스를 보니까 ec2 인스턴스의 id값을 따라가는 것이 아니라 vpc, subnet, sg를 따라감
- 혹시나 해서 걍 NetworkInterfaceId 없애버림
- 에러 메시지 : Either NetworkInterfaceId or InstanceId must be specified
- 문제 : NetworkInterfaceId 없음
- 솔루션 :
- NetworkInterfaceId나 InstanceId 둘 중 하나는 꼭 정의되어 있어야 한다고 함
- EC2EIPAssociation 구글링하니까 networkInterfaceId가 required가 아니라 conditional임
- NetworkInterfaceId 혹은 InstanceId 둘 중 하나만 입력하면 되는 거여서 InstanceId를 입력했음 (앞으로 만들어질 Instance의 id를 입력해야 해서 Ref로 가져옴)
6. dory-test-8
- 대상 : AWS::EC2::EIPAssociation
- 에러 메시지 : 10.1.2.145 is not mapped to the interface eni-0fa8f6546dcd80e67(Service: AmazonEC2; Status Code: 400; Error Code: InvalidParameterValue; Request ID: a61e8266-3728-49ea-a534-d135fda42654; Proxy: null)
- 문제 : PrivateIpAddress를 정의했었는데 이 ip주소와 네트워크 인터페이스가 매핑이 안됨
- 솔루션 : PrivateIpAddress가 필수값이 아니라서 지워버림
7. dory-test-9
- 대상 : AWS::ElasticLoadBalancingV2::Listener
- 에러 메시지 : Resource handler returned message:faf2' is not a valid target group ARNCode: 400, Request ID: c2837691-2147-Request ID: null)" (RequestToken:InvalidRequest) 96219337-6df7-5b1c-788d-f65e84f8a383, HandlerErrorCode: 4137-a261-413fdf41be76, Extended (Service: ElasticLoadBalancingV2, Status'"arn:aws:elasticloadbalancing:ap-northeast-2:647180380627:listener/app/prod-public-gridge-alb/9711b656879151f0/01e2887c278a
- 문제 : DefaultActions의 TargetGroupArn이 잘못 설정된 것 같음
- 솔루션 : AWS::ElasticLoadBalancingV2::Listener Action(DefaultActions)는 필수인데 그 안의 TargetGroupArn은 필수값이 아니길래 지워버림
8. dory-test-10
- 대상 : AWS::ElasticLoadBalancingV2::Listener
- 에러 메시지 : Resource handler returned message: "Model validation failed (#/DefaultActions: expected type: JSONArray, found: JSONObject #/Port: expected type: Number, found: String)" (RequestToken: e59d4231-9cd7-23eb-574c-0264d20827a6, HandlerErrorCode: InvalidRequest)
- 문제 : DefaultActions은 list(배열)로 들어와야 하는데 내가 TargetGroupArn을 지울 때 "-"를 잘못 같이 지워버림
- 솔루션 : 다시 DefaultActions 안에서 type 앞에 "-" 붙여줌
9. dory-test-11
- 대상 : AWS::ElasticLoadBalancingV2::Listener
- 에러 메시지 : Resource handler returned message: "A target group ARN must be specified (Service: ElasticLoadBalancingV2, Status Code: 400, Request ID: f458f3d3-834e-4e00-91e5-e3a6492effa7, Extended Request ID: null)" (RequestToken: 46c6a919-e4e3-065a-7828-310324bb0b2, HandlerErrorCode: InvalidRequest)
- 문제 : 위에서처럼 TargetGroupArn 필수값 아니라 써져있었는데 갑자기 꼭 정의 되어야 한다면서 에러 뱉음
- 솔루션 :
- TargetGroupArn에 ElasticLoadBalancingV2TargetGroup Ref로 입력해줌
- ElasticLoadBalancingV2Listener2는 알고보니 필요 없는거여서 지워줌
10. dory-test-12
- 대상 : AWS::EC2::NatGateway
- 에러 메시지 : Resource handler returned message: "Error occurred during operation 'NatGateway nat-072584a0f41e4fce6 is in state failed and hence failed to stabilize. Detailed failure message: Elastic IP address [eipalloc-0401ba7f72a6b5bOc] is already associated'" (RequestToken: 8c447696-80df-f7a9-2269-1741a3c9a551, HandlerErrorCode: GeneralServiceException)
- 문제 : eip를 다른 ec2 인스턴스와 NatGateway 둘 다 동시에 associate 하고 있었음
- 솔루션 : eip에 기존 EC2 인스턴스 연결되어 있는거 끊고 NatGateway에만 연결하는것으로 바꿈
더보기
yaml 템플릿 코드
AWSTemplateFormatVersion: "2010-09-09"
Description: ""
Resources:
EC2VPC:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: "10.1.0.0/16"
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: "default"
Tags:
- Key: "Name"
Value: "[prod] gridge vpc"
EC2Subnet:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: "ap-northeast-2b"
CidrBlock: "10.1.2.0/24"
VpcId: !Ref EC2VPC
MapPublicIpOnLaunch: false
Tags:
- Key: "Name"
Value: "[prod] public gridge subnet"
EC2Subnet3:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: "ap-northeast-2a"
CidrBlock: "10.1.1.0/24"
VpcId: !Ref EC2VPC
MapPublicIpOnLaunch: false
Tags:
- Key: "Name"
Value: "[prod] private gridge subnet"
EC2Subnet2:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: "ap-northeast-2a"
CidrBlock: "10.1.3.0/24"
VpcId: !Ref EC2VPC
MapPublicIpOnLaunch: false
Tags:
- Key: "Name"
Value: "[prod] public gridge alb subnet 1"
EC2Subnet4:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: "ap-northeast-2d"
CidrBlock: "10.1.4.0/24"
VpcId: !Ref EC2VPC
MapPublicIpOnLaunch: false
Tags:
- Key: "Name"
Value: "[prod] public gridge alb subnet 2"
EC2SecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "[prod] gridge bastion host sg"
GroupName: "[prod] gridge bastion host sg"
VpcId: !Ref EC2VPC
SecurityGroupIngress:
- CidrIp: "0.0.0.0/0"
Description: "temp"
FromPort: 80
IpProtocol: "tcp"
ToPort: 80
- CidrIp: "0.0.0.0/0"
Description: "temp"
FromPort: 443
IpProtocol: "tcp"
ToPort: 443
- CidrIp: "110.12.32.45/32"
Description: "terry"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
- CidrIp: "123.111.222.168/32"
Description: "frontone"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
- CidrIp: "180.66.136.118/32"
Description: "eric-temp"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
- CidrIp: "211.110.88.8/32"
Description: "jerry-temp"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
- CidrIp: "211.217.241.105/32"
Description: "gongduck_softsquared"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
- CidrIp: "211.217.241.19/32"
Description: "gongduck_softsquared_lobby"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
- CidrIp: "211.58.97.145/32"
Description: "dory"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
- CidrIp: "219.240.165.33/32"
Description: "henry"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
- CidrIp: "222.111.230.94/32"
Description: "ark_home_nicednb"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
- CidrIp: "61.37.43.195/32"
Description: "papa_dongguk"
FromPort: 22
IpProtocol: "tcp"
ToPort: 22
SecurityGroupEgress:
- CidrIp: "0.0.0.0/0"
IpProtocol: "-1"
EC2SecurityGroup2:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "[prod] gridge public alb sg"
GroupName: "[prod] gridge public alb sg"
VpcId: !Ref EC2VPC
SecurityGroupIngress:
- CidrIp: "0.0.0.0/0"
FromPort: 80
IpProtocol: "tcp"
ToPort: 80
- CidrIp: "0.0.0.0/0"
FromPort: 443
IpProtocol: "tcp"
ToPort: 443
SecurityGroupEgress:
- CidrIp: "0.0.0.0/0"
IpProtocol: "-1"
EC2SecurityGroup3:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "[prod] gridge private ec2 sg"
GroupName: "[prod] gridge private ec2 sg"
VpcId: !Ref EC2VPC
SecurityGroupIngress:
- CidrIp: !Sub "${EC2Instance.PrivateIp}/32"
Description: "[prod] gridge bastion host private ip"
IpProtocol: "-1"
- SourceSecurityGroupId: !Ref EC2SecurityGroup2
Description: "[prod] gridge public alb sg"
IpProtocol: "-1"
SecurityGroupEgress:
- CidrIp: "0.0.0.0/0"
IpProtocol: "-1"
EC2Instance:
Type: "AWS::EC2::Instance"
Properties:
ImageId: "ami-0e9bfdb247cc8de84"
InstanceType: "t3.micro"
KeyName: "prod-gridge-bastion-host"
AvailabilityZone: "ap-northeast-2b"
Tenancy: "default"
SubnetId: !Ref EC2Subnet
EbsOptimized: false
SecurityGroupIds:
- !Ref EC2SecurityGroup
SourceDestCheck: true
BlockDeviceMappings:
- DeviceName: "/dev/sda1"
Ebs:
Encrypted: false
VolumeSize: 8
SnapshotId: "snap-0eed95f8d349d4ce5"
VolumeType: "gp3"
DeleteOnTermination: true
Tags:
- Key: "Name"
Value: "[prod] gridge bastion host"
EC2Instance2:
Type: "AWS::EC2::Instance"
Properties:
ImageId: "ami-0eddbd81024d3fbdd"
InstanceType: "t3.medium"
KeyName: "prod-gridge-private-ec2"
AvailabilityZone: "ap-northeast-2a"
Tenancy: "default"
SubnetId: !Ref EC2Subnet3
EbsOptimized: false
SecurityGroupIds:
- !Ref EC2SecurityGroup3
SourceDestCheck: true
BlockDeviceMappings:
- DeviceName: "/dev/xvda"
Ebs:
Encrypted: false
VolumeSize: 35
SnapshotId: "snap-033af589cb06bcf09"
VolumeType: "gp2"
DeleteOnTermination: true
Tags:
- Key: "Name"
Value: "[prod] gridge-private-ec2"
ElasticLoadBalancingV2LoadBalancer:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
Name: "prod-public-gridge-alb"
Scheme: "internet-facing"
Type: "application"
Subnets:
- !Ref EC2Subnet2
- !Ref EC2Subnet4
SecurityGroups:
- !Ref EC2SecurityGroup2
IpAddressType: "ipv4"
ElasticLoadBalancingV2Listener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
LoadBalancerArn: !Ref ElasticLoadBalancingV2LoadBalancer
Port: 80
Protocol: "HTTP"
DefaultActions:
- TargetGroupArn: !Ref ElasticLoadBalancingV2TargetGroup
Type: "forward"
ElasticLoadBalancingV2TargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
Port: 80
Protocol: "HTTP"
HealthCheckPort: "traffic-port"
HealthCheckProtocol: "HTTP"
HealthCheckTimeoutSeconds: 5
UnhealthyThresholdCount: 2
TargetType: "instance"
Matcher:
HttpCode: "200"
HealthyThresholdCount: 5
VpcId: !Ref EC2VPC
Name: "prod-public-gridge-alb-tg"
HealthCheckEnabled: true
Targets:
- Id: !Ref EC2Instance2
Port: 80
EC2EIPAssociation:
Type: "AWS::EC2::EIPAssociation"
Properties:
AllocationId: !GetAtt EC2EIP.AllocationId
InstanceId: !Ref EC2Instance
EC2EIPAssociation2:
Type: "AWS::EC2::EIPAssociation"
Properties:
AllocationId: !GetAtt EC2EIP2.AllocationId
InstanceId: !Ref EC2Instance2
EC2KeyPair:
Type: "AWS::EC2::KeyPair"
Properties:
KeyName: "prod-gridge-bastion-host"
KeyType: "rsa"
EC2KeyPair2:
Type: "AWS::EC2::KeyPair"
Properties:
KeyName: "prod-gridge-private-ec2"
KeyType: "rsa"
EC2VPCGatewayAttachment:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
InternetGatewayId: !Ref EC2InternetGateway
VpcId: !Ref EC2VPC
EC2NatGateway:
Type: "AWS::EC2::NatGateway"
Properties:
SubnetId: !Ref EC2Subnet
Tags:
- Key: "Name"
Value: "[prod] gridge nat"
AllocationId: !GetAtt EC2EIP.AllocationId
EC2InternetGateway:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: "Name"
Value: "[prod] gridge igw"
EC2Route:
Type: "AWS::EC2::Route"
Properties:
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref EC2InternetGateway
RouteTableId: !Ref EC2RouteTable
EC2EIP:
Type: "AWS::EC2::EIP"
Properties:
Domain: "vpc"
Tags:
- Key: "Name"
Value: "[prod] gridge bastion host"
EC2EIP2:
Type: "AWS::EC2::EIP"
Properties:
Domain: "vpc"
Tags:
- Key: "Name"
Value: "[prod] gridge nat eip"
EC2RouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref EC2VPC
Tags:
- Key: "Name"
Value: "[prod] public gridge rt"
EC2RouteTable2:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref EC2VPC
Tags:
- Key: "Name"
Value: "[prod] public gridge alb rt"
EC2RouteTable3:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref EC2VPC
Tags:
- Key: "Name"
Value: "[prod] private gridge rt"
EC2Route2:
Type: "AWS::EC2::Route"
Properties:
DestinationCidrBlock: "0.0.0.0/0"
NatGatewayId: !Ref EC2NatGateway
RouteTableId: !Ref EC2RouteTable3
EC2SubnetRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref EC2RouteTable
SubnetId: !Ref EC2Subnet
EC2SubnetRouteTableAssociation2:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref EC2RouteTable2
SubnetId: !Ref EC2Subnet2
EC2SubnetRouteTableAssociation3:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref EC2RouteTable2
SubnetId: !Ref EC2Subnet4
EC2SubnetRouteTableAssociation4:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref EC2RouteTable3
SubnetId: !Ref EC2Subnet3
험난했던 CloudFormation로 인프라 구성하기 끗 ㅡ
참고로 스택 삭제하면 생성했던 인프라들도 함께 삭제해줌!