We are Architect

젠킨스로 배우는 CICD 파이프라인: 젠킨스 파이프라인 이해(16) 본문

CI & CD/Jenkins

젠킨스로 배우는 CICD 파이프라인: 젠킨스 파이프라인 이해(16)

the best infra 2024. 12. 30. 01:02

 

현재 글의 대한 실습은 컨테이너를 사용하여 젠킨스 서버 및 여러 서버들을 가동시킬 것이다.

 

 

* 젠킨스 파이프 라인 

  • 사실 파이프 라인을 구현 하려고 젠킨스를 공부해 온 나로서 여기까지 오는 게 쉽지 않았다. 그래서 한번 열심히 해보고자 한다.
  • 젠킨스 파이프 라인은 젠킨스를 사용해 코드를 통합하고 배포하기 위해 사용하는 플러그인 스크립트 모음이다.
  • 좀 더 자세히 이야기 하면 버전 제어 시스템에서 가져온 코드를 애플리케이션으로 만들어 고객과 사용자에게 전달할 때까지의 프로세스를 자동으로 실행할 수 있도록 코드로 작성한 표현식이다.
  • 애플리케이션에서 수행하는 모든 변경 사항은 최종 릴리스가 되기까지 복잡한 빌드 프로세스를 거친다.
  • 코드를 사용하기 위해서는 API가 필요하고 여러가지의 함수 또한 필요하다.

 

* 파이프라인의 장점

  • 코드 부분
    • 애플리케이션의 CI/CD 프로세스를 코드 형식으로 작성할 수 있고, 애플리케이션의 소스 코드와 함께 코드 리포지터리에 저장할 수 있다. 빌드 프로세스를 기술하는 코드가 중앙 리포지터리에 저장되면 효과적으로 팀원들과 공유할 수 있다.
  • 내구성 부분
    • 파이프라인은 젠킨스 서비스가 의도적으로 또는 우발적으로 재시작되더라도 문제 없이 유지된다.
  • 일시 중지 기능
    • 파이프라인을 실행하는 도중 사람의 승인이나 입력을 기다리기 위해 중단하거나 기다리는 것이 가능.
  • 다양성 부분
    • 분기나 반복, 병렬 처리와 같은 다양한 CI/CD 요구 사항을 지원한다.
  • 확장성 부분
    • 파이프라인 플러그인은 다른 플러그인과의 통합에 필요한 여러 가지 기능을 지원하기 때문에 쉽게 확장할 수 있다.

 

 

* 파이프라인 용어 이해

  • 파이프라인 : 전페 빌드 프로세스를 정의하는 코드를 의미한다. 빌드 프로세스는 애플리케이션의 빌드, 테스트, 배포와 관련된 여러 단계로 구성된다.
  • 노드 : 노드는 파이프라인을 실행하는 시스템이다.
  • 스테이지 : 소프트웨어는 빌드, 테스트, 배포 등과 같은 빌드 프로세스를  처리하는 다양한 단계를 거치는데 스테이지 블록에서는 특정 단계에서 수행되는 작업들을 정의한다.
  • 스텝 : 파이프라인의 특정 단계에서 수행되는 단일 작업을 의미한다. 스테이지 블록은 여러 개의 스텝으로 구성된 블록일 뿐이다.

 

 

* 파이프 라인 구문

  • 선언형 파이프라인 기초 : 
    • 전체 블록 프로세스가 파이프라인 블록 안에서 정의된다.
    •  
