여기에 정리한 내용은 https://www.jenkins.io/doc/book/pipeline/syntax/ 를 기반으로 작성되었음을 알린다.
진한 글씨로 되어 있는 구문은 필수 구문, 연한 글씨는 사용 여부를 선택할 수 있는 구문이다.
위 사진에서 볼 수 있듯 "step"이라는 구문 안에는 DSL, 즉 Declarative Script 고유 문법의 문장이 들어가게 된다.
이 문법을 다 외워 DSL 문을 직접 생성하게 하는 것은 난이도가 너무 높고 활용성이 떨어진다. 따라서 Jenkins 측에서는 "Pipeline Syntax"라는 기능을 통해 원하는 Step 작업에 대한 DSL 문을 자동 생성해주는 기능을 제공한다.
이 Pipeline Syntax 기능에 대해서는 나중에 실습을 통해 알아보자.
pipeline{
# Insert Declarative Pipeline
}
Declarative Pipeline을 활용하기 위해선 반드시 "pipeline { }" 문구를 Script의 Top Level로 지정해야 한다.
Pipeline 내부는 Sections, Direcitves, Steps, Assignment 문으로만 구성되어야 한다.
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 값은 아래와 같다.
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 절차를 수행할 것임을 추측할 수 있다.
특정 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에 대해 알아보자
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
}
...
}
}
}
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 변수 값 출력
}
}
}
}
Pipeline 실행에 대한 Option을 설정할 수 있으며 필수는 아니고 Pipeline Block에 1번만 선언할 수 있다.
사용 방법이 꽤나 복잡하기 때문에 자세히 배우고 싶다면 아래 사이트에 들어가 사용 방법을 배워보도록 하자.
Pipeline이 실행되는 조건을 명시하는 것으로 사용 방법은 아래와 같다.
pipeline{
agent any
triggers {
[triggers option]
}
stages{
...
}
}
Triggers의 option에는 3가지가 존재한다.
사용자가 제공해야 할 변수를 명시하는 구문이다.
environment는 "개발자"가 변수를 정의하는 것이고 parameters는 "사용자"가 입력해야 할 변수를 정의한다는 점에 차이가 존재한다.
parameters 사용 방법은 아래와 같다.
parameters {
[parameters Option](name : [Parameter 변수명], defaultValue : [Parameter 기본 값],
description : [Parameter 설명])
# 단, choice는 사용 방법이 아래와 같이 다름
choice(name : [Choice 변수명], choices : [선택 값을 저장한 Option], description : [설명])
...
}
parameters Option은 아래와 같다.
이렇게 지정한 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}"
}
}
}
}