今、パイプライン界隈がアツい
Continuous Delivery Foundation (CDF)が発足されたので、CI/CD関連ツールの足並みが揃えば、パイプラインおじさんが泥臭いコードでツール間を繋がなくても、スマートな定義ファイルで良しなに実行してくれる未来が来そうです。
Tekton is 何?
Kubernetesを単なるコンテナマネージメントシステムとして使うのでは無く、開発のエコシステムとして使えるようにするぜ!という激アツなプロジェクトKnativeのパイプライン担当です。最近は、Knative依存を減らして、より汎用的に使えるように進化中。
CDFの1プロジェクトでもあり、Cloud Nativeなパイプラインを構築するために、触れておいて損はないかと。
使ってみる
公式のGithub repositoryにドキュメントがあるので、インストール方法は割愛します。
https://github.com/tektoncd/pipeline
git clone -> docker build -> docker push
今回は、とてもシンプルなビルドパイプラインです。
Git serverはGitHub(アクセストークン等が無くても、git cloneできる)、ビルドはDockerのmultistage-buildを利用、ビルド環境自体にはKanikoを利用しています。
Kubernetesの定義ファイルは、下記のリポジトリにコミットしてあります。
https://github.com/TakiTake/tekton-test/tree/sample/task/task/build
用語解説
処理を定義する方法は、大きく分けて2つあり、TaskとPipelineがあります。
Task
Taskは複数のStepによって構成されていて、各Stepは上から順番に実行されることが保証されています。また、各Stepはコンテナの中で実行されるので、Container Imageを指定する必要があります。Task内でビルドするアプリのリポジトリ、もしくは、Taskの成果物としてのContainer Image等は、PipelineResourceとして定義することが可能です。
Pipeline
Taskの実行フローを定義できます。Stepは上から下へ順次実行することしかできませんでしたが、PipelineはTaskを並列で実行することや、Task同士に依存を張ることが可能です。
定義ファイルの解説
まず、defaultのサービスアカウントにcluster-adminを紐付けておきます。本番で使用する場合は、defaultよりも専用の名前で用意した方が良いのですが、検証用ですのでこのまま進めます。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: default-cluster-admin
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
次に、Tekton Pipelineリソースの定義です。定義したリソースは、Taskのinput/outputとして利用できます。
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: hello-world-image
spec:
type: image
params:
- name: url
value: takitake/hello-world-go
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: hello-world-go-git
spec:
type: git
params:
- name: revision
value: master
- name: url
value: https://github.com/TakiTake/hello-world-go.git
いよいよTaskの定義です。理由は後ほど説明しますが、Taskのinput/outputには、gitリソースを使う、成果物としてimageを作るという抽象的な定義を記載します。また、仕様として**/workspace/リソース名**にinputリソースのデータが書き出されます。gitであれば、git clone先という意味です。
そして、Stepの解説です。ContainerのビルドにKanikoを使っており、ビルド後にDocker Hubへアップロードするためにtekton用のannotationを付与したSecretを作成します。annotationにtekton.dev/docker-というプレフィックス始まりのキーを付与すると、Taskの初期化時に$HOME/.docker/config.jsonファイルを自動生成してくれます。詳しくは、Authenticationをご覧ください。
apiVersion: v1
kind: Secret
metadata:
name: basic-user-pass
annotations:
tekton.dev/docker-0: https://index.docker.io/v1/
type: kubernetes.io/basic-auth
stringData:
username: <username>
password: <password>
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-bot
secrets:
- name: basic-user-pass
その他の変数は、input/outputの定義から参照できます。
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: build-push-kaniko
spec:
inputs:
resources:
- name: app
type: git
params:
- name: pathToDockerFile
description: The path to the dockerfile to build
default: /workspace/app/Dockerfile
- name: pathToContext
description: The build context used by Kaniko (https://github.com/GoogleContainerTools/kaniko#kaniko-build-contexts)
default: /workspace/app
outputs:
resources:
- name: builtImage
type: image
steps:
- name: build-and-push
image: gcr.io/kaniko-project/executor
command:
- /kaniko/executor
args:
- --dockerfile=${inputs.params.pathToDockerFile}
- --destination=${outputs.resources.builtImage.url}
- --context=${inputs.params.pathToContext}
最後に、Taskの実行方法です。YAML疲れするかもしれませんが、これもYAMLで定義します。Taskを実行するにあたって渡したい変数や、紐づけたいPipelineResourceを記載します。Taskの定義がやや抽象的だったのは、TaskRunで具体的な値を注入する思想だからです。これにより、Task定義の再利用がしやすくなっています。
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
name: build-push-run
spec:
serviceAccount: build-bot
taskRef:
name: build-push-kaniko
trigger:
type: manual
inputs:
resources:
- name: app
resourceRef:
name: hello-world-go-git
params:
- name: pathToDockerFile
value: /workspace/app/Dockerfile
- name: pathToContext
value: /workspace/app
outputs:
resources:
- name: builtImage
resourceRef:
name: hello-world-image
まとめ
Tektonで簡単なTaskを実行してみました。ローカルPCでマニュアル実行するなら、docker build, docker pushで済む話ですが、より複雑なフローや、似たようなフローを制御する内にありがたみを実感できるのではないかと自分も期待しています。
次回は、Pipelineを解説予定ですー