EMD Blog

Container를 이용한 PHP 개발환경 가상화와 배포 자동화를 해보자 (2) 본문

CICD

Container를 이용한 PHP 개발환경 가상화와 배포 자동화를 해보자 (2)

EmaDam 2021. 4. 29. 13:16
AWS를 사용하여 진행하며 요금이 과금될 수도 있습니다. 주의바랍니다.
꼭 AWS를 사용하지 않아도 다른 개인 서버(Local도 괜찮습니다.)를 사용해도 됩니다.

Jenkins를 이용한 배포 자동화

이번에는 배포 자동화를 구현 해보자. 배포 자동화에 사용될 도구는 대표적인 CI 도구 중 하나인 Jenkins를 활용하도록 하겠다. 배포 프로세스는 이렇다. 먼저 개발을 하고 Commit 후 Github Repository의 Master로 Push를 하게 되면 Github에서는 WebHook을 통해 Jenkins에게 Push 이벤트를 보내고 Jenkins는 서버에 코드를 배포하게 된다. 서버는 AWS를 이용해서 진행하도록 하겠다.

 

먼저 Jenkins 서버로 사용할 EC2를 생성하자. 

EC2 선택

원래는 CentOS를 주로 사용했는데 CentOS가 지원종료 된다고해서 Amazon linux 2를 주로 사용하고 있다. 

유형 선택

공부일 뿐이니 프리티어를 선택하도록 하자

 

세부정보 설정

인스턴스 설정에 대한 상세한 사항은 AWS에 설명이 잘되어 있으니 참고하도록 하고 만약 지금처럼 공부가 목적이라면 별도의 설정없이 넘어가도록 하자. 네트워크의 경우 별도의 구축을 한적이 없다면 기본 VPC와 서브넷을 그대로 사용하면 되지만 만약에 별도의 네트워크를 구축해놓은 상태라면 상황에 맞게 설정하도록 하자.(잘 모르겠으면 그냥 Public Subnet에 배치하자) 

 

보안그룹 설정

그 다음은 보안그룹 설정이다. 위 사진은 비어있지만 사진에 표시된 규칙추가 버튼을 눌러서 꼭 규칙을 생성하도록 하자 

생성할 규칙은 다음과 같다.

 

SSH( 22 ) : 내 IP만 허용해 주도록 하자

사용자 지정 TCP (8080) : 내 IP, Github Hook IP만 허용해 주도록 하자

사용자 지정 TCP (5000) : 내 IP만 허용해 주도록 하자

 

8080의 경우 GitHub의 Hook IP를 허용해주어야 하는데 Webhook을 통해 이벤트를 받기 위함이다. 

이렇게 규칙들을 추가했다면 검토 및 시작을 눌러 다음으로 넘어가자

 

그 다음에는 전체적인 검토화면이 나오는데 천천히 살펴보고 문제가 없다면 인스턴스를 생성하자. 그러면 키페어를 새로 생성할 것인지 기존 것을 활용할 것인지 선택 모달이 나오는데 그냥 적당한 이름으로 새로 만들도록 하자(이 키는 절대 잃어버리면 안된다)

그런데 이번 실습에서는 Jenkins 서버의 Host와 Web server의 Host가 다르다. 그래서 EC2 인스턴스를 한개 더 생성 해주어야한다. 

위의 방법으로 똑같이 하나 더 만들도록하자. 하지만 다르게 해주어야할 부분이 한 군데 있는데 바로 보안그룹이다.

 

이번 EC2는 보안 그룹 규칙을 다음과 같이 설정하자

 

HTTP(80) : 전체 허용

HTTPS(443) : 전체 허용

SSH(22): 내 IP, Jenkins Host IP

 

Jenkins server에서 Web Server로 배포할 때 SSH를 이용할 것이기 때문에 Jenkins Server의 접근을 허용해주어야한다. 

이렇게 두 개의 EC2 인스턴스를 생성했다면 이제 Jenkins를 설치하도록 하자. Jenkins는 Docker를 사용해 설치하도록 한다.

 

$ sudo amazon-linux-extras install -y docker 

후에 Docker를 시작한다.

$ sudo systemctl start docker

그 다음 ec2-user를 docker 그룹에 넣어준다.

$ sudo usermod -aG docker ec2-user

그리고 Docker compose를 설치해주자

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Docker compose에 실행권한도 부여하자

sudo chmod +x /usr/local/bin/docker-compose

Docker compose가 정상적을 설치됐는지 확인해보자

$ docker-compose --version
docker-compose version 1.29.1, build

Docker compose가 정상적으로 설치되었다면 docker-compose.yml 파일을 작성하도록 하자

$ nano /home/ec2-user/docker-compose.yml

docker-compose.yml 내용은 다음과 같다

