0
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

OpenShift Pipeline 入門~PipelineからTemplateの利用

今回は以下にあるPipelineのTutorialを実施します。
OpenShiftのドキュメントに記載されたものになります。
5.4. Pipeline ビルド 4.2 | Red Hat Customer Portal

nodejs-mongodb.json テンプレートを使用して Node.js/MongoDB アプリケーションをビルドし、デプロイし、検証する OpenShift Pipeline を作成する方法を紹介します。

サンプル Jenkins Pipeline の作成

Pipelineのyaml (nodejs-sample-pipeline.yaml) を作成して、BuildConfigを作成します。(Jenkins Masterは構成済みの想定)

>oc create -f nodejs-sample-pipeline.yaml
buildconfig.build.openshift.io/nodejs-sample-pipeline created

nodejs-sample-pipeline.yamlの内容は以下の通りです。
(Jenkinsfile部が長いですがそのままいきます)


kind: "BuildConfig"
apiVersion: "v1"
metadata:
  name: "nodejs-sample-pipeline"
spec:
  strategy:
    jenkinsPipelineStrategy:
      jenkinsfile: |-
        def templatePath = 'https://raw.githubusercontent.com/openshift/nodejs-ex/master/openshift/templates/nodejs-mongodb.json' 
        def templateName = 'nodejs-mongodb-example' 
        pipeline {
          agent {
            node {
              label 'nodejs' 
            }
          }
          options {
            timeout(time: 20, unit: 'MINUTES') 
          }
          stages {
            stage('preamble') {
                steps {
                    script {
                        openshift.withCluster() {
                            openshift.withProject() {
                                echo "Using project: ${openshift.project()}"
                            }
                        }
                    }
                }
            }
            stage('cleanup') {
              steps {
                script {
                    openshift.withCluster() {
                        openshift.withProject() {
                          openshift.selector("all", [ template : templateName ]).delete() 
                          if (openshift.selector("secrets", templateName).exists()) { 
                            openshift.selector("secrets", templateName).delete()
                          }
                        }
                    }
                }
              }
            }
            stage('create') {
              steps {
                script {
                    openshift.withCluster() {
                        openshift.withProject() {
                          openshift.newApp(templatePath) 
                        }
                    }
                }
              }
            }
            stage('build') {
              steps {
                script {
                    openshift.withCluster() {
                        openshift.withProject() {
                          def builds = openshift.selector("bc", templateName).related('builds')
                          timeout(5) { 
                            builds.untilEach(1) {
                              return (it.object().status.phase == "Complete")
                            }
                          }
                        }
                    }
                }
              }
            }
            stage('deploy') {
              steps {
                script {
                    openshift.withCluster() {
                        openshift.withProject() {
                          def rm = openshift.selector("dc", templateName).rollout()
                          timeout(5) { 
                            openshift.selector("dc", templateName).related('pods').untilEach(1) {
                              return (it.object().status.phase == "Running")
                            }
                          }
                        }
                    }
                }
              }
            }
            stage('tag') {
              steps {
                script {
                    openshift.withCluster() {
                        openshift.withProject() {
                          openshift.tag("${templateName}:latest", "${templateName}-staging:latest") 
                        }
                    }
                }
              }
            }
          }
        }
    type: JenkinsPipeline

ポイントは以下のステージ、Templateを指定して新規アプリケーションを作成しています。必要なリソースのビルド、デプロイはこのTemplateにより行われます。

   stage('create') {
      steps {
        script {
            openshift.withCluster() {
                openshift.withProject() {
                  openshift.newApp(templatePath) 
                }
            }
        }
      }
    }

サンプル Pipeline の実行

作成したBuildConfigを実行します。

>oc start-build nodejs-sample-pipeline
build.build.openshift.io/nodejs-sample-pipeline-1 started

WebコンソールからPipeline (Build:nodejs-sample-pipeline-1) の状況を確認できます。
image.png


暫く待っていたのですが、buildステージで失敗してしまいました。
image.png

