글
boto3 를 이용하여, AWS 로컬스택 아키텍처 구성해보기
IT/AWS Lambda & Resources Trouble Shooting
2020. 10. 16. 10:47
반응형
근 두달가까이 소식이 없다가, 그동안 쌓인 내용들을 부랴부랴 올리고 있습니다.
사실 파이썬3에 대한 이용능력을 좀 높일 필요가 있어서, 해커랭크에서 좀 살다 왔습니다.
신기한게 자격증도 주어지더라구요... (어느정도 문제 풀어보니)
한번 들어가셔서 확인해보시기 바랍니다 :)
자 무튼, 한동안 소식이 없기도 했고, 그 소식 없는 기간동안 잠깐 과제를 진행하기도 했습니다.
로컬스택을 이용해, 로컬 환경에서의 AWS 아키텍처링을 테스팅해볼 수 있는 도구입니다.
로컬스택에 대한 설명은 조금 후일담으로 미루어둘게요. (클라우드 개발자이기에 코드를 집중적으로 판다 실시)
(아참, 환경마다 다를 순 있겠지만, 파이썬3를 이용해 로컬스택 설치하지 마시구, 도커 & 도커컴포즈파일 이용해서 설치하세요. 파이썬3 이용해서 설치할 때, 디펜던시 계속 깨지는 오류가 발생합니다. 트러블 슈팅 귀찮으니 도커/컴포즈 로 가는 방법 추천드립니다.)
* 로컬스택 main
https://hub.docker.com/r/localstack/localstack/
* 로컬스택 설치 가이드
과제로 주어진, 구성해야할 아키텍처는 다음과 같습니다.
로컬스택 환경이 모두 구성되었고, 로컬스택 컨테이너가 돌아가고 있다고 가정하겠습니다.
이제 저 모든 구성요소를 의존성 순서대로 주입하여, AWS boto3 & python3 스크립트를 돌리게 할 겁니다.
한편으로는 테라폼 IAC로도 되긴 하지만, 충분히 SDK로도 됩니다..!!!!! 라는 것을 보여주고 싶었어요 ㄷㄷㄷㄷ.... (그래봤자 100% 치환은 되진 않겠지만..)
import json
import boto3
import subprocess
"""
로컬스택 AWS 클라우드 인프라 메이커 (Python3 Script with boto3)
@desc
POC 수행을 위한, AWS 서비스 구성요소
본 파이썬 스크립트 실행 시, 하기 구성요소 생성
IAM : 루트유저 급 마스터 Role
IGW : 신규 인터넷 게이트웨이
VPC : 신규 VPC (10.0.0.0/16)
Subnets Of VPC : 신규 VPC의 서브넷
RouteTable (RT) : 생성된 서브넷을 위한 라우트테이블
Route of RT : 라우트 테이블의 네트워크 경로
Security Group : 모든 대역 / 모든 포트 Open (AnyOpen) (In/Out 포함)
EC2 Key Pair : EC2 머신을 위한 키페어
EC2 Instance Profile : EC2 머신이 사용할 IAM 프로필
EC2 Instance : Nginx가 기동될 EC2 머신
Kinesis : EC2 머신이 로그를 전송할 키네시스 데이터스트림
Lambda : 키네시스 데이터스트림의 이벤트 트리거를 받아 처리할 람다
Lambda Trigger : 키네시스 DS와 람다 이벤트 매핑
S3 : 람다가 정제한 로그를 쌓을 버킷
@author 클라우드 개발자 앙몬드
@since 2020-09-17
"""
print("[System] 로컬스택 AWS 클라우드 인프라 메이커 시작")
print("=" * 30)
PROFILE_NAME = "localstack" # aws API와 통신하기 위한 크리덴셜 프로필
REGION_NAME = "ap-northeast-2" # 로컬스턱 리전 고정 (서울)
ENDPOINT_URL = "http://localhost:4566/" # 로컬스택 Fake AWS API 엔드포인트
session = boto3.session.Session(profile_name=PROFILE_NAME, region_name=REGION_NAME) # boto3 세션 팩토리
iam_client = session.client("iam", endpoint_url=ENDPOINT_URL) # iam 클라이언트
ec2_resource = session.resource("ec2", endpoint_url=ENDPOINT_URL) # ec2 리소스
ec2_client = session.client("ec2", endpoint_url=ENDPOINT_URL) # ec2 클라이언트
kinesis_client = session.client('kinesis', endpoint_url=ENDPOINT_URL) # kinesis 클라이언트
lambda_client = session.client('lambda', endpoint_url=ENDPOINT_URL) # lambda 클라이언트
s3_client = session.client("s3", endpoint_url=ENDPOINT_URL) # s3 클라이언트
LOCALSTACK_LOG_S3_BUCKET_NAME = "localstack-fake-log-bucket" # s3 버킷 이름
LOCALSTACK_KINESIS_DS_NAME = "localstack-fake-kinesis-ds-for-log" # 키네시스 이름
LOCALSTACK_LAMBDA_NAME = "localstack-fake-lambda-for-log-processing" # 람다함수 이름
print("[System] 기본 환경변수 설정 완료")
"""
루트유저 급 마스터 Role 생성
"""
# IAM Policy 생성
managed_policy = {
"Version": "2012-10-17",
"Statement": [{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "*",
"Resource": "*"}]}
response_create_policy = iam_client.create_policy(
PolicyName='localstack-fake-master-policy',
PolicyDocument=json.dumps(managed_policy))
arn_fake_master_policy = response_create_policy["Policy"]["Arn"]
# IAM Role 생성
trust_entity_policy = {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"s3.amazonaws.com",
"kinesis.amazonaws.com",
"ec2.amazonaws.com"
]
},
"Action": "sts:AssumeRole"}]}
response = iam_client.create_role(
Path="/",
RoleName="localstack-fake-master-role",
AssumeRolePolicyDocument=json.dumps(trust_entity_policy),
Description="localstack-fake-master-role",
MaxSessionDuration=3600)
iam_role_arn = response["Role"]["Arn"]
# IAM Role에 Policy 탑재
# arn_fake_master_policy 은, create_policy 의 리턴값으로 획득 가능
iam_client.attach_role_policy(
PolicyArn=arn_fake_master_policy,
RoleName='localstack-fake-master-role')
print("[System] AWS 계정 루트유저급 IAM Role 생성 완료 - 루트유저급 Role 사용 가능 엔티티 : EC2 / Lambda / S3 / Kinesis")
"""
인터넷 게이트웨이 / VPC 생성 & IGW 탑재
"""
igw = ec2_resource.create_internet_gateway()
vpc = ec2_resource.create_vpc(CidrBlock='10.0.0.0/16')
ec2_client.modify_vpc_attribute(VpcId=vpc.id, EnableDnsSupport={'Value': True})
ec2_client.modify_vpc_attribute(VpcId=vpc.id, EnableDnsHostnames={'Value': True})
vpc.attach_internet_gateway(InternetGatewayId=igw.id)
print("[System] IGW/VPC 생성 & 신규 생성 VPC에 IGW 링크 완료")
"""
VPC의 서브넷 생성 (AZ 이중화를 위해 2개로 분할 생성), RT 생성 & 네트워크 라우터 탑재
-> nginx 인스턴스는 이중화되지 않으므로, 서브넷은 이중화하였으며, 실제 라우터는 한 곳만 설정
"""
routetable = vpc.create_route_table()
route_public = routetable.create_route(DestinationCidrBlock='0.0.0.0/0', GatewayId=igw.id)
subnet_a = ec2_resource.create_subnet(CidrBlock='10.0.0.0/24', VpcId=vpc.id, AvailabilityZone="ap-northeast-2a")
subnet_c = ec2_resource.create_subnet(CidrBlock='10.0.1.0/24', VpcId=vpc.id, AvailabilityZone="ap-northeast-2c")
routetable.associate_with_subnet(SubnetId=subnet_a.id)
print("[System] Route Table 및 요청 네트워크 라우팅 설정 완료")
print("[System] VPC IP대역 중, 이중화를 위한 subnet C클래스 분할 & AZ-A 서브넷에 라우트 탑재 완료")
"""
인/아웃바운드 전 대역 전 포트 오픈 Security Group 생성
"""
security_group = ec2_resource.create_security_group(GroupName='sg-localstack', Description='sg-localstack', VpcId=vpc.id)
security_group.authorize_ingress(
IpPermissions=[
{
'FromPort': 0,
'IpProtocol': 'tcp',
'IpRanges': [
{
'CidrIp': '0.0.0.0/0',
'Description': 'all_any_open'
},
],
'ToPort': 65535
},
{
'FromPort': 0,
'ToPort': 65535,
'IpProtocol': 'udp',
'IpRanges': [
{
'CidrIp': '0.0.0.0/0',
'Description': 'all_any_open'
},
],
}])
print("[System] 시큐리티그룹 네트워크 애니오픈 생성 완료")
"""
EC2에 접근하기 위한 Key Pair 생성
"""
LOCAL_STACK_FAKE_KEYPAIR_NAME = "fake-keypair"
fake_keypair = open('fake-keypair.pem', 'w')
key_pair_response = ec2_resource.create_key_pair(KeyName=LOCAL_STACK_FAKE_KEYPAIR_NAME)
KeyPairOut = str(key_pair_response.key_material)
fake_keypair.write(KeyPairOut)
fake_keypair.close()
print("[System] EC2 머신 접근을 위한 키페어 생성 완료 > ./fake-keypair.pem 확인")
"""
nginx 웹서버를 위한 EC2 인스턴스 생성
"""
instance_profile = iam_client.create_instance_profile(InstanceProfileName='ec2-nginx-instance-profile')
arn_of_instance_profile = instance_profile["InstanceProfile"]["Arn"]
response = iam_client.add_role_to_instance_profile(
InstanceProfileName='ec2-nginx-instance-profile',
RoleName='localstack-fake-master-role'
)
print("[System] EC2 머신을 위한 IAM 인스턴스 프로필 생성 완료")
instances = ec2_resource.create_instances(
ImageId='ami-06c2d58d267b830df',
InstanceType='t2.micro',
KeyName=LOCAL_STACK_FAKE_KEYPAIR_NAME,
MinCount=1,
MaxCount=1,
Placement={'AvailabilityZone': 'ap-northeast-2a' },
NetworkInterfaces=[{
'SubnetId': subnet_a.id,
'DeviceIndex': 0,
'AssociatePublicIpAddress': True,
'Groups': [security_group.group_id] }],
IamInstanceProfile={
'Arn': arn_of_instance_profile,
'Name': 'ec2-nginx-instance-profile' }
)
print("[System] EC2 머신 생성 완료")
"""
키네시스 생성 시, 요청에 대한 응답은 200 정상으로 리턴되지만, 실제 생성되지 않는 이슈가 발생
"""
#subprocess.run('aws kinesis create-stream --stream-name "localstack-fake-kinesis-ds-for-log" --shard-count 1 --profile localstack --endpoint http://localhost:4566', shell=True, check=True)
response = kinesis_client.create_stream(StreamName=LOCALSTACK_KINESIS_DS_NAME, ShardCount=1)
#response2 = kinesis_client.list_streams( Limit=100 )
print(f"[DEBUG] Kinesis Creation Response : {response}")
print(f"[System] 키네시스 DS 생성 완료 (응답 Success / 실제 구현은 안되는 버그 존재)")
print("[Warn] 로컬스택 키네시스 ARN : arn:aws:kinesis:ap-northeast-2:000000000000:stream/localstack-kinesis-fake-ds")
"""
람다 생성
"""
response_lambda = lambda_client.create_function(
FunctionName=LOCALSTACK_LAMBDA_NAME,
Runtime='python3.8',
Role=iam_role_arn,
Handler = 'lambda_function.lambda_handler',
Code={'ZipFile': open('./localstack-logs-process-fake-lambda.zip', 'rb').read()},
Description='localstack-lambda',
Timeout=900,
MemorySize=1024,
Publish=True,
VpcConfig={
'SubnetIds': [subnet_a.id, subnet_c.id ],
'SecurityGroupIds': [security_group.group_id ] } )
print("[System] 람다 생성 완료")
response_lambda_trigger = lambda_client.create_event_source_mapping(
EventSourceArn='arn:aws:kinesis:ap-northeast-2:000000000000:stream/localstack-kinesis-fake-ds',
FunctionName=LOCALSTACK_LAMBDA_NAME,
Enabled=True,
BatchSize=100,
MaximumBatchingWindowInSeconds=60,
ParallelizationFactor=1,
MaximumRecordAgeInSeconds= -1,
BisectBatchOnFunctionError=False,
MaximumRetryAttempts=0,
)
print("[System] 람다 이벤트 트리거 매핑 완료 <- Kinesis Fake Stream of Bugs")
"""
s3 버킷 생성
"""
response_s3_create = s3_client.create_bucket(
ACL='private',
Bucket=LOCALSTACK_LOG_S3_BUCKET_NAME,
CreateBucketConfiguration={'LocationConstraint': 'ap-northeast-2' },
)
print(f"[System] S3 버킷 생성 완료")
print("=" * 30)
print("[System] 로컬스택 AWS 클라우드 인프라 메이커 종료")
반응형
'IT > AWS Lambda & Resources Trouble Shooting' 카테고리의 다른 글
쿠버네티스 좀비파드 저격용 파이썬 스크립트 (0) | 2020.10.21 |
---|---|
파이썬3를 이용한, AWS ES 인덱싱 코드 예시 (0) | 2020.10.21 |
키네시스 샤드 input event driven 인/디코딩 데이터 정제 람다함수 (0) | 2020.10.16 |
AWS System Manager / SSM을 이용한, 머신 컨트롤링 스크립트 (0) | 2020.10.14 |
AWS Lambda 에서의 웹크롤링 고찰 (0) | 2020.06.07 |