[GCP 원데이] Jenkins를 이용한 배포

2021. 4. 23. 14:55GCP/원데이

1. 개요

앞서 진행한 방법은 수종 빌드/배포 방식이다. 하지만 Jenkins를 이용한다면 자동화를 할 수 있다.

 

GCP에는 두 가지 인스턴스가 생성이 된다. Jenkins가 실행되는 인스턴스(Jenkins 인스턴스)와  배포 대상이 되는 인스턴스로, 개발한 애플리케이션을 실행시키는 인스턴스(Worker 인스턴스) 두 가지가 있다.

 

 

 

2. 인스턴스 설정

1) 인스턴스 생성

기존에 있던 모든 인스턴스를 삭제하고 새로운 인스턴스 두 개를 만들어준다.

  • jenkins-instance / micro / CentOS 7
  • worker-instacne / micro / CentOS 7

2) Jenkins 설치

jenkins-instance에 Jenkins를 설치해준다.

sudo yum install wget
sudo yum install git
sudo yum install docker

// 패키지 추가
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

// Jenkins 설치
sudo yum install jenkins
sudo systemctl start jenkins
sudo systemctl status jenkins
// 설치할 Java 탐색
sudo yum list java*
sudo yum install -y java-1.8.0-openjdk-devel.x86_64

// javac 확인
javac -version

// javac 심볼릭 링크 확인 및 원본 파일 위치 확인
which javac
readlink -f /usr/bin/javac

// $JAVA_HOME 설정
sudo vi /etc/profile
source /etc/profile
// /etc/profile
...

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.292.b10-1.el7_9.x86_64

3) 방화벽 설정

8080번 포트를 사용하는 Jenkins를 위해 개방해준다.

4) Jenkins 기본 설정

이 후 8080 포트로 로그인하면 Jenkins 화면을 확인할 수 있다.

관리자 초기 비밀번호는 안내에 따라 SSH에서 검색하여 입력해준다.

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

추천하는 플러그인으로 설치를 해준다.

앞으로 사용할 Jenkins 계정 정보를 입력하고 시작하면 Jenkins를 사용할 기본적인 준비는 완료된다.

 

5) SSH 플러그인 설치

6) Worker 인스턴스 Jenkins 접속 설정

가장 보편적으로 많이 사용하는 방법은 SSH로 배포하는 방식이다. Jenkins가 Worker로 접속하여 도커 이미지를 pull 받고 run 하는 과정을 거치는 방법이다. 하지만 보안적인 이유로 Jenkins만 Worker로 SSH로 접속할 수 있어야 한다.

 

이를 위해 Jenkins에서 Jenkins의 개인키와 공개키 쌍을 만들어서 공개키를 Worker에게 등록해주어야 한다. 등록이 완료되면 이 후 오직 Jenkins 만이 Worker에 SSH로 접속할 수 있게 된다. 그리고 SSH로 접속하여 docker run 명령어를 실행해주도록 설정하면 완료가 된다.

 

개인키와 공개키 쌍을 만드는 명령어는 다음과 같다. 생성된 키의 정보는 '~/.ssh' 로 들어가 확인할 수 있다.

// Jenkins 인스턴스에서 생성
ssh-keygen -t rsa -f ~/.ssh/id_rsa
cd ~
cd .ssh

해당 경로로 들어가 확인을 해보면 공개키(.pub)와 개인키가 존재하는 것을 확인할 수 있다. 그리고 공개키를 확인하고 해당 내용을 복사하여 Worker 인스턴스에 등록해준다. 여기서 주의해야할 점은, 쉘에서 복사할 때 개행이 들어가는 경우가 있다. 그럴 경우 개행을 삭제해주고 등록해주어야한다.

// Worker 인스턴스에서 공개키 복붙
sudo vi ~/.ssh/authorized_keys
sudo chmod 700 ~/.ssh
sudo chmod 600 ~/.ssh/authorized_keys 

직접 authorized_keys에 키를 등록해도 상관없지만, GCP의 경우 자체적으로 해당 키 파일을 관리하기 때문에 메타데이터 항목으로 이동하여 키를 추가해주어야 한다.

등록이 완료되었다면 Jenkins에 개인키와 Worker 인스턴스에 대한 정보를 기입해준다. 이 때 Host IP의 경우, 인스턴스간 서로 통신하기 때문에 내부 IP를 적어도 무방하다.


