Openshift Pipelines を構築してみた

以前の記事では、CI 部分を担う OpenShift Pipelines について解説しました。続いて、本記事では実際に OpenShift Pipelines の CI 部分 を構築したいと思います。

構築の概要

Red Hat のチュートリアルを参考にして図のような CI フローを OpenShift 上に構築します。チュートリアルではパブリックリポジトリを利用していますが、実際構築する際はプライベートリポジトリであるケースが多いため、プライベートリポジトリで構築してみます。CI フローの流れとしては、まず初めにプライベートな Git リポジトリに変更をプッシュした際に EventListener への Webhook がトリガーされます。EventListener は受け取った情報から指定されたパラメータを Trigger Template にバインディングして PipelineRun を実行させます。PipelineRun では最初にリポジトリからソースコードの取得をします。次にソースコードのimage をビルドし、image registry にプッシュしたらフロー終了です。

事前準備

下記構成のプライベートなアプリケーション用Git リポジトリを用意します。アプリケーションの設定や定義をDockerfileとindex.phpで設定し、Kubernetesのリソースはk8sディレクトリ配下にまとめています。

.
├── Dockerfile
├── index.php
└── k8s
 ├── deployment.yaml
 ├── route.yaml
 └── service.yaml

Dockerfile

FROM image-registry.openshift-image-registry.svc:5000/openshift/php:latest
ADD ./index.php /var/www/html/
CMD ["php","-S","0.0.0.0:8080","-t","/var/www/html"]

index.php

Hello world!

k8s/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ocp-cicd-appli-ui
  name: ocp-cicd-appli-ui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ocp-cicd-appli-ui
  template:
    metadata:
      labels:
        app: ocp-cicd-appli-ui
    spec:
      containers:
        - image: image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/ocp-cicd-appli-ui
          imagePullPolicy: Always
          name: ocp-cicd-appli-ui
          ports:
            - containerPort: 8080
              protocol: TCP

k8s/route.yaml

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  labels:
    app: ocp-cicd-appli-ui
  name: ocp-cicd-appli-ui
spec:
  port:
    targetPort: 8080-tcp
  to:
    kind: Service
    name: ocp-cicd-appli-ui
    weight: 100

k8s/service.yaml

apiVersion: v1
kind: Service
metadata:
  labels:
    app: ocp-cicd-appli-ui
  name: ocp-cicd-appli-ui
spec:
  type: NodePort
  ports:
    - name: 8080-tcp
      port: 8080
      targetPort: 8080
      protocol: TCP
  selector:
    app: ocp-cicd-appli-ui

前提条件

  • OpenShift クラスターが構築済みであること
  • oc CLI がインストール済みであること
  • tkn CLI がインストール済みであること
  • プライベートな Git リポジトリにssh設定がされており、対となる秘密鍵を持っていること
  • リポジトリ名に”_”が含まれていないこと(“_”が含まれているとPipelineRunリソースが正常に作成できない点に注意

OpenShift Pipelines をインストール

  1. OpenShift OperatorHub で Administrator のパースペクティブにいることを確認します。
  2. Web コンソールで[Operators] > [OperatorHub]に移動します。
  3. 検索バーに「OpenShift Pipelines」と入力して、 OpenShift Pipelines をクリックして Install をクリックします。
  4. デフォルトのまま Install をクリックします。

パイプラインを作成

図の赤枠部分を作成していきます。

サンプルアプリケーションをデプロイ

新規プロジェクトを作成します。

$ oc new-project pipelines-tutorial
Now using project "pipelines-tutorial" on server "URL".

You can add applications to this project with the 'new-app' command. For example, try:

oc new-app rails-postgresql-example

to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:

kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.43 -- /agnhost serve-hostname

ssh接続情報の作成

プライベートな Git リポジトリに接続するためのシークレットを作成します。

$ oc apply -f secret.yaml
secret/ssh-credential created

secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: ssh-credential
data:
  id_rsa: # cat ~/.ssh/id_rsa | base64 で表示された内容を記入(一行で記述すること)

pipeline サービスアカウントを確認

パイプラインを実行するサービスアカウントが存在しているか確認します。

$ oc get serviceaccount pipeline
NAME SECRETS AGE
pipeline 1 102s

タスクをインストール(実行確認のためのCD部分のタスク)

タスクを作成します。これは実行確認のための CD 部分のタスクとなり、続編のCD部分を実装する際は実行しないでください。

$ oc create -f apply_manifest_task.yaml
task.tekton.dev/apply-manifests created
$ oc create -f update_deployment_task.yaml
task.tekton.dev/update-deployment created

apply_manifest_task.yaml

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: apply-manifests
spec:
  workspaces:
  - name: source
  params:
    - name: manifest_dir
      description: The directory in source that contains yaml manifests
      type: string
      default: "k8s"
  steps:
    - name: apply
      image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
      workingDir: /workspace/source
      command: ["/bin/bash", "-c"]
      args:
        - |-
          echo Applying manifests in $(inputs.params.manifest_dir) directory
          oc apply -f $(inputs.params.manifest_dir)
          echo -----------------------------------

update_deployment_task.yaml

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: update-deployment
spec:
  params:
    - name: deployment
      description: The name of the deployment patch the image
      type: string
    - name: IMAGE
      description: Location of image to be patched with
      type: string
  steps:
    - name: patch
      image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
      command: ["/bin/bash", "-c"]
      args:
        - |-
          oc patch deployment $(inputs.params.deployment) --patch='{"spec":{"template":{"spec":{
            "containers":[{
              "name": "$(inputs.params.deployment)",
              "image":"$(inputs.params.IMAGE)"
            }]
          }}}}'
          patched_at_timestamp=`date +%s`
          oc patch deployment $(inputs.params.deployment) --patch='{"spec":{"template":{"metadata":{
            "labels":{
              "patched_at": '\"$patched_at_timestamp\"'
            }
          }}}}'

