IK.AM

@making's tech note


Tanzu Application Platform 1.1でTektonのPipelineでキャッシュを使う

🗃 {Dev/CaaS/Kubernetes/TAP}
🏷 Cartographer 🏷 Kubernetes 🏷 TAP 🏷 Tanzu 🏷 Tekton 🏷 kind 
🗓 Updated at 2022-08-17T20:11:22+09:00  🗓 Created at 2022-06-30T03:21:43+09:00 {✒️️ Edit  ⏰ History  🗑 Delete}

ℹ️ 2022-08-15 TAP 1.2でも同じです。

こちらの記事でTAP 1.1のOut of the Box Supply Chain with Testingを試しました。
OOTBのSupply ChainではTektonのテスト時にキャッシュがないため、毎回依存ライブラリをダウンロードすることにより、テストに時間がかかってしまいます。

今回はSupply Chainをカスタマイズし、TektonのPipelineでキャッシュを使えるようにします。

Tektonでキャッシュを使用する方法は次の記事が参考になります。
https://developers.redhat.com/blog/2020/02/26/speed-up-maven-builds-in-tekton-pipelines#run_a_maven_pipeline

目次

ClusterRunTemplateの更新

キャッシュを使用するにはTektonのPipeline、PipelineRunリソースそれぞれにworkspaceの設定が必要です。

PipelineRunはootb-templateのtekton-source-pipelinerunという名前のClusterRunTemplateでtemplate化されています。
ここをカスタマイズするにはyttのoverlayを作成する必要があります。

次のoverlayファイルを作成します。1 Workloadにつき、1 PVを使用する想定です。PVCの名前は<workload name>-pipeline-cacheに固定します。

cat <<'EOF' > ootb-templates-cache-workspace.yml 
#@ load("@ytt:overlay", "overlay")
#@overlay/match by=overlay.subset({"metadata":{"name":"tekton-source-pipelinerun"}, "kind": "ClusterRunTemplate"})
---
spec:
  template:
    spec:
      #@overlay/match missing_ok=True
      workspaces:
      - name: cache
        persistentVolumeClaim:
          claimName: $(runnable.metadata.name)$-pipeline-cache
EOF

📝 Namespaceにつき1 PVを作りたい場合はclaimName$(runnable.metadata.namespace)$-pipeline-cacheにすれば良いです。
ただし、この場合はReadWriteManyに対応したPVを作成する必要があります。
kindはデフォルトでReadWriteManyのPVをサポートしていません。

overlayをSecretとして登録します。

kubectl -n tap-install create secret generic ootb-templates-cache-workspace \
  -o yaml \
  --dry-run=client \
  --from-file=ootb-templates-cache-workspace.yml \
  | kubectl apply -f-

作成したoverlayのSecret名をtap-values.ymlpackage_overlaysへ次のように設定します。

package_overlays:
# ...
- name: ootb-templates
  secrets:
  - name: ootb-templates-cache-workspace
  # ...

変更したtap-values.ymlを次のコマンドで反映します。

tanzu package installed update -n tap-install tap -f tap-values.yml

更新が完了したら次のコマンドを実行して、ClusterRunTemplateが変更されていることを確認してください。

$ kubectl get clusterruntemplate tekton-source-pipelinerun -oyaml
apiVersion: carto.run/v1alpha1
kind: ClusterRunTemplate
metadata:
  annotations:
    kapp.k14s.io/identity: v1;/carto.run/ClusterRunTemplate/tekton-source-pipelinerun;carto.run/v1alpha1
    kapp.k14s.io/original: '{"apiVersion":"carto.run/v1alpha1","kind":"ClusterRunTemplate","metadata":{"labels":{"kapp.k14s.io/app":"1656510239955370900","kapp.k14s.io/association":"v1.72b4cf08dac7ed1e3cac533f6a62ff76"},"name":"tekton-source-pipelinerun"},"spec":{"outputs":{"revision":"spec.params[?(@.name==\"source-revision\")].value","url":"spec.params[?(@.name==\"source-url\")].value"},"template":{"apiVersion":"tekton.dev/v1beta1","kind":"PipelineRun","metadata":{"generateName":"$(runnable.metadata.name)$-","labels":"$(runnable.metadata.labels)$"},"spec":{"params":[{"name":"source-url","value":"$(runnable.spec.inputs.source-url)$"},{"name":"source-revision","value":"$(runnable.spec.inputs.source-revision)$"}],"pipelineRef":{"name":"$(selected.metadata.name)$"},"workspaces":[{"name":"cache","persistentVolumeClaim":{"claimName":"$(runnable.metadata.name)$-pipeline-cache"}}]}}}}'
    kapp.k14s.io/original-diff-md5: c6e94dc94aed3401b5d0f26ed6c0bff3
  creationTimestamp: "2022-06-29T13:44:00Z"
  generation: 2
  labels:
    kapp.k14s.io/app: "1656510239955370900"
    kapp.k14s.io/association: v1.72b4cf08dac7ed1e3cac533f6a62ff76
  name: tekton-source-pipelinerun
  resourceVersion: "329502"
  uid: 54c10f86-3d28-463f-a310-f9262d2825b0
