안녕하세요! 회사와 함께 성장하고 싶은 KOSE입니다.
이번 포스팅은 깃 액션을 활용한 배포에 대한 내용을 정리하고자 합니다.
개발에서 CI/CD (Continuous Integration/Continuous Delivery) 중요한 부분입니다.
지속적으로 통합하고, 지속적인 배포로 사용자에게 하여금 지속적인 서비스를 제공하는 것이 중요합니다.
이를 위해 적용할 수 있는 깃 액션과 코드 디플로이를 활용한 배포를 설명하겠습니다.
1. 목표 플로우
코드를 배포해야 할 때, 배포를 위한 브랜치로 변경하면 깃 액션이 동작하여 S3에 jar를 비롯한 배포 관련 yml, sh 압축하여 전송합니다.
이어서, Code Deploy를 호출하여 Code Deploy가 S3에 필요한 배포 정보를 바탕으로 EC2에 데이터를 복사합니다.
EC2에서는 앞 서 정의한 배포 관련 yml, sh를 통해 System Manager로부터 필요한 환경 변수를 로드합니다.
이어서, 엔진엑스가 스프링의 포트를 리버스 프록시 하여 배포가 완성되게 됩니다.
엔진엑스를 적용하는 과정을 ALB를 도입하여 안정적이고 관리가 용이하게 바꿀 수 있습니다.
(하지만 비용 문제로 인해 NGINX를 적용하였습니다!)
2. 깃 액션 정의하기
저는 main branch에 PR을 요청할 때는 테스트를 실행하는 깃 액션을 정의하였습니다. 배포는 deploy라는 브랜치를 생성하여
배포가 될 수 있도록 정의하였습니다.
작성하는 워크 플로우는 위에 사진에 자세하게 작성한 파트로 나눌 수 있습니다.
어떠한 브랜치에 적용할 것인지, 어떠한 환경에서 실행할 것인지, 어떻게 단계를 정의할 것인지로 크게 구분할 수 있습니다.
main에 머지된 코드로 deploy 브랜치를 생성하면 하단처럼 깃액션이 활성화됩니다.
다음은 S3에 파일을 올리기 위해 최상위 루트 디렉터리로 tar를 만드는 과정입니다.
jar 혹은 배포를 위한 yml, sh 등을 개별적으로 S3에 올릴 수 있지만 Code Deploy를 활용하려면 tar 혹은 압축 파일로 만들어야 합니다.
위의 코드처럼, 각 build/libs에 있는 파일과 배포를 위해 정의한 sh, yml에서 파일을 복사한 후 압축하여 tar로 만들어 줍니다.
이제, S3에 파일을 올리는 과정을 정의하면 다음과 같습니다.
S3에 올리기 위해서는 S3 버킷의 Region 및 URL을 입력합니다.
이어서, 접근하기 위한 액세스 키와 시크릿 키를 입력해야 합니다.
여기에 필요한 정보를 yml 등에 정의하게 된다면 큰 보안 위협을 받을 수 있습니다.
깃 액션에서는 필요한 환경 정보를 시크릿으로 유지할 수 있도록 정의할 수 있는 공간이 있습니다.
리포지토리의 settings - 좌측 메뉴의 Secrets and variables의 Actions를 클릭하면 New repository secret을 생성할 수 있습니다.
이곳에 S3에 접근 권한을 IAM 권한을 받은 사용자의 액세스키와 시크릿키를 입력하면 됩니다.
(IAM 관련 설명은 좋은 강의가 있어서 링크드립니다! https://www.youtube.com/watch?v=lcly_aIq1KI)
마지막으로 Code Deploy를 실행하기 위해 Code Deploy에 정의한 배포 그룹 및 애플리케이션 이름, 복사할 버킷 이름 등을 작성합니다.
Code Deploy를 설정하는 과정은 다소 복잡하여 다른 포스팅에서 작성하도록 하겠습니다!
이렇게 git Action의 활동에서 처리할 각 역할을 설정해주었습니다.
이제, Code Deploy가 실행될 때, 해야 할 역할을 정의하도록 하겠습니다.
2. Code Deploy appspec.yml 정의
Code Deploy는 정의한 appspec의 내용에 따라, 배포 시나리오를 설정할 수 있습니다.
먼저 Code Deploy는 EC2에 대한 접근 권한, S3에 대한 접근 권한이 있어야 합니다
작성하는 appspec.yml은 다음처럼 복사하고자 하는 위치, 접근 권한, 스크립트 단계별 실행 등으로
구성할 수 있습니다.
이렇게 작성한 appspec.yml은
code deploy가 실행될 때 앞 서 만든 tar를 압축 해제하고 최상위 루트에 작성된 appspec.yml에 따라 해당 시나리오가
동작하는 방식으로 처리가 됩니다.
3. Hooks에 적용할 스크립트
appspec.yml에 작성한 스크립트는 EC2에 적용되어 실행이 됩니다.
먼저 스프링 서버를 실행하기 위한 java 설치 등은 before_install.sh 에 정의할 수 있습니다.
자바가 설치되면, application_start.sh를 수행하여 스프링 서버를 배포할 수 있습니다.
EC2에 스프링을 배포할 때 필요한 환경 변수들이 있을 수 있습니다. 이 정보는 AWS에서 제공하는 System Manager의 파라미터 스토어에 정보를 입력할 수 있습니다. 필요한 정보를 파라미터 스토어에 입력한 후 EC2가 System Manager에 대한 권한을 가지도록 역할을 설정해주면, 이를 안전하게 활용할 수 있습니다.
다음은, 헬스체크를 통해 현재 실행 중인 포트를 확인하여, 다른 포트로 배포하기 위한 과정입니다.
서버에 정의한 헬스체크 url로 먼저 8080 포트로 요청을 보내서, 만약 해당 포트가 정상 응답이 온다면
배포해야 하는 포트는 8081이 됩니다(사용하지 않는 포트)
반면 헬스체크가 안된다면 8080 포트를 사용하지 않는 것이므로 8080 포트로 jar를 실행해야 합니다.
이어서, 정상 일정 시간 기다린 후 jar를 실행한 포트로 헬스체크를 보냅니다. 만약 성공한다면 이전에 배포한 서버를 graceful로 안정적으로 종료하고, 사용한 PID를 KILL 합니다.(graceful은 스프링의 application.yml에 정의되어야 합니다!)
마지막으로, 80 포트로 오는 유저의 요청을 현재 실행 중인 스프링 서버로 연결될 수 있도록,
엔진엑스의 리버스 프록시를 바꿔줍니다.
이렇게 함으로써, 깃 액션과 코드 디플로이를 바탕으로 한 배포 과정을 설정할 수 있습니다!
엔진엑스 리버스 프록시를 연결하는 과정은 향로님이 작성하신 엔진엑를 활용한 무중단 배포 구축하기에 상세하게 작성되어 있어서 링크를 남기겠습니다 (https://jojoldu.tistory.com/267)
이상으로 깃 액션과 코드 디플로이로 배포하는 과정 정리를 마치겠습니다.
읽어주셔서 감사합니다!
'DevOps' 카테고리의 다른 글
[DevOps] Docker Container (1) | 2023.11.04 |
---|---|
[DevOps] Jenkins - Docker - AWS 자동 배포 1편 (0) | 2023.03.06 |