作成したタスクを確認

タスクが作成されていることを確認します。

$ tkn task ls
NAME DESCRIPTION AGE
apply-manifests 6 minutes ago
update-deployment 6 minutes ago

パイプラインを作成

パイプラインを作成します。

$ oc create -f pipeline.yaml
pipeline.tekton.dev/build-and-deploy created

pipeline.yaml

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-and-deploy
spec:
  workspaces:
  - name: shared-workspace
  - name: ssh-creds
  params:
  - name: deployment-name
    type: string
    description: name of the deployment to be patched
  - name: git-url
    type: string
    description: url of the git repo for the code of deployment
  - name: git-revision
    type: string
    description: revision to be used from repo of the code for deployment
    default: main
  - name: IMAGE
    type: string
    description: image to be build from the code
 
  tasks:
  - name: fetch-repository
    taskRef:
      name: git-clone
      kind: ClusterTask
    workspaces:
    - name: output
      workspace: shared-workspace
    - name: ssh-directory
      workspace: ssh-creds
    params:
    - name: url
      value: $(params.git-url)
    - name: subdirectory
      value: ""
    - name: deleteExisting
      value: "true"
    - name: revision
      value: $(params.git-revision)


  - name: build-image
    taskRef:
      name: buildah
      kind: ClusterTask
    params:
    - name: IMAGE
      value: $(params.IMAGE)
    workspaces:
    - name: source
      workspace: shared-workspace
    runAfter:
    - fetch-repository


# 以下CD部分のタスクのため、続編のCD部分を実装する際は記入しないこと
  - name: apply-manifests
    taskRef:
      name: apply-manifests
    workspaces:
    - name: source
      workspace: shared-workspace
    runAfter:
    - build-image


  - name: update-deployment
    taskRef:
      name: update-deployment
    params:
    - name: deployment
      value: $(params.deployment-name)
    - name: IMAGE
      value: $(params.IMAGE)
    runAfter:
    - apply-manifests

作成したパイプラインを確認

パイプラインが作成されていることを確認します。

$ tkn pipeline ls
NAME AGE LAST RUN STARTED DURATION STATUS
build-and-deploy 2 minutes ago --- --- --- ---

パイプラインを手動実行

作成したパイプラインを手動で実行して動作を確認します。

$ tkn pipeline start build-and-deploy \ 
    --prefix-name build-deploy-ui-pipelinerun \ 
    -w name=shared-workspace,volumeClaimTemplateFile=persistent_volume_claim.yaml \
    -w name=ssh-creds,secret=ssh-credential \ 
    -p deployment-name=ocp-cicd-appli-ui \ 
    -p git-url=<リポジトリ名:git@xxx:xxx/xxx.gitの形式> \ 
    -p IMAGE=image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/ocp-cicd-appli-ui \ 
    --use-param-defaults
PipelineRun started: build-deploy-ui-pipelinerun-ngnjn

In order to track the PipelineRun progress run:
tkn pipelinerun logs build-deploy-ui-pipelinerun-ngnjn -f -n pipelines-tutorial

persistent_volume_claim.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: source-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi

Pipelinesを確認するとPipelineが実行中になっています。

Pipeline run を確認するとパイプラインの実行ログなどを確認することが出来ます。Succeeded になっていることを確認します。

アプリケーションのルートを取得

デプロイしたアプリケーションのルートを取得して正しくデプロイされていることを確認します。

$ oc get route ocp-cicd-appli-ui --template='http://{{.spec.host}}'
<アプリケーションのURL>

トリガーを作成

図の赤枠部分を作成していきます。

テンプレートの適用

トリガーテンプレートを作成します。

$ oc create -f triggertemplate.yaml
triggertemplate.triggers.tekton.dev/sample-app created

