目次


Tekton Pipelines を使用して Knative アプリケーションをデプロイする

Tekton Pipelines オープンソース・プロジェクトを使用して Knative アプリをビルドしてデプロイする方法を学ぶ

Tekton Pipelines は、Kubernetes クラスター内に継続的インテグレーションおよび継続的デリバリー (CI/CD) パイプラインを構成して実行するためのオープンソース・プロジェクトです。このチュートリアルでは、以下の概念とスキルを学びます。

  • Tekton Pipelines プロジェクト内で用いられている基本的な概念
  • Knative アプリケーションをビルドしてデプロイするパイプラインを作成する例
  • パイプラインを実行してそのステータスを確認し、問題をトラブルシューティングする例

前提条件

このチュートリアルに取り組む前に、Knative と Tekton がインストールされた Kubernetes 環境をセットアップする必要があります。このチュートリアルでは環境として IBM Cloud Kubernetes サービスを利用します。

所要時間

前提条件のインストールと構成を含め、このチュートリアルを完了するのにかかる時間は約 1 時間です。

ステップ 1. Tekton Pipeline の概念を理解する

Tekton ではパイプラインを定義するための一連の Kubernetes 拡張機能をカスタム・リソースという形で提供しています。

以下の図に、このチュートリアルで使用するリソースを示します。矢印はリソース間の参照を表しています。

Knative と Tekton Pipeline のアーキテクチャー図
Knative と Tekton Pipeline のアーキテクチャー図

このチュートリアルでは以下のリソースを使用します。

  • PipelineResource。パイプラインの入力 (Git リポジトリーなど) または出力 (Docker イメージなど) とするオブジェクトを定義します。
  • PipelineRun。パイプラインの実行方法を定義します。実行する Pipeline と、入力および出力として使用する PipelineResources を参照します。
  • Pipeline。パイプラインを構成する一連の Task を定義します。
  • Task。一連のビルド・ステップを定義します。コードのコンパイル、テストの実行、イメージのビルドとデプロイなどのステップです。

サンプル・パイプランについて説明する次のセクションで、各リソースの詳細を見ていきます。

ステップ 2: サンプル・パイプラインを作成する

このセクションでは、Tekton 内でパイプラインを構築する方法を説明します。サンプル・パイプラインは、以下のアクションに対処するものです。

  • ソース・ファイルから Docker イメージをビルドして、プライベート・コンテナー・レジストリーにプッシュする
  • イメージを Knative サービスとして Kubernetes クラスター内にデプロイする

クラスターに適用する yaml ファイルの中にはあらかじめ編集しておく必要があるものが含まれているため、このプロジェクトをお使いのワークステーションに複製してください。

git clone https://github.com/IBM/tekton-tutorial

基礎から取り組んでいきます。流れとしては、まず、イメージをビルドしてデプロイするために必要となる、タスクのリソースを定義します。 次に、定義したタスクを参照するパイプライン・リソースを定義します。最後に、パイプラインを実行するために必要な PipelineRun リソースと PipelineResource リソースを作成します。

イメージをビルドしてコンテナー・レジストリーにプッシュするタスクを作成します。以下の Tekton タスクは、Docker イメージをビルドしてコンテナー・レジストリーにプッシュします。このコード・スニペットが含まれる完全な YAML ファイルは tekton/tasks/source-to-image.yaml から入手できます。

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: source-to-image
spec:
  inputs:
    resources:
      - name: git-source
        type: git
    params:
      - name: pathToContext
        description: The path to the build context, used by Kaniko - within the workspace
        default: .
      - name: pathToDockerFile
        description: The path to the dockerfile to build (relative to the context)
        default: Dockerfile
      - name: imageUrl
        description: Url of image repository
      - name: imageTag
        description: Tag to apply to the built image
        default: "latest"
  steps:
    - name: build-and-push
      image: gcr.io/kaniko-project/executor
      command:
        - /kaniko/executor
      args:
        - --dockerfile=${inputs.params.pathToDockerFile}
        - --destination=${inputs.params.imageUrl}:${inputs.params.imageTag}
        - --context=/workspace/git-source/${inputs.params.pathToContext}