LogsからJenkinsのログを参照します。
Red Hat Developer IDによるOpenShiftログインが求められ、以下の画面でアクセスを許可します。
image.png

image.png

見慣れたJenkinsのコンソールへ。
image.png

どうもTimeoutしている (待ち時間内にTemplateで定義されたBuildが終了しなかった) ようです。
image.png

Jenkinsfileを見ると、BuildConfig:nodejs-mongodb-exampleのBuildを待っていたようです。
そこで該当のBuildConfigのEventsを確認すると、
image.png
image.png

指定されているImageStreamTagが存在しないようです。
oc get imagestreamtag で調べてみると、

>oc get imagestreamtag -n openshift |findstr nodejs
jenkins-agent-nodejs:latest                  image-registry.openshift-image-registry.svc:5000/openshift/jenkins-agent-nodejs@sha256:8fa18b9fd93cac72f3d9f356fe3633c42e080940ebe53eb14a00551d7db10148                  8 weeks ago
jenkins-agent-nodejs:v4.0                    image-registry.openshift-image-registry.svc:5000/openshift/jenkins-agent-nodejs@sha256:8fa18b9fd93cac72f3d9f356fe3633c42e080940ebe53eb14a00551d7db10148                  8 weeks ago
nodejs:10                                    image-registry.openshift-image-registry.svc:5000/openshift/nodejs@sha256:74a3ef2964efc03dfc239da3f09691b720ce54ff4bb47588864adb222133f0fc                                8 months ago
nodejs:8                                     image-registry.openshift-image-registry.svc:5000/openshift/nodejs@sha256:bf4030ac45b8b3ff0ea2892261f1fb5df5b077a67ef717836ac0de879cc775d9                                5 months ago
nodejs:8-RHOAR                               image-registry.openshift-image-registry.svc:5000/openshift/nodejs@sha256:7f4b9099ea7e1ba5b2be98304c2d0c2eb1d738d8ceee9d9a1464e71a08d78dd4                                6 months ago
nodejs:latest                                image-registry.openshift-image-registry.svc:5000/openshift/nodejs@sha256:74a3ef2964efc03dfc239da3f09691b720ce54ff4bb47588864adb222133f0fc                                8 months ago

なので、確かに指定されたnodejs:12というTagが存在しません。


tagの部分をlatest (存在するImageStreamTag) に修正してみましょう。

image.png

Saveで反映されます。
image.png

修正により自動で新たなBuildが実行され、成功したようです。
image.png

サンプルのnodejsやmongodbのPodがデプロイされていました。
(元のPipelineは失敗したままです・・・)

>oc get all
NAME                                  READY   STATUS      RESTARTS   AGE
pod/mongodb-1-8r2jx                   1/1     Running     0          67m
pod/mongodb-1-deploy                  0/1     Completed   0          67m
pod/nodejs-mongodb-example-1-build    0/1     Completed   0          4m50s
pod/nodejs-mongodb-example-1-deploy   0/1     Completed   0          3m42s
pod/nodejs-mongodb-example-1-mb9zx    1/1     Running     0          3m39s
・・・・

Pipeline の修正と再実行

この状況でサンプル Pipeline を成功させるにはどうすればよいでしょうか。
(そのまま再実行しても手で修正したBuildConfigがTemplateから再作成されるため再度失敗します)

使用しているTemplateの中身を確認してみます。(Jenkinsfileの先頭で定義)
https://raw.githubusercontent.com/openshift/nodejs-ex/master/openshift/templates/nodejs-mongodb.json