version: "3.9"
services:
  jenkins:
    container_name: jenkins
    image: jenkins/jenkins:lts
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - /var/jenkins_home:/var/jenkins_home

jenkins 관련 자세한 설정 및 환경변수는 docker hub를 참고하자

(volume 마운트 경로나 port는 원하는대로 설정하도록하자. 단, port의 경우 다른 port사용시 보안그룹 규칙도 변경해주어야 한다.)

 

작성이 끝났으면 container를 생성하자.

$ docker-compose up -d

생성이 끝났으면 주소창에 http://JenkinsIP:8080/로 접속해보자

 

첫 화면

위와 같은 화면이 출력될건데 붉은색으로 적혀있는 경로가 초기 패스워드 경로가 된다. 저 패스워드 정보는 container내에 적혀있는 정보지안 우리는 위에서 /var/jenkins_home에 대한 경로를 마운트 했으므로 별다른 작업없이 해당 경로를 확인하면 된다.

$ cat /var/jenkins_home/secrets/initialAdminPassword

초기 비밀번호를 설정했다면 다음과 같은 화면이 출력된다.

초기 옵션

왼쪽의 경우 추천하는 플러그인을 설치하고 오른쪽의 경우 사용자가 플러그인을 직접 설치하게 된다. 어차피 플러그인은 나중에도 설치할 수 있기 때문에 뭘 선택해도 상관없다. 지금은 왼쪽 Install suggested plugins를 선택하자

관리자 계정 설정

플러그인 설치가 끝나면 첫 관리자 계정을 설정하는 페이지가 나온다. 적당히 설정하고 넘어가자

 

대시보드

드디어 Jenkins 첫 화면이 출력됐다. 

우리는 다른 EC2서버에 SSH를 통해 배포를 할 것이기 때문에 별도의 Plugin이 필요하다. Publish Over SSH Plugin을 설치하자 

 

Jenkins 관리

설치 가능 목록에서 Publish Over SSH Plugin으로 검색한 후 설치하자.

 

설치가 완료 됐으면 Jenkins 관리의 시스템 설정으로 들어가자.

Jenkins 관리

그 후에 화면에서 Publish over SSH 탭을 찾아 내용을 작성하자

Public over SSH

위에서 부터

Passphrase : 암호 (Key를 사용할 것이라 빈칸으로 두시면 됩니다.)

Path to key: 키 경로 (직접 입력할거라 빈칸으로 두사면 됩니다.)

Key: EC2접속에 사용하는 .pem 키 내용을 전부 다 복사해서 붙여넣습니다. (-----BEGIN/END RSA PRIVATE KEY----- 도 포함해서 전부 복사하셔야됩니다.)

 

그 다음 바로 아래 추가 버튼을 클릭하면 SSH 서버 정보를 입력하는 칸이 출력된다. 위에서부터

Name: 접속 이름 (아무렇게나 작성하셔도 됩니다.)

Hostname: 배포할 Host의 ip나 도메인 입력

Username: 접속 계정 입력

Remote Directory: 접속 시 위치 (저의 경우 /로 해놓았습니다. 이 위치에 따라 배포 경로 설정이 달라지니 설정시 주의해주세요.)

 

위 정보를 전부 입력했으면 Test Configuration을 클릭해 접속 테스트 후 Success가 표시되면 저장을 클릭한다.

 

배포할 서버에 대한 연결정보를 등록했으니 이제 Github와 연동해보자

먼저 Jenkins에 ssh로 접속해서 키를 생성하자. (원하는 위치에 생성하자)

중간에 비밀번호를 등록할 것인지 물어보는데 그냥 엔터쳐서 넘어가도록 하자

$ ssh-keygen -t rsa -f id_rsa
$ ls -l
ec2-user ec2-user 1675  4월 26 08:36 id_rsa
ec2-user ec2-user  435  4월 26 08:36 id_rsa.pub

그 다음 Github에 접속해서 원하는 Repository의 Settings -> Deploy keys -> Add deploy key 로 이동하자

key 추가

그 다음 생성했던 key 중 public key를 등록하자

key 정보

Title: 식별자이니 적절하게 이름을 적어주자

Key: 공개 키 값을 적어주도록 하자 공개 키는 아까 생성한 key중에 id_rsa.pub 내용을 그대로 복사해오면 된다.

$ cat id_rsa.pub
ssh-rsa FEJKSFNKDEdanjfkesfnjk1j2k4nrbufi2nui..

위 처럼 공개 키 값을 출력해서 ssh-rsa부터 전부 복사해서 붙여넣으면 된다.

Allow write access는 이 key를 이용한 push 작업 허용 여부를 체크하는 것이다. 체크를 해제하면 pull만 허용된다. 우리는 jenkins에서 pull -> 배포만 할 것이기 때문에 따로 체크는 하지 않도록 하겠다.

 

