티스토리 뷰

728x170

본 포스팅에서는 Jenkins 파이프라인을 활용하여 자동 빌드 환경을 구성해 보도록 하겠습니다.

파일프라인이란 말 그대로 파이프를 이어 붙인것과 같은 형태로 Step by Step 형식의 각 단계를 이어 붙여 실행하는 방식입니다.

이를 적용하면, Continuous Delivery & Continuous Deploy 손쉽게 구현할 수 있습니다.

최신 버전의 jenkins를 설치할 경우 Pipeline이 Plug-In으로 등록되어 있습니다.

설치되어 있지 않은 Jenkins를 운영 중이라면, Pipeline plugin (https://plugins.jenkins.io/workflow-aggregator)을 설치해야 합니다.

보다 상세한 Jenkins 관리를 원한다면 다음 url (https://jenkins.io/doc/book/managing/plugins/)을 참고하시기 바랍니다.

아래 내용은 Jenkins 메뉴얼의 주요 항목을 추려 작성하였습니다.

1. Jenkins 파이프라인 정의

Jenkins 파이프라인은 여러 방식으로 구현이 가능합니다.

- Jenkins Webadmin : 일반적인 방식으로 Jenkins 파이프라인을 생성하여 Shell Script를 직접 생성하여 빌드하는 방식

- Git SCM : Git Repository에 JenkinsFile을 작성하여 빌드하는 방식

- Blue Ocean : 파이프라인을 시각화하여 손쉽게 구성하여 빌드하는 방식

2. Jenkins 파이프라인 Script 문법 정의

1) Pipeline

1
2
3
pipeline {
    /* insert Declarative Pipeline here */
}

- 파이프라인을 정의하기 위해서는 반드시 pipeline을 포함해야 합니다.

- pipeline은 최상위 레벨이 되어야하며, { }으로 정의해야 합니다.

- pipeline은 Section, Directives, Steps 또는 assignment 문으로만 구성되야 합니다.

 

2) Section

a. agent : agent를 추가할 경우 Jenkins는 해당 agent를 설정합니다.

- any, none, label, node, docker, dockerfile, kubernetes를 파라미터로 포함할 수 있습니다.

- agent는 pipeline의 최상위에 포함되어야 하며, agent가 none으로 작성되었을 경우 stage에 포함되어야 합니다.

ex) docker

1
2
3
4
5
6
7
8
agent {
    docker {
        image 'myregistry.com/node'
        label 'my-defined-label'
        registryUrl 'https://myregistry.com/'
        registryCredentialsId 'myPredefinedCredentialsInJenkins'
    }
}

ex) dockerfile

1
2
3
4
5
6
7
8
9
agent {
    dockerfile {
        filename 'Dockerfile.build'
        dir 'build'
        label 'my-defined-label'
        registryUrl 'https://myregistry.com/'
        registryCredentialsId 'myPredefinedCredentialsInJenkins'
    }
}

ex) agent가 적용 된 JenkinsFile Sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
pipeline {
    agent none 
    stages {
        stage('Example Build') {
            agent { docker 'maven:3-alpine' }
            steps {
                echo 'Hello, Maven'
                sh 'mvn --version'
            }
        }
        stage('Example Test') {
            agent { docker 'openjdk:8-jre' }
            steps {
                echo 'Hello, JDK'
                sh 'java -version'
            }
        }
    }
}

- agent none이 pipeline의 최상위에 정의되어 있을 경우 stage는 각각 agent를 포함하여야 합니다.

- 이 JenkinsFile Sample을 통해 새로 작성된 컨테이너의 pipeline을 정의는데 유용히 사용할 수 있습니다.

 

b. post : 특정 stage나 pipeline이 시작되기 이전 또는 이후에 실행 될 confition block을 정의합니다.

- always, changed, fixed, regression, aborted, failure, success, unstable, unsuccessful,와 cleanup 등의 상태를 정의할 수 있습니다.

- 일반적으로 post는 pipeline의 끝에 배치합니다.

ex) post가 적용 된 JenkinsFile Sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
    post { 
        always { 
            echo 'I will always say Hello again!'
        }
    }
}

 

c. stages : 하나 이상의 stage에 대한 모음을 정의합니다.

- pipeline 블록 안에서 한번만 실행 될 수 있습니다.

- stages 내부에서는 여러 stage를 포함할 수 있습니다.

d. steps : stage 내부에서 실행되는 단계를 정의합니다.

ex) stages와 steps가 적용 된 JenkinsFile Sample

