OpenShift Pipeline 입문 ~ Jenkins Pipeline을 통한 빌드 및 배포

지금부터 OpenShift Pipeline에 의한 CI/CD 파이프라인에 임하고 싶습니다.
이번에는 다음 기사에서 설명하는 Jenkins Pipeline 샘플을 만들고 실행해 보겠습니다.
OpenShift Jenkins Pipeline (DSL) Plugin 입문 - 적모 엔지니어 블로그

Jenkins Master 설정



사전에 Jenkins의 Master를 OpenShift 클러스터에 설정합니다.
이번에는 ephemeral 버전을 이용합니다. 실제로 Master를 사용할 수 있게 되기까지 몇 분 정도 걸립니다.
>oc new-app jenkins-ephemeral
warning: Cannot find git. Ensure that it is installed and in your path. Git is required to work with git repositories.
--> Deploying template "openshift/jenkins-ephemeral" to project nkproject

     Jenkins (Ephemeral)
     ---------
     Jenkins service, without persistent storage.

     WARNING: Any data stored will be lost upon pod destruction. Only use this template for testing.

     A Jenkins service has been created in your project.  Log into Jenkins with your OpenShift account.  The tutorial at https://github.com/openshift/origin/blob/master/examples/jenkins/README.md contains more information about using this template.

     * With parameters:
        * Jenkins Service Name=jenkins
        * Jenkins JNLP Service Name=jenkins-jnlp
        * Enable OAuth in Jenkins=true
        * Memory Limit=1Gi
        * Jenkins ImageStream Namespace=openshift
        * Disable memory intensive administrative monitors=false
        * Jenkins ImageStreamTag=jenkins:2
        * Allows use of Jenkins Update Center repository with invalid SSL certificate=false

--> Creating resources ...
    route.route.openshift.io "jenkins" created
    deploymentconfig.apps.openshift.io "jenkins" created
    serviceaccount "jenkins" created
    rolebinding.authorization.openshift.io "jenkins_edit" created
    service "jenkins-jnlp" created
    service "jenkins" created
--> Success
    Access your application via route 'jenkins-nkproject.2886795287-80-shadow04.environments.katacoda.com'
    Run 'oc status' to view your app.


Jenkins Pipeline 샘플 만들기



먼저 Pipeline에서 애플리케이션의 컨테이너 이미지를 빌드하기 위한 BuildConfig를 만듭니다.--binary=true는 사전 빌드 된 응용 프로그램 바이너리가 런타임에 지정되어 빌드됨을 나타냅니다.
(지정한 Wildfly 이미지는 원래 기사보다 새로운 것을 사용하고 있습니다)
>oc new-build --name=mavenapp --docker-image=openshift/wildfly-160-centos7 --binary=true
warning: Cannot find git. Ensure that it is installed and in your path. Git is required to work with git repositories.
--> Found container image 7ff222e (11 months old) from Docker Hub for "openshift/wildfly-160-centos7"

    WildFly 16.0.0.Final
    --------------------
    Platform for building and running JEE applications on WildFly 16.0.0.Final

    Tags: builder, wildfly, wildfly16

    * An image stream tag will be created as "wildfly-160-centos7:latest" that will track the source image
    * A source build using binary input will be created
      * The resulting image will be pushed to image stream tag "mavenapp:latest"
      * A binary build was created, use 'oc start-build --from-dir' to trigger a new build

--> Creating resources with label build=mavenapp ...
    imagestream.image.openshift.io "wildfly-160-centos7" created
    imagestream.image.openshift.io "mavenapp" created
    buildconfig.build.openshift.io "mavenapp" created
--> Success

그런 다음 Jenkinsfile에 의한 Pipeline 정의가 포함된 BuildConfig를 만듭니다.
>oc create -f https://raw.githubusercontent.com/hashnao/openshift-jee-sample/master/mavenapp-pipeline.yml
buildconfig.build.openshift.io/mavenapp-pipeline created