以下抜粋です

    {
      "kind": "BuildConfig",
      "apiVersion": "v1",
      "metadata": {
        "name": "${NAME}",
        "annotations": {
          "description": "Defines how to build the application",
          "template.alpha.openshift.io/wait-for-ready": "true"
        }
      },
      "spec": {
        "source": {
          "type": "Git",
          "git": {
            "uri": "${SOURCE_REPOSITORY_URL}",
            "ref": "${SOURCE_REPOSITORY_REF}"
          },
          "contextDir": "${CONTEXT_DIR}"
        },
        "strategy": {
          "type": "Source",
          "sourceStrategy": {
            "from": {
              "kind": "ImageStreamTag",
              "namespace": "${NAMESPACE}",
              "name": "nodejs:${NODEJS_VERSION}"
            },
            "env": [
              {
                "name": "NPM_MIRROR",
                "value": "${NPM_MIRROR}"
              }
            ]
          }
        },
・・・
  "parameters": [
    {
      "name": "NAME",
      "displayName": "Name",
      "description": "The name assigned to all of the frontend objects defined in this template.",
      "required": true,
      "value": "nodejs-mongodb-example"
    },
    {
      "name": "NAMESPACE",
      "displayName": "Namespace",
      "description": "The OpenShift Namespace where the ImageStream resides.",
      "required": true,
      "value": "openshift"
    },
    {
      "name": "NODEJS_VERSION",
      "displayName": "Version of NodeJS Image",
      "description": "Version of NodeJS image to be used (10, 12, or latest).",
      "value": "12",
      "required": true
    },
    {
      "name": "MONGODB_VERSION",
      "displayName": "Version of MongoDB Image",
      "description": "Version of MongoDB image to be used (3.6 or latest).",
      "value": "3.6",
      "required": true
    },
・・・

これによると、該当のBuildConfigで使用するnodejsのImageStreamTagはNODEJS_VERSIONという変数でパラメータ化されているようです。
ということは、Templateの利用時にこのパラメータに存在するバージョンのImageStreamTagを指定すれば良さそうです。

元のPipelie用BuildConfigにて、Jenkinsfile部のcreateステージ (先ほどポイントとして抜粋した部分) を以下のように修正します。
--param以下の指定はoc new-appのオプションで、実行時Templateにパラメータを渡すための指定方法としてここでも使えます。
この辺りは、HelmのTemplateとよく似た仕組みですね。

    stage('create') {
      steps {
        script {
            openshift.withCluster() {
                openshift.withProject() {
                  openshift.newApp(templatePath, "--param=NODEJS_VERSION=latest") 
                }
            }
        }
      }
    }

再度BuildConfigを作成し、変更反映を確認します。
image.png

Pipelineを再実行すると、今度はBuildが無事成功しました。
(OpenShiftのコンソール)
image.png
(Jenkinsのコンソール)
image.png

tagステージの処理により、ImageStreamへのタグ付けも行われています。

>oc get imagestream
NAME                             IMAGE REPOSITORY                                                                                   TAGS     UPDATED
nodejs-mongodb-example           default-route-openshift-image-registry.apps-crc.testing/nkproject/nodejs-mongodb-example           latest   38 minutes ago
nodejs-mongodb-example-staging   default-route-openshift-image-registry.apps-crc.testing/nkproject/nodejs-mongodb-example-staging   latest   38 minutes ago

>oc get imagestreamtag
NAME                                    IMAGE REF                                                                                                                                                           UPDATED
nodejs-mongodb-example:latest           image-registry.openshift-image-registry.svc:5000/nkproject/nodejs-mongodb-example@sha256:be25fa2653adde1b9ee70ac82cd8bba9f717ad128635640a4db659c07d44b402           38 minutes ago
nodejs-mongodb-example-staging:latest   image-registry.openshift-image-registry.svc:5000/nkproject/nodejs-mongodb-example-staging@sha256:be25fa2653adde1b9ee70ac82cd8bba9f717ad128635640a4db659c07d44b402   38 minutes ago

当然ですが、RouteのURLにアクセスするとアプリケーションにアクセスできました。
image.png

おわりに

今回はJenkins PipelineからのTemplate利用を確認しました。
よくあるリソース構成のパターンをTemplateとして定義しておけば、Pipelineもシンプルにでき、横展開も容易になりそうですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?