Archive date: 2020-04-27
このコンテンツは作成された時点のものであり、それ以降の更新は適用されていません。テクノロジーの進歩により、コンテンツの一部、手順、説明図などが現在の状況と一致していない可能性があります。Tekton Pipelines は、Kubernetes クラスター内に継続的インテグレーションおよび継続的デリバリー (CI/CD) パイプラインを構成して実行するためのオープンソース・プロジェクトです。このチュートリアルでは、以下の概念とスキルを学びます。
- Tekton Pipelines プロジェクト内で用いられている基本的な概念
- Knative アプリケーションをビルドしてデプロイするパイプラインを作成する例
- パイプラインを実行してそのステータスを確認し、問題をトラブルシューティングする例
前提条件
このチュートリアルに取り組む前に、Knative と Tekton がインストールされた Kubernetes 環境をセットアップする必要があります。このチュートリアルでは環境として IBM Cloud Kubernetes サービスを利用します。
所要時間
前提条件のインストールと構成を含め、このチュートリアルを完了するのにかかる時間は約 1 時間です。
ステップ 1. Tekton Pipeline の概念を理解する
Tekton ではパイプラインを定義するための一連の Kubernetes 拡張機能をカスタム・リソースという形で提供しています。
以下の図に、このチュートリアルで使用するリソースを示します。矢印はリソース間の参照を表しています。
このチュートリアルでは以下のリソースを使用します。
- 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 つの部分からなります。
まず、Alpine Linux コンテナー内で
sed
を実行して、デプロイに使用する YAML ファイルを更新することで、source-to-image タスクによってビルドされたイメージを反映します。YAML ファイル内のこの更新が行われる箇所には__IMAGE__
文字列が必要です。次に、よく使われている 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.io
、registry.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 を試してみてください。