- 암호화

  • 평문 - 암호화 되지 않은 글
  • 암호문 - 암호화 되어 읽을 수 없는 글
  • 암호화 - 암호키를 사용하여 평문을 암호문으로 변경하는 것
  • 복호화 - 암호키를 사용하여 암호문을 평문으로 변경하는 것

 

여기서 반드시 짚고 넘어가야 하는 내용이 있다. 바로 암호학에서 배우는 개념으로는 대칭키와 비대칭키 방식이다. 대칭키는 암호화할때와 그걸 복호화할 때 사용하는 동일한 키다. 반면 비대칭키는 암호화할 때와 복호화할 때 사용하는 키가 다르다. 중요한 것은 비대칭키 두 개는 관계가 있지만 동일하지 않다는 점을 기억해야 한다.

 

비대칭키에서 공개키는 모두에게 공개가 되어있는 키이며, 개인키는 오직 본인만 알고 있는 키다. 공개키로 암호화한 것은 개인키로 복호화할 수 있다.

 

쉽게 나와 너라는 주체로 본다면 다음과 같다.

 

  • 너의 공개키로 암호화 : 다른 사람이 아니라 너만 읽을 수 있음 (암호 통신 가능)
  • 너의 개인키로 암호화 : 너의 개인키를 알 수 없기에 불가능
  • 나의 공개키로 암호화 : 나 밖에 못보기 때문에 의미 없는 암호화
  • 나의 개인키로 암호화 : 모든 사람이 나의 공개키로 복호화할 수 있고 암호화는 오직 나만 할 수 있음 (전자서명)

5) 배포 스크립트

Worker 인스턴스에 대한 배포 스크립트는 모두 아이템 단위로 관리가 된다. 따라서 Jenkins 화면에서 새로운 아이템(Freestyle project)을 생성해준다.

그 후, 배포 스크립트를 설정하기 위해 '빌드 후 조치' 항목을 설정해준다. 'Verbos output in console' 항목을 활성화하여 로그를 자세히 출력할 수 있도록 설정해주고, 도커를 실행시키기 위한 명령어를 작성해준다.

docker run -p 80:80 ozofweird/spring-boot-cpu-bound

6) 에러 해결

- sudo 에러

빌드를 수행하여 로그를 확인해 보면, sudo 명령어로 인한 에러를 확인할 수 있다.

그 동안 sudo를 사용했던 이유는 80번 포트를 사용하기 위해서였다. 하지만 이를 8080 포트로 변경해주어야 한다. 

 

외부로 보이는 것은 NginX가 해당 요청을 받아주기 때문에 NginX만 80번이면 문제가 없어져 변경해도 문제가 없다. 따라서 도커 실행 명령어를 '빌드 후 조치' 항목에서 수정하고 다시 반영해준다.

docker run -p 8080:80 ozofweird/spring-boot-cpu-bound

 

- Worker 인스턴스 미설치 에러

다시 빌드를 수행하고 로그를 확인해보면, Worker 인스턴스에 도커가 설치되지 않아 동작하지 않는 것을 확인할 수 있다. 이를 해결하기 위해 Worker 인스턴스에도 도커를 설치해주도록 한다.

sudo yum install docker
sudo systemctl start docker

 

- 도커 파일 권한 에러

도커 파일 권한 오류는, 원인이 되는 파일의 권한을 Worker 인스턴스에서 수정을 하여 해결할 수 있다.

sudo chmod 666 /var/run/docker.sock

 

- Jenkins 로그 인식 에러

빌드를 하면 정상적으로 동작하는 것 처럶 보이지만, 로그가 끝나지 않아 - 배포가 끝나지 않았다고 Jenkins가 인식하여 문제가 발생한다. 이 에러도 마찬가지로 '빌드 후 조치' 항목의 명령어 실행문을 수정해주면 된다.

이 명령어는 두 가지로 나누어서 보면 된다.

  • nohup [ ... ] & - 명령을 백그라운드로 실행하겠다는 의미
  • > /dev/null 2 >&1 - 표준 에러를 표준 출력으로 리디이렉션한다는 의미

 

nohup docker run -p 8080:80 ozofweird/spring-boot-cpu-bound > /dev/null 2>&1 &

 

마지막으로 다시 빌드를 수행하면 에러가 발생하지 않는 것을 확인할 수 있다.

Worker 인스턴스의 IP로 접속하여 확인해보면 제대로 동작하는 것을 알 수 있다.

728x90