Tekton タスクには 1 つ以上のステップを含めることができます。各ステップが、そのステップの役割を果たすために実行するイメージを定義します。上記のタスクは 1 つのステップからなります。このステップは Kaniko プロジェクトを使用して、ソースから Docker イメージをビルドし、そのイメージをレジストリーにプッシュします。

このタスクには、ソースが置かれている場所を定義する git タイプの入力リソースが必要です。 git ソースは /workspace/git-source にあるローカル・ボリュームに複製されています。ここで、git-source はリソースに指定した名前です (ここでのリソースは、タスクに渡す抽象的な引数に過ぎないことに注意してください)。

このチュートリアルの後のほうで、この引数が実際に使用するリソースを定義する PipelineResources リソースにバインドされる仕組みがわかります。タスクは複数の異なる Git リポジトリーで再利用できます。

Tekton タスクでは入力パラメーターも使用できます。パラメーターを使用すると、Task をより簡単に再利用できるようになります。

上記のタスクは以下のパラメーターを受け入れます。

  • Git ソース内での Docker ビルド・コンテキストのパス
  • ビルド・コンテキスト内での Dockerfile のパス
  • イメージの保管先イメージ・リポジトリーの URL
  • ビルドされたイメージに適用するイメージ・タグ

イメージをプッシュする権限を得るために、タスクがイメージ・リポジトリーに対してどのように認証を行うのか疑問に思われているかもしれません。認証については後述するので、チュートリアルを読み進めてください。

タスクを作成するには、このファイルをクラスターに適用します。

kubectl apply -f tekton/tasks/source-to-image.yaml

ステップ 3. イメージを Kubernetes クラスターにデプロイするタスクを作成する

以下に示す Tekton タスクは、Docker イメージを Kubernetes クラスターにデプロイします。このコード・スニペットが含まれる完全な YAML ファイルは tekton/tasks/deploy-using-kubectl.yaml から入手できます。

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: deploy-using-kubectl
spec:
  inputs:
    resources:
      - name: git-source
        type: git
    params:
      - name: pathToYamlFile
        description: The path to the yaml file to deploy within the git source
      - name: imageUrl
        description: Url of image repository
      - name: imageTag
        description: Tag of the images to be used.
        default: "latest"
  steps:
    - name: update-yaml
      image: alpine
      command: ["sed"]
      args:
        - "-i"
        - "-e"
        - "s;__IMAGE__;${inputs.params.imageUrl}:${inputs.params.imageTag};g"
        - "/workspace/git-source/${inputs.params.pathToYamlFile}"
    - name: run-kubectl
      image: lachlanevenson/k8s-kubectl
      command: ["kubectl"]
      args:
        - "apply"
        - "-f"
        - "/workspace/git-source/${inputs.params.pathToYamlFile}"

イメージを Kubernetes クラスターにデプロイするタスクを作成するプロセスは、2 つの部分からなります。

  1. まず、Alpine Linux コンテナー内で sed を実行して、デプロイに使用する YAML ファイルを更新することで、source-to-image タスクによってビルドされたイメージを反映します。YAML ファイル内のこの更新が行われる箇所には __IMAGE__ 文字列が必要です。
  2. 次に、よく使われている Lachlan Evenson の k8s-kubectl コンテナー・イメージを使用して kubectl を実行し、パイプラインが実行されるのと同じクラスターにこの YAML ファイルを適用します。source-to-image タスクと同じく、このタスクでも入力 PipelineResource とパラメーターを使用して可能な限り再利用しやすくしています。

YAML ファイル内のリソースを適用する権限を得るために、タスクがクラスターに対してどのように認証を行うのか興味がある場合は、この先を読み続けてください。このチュートリアルの後のほうのステップで、認証について説明します。

タスクを作成するには、このファイルをクラスターに適用します。

