cloud9 을 사용하거나,, 뭐 여튼 필요할떄만 쓰는 aws 인스턴스의 경우엔 ip 주소를 매번 확인해줘야하는 번거로움이 추가된다.
따라서 부팅시에 Route 53 A레코드를 변경해주는 스크립트를 작성해보았음.

IAM 권한도 적절히 필요하겠지만, 난 cloud9 instance를 사용해서인지, aws가 알아서 credential 을 관리해줘서 생략.
필요하다면 아래 참고 글 링크를 확인해보자.

아래 파이썬 스크립트를 적절한 곳에 만들어 주고, 상단 변수 역시 설정해준다. 난 ~/route53/update.py 라고 만들었음.
특정 인스턴스의 public ip 를 구해온 다음, 지정한 url의 A레코드 값을 변경(없으면 생성)해주는 코드이다.
호스팅 영역 ID는 Route 53 에서 해당 도메인 이름(ex.com)을 선택하면 볼 수 있고, URL 은 호스팅 영역 내에서 생성하는 서브도메인을 포함한 이름(abc.ex.com)의 형태를 입력해주자.

INSTANCE_REGION="ap-southeast-1"
INSTANCE_ID="i-~~~~~~~~~~"
DOMAIN_ZONE="호스팅 영역 ID (ZGWP~~~~~~)"
URL="사용할 도메인 (abc.ex.com)"

import boto3

client_ec2 = boto3.client('ec2', region_name=INSTANCE_REGION)
r = client_ec2.describe_instances(InstanceIds=[INSTANCE_ID])

ip = r['Reservations'][0]['Instances'][0]['PublicIpAddress']

client_route53 = boto3.client('route53')
client_route53.change_resource_record_sets(
    HostedZoneId=DOMAIN_ZONE,
    ChangeBatch={'Changes': [{
        'Action': 'UPSERT',
        'ResourceRecordSet': {
            'Name': URL,
            'Type': 'A',
            'TTL': 300,
            'ResourceRecords': [{'Value': ip}]
        }
    }]}
)

그 다음 이 스크립트를 부팅시 실행되도록 설정한다. 여러가지 방법이 있지만 난 crontab을 이용하였음.

crontab -e

@reboot sleep 30 && /usr/bin/python3 /home/ec2-user/route53/update.py

경로 등은 알아서 수정해주자.
난 혹시 몰라서 30초 딜레이를 줬는데 안줘도 될 수도.

1번 테스트 해봤는데 일단 잘 된다. ㅎㅎ

참고
Auto-Register EC2 Instance in AWS Route 53

AWS Lambda 에서 Python 을 쓰면서, AWS 서버에 설치되지 않은 패키지를 사용할 때에는 함수에 포함해서 업로드를 해줘야한다.

 

pip -t 옵션으로 패키지 다운로드 경로를 지정해서 람다 함수 루트에 패키지를 다운받아주면 되지만,

이 경우 디렉토리가 지저분해짐.

 

해결책은 당연하게도, 임의의 폴더를 만들어서 패키지를 다운받고, 해당 경로를 환경변수에 추가해주면 된다.

mkdir packages
# python3 -m pip install [package name] -t ./packages/
python3 -m pip install -r requirements.txt -t ./packages/

 

이 후 Python 핸들러 함수에서 환경변수 추가하기 위한 코드를 파일 최상단에 삽입

import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'packages'))

 

이렇게 하고 packages 폴더는 잊어버리거나 .gitignore 등에 추가해주면 된다.

 

+ 배포 스크립트

AWS Lambda 로 업로드 할때, 난 아래와 같은 스크립트를 만들어서 사용함. (2zip.sh)

 

동작 방식은

1. 몇몇 예외 파일을 제외하고 압축파일 생성

2. aws-cli 를 이용하여 업로드 후

3. 해당 압축파일 삭제

 

#!/bin/bash
LAMBDA_FUNC="Lambda 함수 이름"
zip -rq lambda.zip . -x *__pycache__* 2zip.sh env.sh requirements.txt CONFIG
aws lambda update-function-code --function-name $LAMBDA_FUNC --zip-file fileb://lambda.zip > /dev/null 2>&1
rm lambda.zip

-x 옵션의 인자 등은 상황과 필요에 따라 적절하게 수정을 해주자.

내가 만든 Lambda 함수에서는 AWS RDS 에 접근도 필요했고, 외부 인터넷으로의 접근도 필요했다.

RDS SG(Security Group) 설정상 Lambda 를 VPC 내에 뒀는데, 이러면 Lambda 에서 외부 인터넷으로 접근이 안된다..!


현재 내가 찾은 해결법들은 꼼수 포함 4가지.

1. RDS의 SG설정을 전체 허용, 혹은 Amazon EC2 IP 목록 허용한다.

SG를 전체허용한다면 Lambda 를 VPC 내에 두는 이유가 사라진다.


후자는 Lambda 가 있는 리전의 Amazon EC2 IP 들을 RDS 의 SG 에 때려박아두는 방법.


Amazon 이 사용하는 IP 주소 목록은

https://ip-ranges.amazonaws.com/ip-ranges.json

이 주소에서 JSON 형태로 확인할 수 있다.


관련 설명은 https://docs.aws.amazon.com/ko_kr/general/latest/gr/aws-ip-ranges.html 여기 참고.



대충 위의 접어둔 파이썬 코드를 이용해서,

ap-northeast-2 region 의 EC2 service ip prefix 만 가져온 다음에, 이걸 Security Group 에 넣으면 해결.


Source 에 쉼표로 구분된 값을 넣고 저장하면 알아서 분리된다.


2. AWS에서 제공하는 Managed NAT Gateway를 사용한다.

 VPC 에 Managed NAT Gateway 를 생성하여, VPC 내의 Private subnet 이 외부 인터넷 접속이 가능해주게끔 구성하는 방법

다만 이 NAT Gateway 비용이 월 $40가 넘는다...


3. 외부 인터넷으로 접근하는 함수, VPC 내에서 DB에 접근하는 함수 두개를 만들어 함께 사용한다.

Lambda 비용이 두배로 들겠지만, 어차피 1백만회를 초과할 것 같지도 않고, 초과해도 NAT Gateway 비용보다는 쌀 것 같달까...


다만, VPC 설정이 된 람다함수는 다른 람다함수를 호출할 수 없다. 람다 호출 자체가 외부 인터넷을 사용하는 셈이라..

VPC 밖의 함수를 A(외부 인터넷 연결 가능), VPC 안의 함수를 B 라고 한다면,

항상 A 호출 -> A에서 B를 호출하여 DB작업 -> A에서 결과를 받아서 후처리 -> 반환

의 형태를 취해야한다. 경우에 따라 상관없을 수도 있지만 비효율적으로 될 수도 있는 방법.


4번의 방법을 몰랐기 때문에 난 이렇게 구성해뒀다.


4. ec2 로 NAT instance 를 직접 구축한다.

AWS 에 문서가 있다. -> VPC NAT Instances


후에 시간있을때 적용해볼 예정.

위 글에선 미리 만들어진 AMI를 사용하는데, 나는 기존 Ubuntu Instance 를 어떻게 활용해볼 예정이다.


+ Recent posts