From 245c532247a5e67486468369f696e24510a88948 Mon Sep 17 00:00:00 2001 From: "Paul S. Schweigert" Date: Mon, 31 Aug 2020 23:33:48 -0400 Subject: [PATCH] Using CronJobs to automatically clean up completed Runs --- pipeline/cleanup/README.md | 25 ++++++++++++++ pipeline/cleanup/binding.yaml | 10 ++++++ pipeline/cleanup/cleanup-template.yaml | 45 +++++++++++++++++++++++++ pipeline/cleanup/cronjob.yaml | 46 ++++++++++++++++++++++++++ pipeline/cleanup/eventlistener.yaml | 17 ++++++++++ pipeline/cleanup/serviceaccount.yaml | 33 ++++++++++++++++++ 6 files changed, 176 insertions(+) create mode 100644 pipeline/cleanup/README.md create mode 100644 pipeline/cleanup/binding.yaml create mode 100644 pipeline/cleanup/cleanup-template.yaml create mode 100644 pipeline/cleanup/cronjob.yaml create mode 100644 pipeline/cleanup/eventlistener.yaml create mode 100644 pipeline/cleanup/serviceaccount.yaml diff --git a/pipeline/cleanup/README.md b/pipeline/cleanup/README.md new file mode 100644 index 000000000..e11b8eee9 --- /dev/null +++ b/pipeline/cleanup/README.md @@ -0,0 +1,25 @@ +# Cleanup old TaskRuns and PipelineRuns + +Here is how users can clean up old TaskRuns and PipelineRuns. + +The general method is to use a CronJob to trigger a Task that deletes all but the `n` most recent PipelineRuns and `2*n` most recent TaskRuns. + +## Prerequisites + +* A Kubernetes cluster with Tekton Pipelines installed +* Several old TaskRuns and/or PipelineRuns you wish to delete + +## Scheduling the cleanup job + +You'll need to install all the files in this directory to run the cleanup task. + +* [serviceaccount.yaml](serviceaccount.yaml): this creates the service account needed to run the job, along with the associated ClusterRole and Rolebinding. + +* [cleanup-template.yaml](cleanup-template.yaml): this creates the TriggerTemplate that spawns the TaskRun that does the deleting. It uses the `tkn` CLI to do the deleting. + +* [binding.yaml](binding.yaml): this creates the TriggerBinding that is used to pass parameters to the TaskRun. + +* [eventlistener.yaml](eventlistener.yaml): this creates the sink that receives the incoming event that triggers the creation of the cleanup job. + +* [cronjob.yaml](cronjob.yaml): this is used to run the cleanup job on a schedule. There are two environmental variables that need to be set in the job: `NAMESPACE` for the namespace you wish to clean up, and `CLEANUP_KEEP` for the number of PipelineRuns to keep (the job will keep twice as many TaskRuns as this number). The schedule for the job running can be set in the `.spec.schedule` field using [crontab format](https://crontab.guru/) + diff --git a/pipeline/cleanup/binding.yaml b/pipeline/cleanup/binding.yaml new file mode 100644 index 000000000..3e912e4c5 --- /dev/null +++ b/pipeline/cleanup/binding.yaml @@ -0,0 +1,10 @@ +apiVersion: triggers.tekton.dev/v1alpha1 +kind: TriggerBinding +metadata: + name: cleanup-details +spec: + params: + - name: keep + value: $(body.params.cleanup.keep) + - name: namespace + value: $(body.params.target.namespace) \ No newline at end of file diff --git a/pipeline/cleanup/cleanup-template.yaml b/pipeline/cleanup/cleanup-template.yaml new file mode 100644 index 000000000..20d70e3fa --- /dev/null +++ b/pipeline/cleanup/cleanup-template.yaml @@ -0,0 +1,45 @@ +apiVersion: triggers.tekton.dev/v1alpha1 +kind: TriggerTemplate +metadata: + name: cleanup-runs +spec: + params: + - name: namespace + description: Namespace to cleanup to in the target cluster + - name: clusterResource + description: Name of the cluster resource that points to the target cluster + - name: keep + description: Amount of old resources to keep + default: "200" + resourcetemplates: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + metadata: + name: cleanup-runs-$(tt.params.namespace)-$(uid) + spec: + serviceAccountName: tekton-cleaner + taskSpec: + params: + - name: keep + - name: namespace + steps: + - name: cleanup-pr-tr + image: gcr.io/tekton-releases/dogfooding/tkn + script: | + #!/bin/sh + set -ex + # A safety check, to avoid deleting too much! + if [[ $(params.keep) -eq 0 || $(params.keep) == "" ]]; then + echo "This task cannot be used to delete *all* resources from a cluster" >&2 + echo "Please specifcy a value for keep > 0" + exit 1 + fi + # Cleanup pipelineruns first, as this will delete tasksruns too + tkn pr delete -n $(params.namespace) --keep $(params.keep) + # Keep double the amount of tr, for standalone trs + tkn tr delete -n $(params.namespace) --keep $(( $(params.keep) * 2 )) + params: + - name: keep + value: $(tt.params.keep) + - name: namespace + value: $(tt.params.namespace) \ No newline at end of file diff --git a/pipeline/cleanup/cronjob.yaml b/pipeline/cleanup/cronjob.yaml new file mode 100644 index 000000000..d227164ec --- /dev/null +++ b/pipeline/cleanup/cronjob.yaml @@ -0,0 +1,46 @@ +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: cleanup-trigger +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + volumes: + - name: workspace + emptyDir: {} + containers: + - name: trigger + image: curlimages/curl + command: + - /bin/sh + args: + - -ce + - | + cat < /workspace/post-body.json + { + "trigger-template": "cleanup", + "params": { + "target": { + "namespace": "$NAMESPACE" + }, + "cleanup": { + "keep": "$CLEANUP_KEEP" + } + } + } + EOF + curl -d @/workspace/post-body.json $SINK_URL + volumeMounts: + - mountPath: /workspace + name: workspace + env: + - name: SINK_URL + value: "http://el-tekton-cd.default.svc.cluster.local:8080" + - name: NAMESPACE + value: "default" + - name: CLEANUP_KEEP + value: "1" + restartPolicy: Never \ No newline at end of file diff --git a/pipeline/cleanup/eventlistener.yaml b/pipeline/cleanup/eventlistener.yaml new file mode 100644 index 000000000..8bd5b11b4 --- /dev/null +++ b/pipeline/cleanup/eventlistener.yaml @@ -0,0 +1,17 @@ +apiVersion: triggers.tekton.dev/v1alpha1 +kind: EventListener +metadata: + name: tekton-cd +spec: + serviceAccountName: tekton-cleaner + triggers: + - name: cleanup + interceptors: + - cel: + filter: >- + 'trigger-template' in body && + body['trigger-template'] == 'cleanup' + bindings: + - ref: cleanup-details + template: + name: cleanup-runs \ No newline at end of file diff --git a/pipeline/cleanup/serviceaccount.yaml b/pipeline/cleanup/serviceaccount.yaml new file mode 100644 index 000000000..f9e45a346 --- /dev/null +++ b/pipeline/cleanup/serviceaccount.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: tekton-cleaner +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-cleaner +rules: +- apiGroups: [""] + resources: ["namespaces", "configmaps"] + verbs: ["get", "list", "watch"] +- apiGroups: ["tekton.dev"] + resources: ["pipelineruns", "taskruns", "pipelineresources"] + verbs: ["get", "list", "delete", "create"] +- apiGroups: ["triggers.tekton.dev"] + resources: ["eventlisteners", "triggerbindings", "triggertemplates"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: tektoncd-cleaner-delete-pr-tr-default + namespace: default +subjects: +- kind: ServiceAccount + name: tekton-cleaner + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-cleaner