Jenkins

개요

소프트웨어 개발에서 CI/CD 란 Continuous Integration and Continuous delivery 의 약어로 다음과 같은 의미를 가집니다.

먼저, Continuous Integration 이란 여러 사람이 작업한 여러 작업 내용을 하나로 원활하게 병합하는 것을 의미합니다. 예를 들어 한 회사에서 3명의 개발자가 하나의 프로젝트를 개발한다면, 세 사람의 작업내용을 하나로 합치는 것은 매우 번거로운 일이 아닐 수 없습니다. 각 개발자 사이의 작업 내용이 겹칠 수도 있고, 다른 사람의 작업 결과가 또 다른 사람의 작업 내용에 변화를 미칠 수도 있습니다. 또, 각 개발자가 열심히 테스트코드를 작성해 두었다 한들 누군가 한명이 각 개발자의 변화된 개발분을 다운로드 해서 테스트 코드를 돌려보고 그 위에 자신의 개발분의 적용시켜 다음 테스트를 돌리는 등 여러 노력이 필요하게 됩니다.

현대 개발 패러다임에서는 이러한 코드 변화와 버전관리를 위한 여러 tool 이 존재하며, 가장 대표적인 버전관리 툴인 Git 을 예로 들어 설명을 하면, 각 개발자는 각각 자신의 feature 브랜치를 만들어 작업을 하고 이를 하나의 master 브랜치에 합치는 행위를 반복하는데, 각 commit 들이 안정적으로 master 에 반영된 것을 확인하기 위해서는 테스트코드를 돌려보는 등의 검증을 거쳐야 합니다.

Jenkins 는 이렇게 여러 branch 를 master 로 병합함에 있어, 테스트 코드 실행 linting 등 master 로 다른 변화들이 안정적으로 병합되기 위한 일련의 과정을 자동으로 처리하고 모든 commit 이 master 에 안정적으로 반영될 수 있게 도와줍니다.

그 다음으로 Continuous Delivery 란 이렇게 합쳐진 하나의 master 코드 베이스를 실제 사용자가 사용하는 production 환경에 쉽고 안정적으로 배포되게 하는 것을 말합니다.

가령, 소프트 웨어의 배포에는 여러 활동이 포함될 수 있는데, 각 소스코드를 빌드하는 것은 기본이고, 빌드된 바이너리 파일 혹은 docker image 등을 실제 production 환경에 배포하는 것은 규모가 큰 서비스 에서는 수십대의 서버의 프로세스를 교체해 주어야 하며, 또 그 모든 과정에 있어 사용자가 서비스를 이용함에 불편함이 없도록 안정적으로 이루어 져야 합니다. Jenkins 는 이렇게 배포될 소프트웨어를 실제 환경에 안정적으로 배포하기 위한 다양한 기능을 제공합니다.

이번 포스트에서는 Git 과 Jenkins 를 활용하여 아주 기본적인 Continuous Integration 파이프라인을 구축해 보도록 할 것이며, 그 과정은 다음과 같습니다.

  1. Feature 브랜치에 코드를 작성합니다.
    이 코드에는 단순히 서비스 로직 뿐만 아니라 Jenkins 가 실행시킬 테스트코드와 Linting rule 또한 포함이 되어야 합니다.
  2. Master 브랜치에 Feature 브랜치를 머지합니다.
    브랜치가 merge 되면, Jenkins 는 github 에서 이 사실을 듣고, git 소스코드를 다운로드 받아 테스트코드와 lint 를 실행합니다.
  3. 코드가 안정적으로 병합되었다면, Jenkins 는 소스코드를 빌드하고 ( 이번 포스트에서는 docker container 를 활용한 배포를 가정하므로 docker image 를 생성합니다 ) 서버에게 이 이미지를 다운로드 받아 실행하게 합니다.

AWS EC2 Instance 에 Jenkins 설치하기

먼저 이 모든 CI/CD 작업을 수행할 Jenkins Server 를 만들어 봅시다.

AWS 에서 Amazon Linux 기반의 인스턴스 하나를 생성하고 다음과 같은 script 를 통해 Jenkins 를 설치합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
sudo yum update -y

# Jenkins 는 Java 8 runtime 위에서 실행되므로 java open jdk 를 먼저 설치해 줍니다.
sudo yum install -y java-1.8.0-openjdk wget

# Jenkins 설치
wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war

