Deploy) 작업의 컨베이어벨트 GitHub Action - ECS

백준우·2023년 4월 7일
0

Deploy

목록 보기
4/4
post-thumbnail
post-custom-banner

0. 목표

1. GitHub Action 설정

1.1 GitHub Action Security값 설정
1.2 GitHub Action yml파일 작성
1.3 DockerFile 작성

2. AWS ECS

2.1 ECS 만들기
2.2 클러스터 설정
2.3 테스크 정의
2.4 CI/CD 테스트하기


0. 목표

  • 회사내에서 코드를 push하면 CI/CD가 이루어져 자동으로 서버가 Build되는경험을 해본적이 잇다.
  • 이러한 구축을 GitAction을 통해서 ECS로 배포하여 해보려고 한다.
  1. DockerFile이 추가되어있는 springboot가 들어간 git Repository를 만들고
  2. 코드를 업데이트 했을때 github Action -> Docker 이미지 빌드 -> ECR -> ECS배포를 원클릭으로 진행하려고 한다.
  3. ECR에 이미지는 push해놓은 상태이다.

    EC2없이 Fargete(서버리스)를 사용해서 배포를 진행하겠다.

1. GitHub Action 설정

1.1 GitHub Action Security값 설정

  1. 먼저 이전 AWS IAM으로 설정한 Key값들을 써야한다.
    https://velog.io/@baek1008/%E3%85%81
  2. 그리고 이곳에다가 key값을 설정해준다.

    우측 초록색 New repository secret으로 새로운 key값을 넣어준다.
    현재 AWS_ACCESS_KEY_ID와 AWS_SECRET_ACCESS_KEY로 넣어놨다.

1.2 GitHub Action yml파일 작성

  • 다음으로 GitHub Action에 들어갈 Action을 위한 yml파일을 만들어야한다.
    다행히도 GitHub Action에서 지원해주는 예시파일이 있다.
  1. 새로운 GitAction을 추가하고 다음과 같이 ECS를 검색하면 다음과 같은 파일이 존재한다.
  2. Configure을 누르면 다음과 같이 aws.yml이라는 파일이 추가되는것이 확인 가능하다.
    일단 이정도하고 ECS에서 cluster까지 설정하고 재작성해보자

1.3 DockerFile 작성

  • DockerFile통해 SpringBoot환경을 Image로 만들어주는부분이 필요하다.
    다음은 SpringBoot를 빌드하고 jar파일로 Server를 실행하는 멀티스테이지 빌드파일이다.
FROM gradle:7.6-jdk17-alpine as build
ENV APP_HOME=/apps/
WORKDIR $APP_HOME
COPY build.gradle settings.gradle gradlew $APP_HOME
COPY gradle $APP_HOME/gradle
RUN chmod +x gradlew
RUN ./gradlew build || return 0
COPY src $APP_HOME/src
RUN ./gradlew clean build

FROM openjdk:17.0.2-jdk
ENV APP_HOME=/apps
ARG ARTIFACT_NAME=app.jar

ARG JAR_FILE_PATH=build/libs/[applicationFile]-0.0.1-SNAPSHOT.jar
WORKDIR $APP_HOME
COPY --from=build $APP_HOME/$JAR_FILE_PATH $ARTIFACT_NAME

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

이제 로컬에서 설정해야할 부분은 aws.yml작성말고 다 끝났다. 이제 ECS로 가서 Cluter를 설정해보자

2. AWS ECS

  • ECS는 EC2와 다른개념이다. EC2는 서버를 열어서 우리가 설정을하고 설치할 수 있는것이라면 ECS는 Container기반으로 설정이 되는것이므로 image를 통해 서버를 여는것이다. 안에 태스크를 통해 container를 관리 할수 있으며 Kubernetes같은 오케스트레이션도구로 생각하면 되겠다
    업로드중..

2.1 클러스터 설정

  1. ECS로 가서 클러스터를 생성한다.
  2. Cluster 이름을 설정해준다.
    그리고 서브넷에 2a,2b,2c,2d까지 추가해준다(원래 기본으로 잡혀있을것이다.)

2.3 태스크 정의

  • 태스크를 정의해줘야한다. 태스크는 ECS cluster안에서 돌아가는 하나의 단위로 생각하면 되겠다.


1. 테스트 정의 구성 후 작성한다.

  • 먼저 ECR에 푸쉬해놓은 이미지 URI를 가져온다
  • 서버는 springboot로 실행하므로 8080를 열어준다.
  1. 환경 스토리지를 작성해준다.
  • 이외의 사항은 기본값으로 설정하면 되겠다.

