본문 바로가기

클라우드 & 배포

Jenkins를 이용한 Dockerized 애플리케이션 배포 자동화: SSH로 배포하기

저번 글에서는 일일이 빌드와 배포를 해주었습니다. https://mythofsummer-backend.tistory.com/6

이번 글에서는 Jenkins를 설정하고, SSH를 통해 Dockerized 애플리케이션을 자동으로 배포하는 과정을 다룹니다.

  • Jenkins 세팅
  • SSH로 배포하는 과정 이해하기
  • dockerized 애플리케이션 배포 자동화

1. Jenkins 세팅

1.1 Jenkins 주요 기능

 

  • Batch 처리: Jenkins는 실시간 처리가 아닌 일괄 처리를 통해 빌드와 배포 작업을 주기적으로 수행합니다.
  • 빌드 및 배포 자동화: Jenkins는 수동으로 빌드하고 배포하는 번거로움을 없애고, 자동화된 파이프라인을 통해 작업을 효율적으로 처리합니다.

 

1.2 Jenkins와 GCP 인스턴스 설정

 

우리는 두 개의 GCP 인스턴스를 사용할 것입니다:

  • Jenkins 인스턴스: 빌드와 배포를 담당하는 서버.
  • Worker 인스턴스: 실제 애플리케이션이 배포되고 실행되는 서버.

1.3 Jenkins 설치

sudo apt-get update
sudo apt-get install wget
sudo apt-get install maven
  • 시스템 패키지 목록 업데이트
  • wget 설치(wget은 웹에서 파일을 다운로드할 수 있는 명령줄 도구입니다. Jenkins 설치 과정에서 Jenkins 키와 리포지토리를 추가하기 위해 필요합니다.)
  • Maven 설치(Maven은 프로젝트 관리 도구로, Jenkins에서 빌드 프로세스를 관리하는 데 사용됩니다. Maven을 설치하여 Jenkins에서 빌드 작업을 수행할 수 있도록 합니다.)
wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
  • 이 명령어는 Jenkins 패키지의 인증 키를 시스템에 추가합니다. 다음 단계를 통해 Jenkins 리포지토리를 시스템에 추가할 때, 이 인증 키를 사용하여 패키지의 무결성과 출처를 검증합니다.
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
  • 이 명령어는 Jenkins 패키지를 다운로드할 수 있는 리포지토리를 시스템에 추가합니다. sh -c 명령을 사용하여 echo 명령의 출력을 /etc/apt/sources.list.d/jenkins.list 파일에 저장합니다. 이 파일은 새로운 패키지 소스 목록을 포함합니다.
sudo apt-get update
sudo apt-get install jenkins
sudo systemctl start jenkins
sudo systemctl status jenkins
  • 시스템 패키지 목록 업데이트
  • Jenkins 설치
  • Jenkins 서비스 시작
  • Jenkins 서비스 상태 확인

1.4 Jenkins 인스턴스 방화벽 규칙 설정

Jenkins는 기본적으로 8080 포트를 사용하여 웹 인터페이스를 제공합니다. GCP 인스턴스에서 이 포트에 접근할 수 있도록 방화벽 규칙을 설정해야 합니다.

  1. GCP 콘솔에 접속합니다.
  2. 네트워크 서비스 -> VPC 네트워크 -> 방화벽 규칙으로 이동합니다.
  3. "방화벽 규칙 만들기"를 클릭합니다.
  4. 다음과 같이 설정합니다:


     
    • 이름: jenkins-web
    • 소스 IP 범위: 0.0.0.0/0 (모든 IP에서 접근 가능)
    • 프로토콜 및 포트: tcp:8080
  5. "만들기"를 클릭하여 방화벽 규칙을 적용합니다.

1.5 Jenkins 초기 설정

  • Jenkins 설치 후, 초기 관리자 비밀번호를 확인합니다:
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
  • 브라우저에서 http://<YOUR_INSTANCE_IP>:8080으로 접속하여 Jenkins 초기 설정을 완료하고, 추천 플러그인을 설치합니다.

1.6 Publish Over SSH 플러그인 설치

배포를 위해 SSH를 사용해야 하므로, Publish Over SSH 플러그인을 설치해야 합니다.

  1. Jenkins 관리 페이지에서 Manage Jenkins > Manage Plugins로 이동합니다.
  2. Available 탭에서 Publish Over SSH 플러그인을 검색하여 설치합니다.
  3. 설치가 완료되면 Jenkins를 재시작합니다.

 

2. ssh로 배포하는 과정 이해하기

배포에는 여러 가지 방식이 있지만 가장 보편적인 방식은 SSH에 접속하여 배포하는 것입니다. Jenkins가 Worker 인스턴스에 접속하여 Docker 이미지를 pull 받고 run 시키는 과정을 안전하게 수행하기 위해 SSH 키 쌍을 사용합니다.

암호학에서는 대칭 키와 비대칭 키가 있습니다. 대칭 키는 암호화와 복호화에 동일한 키를 사용하는 반면, 비대칭 키는 공개 키와 개인 키라는 두 가지 키를 사용합니다.

  • 비대칭 키 암호화: 메시지를 전달하고자 하는 대상의 공개 키로 메시지를 암호화하면, 이 메시지는 오직 대상의 개인 키로만 복호화할 수 있습니다.
  • 디지털 서명: 개인 키로 메시지를 암호화하면, 누구나 대상의 공개 키로 이 메시지를 열람할 수 있습니다. 이를 통해 메시지의 발신자를 증명할 수 있습니다.

