ECR 구축
ECR Repository를 생성합니다.
프라이빗으로 선택하고, 리포지토리 이름을 작성합니다. 이후 스캔 및 설정은 비활성화로 통일한 뒤 리포지토리를 생성합니다.
리포지토리 생성 완료.
ECS Clusters 생성
ECS 새로운 환경을 off 합니다.
클러스터 생성을 눌러서 클러스터 생성을 진행합니다.
EC2 Linux + 네트워킹 템플릿을 선택하고 다음 단계로 넘어갑니다.
이름과 EC2 인스턴스 유형을 설정하고 나머지는 기본값으로 진행했습니다.
VPC를 선택하고 존재하는 모든 서브넷을 선택하였습니다.
퍼블릭 IP 자동 할당은 비활성화하고 보안 그룹을 설정하였습니다. (80, 8080, 3306 등을 열어둔 보안 그룹입니다.)
이후 IAM 역할 및 태그는 기본값으로 설정하고 생성버튼을 눌렀습니다.
생성 후 해당 클러스터의 ECS 인스턴스 탭으로 들어가면 ECS 인스턴스가 생성된 것을 확인할 수 있습니다.
IAM 생성
AWS 서비스 선택, 다른 AWS 서비스의 사용 사례에서 'Elastic Container Sevice'를 찾고 Elastic Container Service Task를 선택합니다. 그리고 다음버튼을 눌러 다음 화면으로 이동합니다.
권한 정책에서는 "AmazonECSTaskExecutionRolePolicy"를 추가하고 다음 버튼을 눌러 다음 화면으로 넘어갑니다.
역할 이름을 작성하고 역할 생성 버튼을 눌러 역할을 생성합니다.
AWS ECS 태스크 정의
EC2를 선택하고 다음 단계로 넘어갑니다.
태스크 정의 이름(임의의 이름)을 작성하고, 태스크 역할에서 위에서 만든 IAM 역할을 입력합니다.
네트워크 모드는 "브릿지"를 선택하고, 작업 실행 역할 역시 동일하게 위에서 등록한 IAM 역할을 선택합니다.
컨테이너 추가 버튼을 눌러서 컨테이너를 추가합니다.
컨테이너 이름을 작성하고 ECR에 등록한 레파지토리 이미지를 태그까지 입력합니다.
메모리 제한을 작성하고, 포트 매핑을 8080(스프링이니까)으로 열어둡시다.
하단의 스토리지 및 로깅 부분에서 로그 구성만 체크한 후 최종적으로 추가 버튼을 누르면 됩니다.
추가완료.
그리고 하단의 생성 버튼을 눌러서 Task 정의 생성을 완료하도록 하겠습니다.
AWS 서비스 생성
위에서 생성한 클러스터로 들어가서 서비스 탭에 있는 생성 버튼을 누릅니다.
시작 유형은 EC2, 서비스 이름과 작업 개수, 최소 및 최대 백분율을 작성하고 다른 부분들은 모두 기본 값으로 설정한 후 다음 단계로 넘어갑니다.
다음 페이지에서도 아무것도 설정하지 않고 바로 다음 단계로 넘어갑니다.
Auto Scaling 부분도 건들지 않고 다음 단계로 넘어갑니다.
이후 서비스를 생성합니다.
task-definition.json 생성
해당 클러스터로 들어갑니다.
서비스를 클릭합니다.
해당 서비스의 작업 정의를 클릭합니다.
해당 정의의 JSON을 선택하고 내용을 복사합니다.
task_definition.json 파일을 생성
IDE에서 task_definition.json 파일을 생성합니다.
그리고 해당 파일에 위에서 복사한 내용을 붙여 넣기 합니다.
Github Action Script
위와 같이 .github 디렉터리를 생성하고 해당 폴더 안에 workflows 디렉토리를 하나 더 추가합니다.
그 안에 yml 파일 하나를 생성합니다.(이름은 임의로 작성하시면 됩니다. gradle, deploy 등등 많이 사용하시더라구요)
name: Deploy to Amazon ECS
on:
push:
branches: [ "main" ]
env:
AWS_REGION: ap-northeast-2 # set this to your preferred AWS region, e.g. us-west-1
ECR_REPOSITORY: ECR 레포지토리 이름 # set this to your Amazon ECR repository name
ECS_SERVICE: ECS 클러스트에 생성한 서비스 이름 # set this to your Amazon ECS service name
ECS_CLUSTER: ECS 클러스트 이름 # set this to your Amazon ECS cluster name
ECS_TASK_DEFINITION: task_definition.json 파일 위치 # set this to the path to your Amazon ECS task definition
# file, e.g. .aws/task-definition.json
CONTAINER_NAME: 컨테이너 이름 # set this to the name of the container in the
# containerDefinitions section of your task definition
permissions:
contents: read
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: latest
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.ECS_TASK_DEFINITION }}
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.build-image.outputs.image }}
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
IAM 사용자 추가
해당 Github Action Script 중 ECR, ECS에 접근하기 위한 권한이 필요합니다.
위의 스크립트를 확인하면 "Configure AWS credentials" 이 부분이 있는데, 이 과정에서 AWS에 권한을 받아온다고 생각하시면 됩니다.
사용자 이름을 작성하고 다음으로 넘어갑니다.
권한 설정에서 직접 정책 연결을 선택하고 다음 정책들을 추가합니다.
"AdministratorAccess"
"AmazonEC2ContainerRegistryFullAccess"
"IAMUserChangePassword"
세 가지 정책을 선택하고 다음으로 넘어갑니다.
이후 사용자 생성 버튼을 눌러서 사용자를 생성합니다.
해당 사용자의 Key를 받아야 하므로 사용자로 들어가서 보안 자격 증명 탭으로 이동합니다.
해당 탭 하단에 액세스키 만들기 버튼을 클릭합니다.
AWS 컴퓨팅 서비스에서 실행되는 애플리케이션을 선택하고 다음 버튼을 누릅니다.
태그를 입력하고(선택사항) 액세스 키 만들기를 눌러서 키를 생성합니다.
키 생성이 완료되었습니다. 저는 csv 파일을 다운로드하여 별도로 저장하도록 하겠습니다.
해당 키는 다시 확인하기 어려우니 꼭 보관 및 저장해 주세요.
Github Action에 해당 Key 등록
배포하려는 해당 레파지토리의 Settings -> Secrets and variables -> Actions 메뉴로 들어갑니다.
해당 New Repository Secret 버튼을 눌러서 위에서 발급받은 Access Key와 Secret Key를 입력합니다.
여기의 Name 값은 위에 작성했던 스크립트
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }}
변수와 동일하게 들어가니 꼭 신경 써야 합니다.
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY_ID 두 Name으로 두 개의 환경변수를 입력합니다.
완료!
이후 배포를 진행합니다.
로드밸런스 등록
타겟 그룹 생성
EC2 로드밸런싱 메뉴에 있는 대상 그룹 탭으로 이동하여 대상그룹 생성을 진행합니다.
인스턴스를 선택하고, 대상 그룹 이름을 작성합니다.
상태 검사 경로, 정상, 비정상 임계 값, 제한 시간, 간격 등을 입력하고 다음버튼을 눌러 다음 화면으로 넘어갑니다.
해당 인스턴스를 선택하고, 아래에 보류 중인 것으로 포함을 선택합니다.
아래 대상 보이게 추가됩니다. 이후 대상 그룹 생성 버튼을 눌러 다음 페이지로 이동합니다.
로드밸런스 생성
로드밸런서 생성을 누릅니다.
Application Load Balancer 부분의 생성 버튼을 누릅니다
로드 밸런서 이름을 작성하고 나머지는 기본 값을 선택합니다.
기본 VPC를 선택하고, 두 가지를 선택했습니다.
보안 그룹은 default로 기본 값을 그대로 유지했습니다.
위에서 생성했던 대상 그룹을 연동시켜 주고 하단의 로드 밸런서 생성 버튼을 눌러줍시다.
해당 로드밸런서의 보안 그룹에 들어가서 80 포트를 뚫어주도록 하겠습니다.
해당 보안 그룹의 인바운드 규칙 편집을 눌러줍니다.
HTTP를 선택하고, Anywhere IPv4를 선택한 다음 저장합니다.
이후 로드밸런서에 있는 DNS이름을 주소창에 입력하게 되면
502 Bad Gateway로 연결되게 됩니다.
여기까지 하면 성공입니다!
포트번호 변경
해당 ECS의 Service에 접속하여 작업 정의를 클릭해서 들어갑니다.
새 개정을 생성합니다.
컨테이너 이름을 클릭합니다.
호스트 포트를 80으로 변경하고 업데이트합니다.
서비스 재생성
위에 작성한 서비스 생성 방법대로 유지하면서 로드밸런싱 부분만 더하여 추가합니다.
로드밸런서에 추가 버튼을 눌러서
프로덕션 리스너 포트를 연결하고 서비스를 만듭니다.
이후 배포가 완료되면 해당 로드 밸런스의 DNS 주소를 입력하면 됩니다.
에러
1. 504 에러가 발생한다면 로드밸런스 대상그룹 속성 부분의 Target selection configuration을 기본값으로 켜주면 됩니다.
[AWS] 504 Gateway Time-out 에러에 대해
AWS에 구성해놓은 서버에서 REST API를 이용한 요청을 했을 때 Backend에서는 정상적으로 수행을 하고 있는데 웹에는 "504 Gateway Time-out" 이 발생했다. 비슷한 경험으로 ELB 설정을 가장 먼저 의심했고, (
lifeinno.tistory.com
2. 503 Service Temporarily Unavailable 에러가 발생한다면 EC2와 로드밸런서의 보안 그룹의 TCP를 모두 열어줘서 체크합니다.
타겟 그룹의 대상에 있는 포트도 확인해야 합니다.
후기
Docker를 사용하기 위해 ECS, ECR을 도전했고, 약 10일이 넘는 시간 동안 실패를 맛보게 되었다.
76개의 커밋 중 약 66개의 커밋은 ci/cd를 테스트하기 위한 커밋이다...
임시 저장 글 또한 해당 글과 같은 분량을 가지고 있고, 위의 방법이 실패하여 다른 방법으로 글을 작성하고 또 실패해서 비공개된 글도 존재한다(해당 글도 분량이 비슷..) 정말 힘들었는데..
정말 성공으로 끝을 맺고 싶었고, 성공으로 끝맺을 수 있어서 너무 행복하다!!!!!
참조
'Server > Infra' 카테고리의 다른 글
[원티드 프리온보딩] AWS - 0 (0) | 2023.05.09 |
---|---|
[CI/CD] task_definition.json, deploy.yml ECS Docker 환경 변수 설정 (0) | 2023.03.14 |
[AWS] ECR 이미지 푸시 명령 (0) | 2023.03.09 |
[AWS] AWS CLI 및 Docker 설치 (0) | 2023.03.09 |
[AWS] AWS Tools, AWSPowerShell 설치 (0) | 2023.03.09 |