CI-CD

Jenkins Pipeline

Operation CWAL 2021. 3. 1. 18:14

What is Jenkins Pipeline

Jenkins에서 새로운 Job을 생성하거나 기존 설정을 변경하기 위해서, 대부분은 Web UI에서 매뉴얼 방식으로 작업한 경험이 있을 것이다. Job이 몇개 없고 설정도 단순하다면 큰 문제가 되지 않지만, 점차 구성이 복잡해지고 관리해야 할 Job이 늘어날 수록 이 방식은 적합하지 않다.. 예를 들어, 진행중인 프로젝트에 CI/CD 파이프라인을 적용한다고 하자. 동일한 소스 코드에 대해 빌드/테스트/배포 Job이 서로 분리되어 있으므로 설정도 따로 해야하고, 각 단계가 어떻게 진행되었는지 직관적인 파악이 어려운 경우가 있다.

 

Jenkins Pipeline은 프로젝트의 전체 파이프라인을 개발자가 직접 정의한 코드 형태(Pipeline as Code)로 받아 하나의 Job에서 이를 수행할 수 있는 강력한 기능을 제공한다. 파이프라인이 정의된 코드는 'Jenkinsfile'에 저장하는데 이를 프로젝트 소스코드가 있는 Repository에 같이 관리함으로써, 프로젝트 단위의 파이프라인 정의가 이루어진다. 또한 파이프라인의 변경 이력이 모두 commit으로 남기 때문에 추적 및 복구가 용이하다.

 

 

Jenkins와 플러그인에서 제공하는 기능은 DSL(Domain Specific Language)로 작성된 스크립트에서도 동일하게 사용 가능하며, Pipeline 관련 써드파티 플러그인을 추가로 설치하여 파이프라인 기능 확장이 가능하다. 또한 파이프라인의 각 단계별 상황과 빌드 로그를 실시간으로 확인할 수 있도록 시각화 기능이 존재한다.

 

 

2016년부터 Jenkins에 도입되었지만 아직은 기본으로 제공하는 기능이 아니므로,  Pipeline 플러그인을 추가로 설치해야 한다.

 

Pipeline 정의

가장 먼저 Pipeline Job을 생성해야 한다. 아래와 같이 Job 이름을 입력하고 'Pipeline'을 선택한다.

이번 실습은 Pipeline 사용에 대해서만 다루기 때문에 다른 설정은 변경하지 않고, 'Pipeline' 항목만 아래와 같이 추가하겠다. Repository는 GitHub에 공개해 두었으니 필요한 경우, 참고하기 바란다.

 

빌드를 시작하면 지정된 Repository의 main 브랜치로를 체크아웃 후, Jenkinsfile을 사용하여 파이프라인 작업을 수행할 수 있게 작업한 상태이다.

 

 

현재 Scripted Pipeline과 Declarative Pipeline 두가지 타입의 파이프라인 작성 방법이 존재한다. 두 방식 모두 Jenkinsfile에 Groovy Script로 작성해야하는 것은 동일하나, 아래와 같은 프로그래밍 모델 및 문법상의 차이점이 있다.

참고로 두 방식 중 하나를 선택해야 하여 Jenkins 파일을 작성해야 한다. 

Scripted Pipeline

Jenkins Pipeline에 가장 먼저 적용된 Imperative Programming Model이다. 사용자가 원하는 동작을 직접 구현하는 등의 응용이 가능하기 때문에 복잡한 요구사항에 대응하기 좋다. 하지만 Groovy 언어에 대한 이해가 선행되어야 하기 때문에 처음 접하는 경우, 어느 정도 학습이 필요하다.

 

예시

아래와 같은 Jenkinsfile을 작성해보자.