1
2
3
4
5
6
7
8
9
10
pipeline {
    agent any
    stages { 
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

 

3) Directives

a. environment : key-value 형태로 파이프라인 내부에서 사용할 환경 변수로 선언할 수 있습니다.

ex) environment가 적용 된 JenkinsFile Sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pipeline {
    agent any
    environment { 
        CC = 'clang'
    }
    stages {
        stage('Example') {
            environment { 
                AN_ACCESS_KEY = credentials('my-prefined-secret-text') 
            }
            steps {
                sh 'printenv'
            }
        }
    }
}

- environment 최상위에 정의할 경우 pipeline 모든 단계에 환경 변수가 적용됩니다.

- stage 내부에 정의한 환경 변수는 해당 stage에서만 유효합니다.

 

b. options : pipeline의 옵션을 선택적으로 포함 시킬 수 있습니다.

- options는 pipeline에서 한번만 정의 할 수 있습니다.

- buildDiscarder
특정 수의 최근 파이프 라인 실행에 대한 아티팩트 및 콘솔 출력을 유지하십시오.

예를 들면 다음과 같습니다.

options { buildDiscarder(logRotator(numToKeepStr: '1')) }
- checkoutToSubdirectory
작업 공간의 서브 디렉토리에서 자동 소스 제어 체크 아웃을 수행하십시오.

예를 들면 다음과 같습니다.

options { checkoutToSubdirectory('foo') }
- disableConcurrentBuilds
파이프 라인의 동시 실행을 허용하지 않습니다. 공유 리소스 등에 대한 동시 액세스를 방지하는 데 유용 할 수 있습니다.

예를 들면 다음과 같습니다.

options { disableConcurrentBuilds() }
- disableResume
마스터가 다시 시작되면 파이프 라인을 다시 시작하지 마십시오.

예를 들면 다음과 같습니다.

options { disableResume() }
- newContainerPerStage
함께 사용 docker 또는 dockerfile로 지정된 경우 각 스테이지는 동일한 컨테이너 인스턴스에서 실행되는 모든 스테이지가 아니라 동일한 노드의 새 컨테이너 인스턴스에서 실행됩니다.
- overrideIndexTriggers
분기 인덱싱 트리거의 기본 처리를 재정의 할 수 있습니다.

멀티 브랜치 또는 조직 레이블에서 분기 인덱싱 트리거가 비활성화 된 options { overrideIndexTriggers(true) } 경우에 대해서만 활성화됩니다.

그렇지 않으면 options { overrideIndexTriggers(false) }이 작업에 대해서만 분기 인덱싱 트리거를 비활성화합니다.
- preserveStashes
스테이지를 다시 시작할 때 사용할 수 있도록 완료된 빌드에서 숨김을 유지하십시오.

예를 들어 options { preserveStashes() }

가장 최근에 완료된 빌드 options { preserveStashes(buildCount: 5) }에서 stash를 보존 하거나 가장 최근에 완료된 5 개의 빌드에서 stash를 보존합니다.
- quietPeriod
파이프 라인에 대한 자동 기간을 초 단위로 설정하여 글로벌 기본값을 대체하십시오.

예를 들면 다음과 같습니다.

options { quietPeriod(30) }
- retry
실패하면 전체 파이프 라인을 지정된 횟수만큼 재 시도하십시오.

예를 들면 다음과 같습니다.

options { retry(3) }
- skipDefaultCheckout
agent 지시문에서 기본적으로 소스 제어에서 코드 체크 아웃을 건너 뜁니다.

예를 들면 다음과 같습니다.

options { skipDefaultCheckout() }
- skipStagesAfterUnstable
빌드 상태가 불안정 해지면 단계를 건너 뜁니다.

예를 들면 다음과 같습니다.

options { skipStagesAfterUnstable() }
- timeout
Jenkins가 파이프 라인을 중단한 후 파이프 라인 실행에 대한 제한 시간을 설정하십시오.

예를 들면 다음과 같습니다.

options { timeout(time: 1, unit: 'HOURS') }
- timestamps
파이프라인 실행에서 생성된 모든 콘솔 출력 앞에 라인이 생성 된 시간을 추가하십시오.

예를 들면 다음과 같습니다.

options { timestamps() }
- parallelsAlwaysFailFast
파이프 라인의 모든 후속 병렬 단계에 대해 failfast를 true로 설정하십시오.

예를 들면 다음과 같습니다.

options { parallelsAlwaysFailFast() }

ex) options가 적용 된 JenkinsFile Sample

