끊임없이 검증하라

나에게 당연할지라도

Learning

L3_AWS Elastic beanstalk_개고생 체험기

fadet 2023. 2. 28. 20:16

이번 포스트는 학습 과정에서 그 과정을 기록한 글이기에 부정확한 정보가 매우 많이 포함될 수 있습니다.

Blog Driven 학습은 매우 위험하니 정말로 이 포스트는 참고용으로만 봐주시고 틀린 부분이 있다면 알려주시면 감사하겠습니다. 

 

❗ 글 시작에 앞서 이 글은 정말로 제가 맨 땅에 헤딩하며 시간을 갖다 버린 과정이 너무 아까워서 나중에 보도록 기록만 하는데 목적을 둔 글입니다. 따라서 이 포스트는 정보습득보단 반면교사로 삼으시길 바랍니다.


❗ 포스트를 보실때 미리 알면 도움이 될 지식 : 클라우드 IaaS(AWS EC2를 사용해보셨으면 충분)

* 잘 모르시는 기술은 로그인 필요없이  이 곳에서 AI에게 물어보세요!

 


이 포스트의 결론을 먼저 말씀드리겠습니다. 

💢 그냥 EC2 쓰세요

이 화면만 이틀 동안 주구장창 볼거 아니면

 

aws elastic beanstalk(이후 EB) 정말 좋은 클라우드 서비스지만.... 더 추상화되서 간편하다는 한마디 때문에 농담 아니라 하루 이틀을 통째로 설정바꾸고 로그보고 수정해서 배포하고 권한 주고 AWS 설정 만지고를 무한 반복했기에 다소 어그로성이 짙은 말머리를 단 점은 이해해주시길 바랍니다.

 

일단 EB에 대한 간단한 소개를 해드리자면 aws에서 제공하는 클라우드 서비스 중 하나인데 흔히 다들 아시는 EC2같은 IaaS보다 조금 더 추상화된(조금 더 자동화가 더 붙은) PaaS 모델입니다. 경쟁자인 GCP의 app engine과 비슷하다고 생각하시면 됩니다. 쉽게 말해서 내가 개발한 코드를 따로 설정 안하고 바로 배포해서 브라우저에 url만 치면 바로 서비스되는 모델이라고 생각하시면 됩니다.

 

개발 공부하시다보면 대부분 EC2 프리티어 정도는 한번씩 만져봅니다. 저 또한 EC2를 토이 프로젝트로 한 번 경험했었고 그때도 이것저것 설정 만지느라 하루 정도 썼던 기억이 납니다. 그런데 EC2가 아닌 EB(beanstalk의 줄임말)를 쓰게 된 이유는 처음엔 그냥 단순히 '좀 더 배포가 편하대서' 입니다.

 

EC2를 써보시면 알겠지만 인스턴스를 만들고 RDS로 DB 연결하고 또 여기 안에 들어가서 이거저거 설정해주려면 윈도우를 쓰는 사람은 putty도 깔아야하고 vim같은 에디터도 조금은 알아야합니다. 괜히 인프라 전문가가 따로 있는게 아니죠. 그래서 저는 다음에 토이 프로젝트를 한다면 좀 더 쉬운 배포를 해보고 싶다라고 생각했고 이번에 새로운 프로젝트를 하는김에 배포는 EB를 사용하자!란 맘을 먹었습니다.

 

그렇게 대충 프론트랑 백단 개발을 일단락짓고 배포를 하려고 한 최근 이틀간...

 

ㅎㅎㅎ

EB는 EC2보다 한단계 더 추상화된 모델이기에 로드밸런싱이나 오토 스케일링, 리소스 관리가 자동화됩니다. 그래서 모니터링도 되니 로그 보는 것도 더 쉽긴합니다. 하지만 주관적으로 이건 절대 개발 입문자들이 다음 단계를 밟는데 도움이 되지 않는다고 생각됩니다. 물론 인프라 관련 직군이라면 당연히 기본 지식들로 이런 것들을 알겠지만 그게 아니라면 사실 이런 지식들이 익숙치 않으니 이것들이 자동화되서 좋은 것보다 이런 지식들을 모르고 넘어가니 안 좋을게 확실하고 또 로그를 제공해줘서 이걸 본다고 평소 개발할 때처럼 쉽게 해결할 수 있지 않습니다

 