pipline
{
	agent any // 이 파이프라인은 젠킨스의 모든 에이전트에서 실행 할 수 있음.
    stages
    {
    	stage('build') // Build 스테이지 블록을 정의
        {
        	steps
            {
            	// Build 스테이지와 관련된 특정 스텝을 정의
            }
        }
        stage('Test') // Test 스테이지 블록을 정의
        {
        	steps
            {
            	// Test 스테이지와 관련된 특정 스텝을 정의
            }
        }
        stage('Deploy')// Deploy 스테이지 블록을 정의
        {
        	steps
            {
            	// Deploy 스테이지와 관련된 특정 스텝을 정의
            }
        }
    } //stages 블록 끝
}// pipline 블록 끝

 

  • 스크립트형 파이프라인 기초 : 
    • 전체 빌드 프로세스가 노드 블록 안에서 정의.
    • 노드블록 안에 코드를 반드시 포함시킬 필요는 없으나, 코드가 포함된 경우에는 다음과 같은 작업이 수행된다. 
      • 젠킨스 큐에 아이템을 추가해 노드 블록 안에 스텝이 실행될 수 있도록 예약한다. 노드의 실행기를 사용할 수 있는 상태가 되면 즉시 스탭이 실행된다.
        • 젠킨스 큐 : 젠킨스 큐는 병렬 작업을 관리하며, 여러 작업이 동시에 실행되도록 처리
      • 소스 관리 시스템에서 파일을 체크아웃하고, 작업할 수 있는 워크스페이스용 디렉터리를 생성한다.
node
{ // 이 파이프라인은 젠킨스에서 사용 가능한 모든 에이전트에서 실행할 수 있다는 의미.
  // 사용하면 UI에서 각 스테이지의 태스크를 시각적으로 확인가능.
	stage('Build') // 빌드 스테이지 블록을 정의. 
    {
    	// 빌드 스테이지와 관련된 특정 스텝을 정의.
    }
    stage('Test') // Test 스테이지 블록을 정의.
    {
    	// Test 스테이지와 관련된 특정 스텝을 정의.
    }
    stage('Deploy') // Deploy 스테이지 블록을 정의.
    {
    	// Deploy 스테이지와 관련된 특정 스텝을 정의.
    }
}

 

 

* 실습하기 전 실습 환경 세팅

  • 우선은 해당 과정을 컨테이너를 실행해서 해볼 것이며 이를 위해서 젠킨스 서버, 넥서스 리포지터리 서버를 docker compose 파일로 실행시킬 것이다.
  • 해당 파일이 존재하는 디렉터리에서 docker-compose up 실행.(도커가 잘 깔리고 환경변수 설정이 되어있어야 함.)
  • 그 외에 필요한 요소들은 복습 차원에서 다시 플러그인이나 자격증명 등을 설치하고 등록해야 한다.
version: '3.8'
services:
  jenkins:
    image: jenkins/jenkins:lts
    container_name: jenkins
    ports:
      - "8060:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
    environment:
      JAVA_OPTS: "-Djenkins.install.runSetupWizard=false"
    networks:
      - ci_network

  nexus:
    image: sonatype/nexus3
    container_name: nexus
    ports:
      - "8081:8081"
    volumes:
      - nexus_data:/nexus-data
    networks:
      - ci_network

volumes:
  jenkins_home:
  nexus_data:

networks:
  ci_network:

 

 

* 파이프라인 만들어보기

  • 파이프 라인 생성
    • 새로운 item에서 해당 파이프라인 생성하고.
    • 다음과 같이 설정.
  • 파이프라인 속도/내구성 오버라이드(이번 실습에서는 하지않음.)
    • 기본적으로 파이프라인 작업을 실행할 때는 많은 데이터를 디스크에 기록하여 문제가 생겨도 바로 재실행할 수 있도록 하는데 이는 파이프라인의 실행 속도를 느리게 한다. 
    • 그래서 pipline speed/durabilty override를 설정하면 문제를 해결할 수 있다.
      • performace-opmtimized : much faster (requires clean shutdown to save running piplines) : 성능에만 최적화된 가장 빠른 설정이다. 이 옵션을 선택하면 젠킨스 파이프라인은 꼭 필요한 데이터만 기록한다.
      • Less duarility, a bit faster (specialty use only) : 내구성은 낮고, 약간 빠른 설정이다.
      • Maximun duraility but slowest : 내구성은 최대이거나, 가장 느린 설정.
  • 파이프라인 코드 작성
    • 아주 간단한 코드를 작성해 보자. 작성하고 실행 아이콘을 클릭해 보자.
      오타가 안나게 조심하자.
    • 작업이 완료되었는지 확인하자
      • 콘솔 output에서 확인할 수 있다.
        Hello world가 제대로 출력된 모습

