---
title: Tanzu Application Platform 1.1 - 1.3でTektonのPipelineでキャッシュを使う
tags: ["Kubernetes", "Cartographer", "kind", "Tanzu", "TAP", "Tekton"]
categories: ["Dev", "CaaS", "Kubernetes", "TAP"]
date: 2022-06-29T18:21:43Z
updated: 2022-10-31T02:37:33Z
---

> ℹ️ 2022-10-30 TAP 1.3でも同じです。<br>
> ℹ️ 2022-08-15 TAP 1.2でも同じです。

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

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

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

**目次**
<!-- toc -->

### ClusterRunTemplateの更新

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

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

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

```yaml
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`にすれば良いです。<br>
> ただし、この場合はReadWriteManyに対応したPVを作成する必要があります。<br>
> 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.yml`の`package_overlays`へ次のように設定します。

```yaml
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が変更されていることを確認してください。

```yaml
$ 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の更新

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

```yaml
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でキャッシュを使用するように変更します。

```yaml
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を使用してください。

```yaml
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を用意すれば良いです。
カスタマイズが必要ですが、テストを快適に実行するには必要ではないでしょうか。
