Pipeline Syntax

Violet_Evgadn·2023년 4월 25일
0

CI&CD 자동화

목록 보기
22/28

여기에 정리한 내용은 https://www.jenkins.io/doc/book/pipeline/syntax/ 를 기반으로 작성되었음을 알린다.


그림으로 한눈에 보는 Pipeline Script 활용

위 사진에서 볼 수 있듯 "step"이라는 구문 안에는 DSL, 즉 Declarative Script 고유 문법의 문장이 들어가게 된다.

이 문법을 다 외워 DSL 문을 직접 생성하게 하는 것은 난이도가 너무 높고 활용성이 떨어진다. 따라서 Jenkins 측에서는 "Pipeline Syntax"라는 기능을 통해 원하는 Step 작업에 대한 DSL 문을 자동 생성해주는 기능을 제공한다.

이 Pipeline Syntax 기능에 대해서는 나중에 실습을 통해 알아보자.


Pipeline

pipeline{
	# Insert Declarative Pipeline
}

Declarative Pipeline을 활용하기 위해선 반드시 "pipeline { }" 문구를 Script의 Top Level로 지정해야 한다.

Pipeline 내부는 Sections, Direcitves, Steps, Assignment 문으로만 구성되어야 한다.


Section

agent

Jenkins는 Master-Slave Architecutre로 구성 가능하다.

Jenkins가 실제로 설치된 Server를 Master라고 지칭하고 CI/CD 과정은 별도의 Slave 서버에서 수행하도록 하는 것이다.

이렇게 Master-Slave로 구성을 하면 Master Server는 모든 CI/CD 절차를 담당하지 않아도 되기 때문에 부하를 줄일 수 있으며 Slave 서버는 Jenkins가 설치되어 있지 않더라도 Jenkins가 설치된 것과 같은 효과를 누리며 자동화된 CI/CD 절차를 처리할 수 있게 된다.

당연히 이 경우 Master와 Slave 사이에는 연동이 필요하며, 주로 SSH 방식을 활용한다.

이전에 ssh-keygen을 활용해 Server끼리 SSH 연동을 시킨 적이 있는데 같은 방식으로 Master-Slave Architecture를 만들 수 있다.

여기에서 뜬금없이 Master-Slave Architecture가 나온 것은 바로 실제로 CI/CD 절차를 수행하는 Slave Node 혹은 Master Node를 "agent"라고 하기 때문이다.

즉, agent Section은 Pipeline에 존재하는 실제 CI/CD 절차를 수행할 Node를 결정하는 것이다.

agent는 Script에 필수적인 Parameter로써 pipeline 내부 가장 상단에 기입하면 Global Agent, 즉 Pipeline 전체 절차를 수행하는 Agent로 지정할 수 있으며 stage 내부에 존재할 경우 Stage를 시행할 지역 Agent를 지정하는 것이다.

pipeline{
    agent [agent Parameter]
    stages{
        stage('Build') {
            agent [agent Parameter]
            ...
        }
    }
}

agent Parameter 값은 아래와 같다.

  • any : Pipeline이나 Stage를 실행할 수 있는 Agent 중 1개가 절차 수행
  • none : Global Agent 없이 모든 Stage마다 agent를 직접 지정해줘야 함
  • label : 지정한 Server Label을 통해 Pipeline 절차를 수행할 Agent를 지정함
  • docker : Docker Image를 통해 Agent 역할을 할 Container를 만들어 CI/CD 절차를 수행
  • dockerfile : Dockerfile을 통해 Image를 만들어 Agent 역할을 할 Container를 만든 뒤 CI/CD 절차 수행

agent none의 예시 코드를 보면 이해가 쉬울 것이다.

pipeline {
    agent none 
    stages {
        stage('Example Build') {
            agent { docker 'maven:3.8.1-adoptopenjdk-11' } 
            steps {
                echo 'Hello, Maven'
                sh 'mvn --version'
            }
        }
        stage('Example Test') {
            agent { docker 'openjdk:8-jre' } 
            steps {
                echo 'Hello, JDK'
                sh 'java -version'
            }
        }
    }
}

