Tekton Pipelines

Tektonは、kubernetesクラスタ上で動作するCI/CDツールです。

コンテナにスクリプトやパラメータを注入し、ワークフローを制御することでテストやビルドを実装します。
ビルドのパイプラインはすべてk8sのYAML manifestとして定義していくことになります。

Tektonのインストール

Tektonは、kubernetesのリソースとして実装されており、kubectl applyでインストールできます。

基礎的な機能はPipelinesというモジュールが提供しており、以下のコマンドでセットアップできます。

$ kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

CLIインストール

クライアント向けのCLIは GitHub Releasesから各プラットフォーム用のパッケージをダウンロードしてインストールします。

パイプラインやタスクを制御するtknコマンドを利用可能になります。
複数のクラスタがある場合、kubernetesのカレントコンテキストを参照してリクエストを発行します。

Webhook

Webhookの機能はアドオンです。Pipeliesの動作を前提としているため、まずはPipelinesの完備が先決と言えます。
詳細は、 Tekton Triggersを参照してください。

Tekton Pipelinesの概要

Tektonは 公式ドキュメントが充実しているため、個別機能についてはリファレンスを通じて比較的理解しやすいと言えます。

むしろコンテナネイティブの新規性のため、アーキテクチャを把握することの方が手間どりやすいでしょう。

  • 処理手順をTaskPipelineというリソースに実装する。
  • imagevolumeMountsなど、kubernetes由来の機能をそのまま利用でき、プライベートリソースへのアクセスをセットアップできる。
  • 実際のジョブ実行リソースは、TaskRunPipelineRun。主に各ビルドのパラメータを注入する役割を持つ。これらをcreateするとPodが順次作成されビルドが走る。
  • コンテナ間のデータ共有は、 Workspacesを利用する。Pod内のVolume共有と同様の実装になる

TaskRunはコンテキスト情報のセットであり、CLIからタスクを起動する際には以下のようにオプション指定します。
TaskRunを省略した場合には、必要なパラメータをコンソールから対話的に指定するモードになります。

$ tkn task start <task_name> --use-taskrun <taskrun_name>

Pipelinesの構成リソースのうち、現状整備が進んでいないのは、inputoutputの機能です。
アーティファクトはコンテナ間をinputoutputで接続する想定でスタートしていますが、beta段階でやや非推奨状態になっています。
ドキュメントの書き方が一貫していないため、注意が必要です。

k8sバージョン互換性

Tekton Pipelinesは活発なリリースを維持しており、機能や品質、Deprecationの点で新バージョンを積極的に採り入れる運用がベターと言えます。
一方、TektonはKubernetesのサポートバージョンを適宜切り捨てている点には注意が必要です。非サポートのk8sクラスタ上でTektonをアップグレードすると、tekton-pipelinesネームスペース内の新バージョンpodが起動しない挙動になります。

この場合、k8sのバージョンはノードではなくk8sマスターのバージョンを指しています。 component skewの解説のとおり、ノードはマスターより2マイナーバージョンまで古い構成を想定しているため、マスターのみ更新する手段は妥当でしょう。

ノードにはクラウドのストレージドライバなど稼働品質に直結するコンポーネントが含まれるため、検証のうえバージョンアップすべきです。
マネージドサービスではノードがマスターバージョンを自動追従する場合があるため、意図的にバージョン混在させる際には設定に注意が必要です。

Sidecar

taskの各処理はstepsに記載しますが、サイドカー構成をサポートするためsidecarsにもコンテナを追加できます。
sidecarsブロックに複数のコンテナを起動できるため、プロキシ構成も可能です。Sidecarのネットワークサービスには、stepのコンテナからlocalhostでアクセスできます。

フロー制御が自明ではないのですが、Sidecarはsteps実行前に起動され、前提サービスとして利用できます。 Sidecar APIstartupProbeオプションがあり、k8s標準のprobeを指定することで起動完了までsteps開始を待たせられます。

ただし処理遅延などによりprobeに失敗する場合の制御が弱く、kubeletがSidecarコンテナをkillした構成のままstepsが開始します。Sidecarに依存するステップでエラーが起きますが、tkn pr describeなどで原因追跡しない限りトレースできない展開になります。
そのため長いビルドを伴うSidecarはタスク実行品質を落とす傾向を強めます。リモートリポジトリのネットワーク品質にも間接的に影響を受けます。

また、SidecarはStepより前に準備される都合上、gitリポジトリなどを利用する場合、stepとは別にセットアップする必要があります。

PipelineとTask

Taskはstepsの集合であり、PipelineはTaskの集合です。
また、Pipelineにはメインフローのspec.tasksのほか、spec.finallyを定義できます。finallyは、try-catch-finallyのfinallyにあたる処理で、tasksの処理状況によらず最終的に実行されます。

tasks.status変数に処理結果が入るため、whereによるガード判定を追加することで、catch相当の処理を書くことも可能です。

Taskの組み合わせ方については、 Tekton Pipelinesの制御フローで解説しています。

環境変数

