Jenkins & Git Webhooks을 활용하여 EC2에 소스 배포하기

Lee Seung Chan·2023년 10월 5일
4
post-thumbnail

📌 배경

회사에서 20개 가까이되는 개발 프로젝트들이 AWS EC2 서비스로 호스팅이 되어있었으나, 로컬에서 소스 작업 후 배포를 하는 과정에서 오로지 수동으로 scp 명령어를 이용해 배포하고 있었다. 이러한 방식은 효율적이지 않다고 생각이 들었다.


내가 생각한 기존 방식의 문제

EC2 Instance 20개 가량을 모두 scp를 이용해 배포하고 있었음

  • 각 EC2 Instance의 각기 다른 HostName/pw/보안 키를 알고 있어야 명령어를 사용할 수 있다.
  • 각 프로젝트별로 어느 위치에서 배포 되고 있는 지 알고 있어야 한다.
  • 배포 후에 SSH 터미널로 접근하여 프로세스를 수동으로 다시 재시작해야한다.
  • 배포 시간이 다소 길어진다.

해결 방안

깃 저장소의 Git main(deploy) branch가 push 될 때, EC2에 소스가 배포되도록 한다.

  • 최종적으로는 API/통합/단위 테스트를 통과할때만 배포될 수 있게 하고싶지만 아직 학습이 부족하여 추후 적용할 수 있게 공부 할 예정이다.

이렇게 해결 방안을 생각하고 적용할 수 있는 방안을 인터넷을 서칭해보니, Jenkins라는 툴을 발견했고, 짜투리 시간이 주어질때마다 천천히 작업해보기로 했다.


📌 작업

먼저 작업 전 EC2(Ubuntu)/Git/Jenkins가 모두 설치되어 있고, NodeJs 프로젝트 라는 것을 전제로 한다.

GIT ↔ EC2 연동 작업

  1. AWS EC2 Instance에 접속하여 Git 계정과의 연동을 위해 암호화 키를 생성한다.
# ssh 설정 관련 디렉토리로 이동한다.
cd ~/.ssh

# rsa-key 제작
ssh-keygen -t rsa -b 4096 -C "깃허브 이메일 주소" -f 키이름
명령어 실행 후 나오는 모든 질문 Enter
  1. 생성된 암호화 Public 키를 Git 계정에 등록한다. (.pub 확장자 파일을 등록해야함)
    Github → Settings → SSH and GPG Keys에서 New SSH Key 버튼 클릭
cat ~/.ssh/키이름.pub 


3. 여러 사용자가 Git을 사용할 수 있도록 config 파일을 생성하고 내용을 추가한다.

# config 파일 생성
touch ~/.ssh/config

# config 파일 편집
vi ~/.ssh/config

# config 파일에 내용 추가
Host 깃아이디
    HostName github.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/키이름

JENKINS 플러그인 설치

  1. 필수 플러그인 설치
  • Publish Over SSH 설치(SSH 연결 플러그인)
    Dashboard → Jenkins 관리 → Plugins → Available Plugins → Publish Over SSH 설치

  • NodeJS 설치(nodejs 프로젝트 빌드/명령어)
    Dashboard → Jenkins 관리 → Plugins → Available Plugins → NodeJS 설치

  1. EC2 SSH Server 설정
  • Dashboard → Jenkins 관리 → System에서 Public Over SSH 항목으로 이동
  • SSH Server 추가 → 세부 항목 입력 → 고급 → EC2 보안키 Key에 복사 & 붙여넣기
  1. NodeJS 설정
  • Dashboard → Jenkins 관리 → 노드 Tools에서 NodeJS installations 항목으로 이동
  • Add NodeJS → 이름 입력 → Install automatically 체크 → 노드 버전 입력

JENKINS Item 추가

Dashboard → item → Configuration

  1. GitHub Project URL 설정
  • General → GitHub project
  • Project URL 입력, 저장소의 URL(끝에 .git을 제외한 HTTPS 주소)을 입력하면 된다.
  • https://github.com/깃아이디/저장소명
  1. Github Repo 추가
  • General → 소스 코드 관리
  • Repo URL 입력, 저장소의 URL(.git이 포함된 HTTPS 주소)을 입력하면 된다.
  • https://github.com/깃아이디/저장소명.git
  1. Github Credentials 추가
  • Add 버튼을 눌러 Credentials을 추가한다.
  • Kind는 Username with password로 지정
  • Username에 깃아이디 입력
  • Github → Settings → Developer Settings → Personal access tokens에서 토큰 생성
  • Password에 생성된 토큰값 입력
  • ID는 임의로 지정하여 입력한다.(내부 고유 식별자, 본인이 기억하고만 있으면 된다.)
  1. Github build branch 설정
  • 하단 Branches to bulid에 Branch Specifier (blank for 'any')에 */main 입력
  • 최종 소스를 배포할 브랜치 입력, 만약 master면 master를 입력한다.
  1. 빌드 유발(Git Webhooks 설정)
  • General → 빌드 유발
  • git webhooks을 사용하기 위하여 GitHub hook trigger for GITScm polling 항목 체크
  • Github Repo → Settings → WebHooks에서 add Webhook
  • Payload URL에 Jenkins 주소 + /github-webhook/ 추가
  • Jenkins 주소는 public하게 접근이 가능한 주소여야 한다.
  • 예를 들어 로컬 주소를 사용할 경우, 포트 포워딩 설정이 추가적으로 필요하다.
  • content/type을 application/json으로 설정
  • trigger events, active 설정 체크하고, Update webhook으로 최종 추가
  1. 빌드 환경(NodeJS 설정)
  • General → 빌드 환경
  • Provide Node & npm bin/ folder to PATH에 체크
  • NodeJS Installation에 Tools에서 설정한 노드 버전으로 체크
  1. 빌드 후 조치
  • General → 빌드 후 조치
  • Send build artifacts over SSH를 체크
  • SSH Server Name에서 System - Public Over SSH에서 설정한 EC2 서버 이름 선택
  • Exec command 설정
echo "배포 디렉토리 이동"
cd 디렉토리 위치

echo "깃 origin 원격 저장소 설정"
sudo git remote set-url origin git@github.com:깃아이디/저장소명.git

echo "깃 소스 Pull"
sudo git pull
# git pull 이후에 pm2 restart 라던지 프로젝트를 재시작하는 명령어도 추가할 수 있다.

echo "SSH 종료"
exit

이렇게 까지 전부 완료했으면, 로컬에서 작업 완료 후 Main Branch에 Git Push시에 연동된 EC2 Instance Directory에 Git Pull이 되면서 소스가 배포가 될 것입니다.


📌보충해야할 내용

여기서 사용한 GitHub hook trigger for GITScm polling 트리거 옵션은 모든 webhook 요청에 대해 트리거가 발생하는 문제점이 있습니다.
따라서 Jenkins Plugin: Generic Webhook Trigger 으로 젠킨스에서 Webhook 요청 Payload값에 특정 브랜치, 특정 토큰값이 포함되어 있을 때, 혹은 다른 특정 조건을 만족할 때, 트리거를 발생시킬 수 있습니다.
이후 기회가 된다면 이 부분에 관해서도 포스팅 하겠습니다.


📌 마치며

저도 개발 초보라서 많이 헤매면서 작업을 한 것 같네요
만약 제가 쓴 내용 중 틀린 부분이 있다면 수정하겠습니다.
긴 글 읽어주셔서 감사합니다!

profile
기억은 잊혀져도 기록은 영원하다

0개의 댓글