1
2
3
4
5
6
7
8
9
10
11
12
13
pipeline {
    agent any
    options {
        timeout(time: 1, unit: 'HOURS') 
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

- 위와 같이 설정할 경우 Jenkins가 파이프라인 실행을 중단 한 후 1시간의 timeout을 설정합니다.

 

c. parameters : 사용자가 제공해야할 변수에 대해 선언할 수 있습니다.

- string, text, booleanParam, choice, password 등을 정의할 수 있습니다.

- parameters는 pipeline에서 한번만 정의할 수 있습니다.

ex) parameters가 적용 된 JenkinsFile Sample

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
28
29
pipeline {
    agent any
    parameters {
        string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
 
        text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')
 
        booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')
 
        choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
 
        password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
    }
    stages {
        stage('Example') {
            steps {
                echo "Hello ${params.PERSON}"
 
                echo "Biography: ${params.BIOGRAPHY}"
 
                echo "Toggle: ${params.TOGGLE}"
 
                echo "Choice: ${params.CHOICE}"
 
                echo "Password: ${params.PASSWORD}"
            }
        }
    }
}

 

d. triggers : 파이프라인을 다시 트리거해야 하는 자동화된 방법을 정의합니다.

- cron, pollSCM, upstream 등 여러 방식으로 트리거를 구성할 수 있습니다.

ex) triggers가 적용 된 JenkinsFile Sample

1
2
3
4
5
6
7
8
9
10
11
12
13
pipeline {
    agent any
    triggers {
        cron('H */4 * * 1-5')
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

 

e. tools : 설치 도구를 정의합니다.

- agent none으로 지정된 경우 무시됩니다.

- 지원되는 도구는 maven, jdk, gradle이 있습니다.

ex) tools가 적용 된 JenkinsFile Sample

1
2
3
4
5
6
7
8
9
10
11
12
13
pipeline {
    agent any
    tools {
        maven 'apache-maven-3.0.1' 
    }
    stages {
        stage('Example') {
            steps {
                sh 'mvn --version'
            }
        }
    }
}

- tools 이름은 Jenkins 관리의 Global Tool Configuration에서 사전 정의되어 있어야 합니다.

 

f. input : input 지시문을 stage에 사용하면 input 단계를 사용하여 입력하라는 메시지를 표시할 수 있습니다.
- 사용 가능한 옵션으로는 message, id, ok, submitter, submitterParameter, parameters가 있습니다.
ex) input이 적용 된 JenkinsFile Sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
pipeline {
    agent any
    stages {
        stage('Example') {
            input {
                message "Should we continue?"
                ok "Yes, we should."
                submitter "alice,bob"
                parameters {
                    string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
                }
            }
            steps {
                echo "Hello, ${PERSON}, nice to meet you."
            }
        }
    }
}

3. Jenkins 파이프라인의 실행

Jenkins 파이프라인은 순차적 실행과 평행 실행으로 나눌 수 있습니다.

ex) 순차적 실행 예제

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
pipeline {
    agent none
    stages {
        stage('Non-Sequential Stage') {
            agent {
                label 'for-non-sequential'
            }
            steps {
                echo "On Non-Sequential Stage"
            }
        }
        stage('Sequential') {
            agent {
                label 'for-sequential'
            }
            environment {
                FOR_SEQUENTIAL = "some-value"
            }
            stages {
                stage('In Sequential 1') {
                    steps {
                        echo "In Sequential 1"
                    }
                }
                stage('In Sequential 2') {
                    steps {
                        echo "In Sequential 2"
                    }
                }
                stage('Parallel In Sequential') {
                    parallel {
                        stage('In Parallel 1') {
                            steps {
                                echo "In Parallel 1"
                            }
                        }
                        stage('In Parallel 2') {
                            steps {
                                echo "In Parallel 2"
                            }
                        }
                    }
                }
            }
        }
    }
}
 

ex) 평행 실행 예제

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
pipeline {
    agent any
    stages {
        stage('Non-Parallel Stage') {
            steps {
                echo 'This stage will be executed first.'
            }
        }
        stage('Parallel Stage') {
            when {
                branch 'master'
            }
            failFast true
            parallel {
                stage('Branch A') {
                    agent {
                        label "for-branch-a"
                    }
                    steps {
                        echo "On Branch A"
                    }
                }
                stage('Branch B') {
                    agent {
                        label "for-branch-b"
                    }
                    steps {
                        echo "On Branch B"
                    }
                }
                stage('Branch C') {
                    agent {
                        label "for-branch-c"
                    }
                    stages {
                        stage('Nested 1') {
                            steps {
                                echo "In stage Nested 1 within Branch C"
                            }
                        }
                        stage('Nested 2') {
                            steps {
                                echo "In stage Nested 2 within Branch C"
                            }
                        }
                    }
                }
            }
        }
    }
}

이와 같은 Jenkins Pipeline Syntax를 적절히 활용하여 작성한다면, 보다 효과적이고 빠르면서도 다양한 검증 형태를 거칠 수 있지 않을까 생각합니다.

그리드형
댓글
댓글쓰기 폼