Retention Policy Configuration

Tekton Results retention policy provides automated cleanup for both database records and archived logs in S3-compatible storage systems. The retention agent periodically removes expired results according to configurable time-based policies and deletes their associated log payloads on a best-effort basis (see Retention Value Limits).

Configuration

Retention policies are configured through the TektonConfig custom resource using the spec.result.options field to specify ConfigMap overrides:

apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
  name: config
spec:
  result:
    logs_api: true
    logs_type: S3
    secret_name: my-s3-secret
    is_external_db: true
    db_host: your-postgres-host.example.com
    db_port: 5432
    db_name: tekton_results
    db_sslmode: require
    db_secret_name: tekton-results-postgres
    options:
      configMaps:
        tekton-results-config-results-retention-policy:
          data:
            defaultRetention: "30"  # Days to retain results (30 days)
            runAt: "0 2 * * *"      # Cron schedule: daily at 2 AM

Configuration Parameters

FieldDescriptionDefaultRequired
defaultRetentionRetention period before deletion"30" (30 days)No
runAtCron schedule for running the retention agent"5 5 * * 0" (weekly, Sundays at 05:05 )Yes

The defaults above are the values in the tekton-results-config-results-retention-policy ConfigMap installed with Tekton Results. If defaultRetention is removed from the ConfigMap, the retention agent falls back to a built-in value of 30 days instead of failing. There is no usable fallback for runAt: keep it set to a valid five-field cron expression. Its built-in value, 7 7 * * 7, is rejected by the cron parser the retention agent uses, which only accepts day-of-week values from 0 to 6, so the retention agent fails to start when runAt is removed or is not a valid cron expression.

defaultRetention accepts three equivalent formats: a plain integer is a number of days ("30"), a d suffix also means days ("30d"), and any other value is parsed as a Go duration ("720h").

  • defaultRetention: Specifies how long to retain results before automatic deletion. After this period elapses, the database records are deleted and the retention agent also tries to delete the associated log payloads in S3 storage; log deletion is best effort, see Retention Value Limits.

  • runAt: Cron expression defining when the retention agent runs.

    • "0 2 * * *" - Daily at 2:00 AM
    • "0 2 * * 0" - Weekly on Sundays at 2:00 AM
    • "0 2 1 * *" - Monthly on the 1st at 2:00 AM

Retention Value Limits

  • No upper bound or sign check: defaultRetention and each policy retention value are only checked for a parsable format. Tekton Results does not cap the retention period; choose it according to your own audit or compliance requirements. A value in days (a plain integer or the d suffix) is converted to a Go time.Duration without an overflow check, so a value above 106751 days (about 292 years) wraps around to an unrelated duration, which can be negative or close to zero, and the next run then deletes results as described in the next item. Do not use a very large number to mean "keep forever". A Go duration string above the same limit, such as "2562048h", fails to parse instead.
  • "0" and negative values delete every result they cover: A result expires when its record was last updated before now - retention. With "0" the cutoff is the time the job runs, and with a negative value the cutoff is in the future. The retention that applies to a result is the one of its first matching policy, or defaultRetention when no policy matches (see Per-Namespace or Per-Label Retention). So a policy retention of "0" or less makes the next run delete every result whose first matching policy it is, and a defaultRetention of "0" or less makes it delete every result that matches no policy. Their logs are deleted on a best-effort basis, as described in the next item.
  • Log deletion is best effort: Deleting log payloads from external storage can be turned off by a feature gate, and a deletion that still fails after its retries is ignored so that the database cleanup proceeds. Log payloads can therefore remain in storage after their result records are gone. If log expiry is a requirement, also configure a lifecycle rule on the storage bucket, or monitor the bucket for log payloads older than the retention period.
  • A leftover maxRetention overrides defaultRetention: The deprecated maxRetention key is still read. When it is present, its value is used as the default retention and defaultRetention is ignored; the retention agent only logs a deprecation warning. Before you rely on defaultRetention, remove maxRetention from the ConfigMap, moving its value to defaultRetention if you want to keep it.

Relationship with In-Cluster Pruning

The upstream Tekton Results documentation recommends using the retention policy together with an in-cluster pruning mechanism such as Tekton Pruner, with a Results retention period longer than the in-cluster retention period. This avoids a pruned result being re-created in the database while its PipelineRun or TaskRun still exists in the cluster.

Per-Namespace or Per-Label Retention

Use the policies key to give selected results their own retention period, for example a longer period for namespaces that hold audit-relevant pipelines. policies is a YAML string containing a list of policies, each with a name, a selector, and a retention value (same formats as defaultRetention):

  • Policies are evaluated in order, and the first matching policy applies. Results that match no policy use defaultRetention.
  • A selector can combine matchNamespaces, matchLabels, matchAnnotations, and matchStatuses. All specified fields must match; within one field, any listed value matches. matchLabels and matchAnnotations map a key to a list of accepted values and are evaluated against the PipelineRun or TaskRun metadata. matchStatuses is evaluated against the reason of the first status condition, such as Succeeded or Failed.

