오늘 배운 것

오늘은 ECS에서 EC2 서버를 실행시키는 작업을 하다가, 문득 EC2에서 사용하는 데이터베이스가 로컬 mysql DB라는 사실을 깨달았다. 그런데 EC2 인스턴스에선 기본적으로 mysql db가 설치되어있지 않기 때문에, 이렇게 코드를 올리면 로컬에서만 실행되고 원격 인스턴스에서는 실행되지 않을 게 분명했다. 결론은 현재 로컬에서 사용하는 mysql 서버를 RDS로 바꿔야 한다는 것이었다. 

 

이를 위해 AWS 콘솔을 확인해 보니 저번 주에 멘토링하면서 만들어 둔 RDS가 있었다. 그런데 유저 이름과 패스워드가 기억나지 않아서, 새로 RDS 인스턴스를 생성하기로 했다. 

 

그런데 또 생각해보니 RDS를 처음에는 로컬에서 접근 가능하게 해야 하지만, 또 이걸 깃허브 브랜치에 올린 다음 ECR에다가 도커 이미지를 올리는데 그러면 해당 EC2 서버에서만 RDS에 접근 가능하게 해야 하는 게 아닌가? 그러면 RDS의 초기 접근 설정은 Anywhere IPv4로 한 다음에 나중에 특정 VPC에서만 접근 가능하게 하도록 바꿔 줘야 하는 것인가라는 생각이 들었고, 잘 모르지만 일단 초기에 로컬에서 접속은 되어야 하니 처음에는 퍼블릭 엔드포인트를 열어서 어디서든 접속할 수 있게 설정해서 진행해 보기로 했다. 

-> RDS 인스턴스를 생성할 때 자세히 보니, 이 설정은 나중에 RDS 인스턴스에서 변경 가능하다고 했다! 그렇다면 우리는 EC2 인스턴스를 생성한 다음, RDS와 EC2를 같은 VPC에 위치시키고, 이 상태에서 ECS를 통해 EC2에서 이미지를 컨테이너로 만들어서 실행시키면 되지 않을까 싶다. 

 

우선은 새로운 RDS 인스턴스를 생성해서 로컬에서 mysql을 통해 접속한 후, 웹 어플리케이션 서버에서 사용하는 database를 생성해 주었다. 그리고 기존의 settings.py의 DATABASES 변수 관련 설정(HOST, NAME 등)을 RDS에서 설정한 대로 잠시 하드코딩해서 바꾸어주니, 무사히 잘 실행되었다. 

 

그리고 기존의 settings.py에서는 .env 파일을 사용하는 대신 AWS의 secrets manager를 사용해서 환경 변수를 관리하고 있었다. 왜냐하면 기존의 로컬 환경변수 파일은 여러 명의 팀원이 같은 .env 파일을 공유해야 하는 불편함이 있었기 때문이다. 여기서 DB의 유저 이름이나 엔드포인트 등을 불러왔었기 때문에, 이 값들도 AWS secrets manager에서 하나하나씩 바꿔주었다. 

대충 이런 값들이 있었다

 

그리고 어제 막바지에 AWS ECS에서 클러스터 생성하고, 태스크(작업) 정의 생성하고, 그걸 토대로 ECS 서비스(태스크와 서비스 2가지 종류가 있었는데, 태스크는 배치 등 1회성 작업에 적합하고 서비스는 웹 어플리케이션 등 계속해서 유지 및 실행되어야 하는 작업에 적합하다고 설명이 나와있어서 서비스를 선택했다)를 생성했다. 역시나 처음엔 어제처럼 생성 가능한 EC2 인스턴스가 없다는 오류가 떴다. 

 

그래서 또 찾아보니 ECS 클러스터 안에서 서비스를 생성하는 화면에서, 맨 처음에 오른쪽 메뉴(시작 유형)이 아니라 왼쪽 메뉴(용량 공급자 전략)을 선택해서, 사전에 미리 만들어둔 용량 공급자를 여기서 선택할 수도 있는 것 같았다. 

 

결과적으로 이 방법으로 ECS를 통해 EC2 인스턴스를 생성하고 실행시키는 데까지는 성공했다(물론 태스크가 성공하지는 못했지만 이만큼이라도 된게 다행이다). 

 

1. ECS에서 EC2 인스턴스를 생성 및 제어해야 하므로, 이는 하나의 서비스가 다른 서비스에 접근하거나 영향을 주어야 하는 상황이기 때문에 IAM 역할이 필요하다는 것 같다. 그래서 IAM 서비스로 가서 'AmazonEC2ContainerServiceforEC2Role' 이라는 역할을 생성해 주었다. 이름을 보니 ECS에서 EC2 서비스에 접근하기 위해 필요한 역할 같았다. 

 

2. 정확히 왜 그런지는 모르겠는데 EC2 스팟 인스턴스를 제대로 사용하려면 auto scaling 그룹이 필요하다고 한다. 그리고 auto scaling 그룹을 생성하려면 시작 템플릿(launch template)이 필요하단다. 그래서 EC2 메뉴로 가서 시작 템플릿을 생성해 주고, 그걸 토대로 auto scaling 그룹도 생성해 주었다. 1번에서 생성한 IAM 역할은 여기서 필요하다. 

 

3. 이제 이 autoscaling 그룹을 ECS와 연결해야 한단다. ECS에서 이미 생성한 클러스터를 누르고, 용량 공급자(capacity provider) 탭으로 이동하자. 그러면 기본으로 있던 용량 공급자 외에 새로운 용량 공급자를 선택할 수 있다. 여기서 '생성'을 누르고, autoscaling 그룹을 선택하는 영역에서 2번에서 생성한 그룹을 선택해 준다. 

