빌드 및 배포 관리

Print

빌드 및 배포 서비스는 오픈소스 CI(Continuous Integration) 도구인 Jenkins 를 기반으로 제공합니다.

※ CI(지속적 통합) : 퀄리티 컨트롤(Quality Control, 엔티티 생산에 관련된 모든 품질 요인을 검토하는 과정)을 적용하는 프로세스를 실행합니다.

작은 단위의 작업을 빈번하게 적용하며 맨 마지막에 퀄리티 컨트롤을 적용하는 기존 방법을 대체하는 방법으로, 소프트웨어의 질적 향상과 소프트웨어를 배포하는 데 소요되는 시간을 줄이는 데 초점을 맞출 수 있습니다.


서비스를 사용하기 위해 ZCP Console 의 사이드 메뉴에서 DevOps > 빌드 및 배포 를 클릭합니다.

Jenkins 의 계정은 ZCP Console의 사용자와 통합되며, 권한이 있는 Namespace 와 동일한 이름의 Folder 에 대해 권한이 주어집니다.

주요 기능은 다음과 같습니다.

  • 소스코드 체크아웃(Subversion, Git, Perforce, Mercurial, CVS 등)

  • 빌드, 테스트(Ant, Maven, MSBuild, shell script 등)
  • 결과 기록(binary, test results, code coverage, static analysis)
  • 통지 기능(Email, IM, RSS, IDEs)

Jenkins 는 다양한 특징을 가집니다.

  • 다양한 OS 지원
  • 쉽고 빠른 설치 (war 형태로 WAS에 deploy, java 명령어를 이용하여 daemon 형태로 구동)
  • 분산 환경 지원 (Jenkins Agent를 설치하여 Jenkins Master의 부하 방지)
  • Plugin으로 다양한 기능 확장 가능
  • 정기적인 빌드 자동화
  • 빌드한 결과물 자동 배포

Jenkins 폴더에 Credential 관리

Jenkins 에서 빌드, 배포를 수행하려면 기본적으로 2가지 Credential 정보가 필요합니다. 소스를 Checkout 할 Git Repository 의 접속 계정 정보, Docker Image를 Push 하기 위한 Registry 접속 계정 정보입니다.

Jenkins 에서는 계정의 재사용과 관리를 쉽게 할 수 있도록 Credentials 기능을 제공합니다.

Credential 생성

Folder 좌측 메뉴 중 Credentials 를 클릭합니다.

해당 Folder Scope (기본) 의 global 링크를 클릭합니다. 

좌측의 Add Credentials 메뉴를 클릭합니다.


Username with password 를 선택 후, Username, Password, ID 를 입력하고 OK 버튼을 클릭합니다.


이때, ID 는 ZCP 의 Pipeline 에서 사용하는 예약어를 사용하도록 합니다.

  • Git Credential ID : GIT_CREDENTIALS
  • Docker Credential ID : HARBOR_CREDENTIALS

Description 을 입력하면 Credential 목록에서 구분하기가 용이합니다.


Credential 2개를 모두 생성한 모습입니다.

이렇게 Folder 하위에 생성한 Credentials 은 해당 Folder 안에 존재하는 Pipeline 에서만 사용 가능합니다.

Pipeline 관리


Jenkins Pipeline 은 어플리케이션을 빌드하고 배포하는 작업의 흐름을 정의합니다.

기본적인 흐름은 소스 코드 체크아웃 - 어플리케이션 빌드 - Docker 빌드 & Push - Kubernetes 배포 순서입니다.

ZCP 에서는 Pipeline을 Jenkinsfile 이라는 파일안에 Groovy 로 정의하며 소스 코드 안에 포함하여 형상 관리로 관리합니다.

Pipeline 생성

Folder 좌측 메뉴의 New Item 을 클릭합니다.



  1. Item name 에 Job 이름 (Application 명)을 입력합니다.
  2. Pipeline 을 선택합니다.
  3. OK 버튼을 클릭합니다.


Pipeline Tab에 아래와 같이 설정합니다.

  1. Definition 을 Pipeline script from SCM 으로 선택합니다.
  2. SCM 종류를 GIT 으로 선택합니다.
  3. Repositories 의 Repository URL 에 GIT Clone URL 을 입력합니다. 
  4. Credentials 에 위에서 생성한 Git Credentials 를 선택합니다.
  5. Branches to build 에 배포 할 소스 코드의 Git branch 를 입력합니다.
  6. Repository browser 에 gogs 를 선택합니다. ZCP 에서 제공하는 Git이 아닌 다른 Git 을 사용한다면 해당 Git 서비스를 선택하도록 합니다.
  7. Script Path 에 Jenkinsfile 을 입력합니다.
  8. OK 버튼을 클릭합니다.


아래의 Pipeline 코드를 복사하여 어플리케이션 소스의 root 에 Jenkinsfile 로 저장합니다.