이렇게 Github에 공개 키를 등록했다면 이제 Jenkins로 이동해서 Jenkins 관리 -> Manage Credentials 로 이동하자

 

키 관리

그 다음 (global)을 클릭 후 Add Credentials를 클릭하면 자격증명을 등록할 수 있는 페이지가 나온다

Kind: 자격증명에 대한 종류이다. SSH username with private key를 선택한다

Scope: 자격증명의 범위이다. Global로 선택하자

ID: 식별자이다. 자동으로 생성되니 빈칸으로 두자

Description: 자격증명에 대한 설명이다. 적당하게 입력하자

Username: 자격증명 이름이다. 적당한 이름으로 작성하자

Private Key: Private key를 등록할 수 있다. Enter directly를 클릭하고 아까 생성한 key중 id_rsa를 출력해서 전체 복사 후 붙여넣자

Passphrase: Private key에 대한 비밀번호를 별도로 설정하지 않았으므로 빈칸으로 두자

 

이렇게 하면 Private key가 등록되고 Github과 연동할 준비가 완료된 것이다.

그럼 이제 Jenkins에서 SSH를 이용한 실제 배포 프로세스를 설정해보도록 하자

먼저 대시보드에서 새로운 Item을 클릭하자

그 다음 Freestyle project를 생성하자 

 

이후에 상세설정 화면이 나오는데 먼저 소스 코드 관리 탭으로 이동 후 Git을 선택하자

그럼 코드를 가져올 Git정보를 입력할 수 있는 입력창이 출력된다.

위에서 부터 

Repository URL: Repository URL을 입력하면 된다. 우리는 SSH 사용할 것이므로 Github에서 SSH clone경로를 복사해서 붙여넣으면 된다.

Credentials: 이전에 만들었던 자격증명을 선택한다. (Github이라는 이름으로 Global 자격증명을 만들었었다.)

Branch Specifier: 가져올 Branch를 입력한다

 

이후 탭에서 build를 선택 후 Send files or execute commands over SSH를 선택하자

그러면 아래와 같은 화면이 출력된다.

Github에서 Pull해온 파일을 다른 어디에 어떻게 전송할지 정보를 입력하는 화면이다.

위에서부터 

 

Name: 서버 접속정보이다. 이전에 생성했던 서버접속정보를 선택하자

Source files: Repository내 어떤 폴더와 파일을 전송할 지 지정할 수 있다. 전부 전송할 경우 **/**로 입력하자

Remove prefix: 전송시 제외시킬 폴더나 파일을 지정한다. 지금은 제외할 폴더나 파일이 없으므로 빈칸으로 두었다.

Remote directory: 전송할 디렉터리 위치를 지정(아까 지정했던 서버의 접속경로에 대해 상대경로를 입력해야한다.)

Exec command: 전송 후 실행시킬 command를 입력할 수 있다.

 

이제 저장 후 해당 프로젝트로 들어가보자

 

build now를 클릭하면 실제 배포가 시작된다.

파란 동그라미를 클릭 후 나오는 메뉴에서 Console Output을 클릭하면 진행상황에 대한 로그를 확인할 수 있다.

그런데 우리는 수동으로 배포하는 것이 아닌 Push 이벤트에 반응해서 자동 배포하도록 구현해야한다. 그러기 위해서는 Webhook이라는 기능을 사용해야한다.

먼저, Github의 Repository -> Settings ->  Webhooks로 이동 후 Add webhook을 클릭하자

그럼 다음과 같은 화면이 출력된다,

위에서 부터

Payload URL: Push 이벤트를 전송할 URL을 적는다. http:// Jenkins URL /github-webhook/ 형식으로 입력하면된다.

Content type: 전송할 이벤트 데이터 Type이다 application/json을 선택하자

이후에 Add webhook을 클릭하면 webhook이 생성된다.

 

github에 webhook을 추가했으면 이번에 생성한 jenkins 프로젝트에서 해당 이벤트를 받을 수 있도록 설정해야한다. 

Jenkins 프로젝트로 들어가서 구성을 클릭하자

이후에 빌드유발 탭을 클릭 후 Github hook trigger for GITScm polling을 체크하자 

이제 저장하면 Github Push에 반응하는 배포 자동화 설정이 끝이난다. 

미리 세팅을 해놓고 작성하는 글이라 중간에 빠진 부분이라던가 설명이 부족한 부분이 많은 것 같다. 실제로 금방 폐기될 프로젝트에 사용하려고 세팅해놓은거라 꼼꼼히 세팅하지 않은 부분도 있기때문에 다음번 Spring boot로 세팅할때는 좀 더 제대로 다뤄보도록 하겠다.