* 젠킨스 파이프라인의 문자열 보간 이해

  • 문자열 보간은 변수의 값을 문자열에 있는 변수로 변경하는 방법이다.
  • 변수 처리하여 해당 내용을 집어넣어서 출력이나 사용할 수 있다.
# 예제1
def Username = 'LJH'
echo 'Hello, ${Username}'

# 예제2
${젠킨스가 설치된 URL}/pipeline-syntax/global#env

# 코드에 응용
pipeline
{
	agent any
    stages
    {
    	stage('Example')
        {
        	steps
            {
            	echo "Running ${env.BUILD_ID} on
                ${env.JENKINS_URL}"
            }
        }
    }
}

 

 

* 아티팩트까지 넥서스에 저장하는 파이프라인 만들기

  • 이번에는 git push(코드 푸쉬) -> gitlab code upload(깃랩 저장소에 업로드) -> jenkins maven build(젠킨스가 코드 빌드) -> save articfacts in Nexus Repo(아티팩트 산출물 넥서스 리포지터리에 저장) 까지 하는 파이프라인을 구성해 보았다.
  • 우선 새로운 파이프라인 작업을 만든다.


  • Scripted Pipline 누르고 다음과 같이 코드를 넣어 준다.
    • 이때 트리거 설정도 해준다.
      pipeline {
          agent any
          tools {
              maven 'StudyForPipline' // Maven 사용
          }
          environment {
              // Nexus Repository URL
              NEXUS_REPOSITORY_URL = 'http://nexus:8081/repository/maven-releases/'
          }
          triggers {
              gitlab(triggerOnPush: true, triggerOnMergeRequest: true) // GitLab Webhook 트리거
          }
          stages {
              stage('Checkout Code') {
                  steps {
                      checkout([
                          $class: 'GitSCM',
                          branches: [[name: '*/Master']], // 올바른 브랜치 이름
                          userRemoteConfigs: [[
                              url: 'https://gitlab.com/ljh_world/jenkinsbookcalulatorapi.git', // GitLab Repository URL
                              credentialsId: 'GitLabInfo' // Jenkins에 저장된 GitLab 인증 정보 ID
                          ]]
                      ])
                  }
              }
              stage('Build') {
                  steps {
                      script {
                          sh 'pwd && ls -l'
                          def mvnHome = tool name: 'StudyForPipline', type: 'maven'
                          // pom.xml이 위치한 디렉터리로 이동
                          dir('test_folder/maven-nexus-example') {
                              sh "${mvnHome}/bin/mvn clean package"
                          }
                      }
                  }
              }
              stage('Deploy to Nexus') {
                  steps {
                      script {
                          def mvnHome = tool name: 'StudyForPipline', type: 'maven'
                          // pom.xml이 위치한 디렉터리로 이동
                          dir('test_folder/maven-nexus-example') {
                              sh "${mvnHome}/bin/mvn deploy"
                          }
                      }
                  }
              }
          }
          post {
              success {
                  echo 'Build and Deploy completed successfully!'
              }
              failure {
                  echo 'Build or Deploy failed. Please check logs.'
              }
          }
      }

       
      트리거 설정(웹 훅 요청)
  • 컨테이너에 maven이 잘 설치되어 있는지 확인하기 
    • 실습을 하다가 굉장히 많이 애를 먹었다. 컨테이너 안에 /var/jenkins_home/tools/ 안에 maven 관련 파일들이 없었다. 
    • 그래서 젠킨스에서 플러그 인을 다운로드하여 줬더니 실행이 가능해졌다.
    • Pipeline Maven Integration Plugin : tools 섹션을 통해 Maven 도구 명시적 지정