그래서 일단 주관적으로 느낀 생각을 먼저 말해보자면 자신이 배포를 한 번은 해보고 싶은데 맛보기로 해보거나 자신이 한 언어만 사용해서 개발하거나 CI/CD는 관심 없다하시는 분이라면 EB를 써보시는 걸 추천합니다만
자기가 백엔드 개발자로서 자기가 개발한 코드 정도는 계속 배포할 줄 알아야한다거나 CI/CD도 할 생각이 있다하시다면 AWS를 조금 더 공부해서 EC2를 사용해보시는 걸 추천합니다.
EC2를 쓰시다보면 IAM, VPC, 권한 정책, RDS 파라미터 같은 AWS 관련 정보를 공부하실텐데 용어만 생소하지 막상 사용해보면 개발하던거랑 다 연관이 있는거고 계속 AWS를 쓰실 예정이면 조금 익숙해져야 합니다. 또 서버 관리하려면 SSH같은 프로토콜이나 SSL 인증서, VIM 에디터 쓰실텐데 이것도 백엔드 개발자라면 알아둬서 나쁠거 없습니다. 그리고 무엇보다 EC2가 더 reference가 많습니다.(중요)

 

이제부터 아래에 쓸 내용은 대충 EB 알아보다 제가 불편했던 점이랑 그나마 사용할거면 이럴때 쓰자라고 생각한 겁니다. 정말 주관적이니까 그냥 유머글 보듯이 봐주시고 푸념 듣기 싫으시면 여기서 그만 보시길 추천합니다.

 

 

내가 생각한 EB의 불편한 점 및 추천하는 사용법

 

* 다시 한번 말씀드리지만 정말 주관적인 의견입니다.

 

AWS 공식 문서가 소개하는 EB는 

Elastic Beanstalk를 사용하면 애플리케이션을 실행하는 인프라에 대해 자세히 알지 못해도 AWS 클라우드에서 애플리케이션을 신속하게 배포하고 관리할 수 있습니다... (후략)

 

입니다. 그리고 정보 찾아보시면 처음 간단하게 개발한 소프트웨어를 배포하는 덴 이만한 게 없긴합니다. refer에 사용법을 알려주는 유튜브 영상 첨부하니까 궁금하시면 보시면 되구요.

 

하지만 조금 깊게 들어가면 그렇게 간단하진 않았습니다. 이제부터 하는말은 앞서 말했듯 진짜 주관적이고 주니어 레벨에서 경험하고 쓰기에 정보가 맞다고 보장하지 못합니다.

 

1. 선행적으로 Docker를 알아야 함(그것도 조금 자세히)

 

사실 이 부분은 공부하는 데 있어 오히려 좋은 분이 있을 순 있습니다. 그런데 간단히 사용하는 입장에선 그게 아닐 것 같아서 언급합니다. EB에서 어플리케이션을 만들면 지원하는 플랫폼, 그니까 쉽게 말해서 지원 언어가 몇 개 존재합니다.

EB 플랫폼 선택시

뭐 사실 많다면 많다고 할 수 있고 주로 쓰는 언어는 다 있긴 합니다. 하지만 문제는 언어 두 개 이상을 쓰는 프로젝트는 못씁니다. 이게 무슨 말이냐하면 제 프로젝트로 말씀드리면 앞단은 리액트 뒷단은 스프링 부트를 사용해서 개발했습니다. 그러면 제 프로젝트는 javaScript(Node.js)와 java 두 언어를 사용했겠죠? 근데 이럴 경우 EB에 파일 업로드하는 간단한 방법으로는 제가 찾아본 한 없습니다.

 

MSA(마이크로 서비스)라고 들어보셨을텐데 거창하게 거기까지 갈 필요 없이, 보통 어플리케이션이 조금 커지면 기능 단위로 모듈을 쪼개기 마련이고 작은 토이 프로젝트도 개발을 좀 하시다보면 거의 대부분 프론트엔드와 백엔드를 분리해서 진행합니다.

(뭐 Node.js로 서버를 구성하시면 모두 같은 언어로 개발이 가능은 하지만 이것도 검색 좀 하다보니 configure부터 포트까지 수동으로 만져줘야하는 것 같던데...) 

 