spec:
  outputs:
    revision: spec.params[?(@.name=="source-revision")].value
    url: spec.params[?(@.name=="source-url")].value
  template:
    apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      generateName: $(runnable.metadata.name)$-
      labels: $(runnable.metadata.labels)$
    spec:
      params:
      - name: source-url
        value: $(runnable.spec.inputs.source-url)$
      - name: source-revision
        value: $(runnable.spec.inputs.source-revision)$
      pipelineRef:
        name: $(selected.metadata.name)$
      workspaces: # <---------------------- Added
      - name: cache
        persistentVolumeClaim:
          claimName: $(runnable.metadata.name)$-pipeline-cache

PipelineRunが更新されると、テストが自動で再実行されます。 まだPipelineはキャッシュを使用するように設定されていないので、この段階ではキャッシュを使用しないテストが再び実施されます。

Pipelineの更新

次に前の記事で作成したhello-servlet workloadのテストにキャッシュを追加します。 次のコマンドでキャッシュ用のPVCを作成します。PVCの名前はhello-servlet-pipeline-cacheにする必要があります。

cat <<EOF > hello-servlet-pipeline-cache-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: hello-servlet-pipeline-cache
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: "1Gi"
EOF

kubectl apply -f hello-servlet-pipeline-cache-pvc.yaml -n demo

次のコマンドで、Pipelineでキャッシュを使用するように変更します。

cat <<'EOF' > pipeline-maven.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: maven-test-pipeline
  labels:
    apps.tanzu.vmware.com/pipeline: test
spec:
  params:
  - name: source-url
  - name: source-revision
  workspaces:
  - name: cache
  tasks:
  - name: test
    params:
    - name: source-url
      value: $(params.source-url)
    - name: source-revision
      value: $(params.source-revision)
    workspaces:
    - name: cache
      workspace: cache
    taskSpec:
      params:
      - name: source-url
      - name: source-revision
      workspaces:
      - name: cache
      steps:
      - name: test
        image: eclipse-temurin:17
        script: |-
          set -ex
          rm -rf ~/.m2
          mkdir -p $(workspaces.cache.path)/.m2
          ln -fs $(workspaces.cache.path)/.m2 ~/.m2
          cd `mktemp -d`
          curl -s $(params.source-url) | tar -m -xzvf -
          ./mvnw clean test -V --no-transfer-progress
EOF

kubectl apply -f pipeline-maven.yaml -n demo

Pipelineリソースを更新してもテストは再実行されません。テストを強制再実行するには、Pipelineリソースを削除すれば良いです。

kubectl delete pipelinerun -l app.kubernetes.io/part-of=hello-servlet -n demo

キャッシュを設定した直後のテストではキャッシュにデータがないため、ビルドに要する時間はキャッシュなしの場合と同じです。 次の例ではビルドに51sかかっています。

$ kubectl logs -n demo -l app.kubernetes.io/component=test,app.kubernetes.io/part-of=hello-servlet --tail=-1
...

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.example.hello.HelloServletTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.108 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  51.056 s
[INFO] Finished at: 2022-06-29T17:26:21Z
[INFO] ------------------------------------------------------------------------

もう一度Pipelineリソースを削除し、テストを再実行します。

kubectl delete pipelinerun -l app.kubernetes.io/part-of=hello-servlet -n demo

今度はキャッシュ上にデータが残っているため、ビルドは速いです。 次の例ではビルドに3.6sしかかかっていません。

$ kubectl logs -n demo -l app.kubernetes.io/component=test,app.kubernetes.io/part-of=hello-servlet --tail=-1
...
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.example.hello.HelloServletTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.144 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.652 s
[INFO] Finished at: 2022-06-29T17:27:45Z
[INFO] ------------------------------------------------------------------------

Gradleの場合は次のPipelineを使用してください。

cat <<'EOF' > pipeline-gradle.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: gradle-test-pipeline
  labels:
    apps.tanzu.vmware.com/pipeline: test
spec:
  params:
  - name: source-url
  - name: source-revision
  workspaces:
  - name: cache
  tasks:
  - name: test
    params:
    - name: source-url
      value: $(params.source-url)
    - name: source-revision
      value: $(params.source-revision)
    workspaces:
    - name: cache
      workspace: cache
    taskSpec:
      params:
      - name: source-url
      - name: source-revision
      workspaces:
      - name: cache
      steps:
      - name: test
        image: eclipse-temurin:17
        script: |-
          set -ex
          rm -rf ~/.gradle
          mkdir -p $(workspaces.cache.path)/.gradle
          ln -fs $(workspaces.cache.path)/.gradle ~/.gradle
          cd `mktemp -d`
          curl -s $(params.source-url) | tar -m -xzvf -
          ./gradlew --no-daemon test
EOF

TAP 1.1のOut of the Box Supply Chain with Testingでキャッシュを使用する方法を説明しました。この設定はworkspaceなしでPVを使わずにテストを実行することもできるので、キャッシュが必要なテストにのみPVを用意すれば良いです。 カスタマイズが必要ですが、テストを快適に実行するには必要ではないでしょうか。