Tekton Pipelinesは、Kuernetes上で実行するCI/CD形式のパイプラインツールです。Kubernetes Nativeなオープンソースとして開発されています。 TektonはThe Continuous Delivery Foundation(CDF)のプロジェクトとして採用されています。
前回の記事では、Tekton PipelinesのインストールとTaskの実行例を紹介しました。本記事では複数のTaskを組み合わせて実行順番を制御するPipelineの実行例を紹介します。
対象読者
- Kubernetes-nativeなCI/CDツールを探している人
- Cloud Delivery Foundation(CDF)に興味がある人
- Cloud Nativeの思想に興味がある人
もくじ
- 検証環境
- 検証前の準備
- 検証のながれ
- PipelineResourceの定義
- Taskの定義
- Pipelineの定義
- Docker Hub認証情報の作成
- ServiceAccountの定義
- PipelineRunの定義
- Pipelineの実行
- 実行結果の確認
- さいごに
検証環境
GKE環境で検証を行いました。検証に利用したKubernetesのクライアントおよびサーバのバージョンは以下の通りです。
1 2 3 |
<span class="hljs-meta">$</span><span class="bash"> kubectl version --short</span> Client Version: v1.14.1 Server Version: v1.12.8-gke.10 |
検証前の準備
以降の実行例は、Kubernetesクラスタ上にTekton Pipelinesがインストール済みの環境で実行しています。Kubernetesクラスタの構築とTekton Pipelinesのインストール方法は、前回の記事を参照してください。
検証のながれ
今回の実行例では、以下の処理を行います。
- Git Hubからアプリケーションソースをクローン
- アプリケーションソースを含めたDockerイメージをビルド
- 作成したDockerイメージをプッシュ
- 作成したDockerイメージをKubernetes上にデプロイ
1.~3.の処理は、前回の記事で作成したマニフェストファイルを利用します。処理の詳細は前回の記事を参照してください。
PipelineResourceの定義
Git HubのリポジトリおよびDocker Hubのレジストリを指定したPipelineResourceを定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="hljs-comment"># gitResource.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">tekton.dev/v1alpha1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">PipelineResource</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">easydoggie-git</span> <span class="hljs-attr"> namespace:</span> <span class="hljs-string">default</span> <span class="hljs-attr">spec:</span> <span class="hljs-attr"> type:</span> <span class="hljs-string">git</span> <span class="hljs-attr"> params:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">url</span> <span class="hljs-attr"> value:</span> <span class="hljs-attr">https://github.com/sumomo-99/TektonSample.git</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">revision</span> <span class="hljs-attr"> value:</span> <span class="hljs-string">master</span> |
1 2 3 4 5 6 7 8 9 10 11 |
<span class="hljs-comment"># imageResource.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">tekton.dev/v1alpha1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">PipelineResource</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">easydoggie-test-image</span> <span class="hljs-attr"> namespace:</span> <span class="hljs-string">default</span> <span class="hljs-attr">spec:</span> <span class="hljs-attr"> type:</span> <span class="hljs-string">image</span> <span class="hljs-attr"> params:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">url</span> <span class="hljs-attr"> value:</span> <span class="hljs-string">easydoggie/testapp</span> |
Taskの定義
処理の流れに従ってTaskを定義します。
1.~3.の処理は、前回の記事で作成したTaskを利用します。
- Git Hubからアプリケーションソースをクローン
- アプリケーションソースを含めたDockerイメージをビルド
- 作成したDockerイメージをプッシュ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<span class="hljs-comment"># task.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">tekton.dev/v1alpha1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">Task</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">test-doker-image</span> <span class="hljs-attr">spec:</span> <span class="hljs-attr"> inputs:</span> <span class="hljs-attr"> resources:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">app</span> <span class="hljs-attr"> type:</span> <span class="hljs-string">git</span> <span class="hljs-attr"> params:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">dockerfile</span> <span class="hljs-attr"> default:</span> <span class="hljs-string">/workspace/app/Dockerfile</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">context</span> <span class="hljs-attr"> default:</span> <span class="hljs-string">/workspace/app</span> <span class="hljs-attr"> outputs:</span> <span class="hljs-attr"> resources:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">builtImage</span> <span class="hljs-attr"> type:</span> <span class="hljs-string">image</span> <span class="hljs-attr"> steps:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">build-and-push</span> <span class="hljs-attr"> image:</span> <span class="hljs-string">gcr.io/kaniko-project/executor</span> <span class="hljs-attr"> command:</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">/kaniko/executor</span> <span class="hljs-attr"> args:</span> <span class="hljs-bullet"> -</span> <span class="hljs-bullet">--dockerfile=${inputs.params.dockerfile}</span> <span class="hljs-bullet"> -</span> <span class="hljs-bullet">--destination=${outputs.resources.builtImage.url}</span> <span class="hljs-bullet"> -</span> <span class="hljs-bullet">--context=${inputs.params.context}</span> |
今回は追加で4.のTaskを作成します。
- 作成したDockerイメージをKubernetes上にデプロイ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<span class="hljs-comment"># task1.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">tekton.dev/v1alpha1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">Task</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">test-deploy</span> <span class="hljs-attr">spec:</span> <span class="hljs-attr"> inputs:</span> <span class="hljs-attr"> resources:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">source</span> <span class="hljs-attr"> type:</span> <span class="hljs-string">git</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">image</span> <span class="hljs-attr"> type:</span> <span class="hljs-string">image</span> <span class="hljs-attr"> params:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">manifestPath</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">yqArg</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">yamlPathToImage</span> <span class="hljs-attr"> steps:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">replace-image</span> <span class="hljs-attr"> image:</span> <span class="hljs-string">mikefarah/yq</span> <span class="hljs-attr"> command:</span> <span class="hljs-string">["yq"]</span> <span class="hljs-attr"> args:</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">w</span> <span class="hljs-bullet"> -</span> <span class="hljs-bullet">-i</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">${inputs.params.yqArg}</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">${inputs.params.manifestPath}</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">${inputs.params.yamlPathToImage}</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">${inputs.resources.image.url}</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">run-kubectl</span> <span class="hljs-attr"> image:</span> <span class="hljs-string">bitnami/kubectl</span> <span class="hljs-attr"> command:</span> <span class="hljs-string">["kubectl"]</span> <span class="hljs-attr"> args:</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">apply</span> <span class="hljs-bullet"> -</span> <span class="hljs-bullet">-f</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">${inputs.params.manifestPath}</span> |
このTaskでは、はじめにビルドしたイメージのタグでマニフェストファイルの書き換えを行います。マニフェストファイル(yaml)の書き換えに、Yamlのコマンドラインパースツールであるyq
を利用します。-i
オプション(in-place)を利用することで、マニフェストファイルを直接に書き換えを行っています。
次に、書き換えを行ったマニフェストファイルをkubectl apply
コマンドで適用することで、Kubernetesへのデプロイを行っています。
Pipelineの定義
Taskをまとめて順番を制御するPipelineを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<span class="hljs-comment"># pipeline.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">tekton.dev/v1alpha1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">Pipeline</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">test-pipeline</span> <span class="hljs-attr">spec:</span> <span class="hljs-attr"> resources:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">gitSource</span> <span class="hljs-attr"> type:</span> <span class="hljs-string">git</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">dockerImage</span> <span class="hljs-attr"> type:</span> <span class="hljs-string">image</span> <span class="hljs-attr"> tasks:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">build-image</span> <span class="hljs-attr"> taskRef:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">test-doker-image</span> <span class="hljs-attr"> resources:</span> <span class="hljs-attr"> inputs:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">app</span> <span class="hljs-attr"> resource:</span> <span class="hljs-string">gitSource</span> <span class="hljs-attr"> outputs:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">builtImage</span> <span class="hljs-attr"> resource:</span> <span class="hljs-string">dockerImage</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">deploy-kubernetes</span> <span class="hljs-attr"> taskRef:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">test-deploy</span> <span class="hljs-attr"> resources:</span> <span class="hljs-attr"> inputs:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">source</span> <span class="hljs-attr"> resource:</span> <span class="hljs-string">gitSource</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">image</span> <span class="hljs-attr"> resource:</span> <span class="hljs-string">dockerImage</span> <span class="hljs-attr"> from:</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">build-image</span> <span class="hljs-attr"> params:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">manifestPath</span> <span class="hljs-attr"> value:</span> <span class="hljs-string">/workspace/source/deployment.yaml</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">yqArg</span> <span class="hljs-attr"> value:</span> <span class="hljs-string">"-d0"</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">yamlPathToImage</span> <span class="hljs-attr"> value:</span> <span class="hljs-string">"spec.template.spec.containers[0].image"</span> |
後続TaskのInputに先行TaskのOutputを渡したい場合は、from
フィールドを利用することで、受け渡しを行うことができます。上記のPipelineの例では、先行Taskで作成したビルドイメージのリソース情報を後続TaskのInputに引き渡しています。
1 2 3 4 |
<span class="hljs-attr"> - name:</span> <span class="hljs-string">image</span> <span class="hljs-attr"> resource:</span> <span class="hljs-string">dockerImage</span> <span class="hljs-attr"> from:</span> <span class="hljs-comment" style="color: #cc99ff"># fromフィールドで先行TaskのOutputを渡す</span> <span class="hljs-bullet"> -</span> <span class="hljs-string">build-image</span> |
先行TaskのOutputとの紐づけが必要ない場合は、from
の代わりにrunAfter
フィールドを利用します。またTaskの実行に失敗した場合の再実行回数をretries
フィールドで指定することができます。
フィールド名 | 説明 |
---|---|
from | 先行TaskのOutputをInputに利用する後続Taskに設定する |
runAfter | 先行TaskのOutputとの紐づけが必要ない後続Taskに設定する |
retries | Taskの実行に失敗したときの再実行回数 |
params
にはTaskに引き渡すパラメータを指定します。用意したマニフェストファイルの配置場所やimageの指定位置に従って、設定を書き換えてください。
1 2 3 4 5 6 7 |
<span class="hljs-attr"> params:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">manifestPath</span> <span class="hljs-comment" style="color: #cc99ff">#Gitからcloneされたマニフェストファイルのパス</span> <span class="hljs-attr"> value:</span> <span class="hljs-string">/workspace/source/deployment.yaml</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">yqArg</span> <span class="hljs-comment" style="color: #cc99ff">#yqコマンドのオプション。マニフェストファイルに複数のリソースを設定している場合は、書き換えるリソースの位置を変えてください。0が基準でデフォルトは0です。</span> <span class="hljs-attr"> value:</span> <span class="hljs-string">"-d0"</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">yamlPathToImage</span> <span class="hljs-comment" style="color: #cc99ff">#マニフェストファイル(yaml)のコンテナイメージのパス</span> <span class="hljs-attr"> value:</span> <span class="hljs-string">"spec.template.spec.containers[0].image"</span> |
今回の実行例では、以下のようなマニフェストファイルを用意しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span class="hljs-comment">#deployment.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">testapp-deployment</span> <span class="hljs-attr">spec:</span> <span class="hljs-attr"> replicas:</span> <span class="hljs-number">1 selector: matchLabels: app: easydoggie</span> <span class="hljs-attr"> template:</span> <span class="hljs-attr"> metadata:</span> <span class="hljs-attr"> labels:</span> <span class="hljs-attr"> app:</span> <span class="hljs-string">easydoggie</span> <span class="hljs-attr"> spec:</span> <span class="hljs-attr"> containers:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">testapp</span> <span class="hljs-attr"> image:</span> <span class="hljs-string">easydoggie/testapp:latest</span> <span class="hljs-attr"> ports:</span> <span class="hljs-attr"> - containerPort:</span> <span class="hljs-number">80</span> |
Taskが実行されることで、easydoggie/testapp:latest
のイメージ名の書き換えが行われます。
Docker Hub認証情報の作成
Docker Hubへイメージをプッシュするために、Docker Hubの認証情報をKubernetesのSecretに定義します。
1 2 3 4 5 6 7 8 9 10 11 |
<span class="hljs-comment"># secret.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">Secret</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">basic-user-pass</span> <span class="hljs-attr"> annotations:</span> <span class="hljs-string">tekton.dev/docker-0:</span> <span class="hljs-attr">https://index.docker.io/v1/</span> <span class="hljs-attr">type:</span> <span class="hljs-string">kubernetes.io/basic-auth</span> <span class="hljs-attr">stringData:</span> <span class="hljs-attr"> username:</span> <span class="hljs-string"><username></span> <span class="hljs-attr"> password:</span> <span class="hljs-string"><password></span> |
ServiceAccountの定義
パイプラインを実行するアカウント(build-bot)を作成します。先ほど作成したSecretsを紐づけておきます。
1 2 3 4 5 6 7 |
<span class="hljs-comment"># serviceaccount.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">ServiceAccount</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">build-bot</span> <span class="hljs-attr">secrets:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">basic-user-pass</span> |
このアカウントでKunernetesにデプロイを実行するので、cluster-admin
の権限を与えておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="hljs-comment"># buildAccount.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">rbac.authorization.k8s.io/v1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">ClusterRoleBinding</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">build-cluster-admin</span> <span class="hljs-attr">roleRef:</span> <span class="hljs-attr"> apiGroup:</span> <span class="hljs-string">rbac.authorization.k8s.io</span> <span class="hljs-attr"> kind:</span> <span class="hljs-string">ClusterRole</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">cluster-admin</span> <span class="hljs-attr">subjects:</span> <span class="hljs-attr">- kind:</span> <span class="hljs-string">ServiceAccount</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">build-bot</span> <span class="hljs-attr"> namespace:</span> <span class="hljs-string">default</span> |
PipelineRunの定義
PipelineRunでPipelineResources
として定義したリソースをPipelineのInputとOutputに紐づけます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="hljs-comment"># pipelinerun.yaml</span> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">tekton.dev/v1alpha1</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">PipelineRun</span> <span class="hljs-attr">metadata:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">test-pipelinerun</span> <span class="hljs-attr">spec:</span> <span class="hljs-attr"> serviceAccount:</span> <span class="hljs-string">build-bot</span> <span class="hljs-attr"> pipelineRef:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">test-pipeline</span> <span class="hljs-attr"> resources:</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">gitSource</span> <span class="hljs-attr"> resourceRef:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">easydoggie-git</span> <span class="hljs-attr"> - name:</span> <span class="hljs-string">dockerImage</span> <span class="hljs-attr"> resourceRef:</span> <span class="hljs-attr"> name:</span> <span class="hljs-string">easydoggie-test-image</span> |
Pipelineの実行
以上ですべてのKubernetesマニフェストファイルの準備ができました。マニフェストファイルをkubectl apply
コマンドで適用してみましょう。
1 2 3 4 5 6 7 8 9 |
<span class="hljs-meta">$</span><span class="bash"> kubectl apply -f gitResource.yaml -f imageResource.yaml -f task.yaml -f task1.yaml -f secret.yaml -f serviceaccount.yaml -f buildAccount.yaml -f pipeline.yaml -f pipelinerun.yaml</span> pipelineresource.tekton.dev/easydoggie-git created pipelineresource.tekton.dev/easydoggie-test-image created task.tekton.dev/test-doker-image created task.tekton.dev/test-deploy created secret/basic-user-pass created serviceaccount/build-bot created pipeline.tekton.dev/test-pipeline created pipelinerun.tekton.dev/test-pipelinerun created |
実行結果の確認
1 2 3 4 5 |
<span class="hljs-meta">$</span><span class="bash"> kubectl get pods</span> NAME READY STATUS RESTARTS AGE test-pipelinerun-build-image-9d5r5-pod-84ab40 0/3 Completed 0 43s test-pipelinerun-deploy-kubernetes-q2jfj-pod-4456e7 0/3 Completed 0 16s testapp-deployment-cdcf6bdb8-5b2s9 1/1 Running 0 10s |
パイプラインに設定した2つのタスクが実行され、デプロイされたコンテナが起動しました!
PipelineRun
の実行結果は、以下のコマンドで確認することができます。
※PipelineRunの名前は(下記の例ではtest-pipelinesrun
)、確認するリソースに合わせて変更してください。
1 |
<span class="hljs-meta">$</span><span class="bash"> kubectl get pipelineruns/<span class="hljs-built_in">test</span>-pipelinerun -o yaml</span> |
タスクごとの実行時間やエラーの発生個所を調べる場合などに利用できます。
さいごに
本記事ではKubernetes-nativeなCI/CDツールである、Tekton Pipelinesのパイプラインの実行例を紹介しました。前回紹介したTaskの実行例を理解できれば、今回のパイプラインの仕組みは簡単に理解できたのではないでしょうか。
前回および今回の記事はCLIでタスク、パイプラインの実行と確認を行いました。次回はTektonのWebベースUIである、Tekton Dashboardの紹介を行う予定です。
投稿者プロフィール
最新の投稿
- AWS2021年12月2日AWS Graviton3 プロセッサを搭載した EC2 C7g インスタンスが発表されました。
- セキュリティ2021年7月14日ゼロデイ攻撃とは
- セキュリティ2021年7月14日マルウェアとは
- WAF2021年7月13日クロスサイトスクリプティングとは?