各ステップにはPod定義と同様の設定を記述でき、envで環境変数も指定できます。
kubernetesのSecretでクレデンシャル管理で解説しているenvFromを利用するとSecretに定義したクレデンシャルを環境変数としてインポートできます。

imagePullPolicy

Taskで利用するコンテナイメージは、デフォルトではキャッシュされます。
imagePullPolicy: Alwaysを指定することで、各実行時にイメージを更新する挙動になります。

この点はドキュメントの言及がなく、修正してもイメージが差し替わらない挙動になると分かりづらいため、注意が必要です。

ステップの起動フロー

各ステップの実行内容は、主にsteps.[].scriptにbashスクリプトなどを定義します。タスク実行の際、tektonのコンテナがフローを制御し、スクリプトを起動します。
ps auxでコンテナ内のプロセスを表示すると、次のように表示されるでしょう。

USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  1.4  0.2 1272072 31488 ?       Ssl  01:00   0:00 /tekton/bin/entrypoint -wait_file /tekton/downward/ready -wait_file_content -post_file /tekton/run/0/out -termination_path /tekton/termination -step_metadata_dir /tekton/run/0/status -entrypoint /tekton/scripts/script-0-68k45 --
root          20  0.0  0.0   9944  3584 ?        S    01:00   0:00 /bin/bash -eu /tekton/scripts/script-0-68k45

kubernetesはコンテナ内のPID1を実行ステータスとして追跡しており、tektonのツールが制御している様子がうかがえます。この例ではPID20がsteps.[].scriptのユーザースクリプトです。

より詳細な構成を確認するには、分析対象のpodを特定してkubectl get pod -oyamlを実行すると、tektonが注入しているコンテナを含めた実行環境を出力します。

このように、TektonPipelinesはコンテナイメージのフローを置き換えています。イメージによっては、エントリーポイントのプロセスで環境をセットアップするものも多くありますが、既定のスタートアップ処理は実行しないことに注意が必要です。
イメージが提供するスタートアップスクリプトを実行したい場合には、steps.[].script内で直接実行するなどの追加の工夫が必要です。

timeout

各ステップにはtimeout: 30sのようにタイムアウトを指定できます。
ステップの処理が滞留した場合に時間切れでフェイルする挙動になります。

プライベートレジストリの認証

コンテナイメージの認証は、k8s標準の プライベートレジストリへのアクセス権を設定の手順で設定できます。
ただし、ServiceAccountはネームスペースごとに作成されるオブジェクトであることに注意が必要です。taskのネームスペースのデフォルトServiceAccountにsecretをアタッチする必要があります。

podTemplate

TaskRunのspec.podTemplate にはpod標準のspecを書けます。これをPipelineRunに記述する場合はspec.taskRunTemplate.podTemplateに記述します。
たとえば affinityを定義すると、タスクの実行ノードを指定できます。

タスクのリソース制約

tektonはタスクごとのPod内に、step単位でコンテナを作成します。コンテナのCPU、RAMなどのリソースはkubernetes標準の LimitRange設定を参照します。

Tekton Pipelinesのメリット

コンテナネイティブのメリットは、ビルディングブロックの再現性があります。
コンテナイメージに必要なツールをインストールしておくことで、均質なビルド環境を得られます。

実行環境もkubernetesのリソースプールの一角を利用できるため、ハード資源管理をアンバンドルできます。

Tekton Pipelinesは、ワークフロー管理がスムーズである点で良くできています。
JenkinsなどのCIツールで実装しようとすると、Jobの完了waitの機能不足などで細々とした使いにくさに直面します。

また、Pipelinesのマニフェスト規約も妥当な文法になっていると言えます。
従来のCIツールでは、メインのジョブ記述言語でラップされてしまうだめ、パラメータの参照やコンテナ上のスクリプトが素直に書けないという問題がありました。

CI/CDは複雑なシステムですが、Tektonを使うとすべてのプロセスを宣言的なコードとして管理できるようになります。

実行済タスクのクリーンアップ

tektonの実行済タスクを削除する機能は未実装です。
クリーンアップの方法は、 Using CronJobs to automatically clean up completed Runs #479のリンク先に掲載されている方法を利用できます。

ワンライナーのコマンドによりtaskrunの一括削除も可能です。

$ kubectl get taskrun --sort-by=.metadata.creationTimestamp -o name | (while read -r NAME; do kubectl delete "$NAME"; done)

ただし、taskrunにはテンプレートとインスタンスの違いがなく、一括削除するとtaskrunの再作成が必要になります。
| grep -v 'task$' |などのシェルパイプを用いて、名称の末尾マッチで除外するとインスタンスのみ削除しやすくなるでしょう。

k8s標準のJobと同様、一時的なコンテナがたくさん生成されるため、あらかじめ独立のネームスペースを確保した方が使いやすいかもしれません。
TaskやPipelineなどあらゆるリソースにnamespace指定するとコンテナ操作を切り分けられます。

⁋ 2021/06/15↻ 2024/12/18
中馬崇尋
Chuma Takahiro