node {
    stage("Stage 1"){
        echo "Hello"
    }
    stage("Stage 2"){
        echo "World"
        sh "sleep 5"
    }
    stage("Stage 3"){
        echo "Good to see you!"
    }
}
  • node: 빌드를 수행할 node 또는 remote agent를 의미한다. node("label-abc") 방식으로 Label을 특정하여 node를 선택할 수 있다. 'node' 키워드가 최상단에 있는 경우, 해당 Jenkinsfile은 Scripted Pipeline 형식으로 작성되었음을 의미한다.
  • stage: 전체 파이프라인을 구성하는 각 단계(ex: Checkout, Build, Deploy 등)를 의미하며, Stage 안에서 다시 여러개의 Task가 수행된다.

위 Jenkinsfile을 바탕으로 Pipeline을 빌드하면 아래와 같은 Stage View를 확인할 수 있다.

#6의 빌드 로그를 확인해보자.

 

Declarative Pipeline

Groovy Script에 친숙하지 않은 사용자를 위해 최근에 도입된 Declarative Programming Model로, 상대적으로 작성이 쉽고 가독성이 높은 편이다. 사전에 정의된 Structure만 사용할 수 있기 때문에 CI/CD 파이프라인이 단순한 경우에 적합하며 아직은 많은 제약사항이 따른다. 현재 Jenkins Community에서 가장 지향하는 방식이며, 장점이 확실하기 때문에 사용법을 꼭 익혀두도록 하자.

 

예시

Scripted Pipeline에서 작성한 Jenkinsfile을 아래와 같이 다시 작성해보자.

pipeline {
    agent any
    stages {
        stage('Stage 1') {
            steps {
                script {
                    echo 'Hello'
                }
            }
        }

        stage('Stage 2') {
            steps {
                script {
                    echo 'World'
                    sh 'sleep 5'
                }
            }
        }

        stage('Stage 3') {
            steps {
                script {
                    echo 'Good to see you!'
                }
            }
        }
    }
}
  • pipeline: Scripted 방식과는 달리 'node' 대신 'pipeline' 키워드가 top에 위치하였다. 이를 Jenkinsfile이 declarative pipeline 방식으로 작성되었음을 Jenkins에게 알려줄 수 있다.
  • agent: 빌드를 수행할 node 및 remote agent를 의미한다. any로 지정시 빌드 가능한 모든 agent 중 하나를 선택하여 빌드를 맡긴다. label을 설정하여 빌드할 agent를 따로 선택 가능하다.
  • stages: 1개 이상의 stage를 포함한 블럭, 단 하나의 stages 블럭만 선언할 수 있다.
  • stage: scripted 방식의 stage와 동일한 개념이나, task가 아닌 steps로 구성된다.
  • steps: 하나의 stage에서 수행할 작업을 명시한 블럭

Declarative 방식으로 빌드한 결과는 어떤지 확인해보자.

Jenkinsfile에 선언하지 않은 'Checkout SCM' 스테이지가 추가되었다. Declarative 방식의 경우, 이 부분은 사용자가 따로 명시하지 않아도 자동으로 반영된다.

 

두 Jenkinsfile의 형태는 다르지만, 모두 동일한 동작을 한다.

마치며...

이 페이지는 Jenkins Pipeline의 기초적인 개념과 작성법에 대해서만 설명하였다. 당연한 소리겠지만 실사용되는 Jenkinsfile은 이보다 훨씬 복잡하게 구성되어 있다. 예를 들어 Checkout시 SCM 설정, Credential 가져오기, 병렬 수행, Container 기반 Agent 등의 내용은 이번 설명에선 생략하였으며, agent/stage와 같은 각 요소의 상하관계는 경우에 따라 다를 수 있다.

다만 이 글을 읽고 어느 정도 감이 잡혔다면 Jenkins에서 제공하는 공식 문서를 참고하길 바란다. 지금보다 훨씬 높은 수준의 CI/CD 파이프라인을 만들 수 있을 것이다.

'CI-CD' 카테고리의 다른 글

Jenkins - Approval Stage 구현  (0) 2021.03.05
Jenkins - Container 기반 Agent  (0) 2021.03.03
kustomize를 활용한 Manifest 관리  (0) 2021.02.24
CD를 위한 Jenkins, Argo CD 연계  (0) 2021.02.21
CI를 위한 Jenkins, GitHub, Docker Hub 연계  (0) 2021.02.20