Github + Jenkins + AWS EC2를 활용해 CI/CD를 구축해보자 ❕
1. AWS EC2 (Elastic Compute Cloud)
1-1. EC2란
EC2는 클라우드 컴퓨팅 서비스로, 아마존이 전세계적으로 구축한 데이터 센터의 서버 컴퓨터들의 자원을 원격으로 사용할 수 있도록 한다. 여기서 Elastic은 가상 서버를 사용한 만큼 탄력적으로 비용과 용량을 자유롭게 조절할 수 있다는 의미이다.
1-2. EC2 특징
유연성
- 서버를 런칭하고 종료하는 것이 간단하고 빠르다.
- 수평 및 수직 Scailing을 통해 사용량에 따라 인스턴스 조절이 가능하다.
안정성
- 네트워킹 및 보안 기능을 제공하여 안정적인 서비스를 제공한다.
비용 및 위치
- 사용한만큼 비용을 지불한다.
- 전 세계 다양한 지역에서 인스턴스를 시작할 수 있다.
→ 인스턴스의 운영체제, 메모리, CPU 등을 선택적으로 구성하고, 보안 및 네트워킹을 쉽게 구성할 수 있어 빠르게 애플리케이션을 개발하고 배포할 수 있다.
1-3. 인스턴스 생성 및 연결
AWS EC2 접속 > 인스턴스 생성
- 기본으로 선택된 Amazon Linux를 사용
키 페어 생성
- mac에서는 터미널에서 ssh 명령어를 통해 `.pem` 파일을 사용해 AWS EC2에 바로 연결할 수 있는데, windows에서는 보통 PuTTY를 설치해서 ssh 클라이언트를 설치한 후, `.ppk` 파일을 사용해 AWS EC2로 연결해야 한다. (mac에서도 PuTTY를 통해 연결이 가능하다)
이렇게 쉽게 인스턴스가 생성됐다!
이제 terminal에서 `ssh -i {생성한 key}.pem {ec2-user}@{퍼블릭 IPv4 주소}`로 인스턴스에 연결할 수 있다. (연결 정보는 인스턴스 > 연결 > SSH 클라이언트에 쉽게 설명되어 있다)
2. Jenkins
2-1. Jenkins란
젠킨스는 지속적인 통합(CI) 및 지속적인 배포(CD) 파이프라인을 자동화하는 오픈소스 도구이다. 소프트웨어 개발 및 배포 프로세스를 자동화하고 개선하기 위해 사용되며, 개발자 및 팀이 소프트웨어의 품질과 안정성을 관리할 수 있도록 도와준다.
2-2. Jenkins 특징
연동성
- 다양한 플러그인을 통해 빌드, 테스트, 배포와 관련된 대부분의 툴과 쉽게 연동할 수 있다.
- ex) Git, Docker, Kubernetes, AWS 등
자동화
- 변경 사항이 지속적으로 병합되고 빌드되며, 이러한 프로세스를 자동화한다.
- 코드가 중앙 저장소에 푸시될 때마다 Jenkins가 트리거되어, 빌드 및 테스트를 실행한다. (CI)
- 빌드된 애플리케이션을 서버에 자동으로 배포할 수 있다. (CD)
2-3. Jenkins 설치
Jenkins
Jenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy their software
www.jenkins.io
- 초기 비밀번호를 설정하고, Install suggested plugins를 선택해 권장하는 플러그인만 설치한다.
- `brew services start jenkins`
- 젠킨스 접속 (`localhost:8080`)
3. 실습
현재 실습에서는 Spring 프로젝트를 빌드하고 배포하려고 한다.
3-1. Github 설정
먼저 Jenkins에서 Gihub 이벤트를 허용하기 위한 AccessToken을 발급해야 한다.
Gihub > Settings > Developer Settings > Personal access tokens > Tokens > Generate new token
- 두가지(repo, admin:repo_hook)에 체크해주고, 토큰을 생성한다.
- 생성된 토큰을 저장한다. (해당 화면을 벗어나면 토큰을 확인할 수 없으니 미리 저장해놓자)
Jenkins > dashboard > Jenknis 관리 > Credentials
- Username(github id)와 Password(Access Token)을 설정한다.
이제 해당 레포지터리의 이벤트를 받을 *webhook을 생성한다.
Github > 해당 프로젝트 레포지터리 > Settings > Webhooks > Add webhook
- Payload URL에는 `{젠킨스 서버 주소}/github-webhook/`를 입력한다.
- 해당 레포지터리의 이벤트를 받을 주소를 설정하는건데, `localhost:8080`를 입력하면 정상적으로 동작하지 않는다.
- 따라서 ngrok을 사용해서 local의 젠킨스 서버 주소를 호스팅한 경로를 기입한다. (터미널에 `ngrok http http://localhost:8080`을 입력)
* webhook ?
특정 이벤트가 발생했을 때, 지정된 URL로 데이터를 자동으로 전송하여 실시간으로 정보를 전달하는 방식의 HTTP 콜백이다. 주로 시스템 간의 자동화된 통신을 위해 사용된다. Github, Slack 등의 서비스에서 특정 이벤트가 발생하면, 해당 이벤트에 대한 정보를 웹훅을 통해 다른 시스템으로 실시간 전송할 수 있다.
* ngrok ?
ngrok은 로컬 개발 환경에서 실행 중인 애플리케이션을 안전하게 외부 인터넷에 노출할 수 있도록 해주는 도구이다. TSL/SSL 보안 연결을 통해 인터넷에서 서버를 실행할 수 있으며, 웹 애플리케이션을 외부에 노출시키지 않고도 테스트할 수도 있다.
3-2. Jenkins 설정
- 연동을 진행할 github url을 설정한다.
- 소스코드 관리 > Git - Repository URL 설정, Credentials도 방금 만든 것으로 설정한다.
- 빌드 유발 > GitHub hook trigger for GITScm polling을 체크한다. (github push가 이루어졌을 때, 자동으로 jenkins 빌드를 실행하기 위해)
빌드 단계를 설정하기 전에, Dashboard > Jenkins 관리 > Tools
- Maven installations을 통해 사용하려는 maven 버전을 설정한다.
- 다시 아이템 구성으로 돌아와서 Build Steps > 사용할 maven 버전을 설정하고, Goals는 `clean package -Dmaven.test.skip=true`로 설정한다.
여기서, 보통 github에는 `application.properties` 같은 환경 변수 파일은 업로드하지 않으므로 빌드 단계에서 직접 추가해줘야 한다.
- 빌드 환경 > Use secret text(s) or file(s)를 통해 환경변수 파일을 추가한다. (이 때, Variable을 `PROPERTIES`로 설정했다)
- 그 다음 Build Steps > Execute shell을 체크해 위에서 설정한 Variable을 통해 원하는 경로에 파일을 복사한다. (`cp -f ${PROPERTIES} ./src/main/resources/`)
저장을 누르고, 빌드를 실행해본다.
출력된 콘솔에서 jenkins 워크스페이스를 확인할 수 있으며, 해당 경로에 들어가보면 빌드 결과물이 정상적으로 생성됨을 확인할 수 있다.
3-3. Jenkins + EC2 연결
이제 로컬이 아닌 EC2에 연결해보자
Jenkins관리 > System > Publish over SSH
- Key에 발급받은 EC2 key pair를 넣는다.
- SSH Server > Hostname에는 EC2의 퍼블릭 IPv4주소와 Username(ec2-user), Remote Directory(/home/ec2-user, 접속 후 pwd 입력해서 확인)를 설정한다.
- Test Configuration 버튼을 눌러서 연결이 성공하는지 확인
해당 프로젝트 설정으로 돌아가서, 빌드 후 조치 > Send build artifacts over SSH를 다음과 같이 설정한다.
- 전체 소스 파일(**)을 Remote directory(/dev/)로 옮긴후, 실행할 명령어를 작성해주었다.
이로써 설정은 끝났다! 실제로 github에서 변경 사항을 push하면, webhook을 통해 Jenkins에 전달되고 자동으로 자동화된 CI/CD가 가능해진다.
빌드가 완료되면, EC2에 API를 요청해 정상적으로 응답을 받아볼 수 있다.
4. 마무리
기존 서비스 배포 과정은 코드의 변경 내용을 git push한 뒤, EC2에 접속해서 git pull 받고, application.properties 및 환경 변수를 직접 수정하고, Docker로 실행시켜 서비스를 배포하는.. 이런 복잡한 과정을 거쳤다. 작은 규모에서는 수작업이 크게 불편하지 않았지만, 변경 사항의 빈도와 규모가 커질수록 이런 자동화 작업들은 매우 필수적일 것이다. 이번 학습을 통해 배포화 도구에 대한 필요성을 크게 체감했고, Jenkins 또는 다른 자동화 방식에 대해 학습해서 더 나은 개발 프로세스 환경을 만들어야겠다는 다짐을 했다.
참고자료 😃
https://engineerinsight.tistory.com/99
https://velog.io/@rjsdn04111/Jenkins-설치부터-연동까지-dhi2o26m
https://nerd-mix.tistory.com/37
https://junhyunny.github.io/information/jenkins/github/jenkins-github-webhook/
'AWS' 카테고리의 다른 글
[AWS] AWS S3 - Spring 파일 업로드 (0) | 2024.04.11 |
---|---|
[AWS] AWS S3 - 개념 및 버킷 설정 (0) | 2024.04.09 |