이 과정을 완료하면 ECS 클러스터에서 EC2 스팟 인스턴스를 생성할 수 있는 준비가 되었다. 

 

이제 다시 위의 화면(ECS 클러스터 안에서 서비스 생성하는 화면)으로 가서, 왼쪽 메뉴(용량 공급자 전략)를 누르고 여기서 생성한 용량 공급자를 할당해 주자. 그리고 앞서 정의한 태스크 정의를 선택해 주고... 기타 등등을 하면 서비스가 생성되고, EC2에 들어가서 확인해 보면 ECS 클러스터에 의해서 못 보던 EC2 스팟 인스턴스가 생성되어 있는 걸 볼 수 있다. 뿌듯.

 

그리고 서비스 안에 하나의 태스크가 할당되었길래(이건 태스크 정의를 통해 정의된 태스크로 보인다), 이제 이게 실행만 잘 되면 되겠거니 싶었다. 그런데 태스크가 한참을 프로비저닝 상태로 있더니 실패했다. Cloudwatch를 통해 로그를 찾아보고 싶었지만 나오는 게 없어서 원인을 알 수 없는 상태이다... 

 

지금 생각하고 있는 원인으로는

1. ECS에서 EC2 인스턴스를 생성하기만 했지, 사실 클러스터에 제대로 할당된 EC2 인스턴스가 없었던 게 아닐까

2. 코드에서 루트 디렉토리에 도커파일을 별도로 두어 실행하는 커맨드를 두었어야 하는데 그게 안 되었던 게 아닐까

 

그 외에 다른 원인이 있을지는 잘 모르겠어서, 우선 도커파일을 다시 추가하고 main 브랜치를 다시 github action을 통해 도커 이미지로 만들어서 ECR에 올려봐야겠다. 그래도 안 되면 1번에 가능성을 두고 더 찾아봐야겠다. 


다시 찾아보았는데 생각한 원인 중 1번이 맞았다. 우선 2번의 경우 .Dockerfile이 루트 디렉토리에 없나? 싶었는데 멀쩡히 잘 있어서 머쓱해졌다... 대신 1번이 맞는지를 확인하고 싶어서 GPT에게 확인하는 명령어를 알려달라고 해 보았다. 

aws ecs list-container-instances --cluster onestep-production2

그랬더니 이런 명령어를 알려주었다. 이거는 ECS의 해당 클러스터(onestep-production2)에서 현재 연결된 EC2 인스턴스가 있는지를 알려주는 명령어이다. 

그렇다. 나름 기대를 갖고 실행해 보았는데 ECS 클러스터에 연결된 EC2 인스턴스가 하나도 없었던 것이다. 이러면 결국 문제는 다시 이전으로, ECS 클러스터에서 EC2 스팟 인스턴스를 연결하는 부분으로 돌아간다. 

 

또한 짚이는 문제 부분이 하나 더 생겼다! 

어제 작업했던 부분인데 ECS 서비스나 태스크를 추가할 때였나, 아니면 태스크 정의를 할 때였나 암튼 환경변수를 추가하는 부분이 있었어서 그때 보면서 이게 왜 필요한지 의아했었다. 그런데 사실 깃허브 브랜치에 코드를 올릴 때 .env 로컬 환경변수 파일을 올리지는 않지만 분명 코드 상 해당 파일을 참조해야 하는 부분이 있기 마련이다. 그 환경변수 값을 셋팅해주는 것이 이 과정이었던 것으로 예상한다. 

 

그리고 생각해보니 멘토님은 브랜치에 있는 코드를 도커 이미지로 빌드해서 ECR에 올리는 거나, ECR에 있는 이미지를 ECS에서 실행시키는 두 작업 모두 아마 깃허브 액션으로 가능할 거라고 하셨다. 그래서 아 이렇게 복잡하게 돌아가지 말고 최소로 필요한 세팅만 AWS 콘솔에서 한 다음에 나머지는 깃허브 액션에서 yaml 파일로 하는 것이 맞겠구나, 라는 생각이 들어서 노선을 또 바꿔 보았다. 


우선은 yaml 파일을 작성하기 전에 필요한 사전 작업이 있다. AWS 콘솔에서 다음과 같은 작업들을 먼저 하고, 이후에 깃허브 액션으로 ECR 이미지 빌드 + ECS 컨테이너 생성 및 실행까지 하면 되겠다. 

 

+)

GPT와 얘기하면서 삽질을 여러 번 했는데... 어쩌다 보니 다시 ECS 클러스터에 연결된 EC2 인스턴스를 확인해 보니 1개가 되어 있었다..!! 이유는 모르겠다...

 

어쨌든 ECS 클러스터에서 EC2 스팟 인스턴스를 연결하는 부분이 해결되었다! 이제 다음 단계로 가 보자. 

오늘은 GPT가 만들어준 ECR에 이미지를 빌드해서 업로드 해 주고, ECS에서 컨테이너를 생성한 뒤 EC2 인스턴스에서 실행시켜주는 yaml 파일만 테스트해보고 자야겠다. 

'개발 일기장 > SWM Onestep' 카테고리의 다른 글

20240729 TIL: ECR ECS CI/CD 적용기 with fargate & github action  (1) 2024.07.29
20240728 TIL  (2) 2024.07.28
20240726 TIL  (0) 2024.07.26
20240725 TIL  (0) 2024.07.25
20240724 TIL  (0) 2024.07.24

+ Recent posts