EB는 웹 서버를 NginX를 사용합니다. 그러니까 제 프로젝트 기준으로 간단히 표현하면 browser > (리액트) > NginX > (스프링부트) > (DB) 순으로 구성되겠죠? 뭐 DB야 어떻게든 자바 내장 DB인 h2같은 걸 스프링 부트에 욱여 넣거나 RDS를 따로 쓴다면 상관없지만 리액트는 아닙니다.

 

따라서 이 경우엔 거의 플랫폼으로 도커를 사용해야만 합니다.(예외는 후술)

 

도커는 한번씩은 들어보셨을텐데 컨테이너 기반 가상화 플랫폼입니다. 컴퓨터하다 윈도우에서 가상 머신 한번쯤은 돌려보셨을텐데 진짜 쉽게 말해서 가상 머신입니다. 그 가상 머신이 컨테이너 기반의 이미지를 사용하고 레이어란 개념을 적용해서 용량을 정말 획기적으로 줄인 것이라 생각하시면 쉬울 겁니다.

 

하여튼 EB에서 도커를 사용하기 위해선 도커의 push, build 정도는 기본으로 알아야 하고 aws.json 파일이나 dockerfile 작성하는 방법도 숙지해야하며 더 나아가서 docker-compose나 aws ECR도 활용되니 기본만 해도 공부할게 적진 않네요.

 

물론 도커를 알아두면 정말 편리합니다. 도커를 쓸 줄 알면 사용 환경에 도커만 깔아도 다른 언어의 버전이나 툴들을 용량들여가며 설치할 필요 하나 없이 빌드하고 테스트해볼 수 있거든요. EC2를 사용할때도 도커만 사용할 줄 알면 귀찮은 설정들 만지는 걸 엄청 줄일 수 있습니다.

 

그런데 입문자들이 가볍게 배포나 좀 해보려고 EB를 쓰는데 갑자기 도커부터 공부하는 건 좀 아닌 것 같습니다. 저야 원래부터 도커 기초는 알고 있었고 이거 만지다보니 좀 더 공부하게 된 감이 있는 거지만 그게 아니라면 ...

 

하여튼 결론은 내가 하나의 언어로 가볍게 코드를 짜봤는데 인프라 관련 지식을 더 알 필요 없이 간편하게 쓰고 싶다! 이런분들은 EB 적극 추천합니다만 그 이상이라면 솔직히 아니라고 봅니다. 가벼운 사용법은 refer의 유튜브 영상 하나 올려놨으니 보시면 됩니다. 도커를 플랫폼으로 사용하는 예시는 뒤에서 또 언급하겠습니다.

 

* 240113 추가
EB에서 두 가지 언어 이상을 동시에 사용해 배포할 수 있습니다. 그런데 일단 알아야할 지식이 좀 많습니다. 일단 AWS CLI를 사용할 줄 알아야하고 config를 위해 추가적인 지식도 필요합니다. 또 윈도우를 사용하는 저로선 추가적으로 해줘야할 작업도 너무 많고 이슈도 너무 많이 생기더라구요. 따라서 저처럼 배포를 입문하려는 사람은 EB를 사용하는 것은 그리 추천하지 못하겠습니다.

 

2. 조금 깊게 들어가려고 하면 알아야할게 너무 많은데 관련 자료가 적다.

 

우선 이걸 언급하기 전에 보여드릴 사진은 제 AWS IAM 사용자에게 준 권한 정책들입니다.

이 권한들을 제가 한번에 준 것들이 아니라 배포 과정에서 permission denied 뜰 때마다 하나씩 추가한겁니다. 프리티어 사용할때 IAM 사용자에게 허용되는 권한이 총 10개인데, 이틀 동안 그걸 다 채웠습니다. 개발할 때 root 권한 같은 정책이 있나 알아봤는데 그런게 있기는 있는데 AWS에서 권장하지 않는 정책이며 보안 털려서 수 천만원 내게 될 수도 있을 거 같아서 설정 안했더니 이렇게 불어났습니다. EC2를 사용할 때처럼 당연히 VPC와 S3도 알아야하구요.

 