샘플로 제공되는 Pipeline 은 Maven 프로젝트를 빌드/배포하는 예제입니다.

해당 Pipeline 이 정상적으로 수행되게 하려면 아래의 파일을 미리 준비하셔야 합니다.

빌드 및 배포 관련 파일들

  • Dockerfile : Docker build 를 하기 위해 사용됩니다. 어플리케이션 종류에 따라 상이하기 때문에 이 페이지 를 참고하여 작성합니다. 작성한 Dockerfile 은 어플리케이션 root 에 Dockerfile 이란 파일명으로 저장합니다.
  • deploy.yaml : Kubernetes 에 어플리케이션을 배포하기 위해 사용됩니다. 이 페이지를 참고하여 작성합니다. deploy.yaml 파일은 어플리케이션 root 하위에 k8s 라는 폴더를 생성하고 폴더 안에 저장합니다.
  • service.yaml : Kubernetes 에 배포한 deploy 를 외부로 노출하기 위해 사용됩니다.  이 페이지 를 참고하여 작성합니다. 작성한 service.yaml 파일은 어플리케이션 root 하위에 k8s 라는 폴더 안에 저장합니다.


@Library('retort-lib') _
def label = "jenkins-${UUID.randomUUID().toString()}"

def ZCP_USERID='zcpsample'
def DOCKER_IMAGE='zcpsample/sam-springboot'
def K8S_NAMESPACE='default'

timestamps {
    podTemplate(label:label,
        serviceAccount: "zcp-system-sa-${ZCP_USERID}",
        containers: [
            containerTemplate(name: 'maven', image: 'maven:3.5.2-jdk-8-alpine', ttyEnabled: true, command: 'cat'),
            containerTemplate(name: 'docker', image: 'docker:17-dind', ttyEnabled: true, command: 'dockerd-entrypoint.sh', privileged: true),
            containerTemplate(name: 'kubectl', image: 'lachlanevenson/k8s-kubectl:v1.13.6', ttyEnabled: true, command: 'cat')
        ],
        volumes: [
            persistentVolumeClaim(mountPath: '/root/.m2', claimName: 'zcp-jenkins-mvn-repo')
        ]) {
    
        node(label) {
            stage('SOURCE CHECKOUT') {
                def repo = checkout scm
            }
    
            stage('BUILD') {
                container('maven') {
                    mavenBuild goal: 'clean package', systemProperties:['maven.repo.local':"/root/.m2/${JOB_NAME}"]
                }
            }
    
            stage('BUILD DOCKER IMAGE') {
                container('docker') {
                    dockerCmd.build tag: "${HARBOR_REGISTRY}/${DOCKER_IMAGE}:${BUILD_NUMBER}"
                    dockerCmd.push registry: HARBOR_REGISTRY, imageName: DOCKER_IMAGE, imageVersion: BUILD_NUMBER, credentialsId: "HARBOR_CREDENTIALS"
                }
            }
    
            stage('DEPLOY') {
                container('kubectl') {
                    kubeCmd.apply file: 'k8s/service.yaml', namespace: K8S_NAMESPACE
                    yaml.update file: 'k8s/deploy.yaml', update: ['.spec.template.spec.containers[0].image': "${HARBOR_REGISTRY}/${DOCKER_IMAGE}:${BUILD_NUMBER}"]
    
                    kubeCmd.apply file: 'k8s/deploy.yaml', wait: 300, recoverOnFail: false, namespace: K8S_NAMESPACE
                }
            }
        }
    }
}


생성한 Jenkinsfile 에서 아래의 내용을 수정하고 저장합니다.

수정할 부분

  • 4번 라인 ZCP_USERID : 배포담당자의 ZCP Console ID 를 입력합니다.
  • 5번 라인 DOCKER_IMAGE : 생성 할 Docker Image 명을 입력합니다.

Pipeline 에서 Docker Image 를 push 하기 위해 사용하는 Docker Registry 는 기본으로 ZCP Add-on service 로 제공되는 HARBOR 로 지정되어 있습니다. 해당 주소는  HARBOR_REGISTRY 라는 key 값으로 사용가능하며, Jenkins 의 Global Properties 로 저장되어 있어 Cluster-admin 만 수정 가능합니다.


Pipeline 실행

생성한 Pipeline 화면에서 좌측 메뉴의 Build Now 를 클릭합니다.

Pipeline 실행은 Namespace 의 admin 과 cicd-manager 권한을 가진 사용자만 가능합니다.


현재 화면에서 실행중인 상태를 확인할 수 있습니다.

좌측 Build History 에서 현재 실행중인 빌드의 Console Output 을 클릭하면 Pipeline 의 실행 로그를 확인할 수 있습니다.



이 답변이 유용합니까? 아니오

Send feedback
도움을 드리지 못해 죄송합니다. 피드백을 주시면 이 문서의 품질을 높이겠습니다.