Skip to content

Commit

Permalink
delete persistent volume claim
Browse files Browse the repository at this point in the history
PVCs can be specified using volumeClaimTemplates as part of a pipelineRun.
The pipelineRun controller creates a new PVC using the specifications from
the template. Once the pipelineRun is complete, the PVC exist to faciliate
any analysis on the completed pod. Such PVCs are helpful but requires an
extra cleanup if not needed. In the cases where pipelineRuns are kept for a
long period of time, such PVC can waste resources.

This commit introduces an option for the user such that the users can configure
pipelineRun controller to delete such PVCs. There is no API change needed to
support this cleanup.

PipelineRun/TaskRun controller now reads a label from the volumeClaimTemplate
to decide whether to delete PVC or not. Set the label " pvc-protection-finalizer"
to "remove" to take advantage of this kind of cleanup.

kind: PipelineRun
metadata:
  generateName: pipeline-run-
spec:
  workspaces:
    - name: source
      volumeClaimTemplate:
        metadata:
          labels:
            pvc-protection-finalizer: remove

Closes #5776

Signed-off-by: pritidesai <[email protected]>
  • Loading branch information
Priti Desai authored and pritidesai committed May 9, 2023
1 parent 77c1698 commit 8870c5a
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
4 changes: 4 additions & 0 deletions pkg/reconciler/pipelinerun/pipelinerun.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, pr *v1beta1.PipelineRun)

if pr.IsDone() {
pr.SetDefaults(ctx)

if err := c.pvcHandler.PurgeProtectionFromPersistentVolumeClaimsForWorkspaces(ctx, pr.Spec.Workspaces, *kmeta.NewControllerRef(pr), pr.Namespace); err != nil {
logger.Errorf("Failed to update PersistentVolumeClaim for PipelineRun %s: %v", pr.Name, err)
}
err := c.cleanupAffinityAssistants(ctx, pr)
if err != nil {
logger.Errorf("Failed to delete StatefulSet for PipelineRun %s: %v", pr.Name, err)
Expand Down
4 changes: 4 additions & 0 deletions pkg/reconciler/taskrun/taskrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, tr *v1beta1.TaskRun) pkg
return err
}

if err := c.pvcHandler.PurgeProtectionFromPersistentVolumeClaimsForWorkspaces(ctx, tr.Spec.Workspaces, *kmeta.NewControllerRef(tr), tr.Namespace); err != nil {
return fmt.Errorf("failed to update PersistentVolumeClaim for TaskRun %s: %v", tr.Name, err)
}

return c.finishReconcileUpdateEmitEvents(ctx, tr, before, nil)
}

Expand Down
47 changes: 47 additions & 0 deletions pkg/reconciler/volumeclaim/pvchandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ package volumeclaim
import (
"context"
"crypto/sha256"
"encoding/json"
"fmt"

types "k8s.io/apimachinery/pkg/types"

"gomodules.xyz/jsonpatch/v2"

"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
"go.uber.org/zap"
corev1 "k8s.io/api/core/v1"
Expand All @@ -34,11 +39,13 @@ const (
// ReasonCouldntCreateWorkspacePVC indicates that a Pipeline expects a workspace from a
// volumeClaimTemplate but couldn't create a claim.
ReasonCouldntCreateWorkspacePVC = "CouldntCreateWorkspacePVC"
LabelPVCProtectionFinalizer = "pvc-protection-finalizer"
)

// PvcHandler is used to create PVCs for workspaces
type PvcHandler interface {
CreatePersistentVolumeClaimsForWorkspaces(ctx context.Context, wb []v1beta1.WorkspaceBinding, ownerReference metav1.OwnerReference, namespace string) error
PurgeProtectionFromPersistentVolumeClaimsForWorkspaces(ctx context.Context, wb []v1beta1.WorkspaceBinding, ownerReference metav1.OwnerReference, namespace string) error
}

type defaultPVCHandler struct {
Expand Down Expand Up @@ -81,6 +88,46 @@ func (c *defaultPVCHandler) CreatePersistentVolumeClaimsForWorkspaces(ctx contex
return errorutils.NewAggregate(errs)
}

func (c *defaultPVCHandler) PurgeProtectionFromPersistentVolumeClaimsForWorkspaces(ctx context.Context, wb []v1beta1.WorkspaceBinding, ownerReference metav1.OwnerReference, namespace string) error {
var errs []error
for _, claim := range getPersistentVolumeClaims(wb, ownerReference, namespace) {
p, err := c.clientset.CoreV1().PersistentVolumeClaims(claim.Namespace).Get(ctx, claim.Name, metav1.GetOptions{})
if err != nil {
errs = append(errs, fmt.Errorf("failed to get the PVC %s: %w", claim.Name, err))
}
//the label to remove PVC protection is not set to true
if err == nil && p != nil && p.Labels[LabelPVCProtectionFinalizer] == "remove" {
err = c.clientset.CoreV1().PersistentVolumeClaims(claim.Namespace).Delete(ctx, claim.Name, metav1.DeleteOptions{})
if err != nil {
errs = append(errs, fmt.Errorf("failed to delete the PVC %s: %w", claim.Name, err))
}

// get the list of existing finalizers and drop `pvc-protection` if exists
var finalizers []string
for _, f := range p.ObjectMeta.Finalizers {
if f == "kubernetes.io/pvc-protection" {
continue
}
finalizers = append(finalizers, f)
}

// prepare data to remove pvc-protection from the list of finalizers
removeFinalizerBytes, err := json.Marshal([]jsonpatch.JsonPatchOperation{{
Path: "/metadata/finalizers",
Operation: "replace",
Value: finalizers,
}})

// patch the existing PVC to update the finalizers
_, err = c.clientset.CoreV1().PersistentVolumeClaims(claim.Namespace).Patch(ctx, claim.Name, types.JSONPatchType, removeFinalizerBytes, metav1.PatchOptions{})
if err != nil {
errs = append(errs, fmt.Errorf("failed to patch the PVC %s: %w", claim.Name, err))
}
}
}
return errorutils.NewAggregate(errs)
}

func getPersistentVolumeClaims(workspaceBindings []v1beta1.WorkspaceBinding, ownerReference metav1.OwnerReference, namespace string) map[string]*corev1.PersistentVolumeClaim {
claims := make(map[string]*corev1.PersistentVolumeClaim)
for _, workspaceBinding := range workspaceBindings {
Expand Down

0 comments on commit 8870c5a

Please sign in to comment.