Tekton Pipelinesはkubernetesクラスタ上で動作するCI/CDツールです。
ダッシュボードやCLIを用いて操作する方法が一般的ですが、TektonのCRDの1つPipelineRun
リソースをkubernetesのAPIサーバーに直接送信するプリミティブな方法でもタスクを実行できます。
ミニマムな構成では、次のような方法になります。
FRAGMENT=$(cat /dev/urandom | base64 | tr -dC '[:alnum:]' | tr '[A-Z]' '[a-z]' | fold -w 5 | head -n 1)
cat << EOF | kubectl apply -f -
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: <some-pipelinerun-name>-$FRAGMENT
spec:
pipelineRef:
name: <some-pipeline-name>
EOF
ヒアドキュメントには
PipelineRunのマニフェストを記述します。
実際には、metadata.namespace
やspec.params
、spec.workspaces
も指定することになるでしょう。
$FRAGMENT
は繰り返し実行の際に、重複を避けるための識別子生成の例です。
またkubectl
実行時にTekton Pipelinesのリソース作成権限などを前提としています。
なおこの方式は、
Tekton Triggersが適切に動作しているのであれば採用する意味はあまりありません。
Triggersのセットアップもそれなりに複雑であるため、Pipelinesのみで完結したい場合の選択肢と言えます。
コンテナ内で実行する
Pipelineをコンテナ内から起動する典型的な用途は
CronJobでしょう。
コンテナイメージにkubectl
がインストールしてあり、ServiceAccount
経由で必要な権限を供給できれば、ホスト上の操作と同様に動作します。
次のような記述例になります。
apiVersion: batch/v1
kind: CronJob
metadata:
name: <some-job-name>
spec:
jobTemplate:
spec:
template:
spec:
serviceAccountName: <some-serviceaccount>
containers:
- name: create-pipeline
image: <some-image-name-having-kubectl>
env:
- name: PODNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
command: ["bash"]
args:
- "-c"
- |
cat <<EOF | kubectl apply -f -
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: $PODNAME
spec:
pipelineRef:
name: <some-pipeline-name>
EOF
この例の特徴は2点あります。
spec.jobTemplate.spec.template.spec.serviceAccontName
にサービスアカウントを指定している-
DownwardAPIを用いてjobの名前を流用することで、
$FRAGMENT
生成を省略している。必須の方法ではないが各jobとの対応は分かりやすくなる
サービスアカウント
コンテナには、あらかじめServiceAccount
とRole
、RoleBinding
のセットを登録しておくことで権限を供給します。
apiVersion: v1
kind: ServiceAccount
metadata:
name: <some-serviceaccount>
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tekton-pipelines-operator
rules:
- apiGroups: ["tekton.dev"]
resources: ["pipelineruns", "taskruns"]
verbs: ["get", "list", "create"]
- apiGroups: ["tekton.dev"]
resources: ["pipeline"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pipeline-operator-binding
subjects:
- kind: ServiceAccount
name: <some-serviceaccount>
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: tekton-pipelines-operator
おそらくspec.pipelineRef
の影響でPipelineのread権限も要求されます。
コンテナ内の非rootユーザーで実行する
CronJob
はコンテナプロセスのユーザーで実行するため、ServiceAccountを指定するだけで、kubectl
がアクセスに必要なリソースを取得できます。
非rootで実行するような特殊なケースでは、次のような追加の工夫が必要になります。
export KUBERNETES_SERVICE_HOST=<some-host-address>
export KUBERNETES_SERVICE_PORT=<some-host-port>
FRAGMENT=$(cat /dev/urandom | base64 | tr -dC '[:alnum:]' | tr '[A-Z]' '[a-z]' | fold -w 5 | head -n 1)
cat << EOF | sudo -E kubectl apply -f -
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: <some-pipelinerun-name>-$FRAGMENT
spec:
pipelineRef:
name: <some-pipeline-name>
EOF
root実行と異なる点は次のとおりです。
- トークン類はroot向けに供給されるので、コンテナイメージに
sudo
をインストールし、実行ユーザー向けにセットアップしておく kubectl
が参照するAPIサーバーアドレスがrootの環境変数に登録されるので、該当ユーザーの環境変数に設定しておく
sudo
を用いず、トークンを該当ユーザー向けにセットアップする方法も考えられますが、必要な手間は似たようなものでしょう。