kubectl apply -f tekton/tasks/deploy-using-kubectl.yaml

ステップ 4. パイプラインを作成する

以下に示す Tekton パイプラインは、これまでに説明した 2 つのタスクを実行します。このコード・スニペットが含まれる完全な YAML ファイルは tekton/pipeline/build-and-deploy-pipeline.yaml から入手できます。

apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
  name: build-and-deploy-pipeline
spec:
  resources:
    - name: git-source
      type: git
  params:
    - name: pathToContext
      description: The path to the build context, used by Kaniko - within the workspace
      default: src
    - name: pathToYamlFile
      description: The path to the yaml file to deploy within the git source
    - name: imageUrl
      description: Url of image repository
    - name: imageTag
      description: Tag to apply to the built image
  tasks:
  - name: source-to-image
    taskRef:
      name: source-to-image
    params:
      - name: pathToContext
        value: "${params.pathToContext}"
      - name: imageUrl
        value: "${params.imageUrl}"
      - name: imageTag
        value: "${params.imageTag}"
    resources:
      inputs:
        - name: git-source
          resource: git-source
  - name: deploy-to-cluster
    taskRef:
      name: deploy-using-kubectl
    runAfter:
      - source-to-image
    params:
      - name: pathToYamlFile
        value:  "${params.pathToYamlFile}"
      - name: imageUrl
        value: "${params.imageUrl}"
      - name: imageTag
        value: "${params.imageTag}"
    resources:
      inputs:
        - name: git-source
          resource: git-source

Tekton Pipeline リソースは、実行するタスクをリストアップし、各タスクに必要な入力リソース、出力リソース、入力パラメーターを指定します。すべてのリソースがパイプラインの入力または出力として公開される必要があります。パイプラインで所定のリソースを実際の PipelineResource にバインドすることはできません。ただし、タスクの入力パラメーターをパイプラインの入力パラメーターとして公開するか、値を直接設定するか、またはタスクの (オプション・パラメーターに) デフォルト値を受け入れるかは選択できます。

例えば、上記のパイプラインでは source-to-image タスクの pathToContext パラメーターを公開していますが、pathToDockerFile パラメーターは公開せずに、タスク内でデフォルトに設定できるようにしています。

タスク間の依存関係を表すには、runAfter キーを使用します。このキーが指定されたタスクは、リストの前のタスクが完了してから実行されることになります。

この例のパイプラインでは、deploy-using-kubectl タスクを source-to-image タスクの後に実行するように指定しています。Tekton はこの依存関係を満たすために、タスクの実行を順序付けます。

タスク間の依存関係は from キーを使って表すこともできます。このチュートリアルではこのキーを使用していませんが、Tekton のドキュメントで詳細を確認できます。

パイプラインを作成するには、このファイルをクラスターに適用します。

kubectl apply -f tekton/pipeline/build-and-deploy-pipeline.yaml

ステップ 5. PipelineRun と PipelineResources を作成する

イメージをビルドしてデプロイするために再利用できるパイプラインとタスク・リソースを定義したので、実際の入力リソースとパラメーターを使用してパイプラインを実行する方法を見ていきましょう。

以下に示す Tekton PipelineRun リソースは、前のステップで定義したパイプラインを実行します。このコード・スニペットが含まれる完全な YAML ファイルは tekton/run/picalc-pipeline-run.yaml から入手できます。

apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
  generateName: picalc-pr-
spec:
  pipelineRef:
    name: build-and-deploy-pipeline
  resources:
    - name: git-source
      resourceRef:
        name: picalc-git
  params:
    - name: pathToYamlFile
      value: "knative/picalc.yaml"
    - name: imageUrl
      value: <REGISTRY>/<NAMESPACE>/picalc
    - name: imageTag
      value: "1.0"
  trigger:
    type: manual
  serviceAccount: pipeline-account

