[AWS] EC2 IP 변경시마다 자동으로 DNS 매핑되도록 Lambda 구성
0. INTRO
- EC2의 경우 Elastic IP 연결이 되어있지 않다면 Stop/Start 할 때 마다 Public IP가 허용된 CIDR 값 안에서 랜덤으로 변경되게 된다.
- 만약 해당 EC2 IP가 특정 DNS와 연결되어 웹서비스를 하고 있는 상황에서 스케쥴링 작업이 되어야 한다면? 서버가 시작될때마다 변경되는 IP를 Route53의 DNS쪽에서 수동으로 바꿔주는건 정말 번거롭고 서버의 다운타임도 길어지게되는 문제가 있다.
- 이번 실습에서는
서버의 시작을 감지하여 특정 Lambda 함수를 작동시켜 변경된 Public IP를 이미 지정된 DNS에서 자동으로 매핑
시키는 작업을 해 볼 것이다. -
전체적인 아키텍쳐와 작동순서는 아래와 같다.
- EC2의 RUNNING Event를 Eventbridge가 감지
- Eventbridge에 반응이 잡히면 해당 소스를 Trigger로 잡아놓은 Lambda 함수를 호출
- Lambda 함수내에서 Python SDK를 통해 EC2의 Public IP 조회 및 저장
- 변경된 IP를 미리 지정된 DNS와 매핑
- 이렇게 되면 서버의 Stop/Start 액션이 일어나도 웹서비스되는 DNS 주소는 새로 변경된 IP 주소를 가리키게 되므로 Front 단에서 주소의 변경 및 다운타임 없이 서비스가 될 수 있다.
- 사전 요구사항
- 미리 구매된 DNS 주소 (ex> example.com)
- 특정 이름으로 생성된 A Record 주소 (ex> ryan.example.com)
1. Eventbridge Rule 생성
-
Amazon EventBridge > Rules > Create rule 탭으로 들어가 Event의 이름 설정 및 아래와 같이 특정 EC2가 RUNNING 상태일 때 Event가 생성되도록 규칙을 정한다.
-
이후 탭에서
Skip to Review and update
버튼을 눌러 Event에 대해서만 생성을 완료한다.
2. Lambda 함수 구성
- 함수의 역할은 크게 두 가지이다.
- Running EC2에서 Public IP 주소 조회
- 조회한 Public IP 주소를 기존 매핑되어 있는 DNS 주소와 연결
import time import boto3 # EC2 상태 조회 후 Running 상태라면 해당 EC2의 IP 받아오는 함수 def get_instance_status(instance_id, IP:bool=False): ec2 = boto3.client("ec2") describeInstance = ec2.describe_instances(InstanceIds=[instance_id]) status = describeInstance['Reservations'][0]['Instances'][0]['State']['Name'] if IP == True: public_ip = describeInstance['Reservations'][0]['Instances'][0]['PublicIpAddress'] return status, public_ip return status # EC2의 IP를 받아 A record 주소와 매핑시켜주는 함수 def change_A_record(public_ip): hosted_zone_id = '구매한 DNS의 zone ID' record_name = 'DNS 주소 이름' route53_client = boto3.client('route53') response = route53_client.change_resource_record_sets( HostedZoneId=hosted_zone_id, ChangeBatch={ 'Changes': [ { 'Action': 'UPSERT', 'ResourceRecordSet': { 'Name': record_name, 'Type': 'A', 'TTL': 300, 'ResourceRecords': [{'Value': public_ip}] } } ] } ) return { 'statusCode': 200, 'body': f'A record updated successfully to {public_ip}' } def lambda_handler(event, context): INSTANCE_ID = 'EC2 Instance ID' status = get_instance_status(INSTANCE_ID) while True: time.sleep(5) current_status = get_instance_status(INSTANCE_ID) print(current_status) if current_status == 'running': current_status, public_ip = get_instance_status(INSTANCE_ID, True) record_cng = change_A_record(public_ip) break else: pass return record_cng
3. Lambda 함수의 Trigger 설정
-
Lambda > Add Trigger 섹션에서 위에서 만든 Eventbridge의 Rule을 Lambda 함수의 Trigger로 설정한다.
-
EC2의 Start Event가 감지되면 Lambda가 Trigger 되며 이와 관련된
Log는 Lambda와 연결된 Cloudwatch Log Group에서 볼 수 있다.
4. OUTRO
- DNS 주소를 통해 웹서비스를 하는 경우 보통은 서버가 항상 Running 중이거나 Elastic IP를 통해 Public IP를 고정시켜 이 IP를 DNS 주소와 연결시키는 경우가 많다.
- 서버에 SSH로 접속하여 작업해야할 상황에서는 조금 번거로울 수 있겠지만 Elastic IP 비용 절감을 할 수 있으며 EC2가 많아지더라도 Elastic IP 할당량에 대한 고민 없이 A Record와 즉각적인 1:1 대응이 가능해진다.
Leave a comment