먼저 pipeline 가장 상단의 agent가 none이기 때문에 Pipeline 전체 과정을 수행할 Global Agent는 존재하지 않을 것이다.

Example Build stage를 수행할 agent는 "maven ~" Docker Image를 통해 만들어질 것이며 Example Test를 수행할 agent는 "openjdk ~" Docker Image를 통해 만들어진 뒤 CI/CD 절차를 수행할 것임을 추측할 수 있다.

post

특정 Stage나 Pipeline이 수행된 이후 실행되어야 할 동작을 명시하는 구문이다.

필수 구문은 아니며 stage Block 내부의 steps 뒤에 추가하거나 stages Block 뒤에 추가하여 활용한다.

post의 사용 방법은 아래와 같다.

post{
    [post Parameters]{
    	# post 과정에서 수행할 내용
    }
}

post 사용 예시를 보자.

pipeline {
    agent any
    stages {
        stage('Compile') {
            steps {
                echo "Compiled successfully!";
            }
            post{
                always{
                    echo "After Compile";
                }
            }
        }
        stage('test'){
            steps{
                echo "Test successfully!";
            }
        }
    }
    post{
        always{
            echo "Finish Pipeline!";
        }
    }
}

예측을 하자면 "Compiled successfully → After Compile → Test successfully → Finish Pipeline"이 출력될 것 같다.

빌드 결과를 보자.

그렇다면 post의 Parameter에 대해 알아보자

  • always : pipeline, stage 실행 완료 상태에 관계없이 명령을 실행함
  • changed : pipeline, stage 실행 완료 후 이전 상태와 달라진 부분이 존재할 경우 명령을 실행함
  • fixed : 직전에 실행했던 Pipeline이나 Stage 실패했거나 Unstable인 상황에서 현재 실행시킨 Pipeline이나 Stage가 성공했다면 명령을 실행함
  • regression : 직전에 실행했던 Pipeline이나 Stage가 성공했지만 현재 실행시킨 pipeline이나 Stage가 실패하거나 Unstable일 경우 명령을 실행함
  • aborted : pipeline, stage 실행이 강제로 중지되었을 때 실행함
  • failure : pipeline, stage 실행이 실패하였을 경우 실행함
  • success : pipeline, stage 실행이 성공하였을 경우 실행함
  • unsuccessful : pipeline, stage 실행이 성공 상태가 아닌 경우 실행함
  • unstable : pipeline, stage 실행이 uunstable 상태일 경우 실행
    • Unstable : Build 과정 자체는 성공했지만 Build 외적인 부분에서 문제가 생겼을 경우 실행함
  • cleanup : pipeline, stage 실행 상태에 관계 없이 Post section 내부 작업이 모두 종료되었을 때 실행

stages & steps

Stages란 pipeline Block에서 단 한 번만 사용될 수 있는 구문으로 필수 요소이다.

Stages 내부에는 여러 stage가 포함될 수 있어 Pipeline에서 수행할 CI/CD 절차를 모두 포함하는 Section이다.

Stages 내부에는 여러개의 Stage가 존재하며, 1개의 Stage에는 여러 개의 steps가 존재한다.

Stages, Stage, Steps의 사이는 Jenkins의 Ansible의 Playbook, Play, Tasks와 비슷하다.

Stages는 Ansible의 Playbook과 유사한 역할로써 CI/CD 절차에서 수행되어야 할 내용 전체를 기록한 장소이다.

Stage는 Ansible의 Play와 유사한 역할이다. CI/CD 전체 절차는 여러 개의 작은 절차로 나뉠 것이다. 예를 들어 Build, Test, Compile, Deploy 과정으로 나뉠 수 있을 것이다.

이때 나눠진 각 단계를 Stage로 처리하는 것이다.

Stage에 어떤 작업이 수행되어야 할지를 명시했다면 실제 Stage 절차를 어떻게 수행시켜야 할지를 알려야 한다.

Ansible의 Play 절차를 처리하기 위해 Tasks를 활용했던 것처럼 Pipeline Script의 Stage를 처리하기 위해 Steps를 활용하게 되는 것이다.

