Merge pull request #105609 from pohly/generic-ephemeral-volume-ga

generic ephemeral volume GA
This commit is contained in:
Kubernetes Prow Robot
2021-10-28 17:36:50 -07:00
committed by GitHub
37 changed files with 175 additions and 570 deletions

View File

@@ -47,10 +47,9 @@ func CreateVolumeSpec(podVolume v1.Volume, pod *v1.Pod, nodeName types.NodeName,
claimName = pvcSource.ClaimName
readOnly = pvcSource.ReadOnly
}
isEphemeral := false
if ephemeralSource := podVolume.VolumeSource.Ephemeral; ephemeralSource != nil && utilfeature.DefaultFeatureGate.Enabled(features.GenericEphemeralVolume) {
isEphemeral := podVolume.VolumeSource.Ephemeral != nil
if isEphemeral {
claimName = ephemeral.VolumeClaimName(pod, &podVolume)
isEphemeral = true
}
if claimName != "" {
klog.V(10).Infof(

View File

@@ -20,9 +20,8 @@ import (
"fmt"
v1 "k8s.io/api/core/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/tools/cache"
"k8s.io/kubernetes/pkg/features"
"k8s.io/component-helpers/storage/ephemeral"
)
const (
@@ -31,9 +30,9 @@ const (
)
// PodPVCIndexFunc creates an index function that returns PVC keys (=
// namespace/name) for given pod. If enabled, this includes the PVCs
// namespace/name) for given pod. This includes the PVCs
// that might be created for generic ephemeral volumes.
func PodPVCIndexFunc(genericEphemeralVolumeFeatureEnabled bool) func(obj interface{}) ([]string, error) {
func PodPVCIndexFunc() func(obj interface{}) ([]string, error) {
return func(obj interface{}) ([]string, error) {
pod, ok := obj.(*v1.Pod)
if !ok {
@@ -44,9 +43,8 @@ func PodPVCIndexFunc(genericEphemeralVolumeFeatureEnabled bool) func(obj interfa
claimName := ""
if pvcSource := podVolume.VolumeSource.PersistentVolumeClaim; pvcSource != nil {
claimName = pvcSource.ClaimName
}
if ephemeralSource := podVolume.VolumeSource.Ephemeral; genericEphemeralVolumeFeatureEnabled && ephemeralSource != nil {
claimName = pod.Name + "-" + podVolume.Name
} else if podVolume.VolumeSource.Ephemeral != nil {
claimName = ephemeral.VolumeClaimName(pod, &podVolume)
}
if claimName != "" {
keys = append(keys, fmt.Sprintf("%s/%s", pod.Namespace, claimName))
@@ -56,10 +54,9 @@ func PodPVCIndexFunc(genericEphemeralVolumeFeatureEnabled bool) func(obj interfa
}
}
// AddPodPVCIndexerIfNotPresent adds the PodPVCIndexFunc with the current global setting for GenericEphemeralVolume.
// AddPodPVCIndexerIfNotPresent adds the PodPVCIndexFunc.
func AddPodPVCIndexerIfNotPresent(indexer cache.Indexer) error {
return AddIndexerIfNotPresent(indexer, PodPVCIndex,
PodPVCIndexFunc(utilfeature.DefaultFeatureGate.Enabled(features.GenericEphemeralVolume)))
return AddIndexerIfNotPresent(indexer, PodPVCIndex, PodPVCIndexFunc())
}
// AddIndexerIfNotPresent adds the index function with the name into the cache indexer if not present

View File

@@ -56,18 +56,14 @@ type Controller struct {
// allows overriding of StorageObjectInUseProtection feature Enabled/Disabled for testing
storageObjectInUseProtectionEnabled bool
// allows overriding of GenericEphemeralVolume feature Enabled/Disabled for testing
genericEphemeralVolumeFeatureEnabled bool
}
// NewPVCProtectionController returns a new instance of PVCProtectionController.
func NewPVCProtectionController(pvcInformer coreinformers.PersistentVolumeClaimInformer, podInformer coreinformers.PodInformer, cl clientset.Interface, storageObjectInUseProtectionFeatureEnabled, genericEphemeralVolumeFeatureEnabled bool) (*Controller, error) {
func NewPVCProtectionController(pvcInformer coreinformers.PersistentVolumeClaimInformer, podInformer coreinformers.PodInformer, cl clientset.Interface, storageObjectInUseProtectionFeatureEnabled bool) (*Controller, error) {
e := &Controller{
client: cl,
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "pvcprotection"),
storageObjectInUseProtectionEnabled: storageObjectInUseProtectionFeatureEnabled,
genericEphemeralVolumeFeatureEnabled: genericEphemeralVolumeFeatureEnabled,
client: cl,
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "pvcprotection"),
storageObjectInUseProtectionEnabled: storageObjectInUseProtectionFeatureEnabled,
}
if cl != nil && cl.CoreV1().RESTClient().GetRateLimiter() != nil {
ratelimiter.RegisterMetricAndTrackRateLimiterUsage("persistentvolumeclaim_protection_controller", cl.CoreV1().RESTClient().GetRateLimiter())
@@ -85,7 +81,7 @@ func NewPVCProtectionController(pvcInformer coreinformers.PersistentVolumeClaimI
e.podLister = podInformer.Lister()
e.podListerSynced = podInformer.Informer().HasSynced
e.podIndexer = podInformer.Informer().GetIndexer()
if err := common.AddIndexerIfNotPresent(e.podIndexer, common.PodPVCIndex, common.PodPVCIndexFunc(genericEphemeralVolumeFeatureEnabled)); err != nil {
if err := common.AddIndexerIfNotPresent(e.podIndexer, common.PodPVCIndex, common.PodPVCIndexFunc()); err != nil {
return nil, fmt.Errorf("could not initialize pvc protection controller: %w", err)
}
podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
@@ -252,23 +248,12 @@ func (c *Controller) askInformer(pvc *v1.PersistentVolumeClaim) (bool, error) {
continue
}
if c.genericEphemeralVolumeFeatureEnabled {
// We still need to look at each volume: that's redundant for volume.PersistentVolumeClaim,
// but for volume.Ephemeral we need to be sure that this particular PVC is the one
// created for the ephemeral volume.
if c.podUsesPVC(pod, pvc) {
return true, nil
}
continue
// We still need to look at each volume: that's redundant for volume.PersistentVolumeClaim,
// but for volume.Ephemeral we need to be sure that this particular PVC is the one
// created for the ephemeral volume.
if c.podUsesPVC(pod, pvc) {
return true, nil
}
// This is the traditional behavior without GenericEphemeralVolume enabled.
if pod.Spec.NodeName == "" {
continue
}
// found a pod using this PVC
return true, nil
}
klog.V(4).InfoS("No Pod using PVC was found in the Informer's cache", "PVC", klog.KObj(pvc))
@@ -300,7 +285,7 @@ func (c *Controller) podUsesPVC(pod *v1.Pod, pvc *v1.PersistentVolumeClaim) bool
if pod.Spec.NodeName != "" {
for _, volume := range pod.Spec.Volumes {
if volume.PersistentVolumeClaim != nil && volume.PersistentVolumeClaim.ClaimName == pvc.Name ||
c.genericEphemeralVolumeFeatureEnabled && !podIsShutDown(pod) && volume.Ephemeral != nil && ephemeral.VolumeClaimName(pod, &volume) == pvc.Name && ephemeral.VolumeIsForPod(pod, pvc) == nil {
!podIsShutDown(pod) && volume.Ephemeral != nil && ephemeral.VolumeClaimName(pod, &volume) == pvc.Name && ephemeral.VolumeIsForPod(pod, pvc) == nil {
klog.V(2).InfoS("Pod uses PVC", "pod", klog.KObj(pod), "PVC", klog.KObj(pvc))
return true
}
@@ -407,7 +392,7 @@ func (c *Controller) enqueuePVCs(pod *v1.Pod, deleted bool) {
switch {
case volume.PersistentVolumeClaim != nil:
c.queue.Add(pod.Namespace + "/" + volume.PersistentVolumeClaim.ClaimName)
case c.genericEphemeralVolumeFeatureEnabled && volume.Ephemeral != nil:
case volume.Ephemeral != nil:
c.queue.Add(pod.Namespace + "/" + ephemeral.VolumeClaimName(pod, &volume))
}
}

View File

@@ -146,7 +146,7 @@ func generateUpdateErrorFunc(t *testing.T, failures int) clienttesting.ReactionF
}
}
func testPVCProtectionController(t *testing.T, genericEphemeralVolumeFeatureEnabled bool) {
func TestPVCProtectionController(t *testing.T) {
pvcGVR := schema.GroupVersionResource{
Group: v1.GroupName,
Version: "v1",
@@ -430,7 +430,7 @@ func testPVCProtectionController(t *testing.T, genericEphemeralVolumeFeatureEnab
podInformer := informers.Core().V1().Pods()
// Create the controller
ctrl, err := NewPVCProtectionController(pvcInformer, podInformer, client, test.storageObjectInUseProtectionEnabled, genericEphemeralVolumeFeatureEnabled)
ctrl, err := NewPVCProtectionController(pvcInformer, podInformer, client, test.storageObjectInUseProtectionEnabled)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
@@ -518,8 +518,3 @@ func testPVCProtectionController(t *testing.T, genericEphemeralVolumeFeatureEnab
}
}
func TestPVCProtectionController(t *testing.T) {
t.Run("with-GenericEphemeralVolume", func(t *testing.T) { testPVCProtectionController(t, true) })
t.Run("without-GenericEphemeralVolume", func(t *testing.T) { testPVCProtectionController(t, false) })
}