이 개념을 사용하여 Worker 인스턴스에 오직 Jenkins만이 SSH로 접속할 수 있도록 설정합니다. Jenkins의 SSH 키 쌍을 생성하고, 공개 키를 Worker 인스턴스에 등록하면, 이후에는 Jenkins만 Worker 인스턴스에 접속할 수 있습니다. 이를 통해 보안이 강화됩니다.

 

Worker 인스턴스 준비

Jenkins가 Worker 인스턴스에 SSH로 접속하여 Docker 이미지를 pull하고 run할 수 있도록 설정합니다. 이를 위해 SSH 키 쌍을 생성하고, Worker 인스턴스에 공개 키를 등록합니다.

 

SSH 키 쌍 생성

먼저 Jenkins 인스턴스에서 SSH 키 쌍을 생성합니다:

ssh-keygen -t rsa -f ~/.ssh/id_rsa

생성된 키 쌍은 ~/.ssh 디렉토리에 저장됩니다.

 

공개 키 등록

 

Worker 인스턴스에 SSH로 접속하여 공개 키를 등록합니다:

 

  • Worker 인스턴스에 SSH로 접속합니다.
  • authorized_keys 파일에 Jenkins 인스턴스의 공개 키를 추가합니다:
vi ~/.ssh/authorized_keys

 

  • 공개 키 내용을 복사하여 authorized_keys 파일에 붙여넣습니다.
  • 권한 설정을 합니다

 

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

 

3. dockerized 애플리케이션 배포 자동화

이제 Jenkins를 통해 Worker 인스턴스에 Dockerized 애플리케이션을 자동으로 배포할 수 있습니다. Jenkins에서 SSH를 통해 Worker 인스턴스에 접속하여 Docker 이미지를 pull하고 run합니다.

 

1. SSH 자격 증명 추가

  1. Jenkins 관리 페이지에서 Manage Jenkins > Configure System으로 이동합니다.
  2. Publish over SSH 섹션으로 이동하여 SSH 서버를 설정합니다:
    • Key: Jenkins 인스턴스의 개인 키 (~/.ssh/id_rsa)를 추가합니다.
    • SSH Servers: 다음과 같이 입력합니다:
      • Name: cpu-worker-instance-1
      • Hostname: Worker 인스턴스의 내부 IP
      • Username: Worker 인스턴스의 계정 ID
      • Remote Directory: 홈 디렉토리 경로

2. 배포 스크립트 작성

  1. Jenkins 대시보드에서 새로운 아이템을 선택하고 Freestyle project를 선택합니다.
  2. 빌드 후 조치 섹션에서 Send build artifacts over SSH를 선택합니다.
  3. SSH Server에 앞서 설정한 cpu-worker-instance-1을 선택합니다.
  4. 고급을 클릭하고 Verbose output in console을 선택하여 로그를 출력하도록 설정합니다.
  5. Exec command에 다음 명령어를 입력합니다:
nohup docker run -p 8080:80 mythofsummer/spring-boot-cpu-bound > /dev/null 2>&1 &

 

 

  • nohup:
    • nohup은 “no hangup”의 약자로, 현재 세션이 종료되더라도 명령어가 계속 실행되도록 합니다. 이 명령어를 사용하면 사용자가 SSH 세션을 종료하거나 로그아웃해도 프로세스가 계속 실행됩니다.
  • docker run:
    • docker run은 Docker 이미지를 실행하는 명령어입니다. 새로운 Docker 컨테이너를 생성하고, 지정된 이미지로부터 컨테이너를 시작합니다.
  • -p 8080:80:
    • -p 플래그는 포트 포워딩을 설정합니다. 8080:80은 호스트의 8080 포트를 컨테이너의 80 포트에 연결합니다. 즉, 호스트의 8080 포트로 들어오는 요청은 컨테이너의 80 포트로 전달됩니다.
  • mythofsummer/spring-boot-cpu-bound:
    • 실행할 Docker 이미지의 이름입니다. 이 이미지는 Docker Hub 또는 로컬 레지스트리에서 pull받은 Spring Boot 애플리케이션 이미지입니다.
  • > /dev/null:
    • > 연산자는 표준 출력을 리디렉션합니다. /dev/null은 모든 입력을 버리는 장치 파일로, 이 명령어는 표준 출력을 무시하고 버리겠다는 의미입니다.
  • 2>&1:
    • 2>는 표준 에러 출력을 리디렉션하는 연산자입니다. &1은 표준 에러 출력을 표준 출력으로 리디렉션합니다. 즉, 표준 에러도 /dev/null로 보내어 에러 메시지도 무시하게 됩니다.
  • &:
    • &는 명령어를 백그라운드에서 실행하도록 합니다. 이 명령어는 즉시 프롬프트를 반환하고 명령어가 백그라운드에서 실행됩니다.

 

3. 빌드

worker instance에 docker를 설치하고, jenkins에서 지금 빌드를 누르면 애플리케이션이 잘 실행되는 걸 알 수 있습니다.