또 EB를 사용할 때 조금 복잡한 명령은 cli를 통해 내려야하는데, 그래서 저는 aws cli와 eb cli 둘다 깔았습니다. aws cli는 사용하려면 credentials란 보안 자격 증명 키와 시크릿을 받아서 configure로 정해줘야하더라구요. 그래서 그것도 알아봤습니다. 또 EB를 수동으로 사용하려니 eb cli를 깔았는데 이건 python으로 만들어놔서 중간에 virtulalenv 에러 때문에 고생 좀 했습니다.

 

AWS에는 서비스들이 정말 어마무지하게 많습니다. 당연히 그런만큼 우리가 흔히 들은 외부 서비스들은 비슷한 모델이 다 존재합니다. EB cli를 사용하다보니 로그를 보면 호환성때문인지 설정문제인지 헷갈리게 에러가 나곤 합니다. 그래서 공부하게 된 것들도 있습니다.

 

도커를 사용하신다면 도커 허브를 아실건데 이 도커 허브란 곳은 쉽게 github 공용 레포라고 생각하시면 됩니다. 이쪽으로 이미지를 푸쉬하면 도커가 깔린 어디서든 그 이미지를 pull해서 사용할 수 있거든요. 그런데 AWS에도 이런 도커 허브같은 공용 레포가 ECR이라고 존재합니다, 이 ECR을 사용하는 방법은 도커 허브와 동일하게 태그 붙여서 push하고 pull하는 것

으로 동일한데 설정 명령이 또 존재해서 이것들도 알아봤습니다.

 

또 github를 당연히 다들 아실텐데 AWS에도 codeCommit이 존재합니다. 이것도 마찬가지로 평소에 git push해서 사용하는 것이랑 방법은 동일한데 역시나 설정을 해줘야 합니다.

 

이런 AWS 관련 정보들은 EC2와 S3를 제외하면 한글 reference가 거의 없습니다. 그래서 제가 이틀 동안 AWS 문서와 stack overflow만 수없이 들락날락한 것 같네요. 그런데 이런 AWS 관련 정보를 알아보는 것으로 이틀을 다 날린건 아닙니다.

 

로그 역시 꽤나 골치 아픈 놈이었는데, 개발할 때는 솔직히 에러나 예외가 나도 스택트레이스 확인하면 에러 명이랑 친절하게 예상 위치 다 알려주고 심지어 인텔리제이는 디버깅도 잘되있습니다. 그런데 EB에서 에러 발생하면 우리가 참고할 건 eb-engine.log 파일 밖에 없습니다.

 

eb-engine.log

뭐 로그 좀 보면 어떠냐 에러 다 알려줄텐데 라고 하실 수 있겠지만 도커를 사용해서 배포할 때 뜨는 에러를 읽어보면 죄다 '도커 배포 중 문제가 발생했습니다'라는 말에서 조금 가감이 있는 정도입니다. 개발할 때처럼 예외명이랑 위치를 절대 알려주지 않습니다.

 

이런 로그가 의미 있게 바뀌는 걸 보려고 리액트만 따로 빌드해서 배포해보고 스프링만 따로 빌드해서 배포해보고 포트도 계속 바꾸고 배포 방식도 hub, ECR, CodeCommit에서 각자 pull도 해보고 파일을 직접 압축해서 올려도 보고 했던 것 같습니다.

 

지금까지 꽤나 주절주절 제가 만난 장애들에 대해 말이 많았던 거 같은데 이렇게 쓸데 없는 말들을 쭉 쓴 이유는 절대 선행 지식 없이 맨 땅에 헤딩하는 식으로 EB를 사용하시는 걸 지양하시길 바래서 그렇습니다. 그래서 만약 EB를 좀 깊게 쓰셔야한다면 차근차근 강의를 보시면서 따라가시거나 시니어의 도움이 있을 때 하시길 바랍니다.

 

그래도 EB와 도커를 사용해야 한다면

 

사실 저는 처음에 별거 없을 줄 알고 docker-compose를 사용해 제가 개발한 코드들 전부 간단하게 배포할 수 있겠다싶어서 기왕 하는 김에 CI/CD도 자동화 해볼까? 이렇게 접근했었는데 이틀이 지난 지금은 그냥 다 포기하고 EC2를 쓰려고 합니다. 

 