# Jenkins 가 사용할 docker 와 git 을 설치해 줍니다.
sudo yum install -y jenkins git docker
java -jar jenkins.war --httpPort=8080

# Git configuration
sudo -u jenkins git config --global credential.helper '!aws codecommit credential-helper $@'
sudo -u jenkins git config --global credential.useHttpPath true
sudo -u jenkins git config --global user.name 'jenkins-workder'

# Start docker machine
sudo chmod 666 /var/run/docker.sock
sudo service docker start

# Add jenkins user in docker group so that jenkins user can use docker machine
groupadd docker
sudo usermod -aG docker jenkins

# You should restart jenkins to apply updated user group
sudo service jenkins restart

Jenkins 설정하기

위처럼 Jenkins 를 설치하고 Jenkins server 를 생행했다면, http://localhost:8080 에 jenkins dashboard 가 열리게 됩니다.

본 dashboard 에서 jenkins 를 설정하면되며, 초기 비밀번호는 /var/lib/jenkins/secrets/initailAdminPassword 에 위치해 있다.

AWS configuration

Jenkins 가 was 를 사용하기 위해 다음과 같이 AWS 계정 설정을 해준다.

1
sudo -u jenkins aws configure
1
2
3
4
5
6
7
8
9
echo "AWS_ACCESS_KEY=123456789">>~/.bash_profile
echo "AWS_SECRET_ACCESS_KEY=123456789">>~/.bash_profile
echo "AWS_DEFAULT_REGION=123456789">>~/.bash_profile

sudo mkdir /var/lib/jenkins/.aws
sudo touch /var/lib/jenkins/.aws/credentials
sudo echo "[default]" >> /var/lib/jenkins/.aws/credentials
sudo echo "aws_access_key_id=123456789" >> /var/lib/jenkins/.aws/credentials
sudo echo "aws_secret_access_key=123456789" >> /var/lib/jenkins/.aws/credentials

만약 jenkins 에서 aws cli 를 사용하는 경우 aws credential을 /var/lib/jenkins/.aws/credentials 에서 찾기 때문에 해당 파일에도 credentials 을 위치시켜야 한다.

jenkins 설정에서도 위의 Environment Variables 를 설정해 준다.

Jenkins node 가 ecr 을 사용할 수 있도록 다음 명령어를 실행한다.

1
$(aws ecr get-login --no-include-email)

만약 git repository 대신 AWS codecommit repository 를 사용한다면, 해당 key 를 AWS IAM user 탭에서 code commit http 설정을 할 수 있다.

Git configuration

Jenkins 가 git 을 사용하기 위해 다음과 같이 git 설정을 해준다.

1
2
3
4
5
6
cd ~jenkins

sudo -u jenkins git config --global credential.helper '!aws codecommit credential-helper $@'
sudo -u jenkins git config --global credential.useHttpPath true
sudo -u jenkins git config --global user.email "me@mycompany.com"
sudo -u jenkins git config --global user.name "MyjenkinsServer"

또한 jenkins 가 private repository 에 접근하려면, git credential 을 jenkins 에 등록해 주어야 하며 이는 jenkins configuration 의 credential 세팅에서 해줄 수 있다.

Jenkins migration guide

Jenkins 를 설치운영할때 Jenkins 서버를 migrate 할 필요성이 생길 수 있다.

Jenkin 의 모든 설정을 GUI 를 통해 했기 때문에, 모든 과정을 반복하는 것은 정말 성가신 일이 아닐 수 없다.

Jenkins 는 모든 설정을 파일 시스템에 저장하기 때문에, Jenkins directory 의 data 들만 잘 이동해 주면, 모든 설정 정보를 안전하고 편리하게 이관할 수 있으며, 그 위치는 /var/lib/jenkins 에 있다.

주의 사항

여기서 주의할 사항이 있는데, Jenkins directory 는 system directory 이므로 mv 명령이 제대로 수행되지 않는 경우가 있다.

때문에, 파일을 복사하기 앞서 directory 권한을 알맞게 변경해 주어야 한다. 또한, 복사한 파일의 user 와 group 이 linux user 로 변경되므로 반드시 복사 이후에 올바른 file owner 인 jenkins 로 변경해 주어야 하는데, 이는 다음의 명령어로 해결할 수 있다.

1
2
3
# jenkins:jenkins 사용자:그룹
# -R recursive
sudo chown -R jenkins:jenkins /var/lib/jenkins
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×