このファイルは小さいながらも、かなり濃い内容になっています。

  • PipelineRun リソースの名前は固定されていません。このリソースが作成されるたびに、generateName を使用して名前が生成されます。なぜでしょうか?どの PipelineRun リソースもパイプラインを 1 回しか実行しません。パイプラインを再度実行する必要がある場合、パイプラインの再実行をリクエストするように既存の PipelineRun リソースを変更することはできないため、別の PipelineRun リソースを作成しなければなりません。PipelineRun リソースを作成するたびに、name を使用して固有の名前を割り当てることもできますが、それよりも generateName を使ったほうが遥かに簡単です。
  • Pipeline リソースは pipelineRef キーで識別されます。
  • パイプラインに必要な Git リソースは、次のステップで定義する、picalc-git という名前の特定の PipelineResources にバインドされています。
  • パイプラインで公開されるパラメーターは、特定の値に設定されています。
  • pipeline-account という名前のサービス・アカウントが、パイプラインを正常に実行するために必要な資格情報を提供するように指定されています。このサービス・アカウントはチュートリアルの次のステップで定義します。

このファイルを編集して、<REGISTRY><NAMESPACE> の値を実際のプライベート・コンテナー・レジストリーの情報で置き換える必要があります。<REGISTRY> の値を調べるには、コマンド ibmcloud cr region を実行します。<NAMESPACE> の値を調べるには、コマンド ibmcloud cr namespace-list を実行します。

以下に示す、picalc-git の Tekton PipelineResource が Git ソースを定義します。このコード・スニペットが含まれる完全な YAML ファイルは tekton/resources/picalc-git.yaml から入手できます。

apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: picalc-git
spec:
  type: git
  params:
    - name: revision
      value: master
    - name: url
      value: https://github.com/IBM/tekton-tutorial

このサンプルのソース・コードは、円周率の近似値を計算する Go プログラムです。このソースに含まれる Dockerfile がテストを実行し、コードをコンパイルして、実行するイメージをビルドします。

現時点で、PipelineResource ファイルをクラスターに適用できます。PipelineRun ファイルはまだ適用しないでください。このリソース用のサービス・アカウントを定義する作業がまだ残っています。

kubectl apply -f tekton/pipeline/tekton/resources/picalc-git.yaml

ステップ 6. サービス・アカウントを定義する

パイプラインを実行する前に必要な最後のステップは、パイプラインが保護されたリソースにアクセスできるよう、サービス・アカウントをセットアップすることです。特定の Kubernetes リソースを作成して変更する権限を与えるために、サービス・アカウントは認証用の資格情報を含むシークレットを RBAC 関連のリソースに結び付けます。

まず、プライベート・コンテナー・レジストリーにプログラムでアクセス可能にするために、レジストリー・トークンまたは IBM Cloud Identity and Access Management (IAM) API キーのいずれかを作成します。 トークンまたは API キーの作成プロセスは、ここに説明されています。

トークンまたは API キーを作成した後、以下のシークレットを作成できます。

kubectl create secret generic ibm-cr-push-secret --type="kubernetes.io/basic-auth" --from-literal=username=<USER> --from-literal-password=<TOKEN/APIKEY>
kubectl annotate secret ibm-cr-push-secret tekton.dev/docker-0=<REGISTRY>

ここで

  • <USER> は、token (トークンを使用する場合) または iamapikey (API キーを使用する場合) です。
  • <TOKEN/APIKEY> は、作成したトークンまたは API キーです。
  • <REGISTRY> は、コンテナー・レジストリーの URL です (us.icr.ioregistry.ng.bluemix.net など)

これで、以下の YAML ファイルを使用してサービス・アカウントを作成できます。このコード・スニペットが含まれる完全な YAML ファイルは tekton/pipeline-account.yaml から入手できます。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: pipeline-account
secrets:
- name: ibm-cr-push-secret

---

apiVersion: v1
kind: Secret
metadata:
  name: kube-api-secret
  annotations:
    kubernetes.io/service-account.name: pipeline-account