사용 방법은 아래와 같다.

pipeline {
    agent any
    stages {
        stage([Stage에서 수행할 내용]) {
            steps {
                # Stage 처리를 위한 명령
            }
            steps {
            	# Stage 처리를 위한 명령 2
            }
            ...
        }
    }
}

Directives(파이프라인 Configure)

environment

key-value Style을 통해 파이프라인 내부에서 사용할 수 있는 변수 선언을 위한 구문이다.

Top level에 설정하면 Pipeline 내부 어디서든 활용할 수 있는 전역 변수이며 stage 내부에 설정하면 stage 내에서만 활용할 수 있는 지역 변수 역할을 할 수 있다.

Key-Value로 지정한 변수는 $[Key] 방식으로 Value 값을 활용할 수 있다.

사용 예시는 아래와 같다.

pipeline {
    agent any
    environment { 
        CC = 'clang'
    }
    stages {
        stage('Example') {
            environment { 
                AN_ACCESS_KEY = credentials('my-prefined-secret-text') 
            }
            steps {
                sh 'echo "$CC"' # CC 변수 값 출력
                sh 'echo "$AN_ACCESS_KEY"' # AN_ACCESS_KEY 변수 값 출력
            }
        }
    }
}

options

Pipeline 실행에 대한 Option을 설정할 수 있으며 필수는 아니고 Pipeline Block에 1번만 선언할 수 있다.

사용 방법이 꽤나 복잡하기 때문에 자세히 배우고 싶다면 아래 사이트에 들어가 사용 방법을 배워보도록 하자.

Pipeline Syntax

triggers

Pipeline이 실행되는 조건을 명시하는 것으로 사용 방법은 아래와 같다.

pipeline{
    agent any
    triggers {
        [triggers option]
    }
    stages{
    	...
    }
}

Triggers의 option에는 3가지가 존재한다.

  • cron : Cron Scheduling을 통해 Pipeline을 실행시키는 시간대를 결정
    • 사용 방법 : cron([Cron Syntax])
  • pollSCM : Cron Scheduling을 통해 특정 시간마다 Git에 Commit이 발생되었는지를 확인 후 Commit 발생 시 Pipline 실행
    • 이전에 배웠던 Poll SCM과 동일함
    • 사용 방법 : pollSCM([Cron Syntax])
  • upstream : 문자열로 기입된 여러 작업 중 Threshold로 기입한 작업 상태를 충족시킨다면 Pipline이 실행됨
    • 사용 방법 : upstream(upstreamProjects : 'job1, job2', threshold: hudson.model.Result.SUCCESS)
      • upstreamProjects : 작업 개수에 제한 없이 쉼표 구분자(,)를 통해 여러 개 입력 가능
      • threshold : 미리 정해진 Threshold값이 있어 그중 하나를 입력해 등록된 작업의 상태를 확인

parameters

사용자가 제공해야 할 변수를 명시하는 구문이다.

environment는 "개발자"가 변수를 정의하는 것이고 parameters는 "사용자"가 입력해야 할 변수를 정의한다는 점에 차이가 존재한다.

parameters 사용 방법은 아래와 같다.

parameters {
	[parameters Option](name : [Parameter 변수명], defaultValue : [Parameter 기본 값], 
    									description : [Parameter 설명])
                                        
    # 단, choice는 사용 방법이 아래와 같이 다름
 	choice(name : [Choice 변수명], choices : [선택 값을 저장한 Option], description : [설명])   
	...
}

parameters Option은 아래와 같다.

  • string : 단일 Line 문자열
  • text : Multiple Line까지 처리 가능한 문자열
  • booleanParam : Boolean 자료형
  • choice : Array 자료형 중 1개의 값을 선택할 수 있음
  • password

이렇게 지정한 Parameter는 ${params.[Parameter 변수명]} 형식으로 값을 활용할 수 있다.

사용 예시를 보자.

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}"
            }
        }
    }
}
profile
혹시 틀린 내용이 있다면 언제든 말씀해주세요!

0개의 댓글