Skip to content

Commit

Permalink
enable mcloneset deleting pvc when pod hanging
Browse files Browse the repository at this point in the history
  • Loading branch information
sunshuai09 committed Nov 1, 2022
1 parent a639a6f commit a447a1a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
3 changes: 3 additions & 0 deletions apis/apps/v1alpha1/cloneset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ type CloneSetScaleStrategy struct {
// The scale will fail if the number of unavailable pods were greater than this MaxUnavailable at scaling up.
// MaxUnavailable works only when scaling up.
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"`

// Enable cloneset to clean up the useless pvc when pod hangs in terminating state.
CleanUpPVC bool `json:"cleanUpPVC,omitempty"`
}

// CloneSetUpdateStrategy defines strategies for pods update.
Expand Down
4 changes: 4 additions & 0 deletions config/crd/bases/apps.kruise.io_clonesets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ spec:
description: ScaleStrategy indicates the ScaleStrategy that will be
employed to create and delete Pods in the CloneSet.
properties:
cleanUpPVC:
description: Enable cloneset to clean up the useless pvc when
pod hangs in terminating state.
type: boolean
maxUnavailable:
anyOf:
- type: integer
Expand Down
4 changes: 4 additions & 0 deletions config/crd/bases/apps.kruise.io_uniteddeployments.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,10 @@ spec:
that will be employed to create and delete Pods in the
CloneSet.
properties:
cleanUpPVC:
description: Enable cloneset to clean up the useless
pvc when pod hangs in terminating state.
type: boolean
maxUnavailable:
anyOf:
- type: integer
Expand Down
57 changes: 57 additions & 0 deletions pkg/controller/cloneset/sync/cloneset_scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/openkruise/kruise/pkg/util/expectations"
"github.com/openkruise/kruise/pkg/util/lifecycle"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog/v2"
Expand Down Expand Up @@ -60,6 +61,21 @@ func (r *realControl) Scale(
return false, nil
}

// If cloneset doesn't want to reuse pvc, clean up the existing pvc first.
// Then it looks like the pod is deleted by controller, new pod with new name
// can be created.
if updateCS.Spec.ScaleStrategy.CleanUpPVC {
ins := getInstanceIDsFromPods(pods)
usingPVCs, uselessPVCs := classifyPVCs(ins, pvcs)
if len(uselessPVCs) > 0 {
klog.V(3).Infof("Begin to clean up cloneset %s useless PVCs", controllerKey)
if modified, err := r.cleanupPVCs(updateCS, uselessPVCs); err != nil || modified {
return modified, err
}
pvcs = usingPVCs
}
}

// 1. manage pods to delete and in preDelete
podsSpecifiedToDelete, podsInPreDelete, numToDelete := getPlannedDeletedPods(updateCS, pods)
if modified, err := r.managePreparingDelete(updateCS, pods, podsInPreDelete, numToDelete); err != nil || modified {
Expand Down Expand Up @@ -403,3 +419,44 @@ func (r *realControl) choosePodsToDelete(cs *appsv1alpha1.CloneSet, totalDiff in

return podsToDelete
}

func (r *realControl) cleanupPVCs(cs *appsv1alpha1.CloneSet, pvcs []*v1.PersistentVolumeClaim) (bool, error) {
var modified bool
for _, pvc := range pvcs {
clonesetutils.ScaleExpectations.ExpectScale(clonesetutils.GetControllerKey(cs), expectations.Delete, pvc.Name)
if err := r.Delete(context.TODO(), pvc); err != nil {
clonesetutils.ScaleExpectations.ObserveScale(clonesetutils.GetControllerKey(cs), expectations.Delete, pvc.Name)
r.recorder.Eventf(cs, v1.EventTypeWarning, "FailedCleanUp", "failed to clean up %s: %v", pvc.Name, err)
return modified, err
}
}
return modified, nil
}

func getInstanceIDsFromPods(pods []*v1.Pod) sets.String {
ins := sets.NewString()
for _, pod := range pods {
ins.Insert(pod.Labels[appsv1alpha1.CloneSetInstanceID])
}
return ins
}

func classifyPVCs(ids sets.String, pvcs []*v1.PersistentVolumeClaim) (using, useless []*v1.PersistentVolumeClaim) {
usingMap := map[types.UID]*v1.PersistentVolumeClaim{}
uselessMap := map[types.UID]*v1.PersistentVolumeClaim{}
for _, pvc := range pvcs {
if ids.Has(pvc.Labels[appsv1alpha1.CloneSetInstanceID]) {
usingMap[pvc.UID] = pvc
} else {
uselessMap[pvc.UID] = pvc
}
}

for _, p := range usingMap {
using = append(using, p)
}
for _, p := range uselessMap {
useless = append(useless, p)
}
return using, useless
}

0 comments on commit a447a1a

Please sign in to comment.