Pipeline Maven Integration Plugin 만 다운로드

 

 

 

  • 혹시 모르니 빌드와 넥서스 리포지터리에서 스테이지가 실패하면 참고해라.
    • Git Lab의 pom.xml 파일을 수정할 것.
      • 젠킨스에서 pom.xml 파일을 가지고 빌드를 실행한다. 만약에 없다면 해당 코드를 참고해라.
        • 실제로 실습할 때 사용했던 코드이다. 물론 상황에 맞게 수정을 해야 한다. 
    • 컨테이너라면 /var/jenkins_home/tools/ 안에 maven 관련 파일 중 setting.xml 파일을 수정하여 넥서스 리포지터리에 로그인할 수 있도록 정보 설정하기.
// 샘플 pom.xml 형식이다. 잘 참고해서 수정해야 한다.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>JenkinsCalculatorAPI</artifactId>
    <version>2.0.0</version>
    <packaging>jar</packaging>
    <name>Maven Nexus Example</name>
    <url>https://example.com</url>

    <dependencies>
        <!-- JUnit for testing -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <!-- Apache Commons Lang -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Compiler Plugin for Java 17 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <distributionManagement>
        <repository>
            <id>ljhNexusRepo</id>
            <url>http://nexus:8081/repository/Jenkins-Maven-releases/</url>
        </repository>
    </distributionManagement>

</project>

 

 

  • GIt Lab에 웹 훅 트리거하기 
    • 젠킨스는 웹 훅 트리거가 작동하면 코드를 GIt Lab으로부터 받아 오게 코드가 되어있다.
    • 우선은 예제이기에 push와 marge 시에만 트리거를 작동하게 시켰다.
    • 가장 큰 문제는 URL인데 젠킨스 서버로부터 요청을 보내고 받아야 한다. 
      • 그러나 알다싶히 로컬에서 실습을 하는 건데 어떻게 서버가 외부와 통신하냐면 해당 사이트를 이용하면 된다.
      • ngrok 은 무료로 로컬 도메인을 외부로 접근할 수 있게 도메인 변환을 해준다. (일부 기능은 유료)
        • 무제한은 아니여서 테스트 용도로 적합하다. 무제한은 돈을 지불... ㅠㅠ
        • 사용법은 먼저 설치를 한다.
        • 이후에 cmd 창에서 다음과 같은 커맨드를 입력한다.
          # 이용하기 위한 토큰 값.
          ngrok config add-authtoken <token>
          
          # 변환하고자 하는 도메인
          ngrok http <localhost:포트번호>


      • 해서 https://<ngrok 도메인>/project/<나의 프로젝트> 이런 식으로 URL을 넣어주면 된다.
      • 이후에는 테스트를 해보고 서버와 통신이 가능한지 살펴본다.
      • https://ngrok.com/

 

 

ngrok | API Gateway, IoT Device Gateway, Secure Tunnels for Containers, Apps & APIs

ngrok is a secure ingress platform that enables developers to add global server load balancing, reverse proxy, firewall, API gateway and Kubernetes Ingress to applications and APIs.

ngrok.com

코드 200번을 잘 받아오는 모습

 

  • 이제 실질적으로 젠킨스 파이프 라인이 잘 작동하는지 테스트하기
    • 일단 git push로 코드를 gitlab에 올린다.

테스트 용 자바 코드(계산기 코드)

 

  • 젠킨스 프로젝트 상태를 본다. (필자는 이미 미리 테스트를 하여서 시간이 지났다는 걸 감안해야 한다.)

  • Git Lab에 잘 코드가 들어갔는지 확인

 

  • 아티팩트 또한 넥서스 리포지터리에 잘 들어갔는지 확인.

넥서스 리포지터리에 잘 저장이 되었다.
pom.xml 파일에 있던 형식들이 아티펙트에 적용된 모습

 

* 이렇게 하면 실습이 잘 완료된다. 우여곡절이 있었지만 결국 성공했다. 다음 글에서는 파이프라인 코드 분석을 해볼 것이다.