triggertemplate.yaml

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: sample-app
spec:
  params:
  - name: git-repo-url
    description: The git repository url
  - name: git-revision
    description: The git revision
    default: main
  - name: git-repo-name
    description: The name of the deployment to be created / patched


  resourcetemplates:
  - apiVersion: tekton.dev/v1
    kind: PipelineRun
    metadata:
      generateName: build-deploy-$(tt.params.git-repo-name)
    spec:
      taskRunTemplate:
        serviceAccountName: pipeline
      pipelineRef:
        name: build-and-deploy
      params:
      - name: deployment-name
        value: $(tt.params.git-repo-name)
      - name: git-url
        value: $(tt.params.git-repo-url)
      - name: git-revision
        value: $(tt.params.git-revision)
      - name: IMAGE
        value: image-registry.openshift-image-registry.svc:5000/$(context.pipelineRun.namespace)/$(tt.params.git-repo-name):$(tt.params.git-revision)
        # Pipelineで実行結果確認のCD部分を実装する場合はコミットIDを参照しないため下記に置き換える
        # value: image-registry.openshift-image-registry.svc:5000/$(context.pipelineRun.namespace)/$(tt.params.git-repo-name)
      workspaces:
      - name: shared-workspace
        volumeClaimTemplate:
          spec:
            accessModes:
              - ReadWriteOnce
            resources:
              requests:
                storage: 500Mi
      - name: ssh-creds
        secret:
          secretName: ssh-credential

バインディングの適用

トリガーバインディングを作成します。

$ oc create -f triggerbinding.yaml
triggerbinding.triggers.tekton.dev/sample-app created

triggerbinding.yaml

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: sample-app
spec:
  params:
  - name: git-repo-url
    # privateリポジトリのためssh_urlを参照
    value: $(body.repository.ssh_url)
  - name: git-repo-name
    value: $(body.repository.name)
  - name: git-revision
    value: $(body.head_commit.id)

トリガーの適用

トリガーを適用します。webhookのsecretも作成するため、後程トークンの値を使います。

$ oc create -f trigger.yaml
trigger.triggers.tekton.dev/sample-trigger created
secret/github-secret created

trigger.yaml

apiVersion: triggers.tekton.dev/v1beta1
kind: Trigger
metadata:
  # event_listenerで参照するTrigger名
  name: sample-trigger
spec:
  serviceAccountName: pipeline
  interceptors:
    - ref:
        name: "github"
      params:
        - name: "secretRef"
          value:
            secretName: github-secret
            secretKey: secretToken
        - name: "eventTypes"
          value: ["push"]
  bindings:
    - ref: sample-app
  template:
    ref: sample-app
---
apiVersion: v1
kind: Secret
metadata:
  name: github-secret
type: Opaque
stringData:
# webhookのシークレット
  secretToken: "1234567"

EventListenerの作成

EventListenerを作成します。

$ oc create -f event_listener.yaml
eventlistener.triggers.tekton.dev/sample-app created

event_listener.yaml

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: sample-app
spec:
  serviceAccountName: pipeline
  triggers:
    # webhookをインターセプトするTrigger名を参照
    - triggerRef: sample-trigger

EventListener サービスをルートとして公開

EventListener サービスをルートとして公開します。

$ oc expose svc el-sample-app
route.route.openshift.io/el-sample-app exposed

webhook-url を取得

webhook-url を取得を取得します。取得したURLはGit リポジトリのwebhook設定に使用します。

$ echo "URL: $(oc get route el-sample-app --template='http://{{.spec.host}}')"
URL: <webhook-url>

Webhookを手動設定する

Git リポジトリにWebhookを設定します。

  1. GitHubのリポジトリを開きます。
  2. Settings > Hook > Add Webhook をクリックします。
  3. payload URL に webhook-url を追加 > コンテンツタイプをapplication/jsonに選択 > シークレットを追加 例:1234567 > Add Webhook をクリックして設定完了です。

パイプライン実行テスト

Git リポジトリの index.php に適当な変更を加え、コミットを Git リポジトリにプッシュします。

git add .
git commit -m "hogehoge"
git push

OpenShift WebConsole Developer パースペクティブを見ると、PipelineRun が自動的に作成されます。

Succeeded になっていることを確認します。

続いて、アプリケーションに加えた変更が反映されていることを確認して完了です。

まとめ

本記事では実際に Red Hat のチュートリアルを参考にしてOpenShift Pipelines の CI 部分を構築してみました。実行確認のために CD 部分を実装しましたが、これはマニフェストファイルを適用しただけの push 型のデプロイでした。次回は CD 部分となる OpenShift GitOps を構築して デプロイ先の状態変化を検知してマニフェストファイルの状態を保ち続ける pull 型のデプロイを実装してみます。

参考文献

https://github.com/openshift/pipelines-tutorial/tree/master

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です