왜 그러냐면 EB에서 도커를 사용할 때 EB가 자동화해주는 부분에서 에러가 발생하면 절대 얕은 지식으론 이걸 해결할 수도, 뭐가 문제인지도 알 수가 없습니다.(아마도)

 

제가 아는 EB에서 도커를 사용해서 배포할 때는 3가지 과정이 있습니다.

1. docker hub나 ECR에 push한 이미지를 pull해서 배포 => dockerrun.aws.json
2. 직접 dockerfile로 배포 => dockerfile
3. docker-compose.yml로 배포 => 설정 필요

사실 도커를 아시는 분이라면 이 세 과정 사이 교집합이 있다는 걸 아실겁니다. docker-compose를 쓸 때도 hub에서 pull해와서 배포가 가능하고 직접 dockerfile들을 compose에서 빌드해서 배포하는 등등 말이죠. 그런데 제가 이렇게 3가지 과정으로 나눈 이유는 EB가 인식하는 파일에 관련되어 있습니다.

 

EB에서 플랫폼으로 도커를 선택하면 일단 처음 두 가지 선택이 있습니다. 직접 파일을 업로드하는 것과 s3 url을 사용하는 것입니다. 일단 여기서 s3 url을 사용하려면 또 관련 AWS 설정들을 공부해야합니다. 그렇기에 직접 파일을 업로드하는 것으로 말씀드리겠습니다.

 

EB에 올릴 수 있는 파일은 형식에 제한이 없지만 조건이 필요합니다. 반드시 EB가 dockerfile이나 dockerrun.aws.json을 인식할 수 있어야합니다. 이 조건때문에 사실상 제가 docker-compose 사용을 포기하게 된건데, 저는 아무리 설정을 바꿔봐도 직접 파일을 업로드했을때 EB가 docker-compose.yml을 인식하지 않았습니다. 그래서 github actions나 jenkins를 사용해서 코드를 push해주도록 스크립트를 사용해서 배포해봤는데 이 역시 자꾸 에러가 발생했고 이걸 해결하려고 이것저것 해봤는데도 잘 되지 않았습니다.

* 사실 이 부분은 제 실력 미숙일 가능성이 엄청 커서 만약 글을 보시다 해결 방법을 아신다면 적극적으로 이 문단을 비판해주시면 감사하겠습니다....

 

그래서 결국 제가 다 시도해보다가 얻은 그나마 제일 괜찮은 방법은 

1. docker 허브에 필요한 image를 push합니다.
2. dockerrun.aws.json을 작성해서 pull할 image를 작성하고 열 포트를 명시해줍니다.
3..EB에 작성한 dockerrun.aws.json 파일 하나만 업로드합니다.

dockrrun.aws.json 파일은 별거 없고 아래처럼

{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "kth1017/testw1", // hub에 올려놓은 image
    "Update": "true"
  },
  "Ports": [
    {
      "ContainerPort": "8080"
    }
  ]
}

작성하면 끝입니다. 이렇게 작성하고 EB에 아래처럼 업로드하면 끝입니다.

 

 

이 방법이 그나마 제일 낫다고 생각한건 여러 이유가 있지만 그 중 큰 두 개는 

1. 적어놓은대로 docker hub에서 이미지를 pull 해오므로 다른 파일들을 zip으로 묶어서 업로드할 필요 없이 dockrrun.aws.json 파일 하나만 올리면 됩니다.
2. 올리는 파일 안에 dockerfile과 docker-compose.yml이 없으므로 어느 파일에서 에러가 발생했는지, 설정을 어떻게 바꿔야하는지 찾을 필요 없이 json만 수정해주면 됩니다. 

 

이렇게 있겠네요. 물론 도커 숙련자시라면 AWS가 제공해주는 로그를 보고 어디가 문제인지 유추하실 수 있겠지만 그게 아니라면 이 방법이 제일 나은 것 같습니다.

 


 참고한 refer를 적으려니 죄다 공식 문서 아니면 stack overflow에서 파편화된 정보여서 크게 의미가 없을 것 같아 앞서 얘기한 EB 입문용 영상 하나 정도만 올리겠습니다.

 

refer

 

https://www.youtube.com/watch?v=cOUhREAWJNw