type: kubernetes.io/service-account-token

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pipeline-role
rules:
- apiGroups: ["serving.knative.dev"]
  resources: ["services"]
  verbs: ["get", "create", "update", "patch"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pipeline-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pipeline-role
subjects:
- kind: ServiceAccount
  name: pipeline-account

この YAML により、以下の Kubernetes リソースが作成されます。

  • pipeline-account という名前の ServiceAccount。前に記載した PipelineRun は、この名前を使用してサービス・アカウントを参照します。サービス・アカウントは ibm-cr-push-secret シークレットを参照するため、パイプラインはコンテナー・イメージをプッシュする際にプライベート・コンテナー・レジストリーに対して認証することができます。
  • kube-api-secret という名前の Secret。これには、Kubernetes API にアクセスするための (Kubernetes によって生成された) API 資格情報が含まれています。この kube-api-secret を使用することで、パイプラインは kubectl を使ってクラスターと対話できます。
  • pipeline-role という名前の Role と、pipeline-role-binding という名前の RoleBinding。この 2 つのリソースにより、パイプラインが Knative サービスを作成、変更するために必要なリソース・ベースのアクセス制御権限が提供されます。

サービス・アカウントとその関連リソースを作成するには、このファイルをクラスターに適用します。

kubectl apply -f tekton/pipeline-account.yaml

ステップ 7. パイプラインを実行する

すべての要素が揃い、パイプラインを実行できる状態になりました。

kubectl create -f tekton/run/picalc-pipeline-run.yaml

このチュートリアルでは apply ではなく create を使用していることに注意してください。前述のとおり、PipelineRun リソースはパイプラインを 1 回しか実行できないため、パイプラインを実行するたびに新しく作成し直す必要があります。

この kubectl を実行すると、生成された PipelineRun リソースの名前が返されます。

pipelinerun.tekton.dev/picalc-pr-db6p6 created

パイプラインのステータスを確認するには、kubectl describe コマンドを使用します。

kubectl describe pipelinerun picalc-pr-db6p6

PipelineRun を作成した直後にこのコマンドを入力すると、以下のような出力が表示される場合があります。

Name:         picalc-pr-db6p6
Namespace:    default
Labels:       tekton.dev/pipeline=build-and-deploy-pipeline
Annotations:  <none>
API Version:  tekton.dev/v1alpha1
Kind:         PipelineRun
Metadata:
  Creation Timestamp:  2019-04-15T14:29:23Z
  Generate Name:       picalc-pr-
  Generation:          1
  Resource Version:    3893390
  Self Link:           /apis/tekton.dev/v1alpha1/namespaces/default/pipelineruns/picalc-pr-db6p6
  UID:                 dd207211-5f8a-11e9-b66d-8eb09a9ab3eb
Spec:
  Status:  
  Params:
    Name:   pathToYamlFile
    Value:  knative/picalc.yaml
    Name:   imageUrl
    Value:  registry.ng.bluemix.net/mynamespace/picalc
    Name:   imageTag
    Value:  1.3
  Pipeline Ref:
    Name:  build-and-deploy-pipeline
  Resources:
    Name:  git-source
    Resource Ref:
      Name:         picalc-git
  Service Account:  pipeline-account
  Trigger:
    Type:  manual
Status:
  Conditions:
    Last Transition Time:  2019-04-15T14:29:23Z
    Message:               Not all Tasks in the Pipeline have finished executing
    Reason:                Running
    Status:                Unknown
    Type:                  Succeeded
  Start Time:              2019-04-15T14:29:23Z
  Task Runs:
    Picalc - Pr - Db 6 P 6 - Source - To - Image - Kczdb:
      Pipeline Task Name:  source-to-image
      Status:
        Conditions:
          Last Transition Time:  2019-04-15T14:29:28Z
          Reason:                Building
          Status:                Unknown
          Type:                  Succeeded
        Pod Name:                picalc-pr-db6p6-source-to-image-kczdb-pod-7b4e7c
        Start Time:              2019-04-15T14:29:23Z
        Steps:
          Running:
            Started At:  2019-04-15T14:29:26Z
          Terminated:
            Container ID:  containerd://b8f770e2b57d59c2bce76c63713d0b0a33f3fd02a14bad6b96978012060a436a
            Exit Code:     0
            Finished At:   2019-04-15T14:29:26Z
            Reason:        Completed
            Started At:    2019-04-15T14:29:26Z
          Terminated:
            Container ID:  containerd://a637b1cb5d83b1ad2aa0dbecd962bb70b0452900189f611e404c0c9515262443
            Exit Code:     0
            Finished At:   2019-04-15T14:29:26Z
            Reason:        Completed
            Started At:    2019-04-15T14:29:26Z
Events:                    <none>

Not all Tasks in the Pipeline have finished executing」というメッセージが示されています。この場合、コマンドを再実行してステータスを確認してください。パイプラインが正常に実行されると、最終的にパイプライン全体のステータスは以下のようになります。

Status:
  Conditions:
    Last Transition Time:  2019-04-15T14:30:46Z
    Message:               All Tasks have completed executing
    Reason:                Succeeded
    Status:                True
    Type:                  Succeeded
  Start Time:              2019-04-15T14:29:23Z

デプロイ済み Knative サービスのステータスを確認すると、以下のように実行可能な状態になっているはずです。

$ kubectl get ksvc picalc
NAME      DOMAIN                                                          LATESTCREATED   LATESTREADY    READY     REASON
picalc    picalc.default.mycluster6.us-south.containers.appdomain.cloud   picalc-00001    picalc-00001   True

レスポンスに示されている URL を使用して、サービスに対して curl を実行できます。

$ curl picalc.default.mycluster6.us-south.containers.appdomain.cloud?iterations=20000000
3.1415926036

パイプラインが正常に実行されなかった場合、パイプライン全体のステータスは以下のようになります。

Status:
  Conditions:
    Last Transition Time:  2019-04-15T14:30:46Z
    Message:               TaskRun picalc-pr-db6p6-deploy-to-cluster-7h8pm has failed
    Reason:                Failed
    Status:                False
    Type:                  Succeeded
  Start Time:              2019-04-15T14:29:23Z

この場合、タスクの実行ステータスとして以下のようなメッセージが示されます。このメッセージを参考に、失敗したビルド・ステップからのログを取得してください。ログを調べると、問題を特定できます。

build step "build-step-deploy-using-kubectl" exited with code 1 (image: "docker.io/library/alpine@sha256:28ef97b8686a0b5399129e9b763d5b7e5ff03576aa5580d6f4182a49c5fe1913"); for logs run: kubectl -n default logs picalc-pr-db6p6-deploy-to-cluster-7h8pm-pod-582c73 -c build-step-deploy-using-kubectl

ヒント

PipelineResource をあるタスクの出力として定義し、別のタスクの入力として定義する場合には注意が必要です。

例えば、このチュートリアルではイメージ PipelineResource を使用して、source-to-image タスクからの出力イメージと、deploy-using-kubectl タスクへの入力イメージを定義することも考えられました。

このように定義すると、Tekton がタスク間でデータを共有するための PersistentVolumeClaim を作成することになります。この記事を公開する時点では、Tekton Pipeline のこの機能は部分的にしか実装されていないため、チュートリアルでは使用しませんでした。

まとめ

Tekton は、Kubernetes 上で実行する CI/CD を構築するためのシンプルで習得しやすい機能を提供します。

このチュートリアルでは皆さんが独自のパイプラインの構築を開始できるよう、Tekton の基礎を説明しました。チュートリアルでは取り上げていない機能は他にもたくさんあります。また、今後のリリースに向けてさらに多くの機能が計画されています。IBM Cloud Kubernetes サービスで Tekton を試してみてください。


ダウンロード可能なリソース

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing
ArticleID=1067914
ArticleTitle=Tekton Pipelines を使用して Knative アプリケーションをデプロイする
publish-date=06052019