The following example keeps results from one namespace and from runs with one label for different periods. It shows only the retention keys: merge them into spec.result.options of the existing TektonConfig (for example with kubectl edit tektonconfig config) and keep its other spec.result fields, such as the database and log settings shown in Configuration:

apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
  name: config
spec:
  result:
    options:
      configMaps:
        tekton-results-config-results-retention-policy:
          data:
            defaultRetention: "30"
            runAt: "5 5 * * 0"
            policies: |
              - name: audit-namespaces
                selector:
                  matchNamespaces:
                    - release-prod
                retention: "365"  # Example value; set it from your retention requirements
              - name: ci-runs
                selector:
                  matchLabels:
                    team:
                      - ci
                retention: "7"    # Example value

Apply Configuration

Apply the TektonConfig configuration. The file must contain the complete spec.result you want, including the existing database and log settings; to change only the retention keys, edit the existing TektonConfig instead of applying a file that holds only those keys:

kubectl apply -f tekton-config-retention-config.yaml

Example Output:

tektonconfig.operator.tekton.dev/config configured

Wait for the retention agent to restart:

kubectl rollout status -n tekton-pipelines deployment/tekton-results-retention-policy-agent

Example Output:

deployment "tekton-results-retention-policy-agent" successfully rolled out

Verify the configuration is active:

kubectl get pods -n tekton-pipelines -l app.kubernetes.io/name=tekton-results-retention-policy-agent

Example Output:

NAME                                                   READY   STATUS    RESTARTS   AGE
tekton-results-retention-policy-agent-5c9g2            1/1     Running   0          5m

Important Note

Important: The unified cleanup functionality (deleting database records and, on a best-effort basis, their S3 log payloads; see Retention Value Limits) is a enhancement (patch-based) and is not currently available in community Tekton Results. The community version only removes database records but leaves log payloads in S3 storage, which can lead to unbounded storage growth.

Check TektonConfig retention configuration:

kubectl get tektonconfig config -o yaml

Example Output (abbreviated):

apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
  name: config
spec:
  result:
    logs_api: true
    logs_type: S3
    secret_name: my-s3-secret
    is_external_db: true
    db_host: your-postgres-host.example.com
    options:
      configMaps:
        tekton-results-config-results-retention-policy:
          data:
            defaultRetention: "30"
            runAt: "0 2 * * *"

Check retention agent logs:

kubectl logs -n tekton-pipelines deployment/tekton-results-retention-policy-agent

Example Output:

{"level":"info","ts":"2023-05-15T10:30:45.123Z","caller":"retention/main.go:89","msg":"Starting Tekton Results retention policy agent"}
{"level":"info","ts":"2023-05-15T10:30:45.124Z","caller":"retention/agent.go:45","msg":"Retention policy configured: 30 days, schedule: 0 2 * * *"}
{"level":"info","ts":"2023-05-15T10:30:45.125Z","caller":"retention/scheduler.go:123","msg":"Next execution scheduled for: 2023-05-16T02:00:00Z"}

Verification

To quickly verify that the retention policy is functioning as expected, follow these steps:

  1. Create test results/logs: Generate some Tekton PipelineRuns or TaskRuns that will produce results and logs in your Tekton Results database.

    # Create a sample PipelineRun to generate test data
    kubectl apply -f sample-pipelinerun.yaml
  2. Verify initial state: Check that the results and logs are present in the database and S3 storage (if applicable).

    # Check Tekton Results
    tkn results list
    
    # Or query directly from the database if accessible
    kubectl exec -it -n tekton-pipelines deployment/tekton-results-read-api -- grpcurl -plaintext -d '{}' localhost:8080 api.v1alpha2.Results.ListResults
  3. Modify retention policy for testing: Temporarily set a very short retention period and a specific cron schedule for testing purposes (e.g., execute once at current time + 10 minutes).

    options:
      configMaps:
        tekton-results-config-results-retention-policy:
          data:
            defaultRetention: "0"  # Retain for 0 days (immediate cleanup)
            # Execute once at a specific time (current time + 10 minutes)
            # Example: If current time is 14:30, set to "40 14 * * *" for 14:40
            # Modify the minute value to current minute + 10 (with day/hour adjusted if needed)
            runAt: "40 14 * * *"  # Example: run at 14:40 (current time + 10 mins approx)
  4. Apply modified configuration: Apply the temporary test configuration and wait for the retention agent to restart.

    kubectl apply -f tekton-config-test-config.yaml
    kubectl rollout restart -n tekton-pipelines deployment/tekton-results-retention-policy-agent
  5. Monitor retention agent logs: Watch the retention agent logs to confirm cleanup operations are occurring.

    kubectl logs -n tekton-pipelines deployment/tekton-results-retention-policy-agent -f
  6. Verify cleanup occurred: After the retention schedule executes, verify that the older results and logs have been removed.

    # Check if results have been cleaned up
    tkn results list
    
    # Also check S3 storage to verify log files have been cleaned up
    # Use your S3 client to list objects in the bucket
    aws s3 ls s3://your-bucket-name/path/to/tekton-logs/ --recursive
  7. Revert to production settings: Once verified, revert the retention policy to your intended production values.

Warning: Be careful when setting very short retention periods as this will delete results immediately. Ensure you are using a test environment for verification.