Jenkinsfile의 내용은 다음과 같이 BuildConfig에 내장되어 있습니다.
내용에 대한 자세한 설명은 원래 기사에 있지만 다음 단계로 구성되어 있습니다.
  • Git 저장소에서 응용 프로그램 소스 git clone (Clone Source)
  • Maven에서 아티팩트 (WAR) 빌드 (Build Artifact)
  • Maven에서 단위 테스트 실행 (Run Unit Test)
  • 생성 된 아티팩트를 지정하고 컨테이너 이미지를 이진 빌드 (Build Image)
  • 빌드한 컨테이너 이미지에 버전 + 빌드 번호로 태그를 릴리스한다 (Promote Image)
  •         pipeline {
              agent { label "maven" }
              environment {
                version = "1.0"
                devTag = "${version}-${BUILD_NUMBER}"
              }
              stages {
                stage("Clone Source") {
                  steps {
                    git url: "https://github.com/openshift/openshift-jee-sample.git", branch: "master"
                  }
                }
                stage("Build Artifacts") {
                  steps {
                    sh "mvn clean package -Popenshift -DskipTests=true"
                    stash includes: "target/ROOT.war", name: "war"
                  }
                }
                stage("Run Unit Test") {
                  steps {
                    sh "mvn test"
                  }
                }
                stage("Build Image") {
                  steps {
                    unstash "war"
                    script {
                      openshift.withCluster() {
                        openshift.withProject() {
                          def nb = openshift.selector("bc", "mavenapp")
                          nb.startBuild("--from-file=./target/ROOT.war").logs("--follow")
                          def buildSelector = nb.narrow("bc").related("builds")
                          timeout(5) {
                            buildSelector.untilEach(1) {
                              return (it.object().status.phase == "Complete")
                            }
                          }
                          echo "Builds have been completed: ${buildSelector.names()}"
                        }
                      }
                    }
                  }
                }
                stage("Promote Image") {
                  steps {
                    script {
                      openshift.withCluster() {
                        openshift.withProject() {
                          // Tag the mavenapp:latest image as mavenapp:${devTag}
                          openshift.tag("mavenapp:latest", "mavenapp:${devTag}")
                        }
                      }
                    }
                  }
                }
              }
            }
    

    Jenkins Pipeline 샘플 실행


    oc start-build 에 의해 Jenkins Pipeline으로 빌드를 실행합니다.
    >oc start-build mavenapp-pipeline
    build.build.openshift.io/mavenapp-pipeline-1 started
    

    빌드는 몇 분 안에 완료됩니다.oc get build 그러면 작성한 두 개의 빌드가 실행 중임을 알 수 있습니다.
    >oc get build
    NAME                  TYPE              FROM     STATUS     STARTED         DURATION
    mavenapp-pipeline-1   JenkinsPipeline            Complete   3 minutes ago
    mavenapp-1            Source            Binary   Complete   2 minutes ago   1m38s
    

    Jenkins Pipeline의 상태는 OpenShift(위) 및 Jenkins(아래) 웹 콘솔에서 확인할 수 있습니다.




    빌드의 결과, 어플리케이션 (mavenapp) 의 신규 ImageStream 와 ImageStreamTag 가 작성되고 있습니다.mavenapp:1.0-1 가 Pipeline의 마지막 스테이지에 태그 붙여진 것이 됩니다.
    >oc get imagestream
    NAME                  IMAGE REPOSITORY                                                                        TAGS           UPDATED
    mavenapp              default-route-openshift-image-registry.apps-crc.testing/nkproject/mavenapp              1.0-1,latest   28 seconds ago
    wildfly-160-centos7   default-route-openshift-image-registry.apps-crc.testing/nkproject/wildfly-160-centos7   latest         5 minutes ago
    
    >oc get imagestreamtag
    NAME                         IMAGE REF                                                                                                                                     UPDATED
    mavenapp:1.0-1               image-registry.openshift-image-registry.svc:5000/nkproject/mavenapp@sha256:e5e6894d57bb3cf5ec4e569f10b8ca464f5b62653366061426c993ba13cc3c19   36 seconds ago
    mavenapp:latest              image-registry.openshift-image-registry.svc:5000/nkproject/mavenapp@sha256:e5e6894d57bb3cf5ec4e569f10b8ca464f5b62653366061426c993ba13cc3c19   40 seconds ago
    wildfly-160-centos7:latest   openshift/wildfly-160-centos7@sha256:d12c6ef86991edf35e51aef804822f76897cbc579f7518ce84eaf55ec8ec6f9d                                         5 minutes ago
    

    이미지 배포 및 앱 실행



    빌드된 애플리케이션 이미지를 oc new-app로 배포합니다.
    >oc new-app -i mavenapp:latest
    warning: Cannot find git. Ensure that it is installed and in your path. Git is required to work with git repositories.
    --> Found image f419a9c (2 minutes old) in image stream "nkproject/mavenapp" under tag "latest" for "mavenapp:latest"
    
        WildFly 16.0.0.Final
        --------------------
        Platform for building and running JEE applications on WildFly 16.0.0.Final
    
        Tags: builder, wildfly, wildfly16
    
        * This image will be deployed in deployment config "mavenapp"
        * Port 8080/tcp will be load balanced by service "mavenapp"
          * Other containers can access this service through the hostname "mavenapp"
    
    --> Creating resources ...
        deploymentconfig.apps.openshift.io "mavenapp" created
        service "mavenapp" created
    --> Success
        Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
         'oc expose svc/mavenapp'
        Run 'oc status' to view your app.
    
    >oc get pod
    NAME                READY   STATUS      RESTARTS   AGE
    jenkins-1-64gbk     1/1     Running     0          10m
    jenkins-1-deploy    0/1     Completed   0          10m
    mavenapp-1-build    0/1     Completed   0          4m56s
    mavenapp-1-deploy   0/1     Completed   0          59s
    mavenapp-1-jvtpt    1/1     Running     0          50s
    

    배포한 애플리케이션에 액세스하기 위해 Route를 만듭니다.
    >oc expose svc/mavenapp
    route.route.openshift.io/mavenapp exposed
    
    >oc get route
    NAME       HOST/PORT                                                           PATH   SERVICES   PORT       TERMINATION     WILDCARD
    jenkins    jenkins-nkproject.2886795308-80-jago05.environments.katacoda.com           jenkins    <all>      edge/Redirect   None
    mavenapp   mavenapp-nkproject.2886795308-80-jago05.environments.katacoda.com          mavenapp   8080-tcp                   None
    

    Route URL에 브라우저를 통해 액세스하면 다음 화면이 표시됩니다.


    Jenkins Pipeline 수정 및 실행



    이번에 만든 Jenkins Pipeline에 이미지 배포를 통합해 보겠습니다.
    실은 방금전의. 로 변경합니다.
    >oc get deploymentconfig mavenapp
    NAME       REVISION   DESIRED   CURRENT   TRIGGERED BY
    mavenapp   2          1         1         config,image(mavenapp:latest)
    

    위의 DeploymentConfig 트리거를 oc new-app 에서 변경하여 자동으로 재배포하지 않도록 합니다.
    >oc set triggers dc/mavenapp --manual
    deploymentconfig.apps.openshift.io/mavenapp triggers updated
    

    Jenkins Pipeline (mavenapp-pipeline)의 Jenkinsfile 부분을 수정하고 다음 oc set triggers 스테이지를 deploy 스테이지 다음에 추가합니다.
    OpenShift 웹 콘솔에서 직접 수정할 수 있습니다.
                stage('deploy') {
                  steps {
                    script {
                      openshift.withCluster() {
                        openshift.withProject() {
                          def rm = openshift.selector("dc", "mavenapp").rollout().latest()
                          timeout(5) {
                            openshift.selector("dc", "mavenapp").related('pods').untilEach(1) {
                              return (it.object().status.phase == "Running")
                            }
                          }
                        }
                      }
                    }
                  }
                }
    



    Pipeline을 실행하면 이미지 빌드에서 배포까지 Pipeline에서 실행됩니다.
    >oc start-build mavenapp-pipeline
    build.build.openshift.io/mavenapp-pipeline-5 started
    
    >oc get pod
    NAME                READY   STATUS      RESTARTS   AGE
    jenkins-1-64gbk     1/1     Running     0          51m
    jenkins-1-deploy    0/1     Completed   0          51m
    mavenapp-1-build    0/1     Completed   0          45m
    mavenapp-1-deploy   0/1     Completed   0          41m
    mavenapp-2-build    0/1     Completed   0          32m
    mavenapp-2-deploy   0/1     Completed   0          31m
    mavenapp-3-5mm76    1/1     Running     0          66s
    mavenapp-3-build    0/1     Completed   0          21m
    mavenapp-3-deploy   0/1     Completed   0          76s
    mavenapp-4-build    0/1     Completed   0          11m
    mavenapp-5-build    0/1     Completed   0          2m39s
    

    결론



    OpenShift는 미리 빌드 및 배포의 기본 메커니즘을 제공하지만 Jenkins Pipeline Plugin을 사용하여 Jenkins Pipeline과 이를 결합하여 고급 CI/CD 파이프라인을 간단하게 구현할 수 있습니다.

    좋은 웹페이지 즐겨찾기