인생은 고통의 연속

Zappa + AWS IAM Role 관련 이슈 본문

카테고리 없음

Zappa + AWS IAM Role 관련 이슈

gnidoc 2021. 2. 17. 22:01
    반응형

    오늘 글은 GDG 글쓰기 공방(aka 모각글) 행사를 참가하면서 작성된 글입니다
    gdg.community.dev/events/details/google-gdg-seoul-presents-gdg-geulsseugi-gongbangaka-mogaggeul/#/purchase

     

    GDG 글쓰기 공방(aka 모각글) | Google Developer Groups

    I’m attending the GDG Seoul meetup on 2021년 2월 17일! Learn more and join me: https://gdg.community.dev/e/mv5y5y/ @GDG

    gdg.community.dev

     

    Zappa

    난 그동안 주로 Elastic Beanstalk을 통해서 웹서버를 배포 했었는데

    사내 시스템의 경우엔 동접자는 거의 1명 이하이고 서버 자원을 거의 안쓰고 있어서 이게 너무 아까웠다

    물론 내 돈은 아니지만 약간 요런 부분에 대해서 트레이닝겸해서 이것 저것 시도하고 있는데

    최근 zappa라는 python 기반의 serverless web hosting 프레임워크를 발견했다

    간단하게 설명하자면,
    lambda에 django를 배포해서 이걸 API Gateway와 엮어서
    serverless web hosting이 가능하도록 쉽게 배포해주는 서비스라고 보면 된다

    링크 : github.com/Miserlou/Zappa

     

    Miserlou/Zappa

    Serverless Python. Contribute to Miserlou/Zappa development by creating an account on GitHub.

    github.com

    그럼 분명 누군가를 그럴 것이다

    왜 Zappa를 써야하냐, 장점이 무엇인가?

     

    Elastic Beanstalk VS Zappa

    그럼 Elastic Beanstalk(이하 EB)과 Zappa 의 기본적인 구조를 보면 아래와 같다

    Elastic Beanstalk 기본 구조
    Zappa 로 배포했을때 구조

    비교를 해보자면 ELB = API Gateway, EC2 = Lambda 의 역할을 해주는 것이고

    EB와 Zappa은 단지 이 전체적인 인프라를 DevOps로 관리할 수 있다는 것이다

    쉽게 말하자면 복잡하게 terraform을 쓰지 않아도 코드로 인프라 관리가 가능하다는 점이다

     

    근데 Zappa 그림을 보면 Zappa는 없다... ㅎㅎ

    사실 배포는 CloudFormation이 대신하고

    Zappa는 이 CloudFormation을 매우 간단하게 json 형태로 사용할 수 있게 해주는 역할만 한다

     

     

    그럼 둘의 공통점은 뭐냐?

    아래와 같이, 바로 배포가 명령어 한줄로 된다는 것이다!

    # EB배포
    # eb use [환경명]
    eb deploy
    
    # zappa 배포
    zappa update [환경명]

     

    그럼 큰 차이점은 뭐냐?

    EB는 서버기반

    Zappa는 Serverless라는 것이다!

     

    Elastic Beanstalk / Zappa 가격비교

    사실 serverless는 가격에서 많은 차이가 난다

    예를 들어서 이중화(HA) 구성을 해야되는 어떤 웹서비스를 EB와 serverless로 운영한다고 가정해보자

    과연 금액차이는 얼마나 날까?

    Elastic Beanstalk)
    ELB, EBS, 트래픽 비용을 제외하고 순수하게 EC2 t3.small 2대의 비용만 고려하면

    서울 기준으로 별도 할인없이 on-demand로 사용할때 시간당 $0.052 한달에 $39, 1년에 $468 가 발생한다

    대충 EB는 숨만 쉬어도 최소 50만원이 발생하고 트래픽이 증가할 경우 추가요금이 발생한다

    서울 t3.small 가격

    Zappa)

    serverless는 사용하는 리소스에 대해서만 비용이 발생하기 때문에 대략적인 사용량을 예측해야되는데

    한달에 1번 약 1MB정도가 되는 HTTP API 요청을 1백만번 하고
    1백만번 Lambda를 호출하며 호출된 Lambda는 256MB 성능으로 5초간 실행된다고 가정했다

    대충 계산해보면 1분에 약 24번 호출된다는 뜻이다

    매우 넉넉하게 계산했는데

    일반적으로 API가 1초가 넘어가면 사용자들은 로딩을 봐야하기 때문에 5초도 너무 길고

    HTTP API가 나르는 데이터가 1MB면 진짜 매우 큰 요청이라고 볼 수 있다

    더보기

    그래도 크게 잡은 이유는 예산은 언제나 최악의 상황을 계산해야되기 때문이다 ㅎㅎ

    만약에 회사에서 정해진 예산을 초과하면 매우 귀찮은 일이 발생하기 때문에... ㅂㄷㅂㄷ

    구체적인 계산은 AWS에서 제공해주는 계산기를 사용했다

    calculator.aws/#/

     

    AWS Pricing Calculator

     

    calculator.aws

    결과는 1년에 $281.88이며 대략 30만원정도다

    쌉니다 싸요

     

    대충보면 Zappa(serverless)의 비용이 절반 밖에 되지 않는데

    Zappa는 트레픽비용을 모두 고려했고

    EB의 경우엔 사실 상용서비스라면 t시리즈를 쓰면 안되고 최소 범용타입인 M5를 써야되는데

    이를 모두 같은 조건에서 비교한다면... 최소 5배~10배까지 비용차이가 나게 된다

    덤으로 EB는 EC2 인스턴스를 관리해야되는 운영비용도 생각해야된다!

     

    물론 규모가 크거나 사용량이 많은 서비스는 당연하게도 EC2 Base인 EB가 훨씬 가성비가 좋다

    이 글은 동접자가 1명 밖에 안되는 매우 micro한 서비스를 운영하기 위해서 Zappa를 도입한 글임을 참고했으면 좋겠다

    꼭 Zappa로 하는게 제일 싸고 좋은게 아니다라는걸 말하고 싶은 것이다!

     

    CI/CD

    어쨋든 난 비용이 저렴하고 쉽게 배포, 운영 가능한 Zappa를 선택했고

    아래와 같은 구조로 Code Commit, Code Build를 사용해서 CI/CD를 구축했다

    CI/CD 및 알림까지 크...

    Code Commit에 코드를 push하면 해당 이벤트를 받아서 Code Pipeline이 동작하게되고

    Code Build에서는 build 이후에 pylint, pytest 를 실행 후 모두 통과한다면 최종 배포가 되며

    이 모든 단계에 대해서는 Code Star에서 제공하는 Chatbot을 통해서 Slack 에 알림도 받았다

    라는 상상을 해보았다...

     

    하지만 여기서 문제가...

    다 잘됐다...

    문제는 Code Build에서 마지막 단계로 zappa를 통해서 배포를 해야되는데

    Code Build에 할당한 IAM Role에 모든 권한을 때려 박았지만 배포가 되지 않았다...

    왜냐? zappa init 이후에 생성되는 json 파일에는 이런 비밀이 있었는데....

    github.com/Miserlou/Zappa#advanced-settings

     

    Miserlou/Zappa

    Serverless Python. Contribute to Miserlou/Zappa development by creating an account on GitHub.

    github.com

    {
    	...,
    	"profile_name": "your-profile-name", // AWS profile credentials to use. Default 'default'. Removing this setting will use the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables instead.
    }

    zappa 배포시 iam user에 대한 profile 을 기본적으로 default를 쓴다

    문제는 해당 profile_name의 key/value를 삭제하면 AWS_ACCESS_KEY_ID와 AWS_SECRET_ACCESS_KEY를 쓴다는 것이다

    즉, profile를 지정하면 지정한 access key를 쓰는거고 아니면 환경 변수에서 해당 값을 찾는다는 것이다...

     

    그럼 이게 또 뭐가 문제냐...

    Code Build에 배포 권한을 가진 IAM Role을 기본적으로 access key를 생성할 수 없다

    그럼 배포만을 위한 별도의 IAM User를 생성해서 그 access key를 환경 변수에 직접 박거나

    환경변수에 직접 쓰지 않고 parameter store를 사용해야된다

    더 큰 문제는 보통 저런 access key는 보안을 위해서 일정 기간(보통 90일)마다 바꿔야되는데

    누군가는 이걸 매번 해줘야된다는 것이다

    아니면... 갱신해주는 Lambda를 따로 만들어야된다는 것이고...

    게다가 이 프로젝트에서 쓰던 모든 IAM User에는 MFA 적용이 필수인 조건이 있어서

    단순히 access key를 사용할 순 없고 매번 STS로 임시토큰을 만들어야 줘야한다

    더보기

    STS가 뭔지는 예전에 기술해놨으니 여길 보면 된다

    2021/02/01 - [아키텍쳐/Cloud] - 맥에서 AWS STS + CodeCommit 사용하기

    진짜 상상만 해도 귀찮았다

    배포하기 귀찮아서 zappa까지 도입하고 다 했는데 여기서 저저저 access key 하나 땜에 다 말아먹어야되나...?

    아니 이럴려고 Role을 쓰는거 아닌가?? 얘는 왜 이따구로 해놨지?? Role 쓰는게 사실 호구인가?

    별에 별 생각이 다 들었고 하루종일 여기에 시간 투자한 내 자신이 한심해지던 순간

    분명 누가 github issue로 물어봤을거 같아서 찾아봤다

     

    해결방법

    zappa도 코드를 까서 보니 어쨌든 python이기 때문에 boto3를 쓰는데

    만약 python 코드에서 access key를 넣어주지 않으면 기본적으로 aws credentials을 찾기 시작한다

    관련 내용 : boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials

     

    Credentials — Boto3 Docs 1.17.9 documentation

    There are valid use cases for providing credentials to the client() method and Session object, these include: The first option for providing credentials to Boto3 is passing them as parameters when creating clients: The second option for providing credentia

    boto3.amazonaws.com

    맥북으로 치자면 ~/.aws/credentials 를 뒤져서 거기있는 값을 쓰는 것이고

    여기도 없다면? 마지막으로 해당 인스턴스에 할당되어있는 Role을 boto3가 쓴다

    위의 내용에서 해당되면 부분만 뽑으면 아래와 같다

    Boto3 will look in several locations when searching for credentials. The mechanism in which Boto3 looks for credentials is to search through a list of possible locations and stop as soon as it finds credentials. The order in which Boto3 searches for credentials is:
    1. Passing credentials as parameters in the boto.client() method
    2. Passing credentials as parameters when creating a Session object
    3. Environment variables
    4. Shared credential file (~/.aws/credentials)
    5. AWS config file (~/.aws/config)
    6. Assume Role provider
    7. Boto2 config file (/etc/boto.cfg and ~/.boto)
    8. Instance metadata service on an Amazon EC2 instance that has an IAM role configured.

     

    즉, Code Build에 할당한 IAM Role에 배포를 위한 권한 적당히 넣어주고
    profile_name 의 key/value를 지워버리면 알아서 boto3가 IAM Role을 찾아서 사용하여 문제가 해결된다!

    결국 내용이 zappa 소개하다가 끝났는데...

    어쨋든 해당 이슈를 겪게된 역사를 쭉 써보았다 ㅎㅎ

     

    반응형
    Comments