2.4 Cluster에 서비스 정의

  • 이제 클러스터에 Service를 통해서 테스크를 붙여줄 차례이다.
  1. 아까 생성했던 Cluster에 Service를 만든다.
  2. 환경은 기존대로 설정하고 우리는 Fargate를 쓸예정이므로 아래와 같이 설장한다.
  3. 패밀리는 방금 만든 테스크를 추가 할 수 있도록 한다. 그리고 서비스 이름은 본인 이 편한대로 설정하면 되겠다.
  4. 로드밸런싱도 설정한다.
  • Application Load Balacner를 선택하여 새로 생성하기를 한다.
  • 상태확인 경로는 /health를 해준다.(이후 서버에서 설정을 해준다)
  • 대상그룹 이름도 sample-group으로 해준다.

!! 혹시 에러가 날경우

상단에 이렇게 현재 진행상태가 보일것이다. 우측에 [CloudFormation으로 보기]를 눌러서 우측에 이벤트 탭을 보면 log확인이 가능하다.

  1. yml파일 설정
  • 이제 마지막으로 GitHub Action에 있는 aws.yml파일을 수정하겠다.
...생략... 
# env파일에 본인이 설정을하면 되겠다.
env:
  AWS_REGION: #본인이 만든 Region명          
  ECR_REPOSITORY: # ECR 레포지토리 명    
  ECR_IMAGE_TAG: # ECR에 Image 생성시 붙일 태그
  AWS_ACCESS_KEY: # GitHub Security에 넣은 AWS Access Key
  AWS_SECRET_KEY: # GitHub Security에 넣은 AWS Secrity Key         ECS_CLUSTER: # 생성한 클러스터 명                        
  ECS_SERVICE: # 클러스터의 서비스명
  CONTAINER_NAME: # 태스크설정시 넣은 컨테이너 명
                                             

... 생략... 
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ env.AWS_ACCESS_KEY}}
        aws-secret-access-key: ${{ env.AWS_SECRET_KEY }}
        aws-region: ${{ env.AWS_REGION }}
... 생략... 
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ env.ECR_IMAGE_TAG }}
      run: | 
      	#ECR에 넣을 Docker Image를 생성하는 과정
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./TestDockerGit/.
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
...생략...
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        # task-definition을 확인가능하다.
        task-definition: task-definition.json
        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: task-definition.json
        service: ${{ env.ECS_SERVICE }}
        cluster: ${{ env.ECS_CLUSTER }}
        wait-for-service-stability: true
  • 위와 같이 yml파일을 설정한다.

    위 yml에 task-deficition이 보일것이다. 설정하는법은 아래와 같다.
    생성한 task로 가서 컨테이너 우측에 json으로 클립보드로 복사한다.
    복사한 데이터를 gitRepository 최 상위폴더에 task-definition.json파일을 생성후 붙여넣는다.

2.5 CI/CD 테스트하기

  • 먼저 생성한 로드밸런서로 서버상태를 확인을 해본다.
  • EC2 > 좌측택 Load balance > 생성한 Load Balance 클릭 > DNS name 복사 > URL 입력

    위 와 같이 서버가 정상적으로 열리는것을 확인 할 수 있다.
  • 다음으로 Spring Boot 코드를 살펴보겠다.
@RestController
public class Testcontroller {
    @GetMapping("/test")
    public ResponseEntity TestAPI(){
        return new ResponseEntity("테스트 데이터" , HttpStatus.OK );
    }

    @GetMapping("/health")
    public ResponseEntity HealthAPI(){
        return new ResponseEntity("up" , HttpStatus.OK );
    }
}
  • /test 앤드포인트로 가면 "테스트 데이터"라는 값을 반환한다.

!!주의) /health 아까 로드밸런서에서 상태확인경로인데 이 값이 정상적으로 반환되지 않으면 load balance에서는 서버가 정상적으로 실행이 안된것으로 간주해 이 컨테이너를를 죽였다 살렸다를 반복한다.

  • API 요청해보기 (/test)
    정상적으로 "테스트 데이터"라는 값이 반환된다.

  • 데이터값 변환

@RestController
public class Testcontroller {
    @GetMapping("/test")
    public ResponseEntity TestAPI(){
        return new ResponseEntity("CI/CD TEST" , HttpStatus.OK );
    }

    @GetMapping("/health")
    public ResponseEntity HealthAPI(){
        return new ResponseEntity("up" , HttpStatus.OK );
    }
}

이렇게하면 같은 엔드포인트라도 "CI/CD TEST"를 갑을 반환하게 한다.
이렇게 수정한뒤 별도의 작업없이 git에 push 해보도록 하겠다.

git add .
git commit -m'/test 반환값 변환'
git push


이렇게 하면 정상적으로 workflows가 돌아가는것이 보인다.
git action이 돌아가는 중이다.
새로운 값이 잘 반환되었다. 서버에서 변경값이 잘 적용된것이다.

결론

  • 진짜 간편하다.
  • Front-end는 S3를 활용하거나 AWS Amplify를 활용해봐도 될거같다.
  • Fargate가 돈이들경우 AWS에서 지언하는 Fargete Spot을 활용해서 비용을 절감해도 될거같다.

참고

profile
이게 되네?
post-custom-banner

0개의 댓글