5.1 CI/CD 와 Jenkins.
CI/CD 소개
CI/CD 는 지속적 통합(Continuous Integration)과 지속적 배포(Continuous Deployment)를 의미하는 용어로, 소프트웨어 개발 과정을 자동화하여 개발의 효율성과 배포의 안정성을 극대화하는 접근법입니다. 이 과정에서 개발자는 코드 변경사항을 자동으로 통합, 테스트, 배포함으로써 소프트웨어의 질을 지속적으로 개선하고, 사용자에게 빠르게 새로운 기능을 제공할 수 있습니다.
CI/CD의 이론적 개념
CI/CD는 두 가지 개념으로 구분됩니다:
- Continuous Integration (CI) : 지속적인 통합
- 코드 변경사항을 주기적으로 리포지토리에 통합하는 과정입니다. 이 과정에 자동화된 테스트가 포함되어 있어 통합 과정에서 발생할 수 있는 문제를 즉시 발견하고 해결할 수 있습니다
- 주요 목적은 코드의 품질을 지속적으로 유지하고, 배포 가능한 상태를 유지하는 것입니다.
- Continuous Deployment or Delivery (CD) : 지속적인 배포 : 통합된 코드를 배포하는 과정을 자동화
- CI 과정을 통해 통합된 코드를 자동으로 스테이징 및 프로덕션 환경에 배포하는 단계입니다.
- 주요 목적은 언제든지 최신 버전의 소프트웨어를 사용자에게 안정적으로 제공할 수 있는 상태를 유지하는 것 입니다.
Jenkins
Jenkins는 자바로 작성된 오픈 소스 자동화 서버로, CI/CD 파이프라인을 구축 및 관리하는 데 널리 사용됩니다. 확장 가능한 플러그인 생태계를 통해 다양한 개발, 테스팅, 배포 도구와 통합할 수 있으며, 사용자의 요구에 맞게 파이프라인을 맞춤 설정할 수 있습니다. Jenkins의 유연성은 높은 자유도를 제공하지만, 초기 설정과 관리에는 상대적으로 높은 러닝 커브가 존재합니다.
사전 준비사항
- 기본적인 Git 지식 및 깃허브 계정
- Docker 기초 지식 및 Docker 계정
Jenkins 설치가이드
Jenkins 설치 및 실행
Docker 이미지를 이용한 Jenkins 설치를 Docker 통해서 진행하겠습니다. Docker 를 사용하는 이유는 Jenkins 의 복잡한 설치 과정을 단순화하기 위함입니다.
docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-v jenkins_home:/var/jenkins_home \
-p 8080:8080 \
-p 50000:50000 \
--name jenkins \
-u root \
jenkins/jenkins:lts
-v /var/run/docker.sock:/var/run/docker.sock
: jenkins 컨테이너에서 host 머신의 docker socket 을 사용하기 위한 설정입니다. Docker 컨테이너 안에서 Docker 를 사용하는데 설정이 복잡하여 Host 의 Docker Socket 을 사용하도록 설정합니다.-v jenkins_home:/var/jenkins_home
: jenkins 컨테이너의 데이터를 저장하기 위한 설정입니다. jenkins 컨테이너가 삭제되거나 재시작해도 데이터가 유지되도록 설정합니다.-u root
: jenkins 컨테이너를 root 권한으로 실행하기 위한 설정입니다. jenkins 컨테이너에서 host 의 Docker socket 을 사용하기 위해서는 root 권한이 필요합니다. 프로덕션 환경에서 권장하는 방법은 아닙니다만 간단하게 테스트하기에는 용이한 설정입니다.
localhost:8080 으로 접속하여 Jenkins 가 정상적으로 실행되었는지 확인한 후 비밀번호 설정이나 권장 Plugin 설정과 같은 초기설정을 진행합니다.
Jenkins 컨테이너 안에서 Docker 설치
Jenkins 안에서 docker image 를 빌드하기 위해서는 컨테이너 안에서 docker 를 설치해야합니다. Jenkins 컨테이너에 접속하여 docker 를 설치합니다. jenkins/jenkins 이미지는 debian 기반의 os 이기 때문에 docker 설치시 debian os 설치 가이드를 따릅니다.
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install sudo
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
## Verify that the installation is successful by running the hello-world image
sudo docker run hello-world
Jenkins Pipeline
Jenkins 에서 Pipeline 이란 Jenkins 가 수행해야할 프로세스의 지침이라고 생각하면 됩니다. 프로세스 지침은 코드 컴파일, 테스트 실행, 소프트웨어 배포와 같이 단계별로 수행할 작업을 설정합니다.
Pipeline 예시 및 구성요소
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'echo "Hello World"'
}
}
}
}
- pipeline : 파이프라인을 정의하는 블록입니다. 파이프라인의 전체 구조를 정의합니다.
- agent : jenkins pipeline 이 실행될 에이전트를 지정할 수 있습니다. 에이전트는 머신 또는 컨테이너 등이 될 수 있습니다.
- stages : 하나 이상의 stage 블록의 모음입니다. 각 stage는 파이프라인 프로세스의 구별되는 부분을 대표하며, 빌드, 테스트, 배포 등과 같은 작업을 의미합니다.
- stage : 파이프라인의 일부로 특정 작업을 수행하는 하나의 단계 또는 여러 단계의 그룹입니다.
- steps : 각 stage 내에는 실행할 실제 명령이나 스크립트를 정의하는 steps가 있습니다.
사전 준비
- plugins : 기본적으로 Jenkins 에서 파이프라인을 실행하기 위해서는 Jenkins 에서 사용할 수 있는 플러그인을 설치해야합니다. 초기 admin 페이지에 접근시 권장하는 플러그인을 설치한 경우 추가작업은 필요없습니다.
- Jenkins 어드민 페이지에 로그인 한 후
Manage Jenkins
->Plugins
->Available Plugins
에 접근하여 plugin 을 설치합니다. - 이 예제에서는 docker 를 사용해야하기 때문에
Docker Commons Plugin
와Docker Pipeline
플러그인을 설치합니다.
- Jenkins 어드민 페이지에 로그인 한 후
- docker hub credentials : docker hub 에 이미지를 푸시하기 위해서는 docker hub 에 로그인할 수 있는 credentials 가 필요합니다. Jenkins 에서 credentials 를 추가하는 방법은 다음과 같습니다.
- 개인 docker hub 에 로그인 한 후
My Account
->Security
->New Access Token
을 클릭하여 새로운 토큰을 생성하고 이 토큰을 반드시 안전한 곳에 보관합니다. - Jenkins 에 로그인 후
Dashboard
->Credentials
->System
->Global credentials
->Add Credentials
를 클릭합니다. Kind
를Username with password
로 선택하고,Username
에 docker hub 의 username 을Password
에 위에서 발급한 access token 을 입력합니다.ID
는 이 token 의 접근하기위한 식별자이며docker-hub-credentials
로 입력합니다.
- 개인 docker hub 에 로그인 한 후
- docker hub repository : docker hub 에 이미지를 푸시하기 위해서는 docker hub 에 이미지를 푸시할 수 있는 repository 가 필요합니다. 예제를 위해 public 한 repository 를 생성합니다.
Jenkins Pipeline 작성
Jenkins 에 Dashboard 에서 New Item
을 클릭하고, Pipeline
을 선택합니다. Pipeline 의 이름을 입력하고, OK
를 클릭합니다.
Pipeline 설정에서 가장 아래 섹션에서 script 를 아래와 같이 작성합니다.
pipeline {
agent any
environment {
IMAGE_NAME = '<docker-hub-username>/<docker-repository>'
GIT_REPO_URL = '<github-repository-url>'
DOCKER_REGISTRY = 'https://index.docker.io/v1/'
DOCKER_CREDENTIALS_ID = 'docker-hub-credentials'
}
stages {
stage('Clone repository') {
steps {
git url: GIT_REPO_URL
}
}
stage('Build Docker image') {
steps {
script {
docker.build( "${IMAGE_NAME}:${env.BUILD_NUMBER}")
}
}
}
stage('Push Docker image') {
steps {
script {
docker.withRegistry(DOCKER_REGISTRY, DOCKER_CREDENTIALS_ID) {
def dockerImage = docker.image(env.IMAGE_TAG)
dockerImage.push("latest")
dockerImage.push("${env.BUILD_NUMBER}")
}
}
}
}
}
}
각 Stage 에서는 Git, Docker Pipeline plugin 을 사용하여 docker image 를 빌드하고, docker hub 에 푸시하는 작업을 수행합니다.
각 Stage 설명
- Clone repository : Git plugin 을 사용하여 만들 이미지의 코드가 있는 repository 를 Clone 합니다.
- Build Docker image : Docker Pipeline plugin 을 이용하여 docker image 를 빌드합니다. 이 때 build 의 옵션값들을 설정할 수 있습니다.
- Push Docker image : Docker Pipeline plugin 을 이용하여 docker image 를 docker hub 에 푸시합니다. docker.withRegistry 의 블록 안에서는 로그인한 session 이 유지됩니다.
Pipeline 실행
Pipeline 을 실행하기 위해서는 Dashboard
-> 정의한 pipe-line
-> Build Now
를 클릭합니다. Pipeline 이 실행되면서 각 stage 들이 실행되는 것을 확인할 수 있습니다.
또한 각 스테이지별 진행 내역과 전체 pipeline log 또한 확인할 수 있습니다.
CI/CD 잘 구성하기
CI/CD 를 구현한다는 것은 단순히 Jenkins 를 설치하고 파이프라인을 작성하는 것이 아닙니다. CI/CD 를 잘 구성하기 위해서는 다음과 같은 사항을 고려해야합니다. CI/CD 는 개발팀의 문화와 프로세스를 지속적으로 발전시키는 변화이기 때문에, 이러한 변화를 잘 이끌어내기 위해서는 CI/CD 구성 목적과 평가를 잘 해야합니다.
명확한 목적을 설정하여 어떤 문제를 해결하고자 하는지, 어떤 결과를 얻고자 하는지를 명확히 설정해야합니다. 예를 들어 배포시간 단축, 버그 발생률 감소, 잦은 배포에도 안정적인 서비스 등을 목적으로 설정할 수 있습니다. 얻고자 하는 결과를 평가하기 위한 메트릭을 위해 KPIs 를 설정하여 목적을 달성했는지를 확인할 수 있어야합니다. 예를 들어 배포시간, 버그 발생률, 장애 복구시간, 배포 주기 등을 메트릭으로 설정할 수 있습니다.
결론
CI/CD 환경은 역동적으로 변화하고 있습니다. Jenkins 이외에도 GitHub Actions 과 같은 도구가 민첩하고 효율적으로 높은 품질의 소프트웨어 개발 관행을 촉진하는 데 앞장서고 있습니다. 전략적인 CI/CD 구현 사례를 채택하고 실제 구현 및 사례를 통해 개선시켜야할 뿐만 아니라 새로운 트렌드를 파악함으로써 CI/CD의 잠재력을 최대한 활용하여 더 고품질의 소프트웨어를 빠르게 제공할 수 있도록 해야합니다.