Skip to content

Commit 931758e

Browse files
authored
Merge pull request #11386 from sbueringer/pr-add-fg-volume-detach-attachments
🌱 Add feature gate to consider VolumeAttachments when waiting for volume detach
2 parents ec04dcb + 938a34b commit 931758e

File tree

5 files changed

+64
-13
lines changed

5 files changed

+64
-13
lines changed

config/manager/manager.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ spec:
2424
- "--diagnostics-address=${CAPI_DIAGNOSTICS_ADDRESS:=:8443}"
2525
- "--insecure-diagnostics=${CAPI_INSECURE_DIAGNOSTICS:=false}"
2626
- "--use-deprecated-infra-machine-naming=${CAPI_USE_DEPRECATED_INFRA_MACHINE_NAMING:=false}"
27-
- "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=true},ClusterResourceSet=${EXP_CLUSTER_RESOURCE_SET:=true},ClusterTopology=${CLUSTER_TOPOLOGY:=false},RuntimeSDK=${EXP_RUNTIME_SDK:=false},MachineSetPreflightChecks=${EXP_MACHINE_SET_PREFLIGHT_CHECKS:=true}"
27+
- "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=true},ClusterResourceSet=${EXP_CLUSTER_RESOURCE_SET:=true},ClusterTopology=${CLUSTER_TOPOLOGY:=false},RuntimeSDK=${EXP_RUNTIME_SDK:=false},MachineSetPreflightChecks=${EXP_MACHINE_SET_PREFLIGHT_CHECKS:=true},MachineWaitForVolumeDetachConsiderVolumeAttachments=${EXP_MACHINE_WAITFORVOLUMEDETACH_CONSIDER_VOLUMEATTACHMENTS:=true}"
2828
image: controller:latest
2929
name: manager
3030
env:

docs/book/src/tasks/experimental-features/experimental-features.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
Cluster API now ships with a new experimental package that lives under the `exp/` directory. This is a
44
temporary location for features which will be moved to their permanent locations after graduation. Users can experiment with these features by enabling them using feature gates.
55

6+
Currently Cluster API has the following experimental features:
7+
* `ClusterResourceSet` (env var: `EXP_CLUSTER_RESOURCE_SET`): [ClusterResourceSet](./cluster-resource-set.md)
8+
* `MachinePool` (env var: `EXP_MACHINE_POOL`): [MachinePools](./machine-pools.md)
9+
* `MachineSetPreflightChecks` (env var: `EXP_MACHINE_SET_PREFLIGHT_CHECKS`): [MachineSetPreflightChecks](./machineset-preflight-checks.md)
10+
* `MachineWaitForVolumeDetachConsiderVolumeAttachments` (env var: `EXP_MACHINE_WAITFORVOLUMEDETACH_CONSIDER_VOLUMEATTACHMENTS`):
11+
* During Machine drain the Machine controller waits for volumes to be detached. Per default, the controller considers
12+
`Nodes.status.volumesAttached` and `VolumesAttachments`. This feature flag allows to opt-out from considering `VolumeAttachments`.
13+
The feature gate was added to allow to opt-out in case unforeseen issues occur with `VolumeAttachments`.
14+
* `ClusterTopology` (env var: `CLUSTER_TOPOLOGY`): [ClusterClass](./cluster-class/index.md)
15+
* `RuntimeSDK` (env var: `EXP_RUNTIME_SDK`): [RuntimeSDK](./runtime-sdk/index.md)
16+
* `KubeadmBootstrapFormatIgnition` (env var: `EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION`): [Ignition](./ignition.md)
17+
618
## Enabling Experimental Features for Management Clusters Started with clusterctl
719

820
Users can enable/disable features by setting OS environment variables before running `clusterctl init`, e.g.:

feature/feature.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ const (
6262
// alpha: v1.5
6363
// beta: v1.9
6464
MachineSetPreflightChecks featuregate.Feature = "MachineSetPreflightChecks"
65+
66+
// MachineWaitForVolumeDetachConsiderVolumeAttachments is a feature gate that controls if the Machine controller
67+
// also considers VolumeAttachments in addition to Nodes.status.volumesAttached when waiting for volumes to be detached.
68+
//
69+
// beta: v1.9
70+
MachineWaitForVolumeDetachConsiderVolumeAttachments featuregate.Feature = "MachineWaitForVolumeDetachConsiderVolumeAttachments"
6571
)
6672

6773
func init() {
@@ -72,9 +78,10 @@ func init() {
7278
// To add a new feature, define a key for it above and add it here.
7379
var defaultClusterAPIFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
7480
// Every feature should be initiated here:
75-
ClusterResourceSet: {Default: true, PreRelease: featuregate.Beta},
76-
MachinePool: {Default: true, PreRelease: featuregate.Beta},
77-
MachineSetPreflightChecks: {Default: true, PreRelease: featuregate.Beta},
81+
ClusterResourceSet: {Default: true, PreRelease: featuregate.Beta},
82+
MachinePool: {Default: true, PreRelease: featuregate.Beta},
83+
MachineSetPreflightChecks: {Default: true, PreRelease: featuregate.Beta},
84+
MachineWaitForVolumeDetachConsiderVolumeAttachments: {Default: true, PreRelease: featuregate.Beta},
7885
ClusterTopology: {Default: false, PreRelease: featuregate.Alpha},
7986
KubeadmBootstrapFormatIgnition: {Default: false, PreRelease: featuregate.Alpha},
8087
RuntimeSDK: {Default: false, PreRelease: featuregate.Alpha},

internal/controllers/machine/machine_controller.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import (
4949
"sigs.k8s.io/cluster-api/controllers/clustercache"
5050
"sigs.k8s.io/cluster-api/controllers/external"
5151
"sigs.k8s.io/cluster-api/controllers/noderefutil"
52+
"sigs.k8s.io/cluster-api/feature"
5253
"sigs.k8s.io/cluster-api/internal/controllers/machine/drain"
5354
"sigs.k8s.io/cluster-api/internal/util/cache"
5455
"sigs.k8s.io/cluster-api/internal/util/ssa"
@@ -1125,17 +1126,19 @@ func getAttachedVolumeInformation(ctx context.Context, remoteClient client.Clien
11251126
attachedVolumeName.Insert(string(attachedVolume.Name))
11261127
}
11271128

1128-
volumeAttachments, err := getVolumeAttachmentForNode(ctx, remoteClient, node.GetName())
1129-
if err != nil {
1130-
return nil, nil, errors.Wrap(err, "failed to list VolumeAttachments")
1131-
}
1129+
if feature.Gates.Enabled(feature.MachineWaitForVolumeDetachConsiderVolumeAttachments) {
1130+
volumeAttachments, err := getVolumeAttachmentForNode(ctx, remoteClient, node.GetName())
1131+
if err != nil {
1132+
return nil, nil, errors.Wrap(err, "failed to list VolumeAttachments")
1133+
}
11321134

1133-
for _, va := range volumeAttachments {
1134-
// Return an error if a VolumeAttachments does not refer a PersistentVolume.
1135-
if va.Spec.Source.PersistentVolumeName == nil {
1136-
return nil, nil, errors.Errorf("spec.source.persistentVolumeName for VolumeAttachment %s is not set", va.GetName())
1135+
for _, va := range volumeAttachments {
1136+
// Return an error if a VolumeAttachments does not refer a PersistentVolume.
1137+
if va.Spec.Source.PersistentVolumeName == nil {
1138+
return nil, nil, errors.Errorf("spec.source.persistentVolumeName for VolumeAttachment %s is not set", va.GetName())
1139+
}
1140+
attachedPVNames.Insert(*va.Spec.Source.PersistentVolumeName)
11371141
}
1138-
attachedPVNames.Insert(*va.Spec.Source.PersistentVolumeName)
11391142
}
11401143

11411144
return attachedVolumeName, attachedPVNames, nil

internal/controllers/machine/machine_controller_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3131
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3232
"k8s.io/client-go/tools/record"
33+
utilfeature "k8s.io/component-base/featuregate/testing"
3334
"k8s.io/utils/ptr"
3435
ctrl "sigs.k8s.io/controller-runtime"
3536
"sigs.k8s.io/controller-runtime/pkg/cache/informertest"
@@ -44,6 +45,7 @@ import (
4445
"sigs.k8s.io/cluster-api/controllers/clustercache"
4546
"sigs.k8s.io/cluster-api/controllers/external"
4647
externalfake "sigs.k8s.io/cluster-api/controllers/external/fake"
48+
"sigs.k8s.io/cluster-api/feature"
4749
"sigs.k8s.io/cluster-api/internal/util/cache"
4850
"sigs.k8s.io/cluster-api/internal/util/ssa"
4951
"sigs.k8s.io/cluster-api/util"
@@ -2007,6 +2009,7 @@ func TestShouldWaitForNodeVolumes(t *testing.T) {
20072009
name string
20082010
node *corev1.Node
20092011
remoteObjects []client.Object
2012+
featureGateDisabled bool
20102013
expected ctrl.Result
20112014
expectedDeletingReason string
20122015
expectedDeletingMessage string
@@ -2158,6 +2161,28 @@ func TestShouldWaitForNodeVolumes(t *testing.T) {
21582161
expectedDeletingMessage: `Waiting for Node volumes to be detached (started at 2024-10-09T16:13:59Z)
21592162
* PersistentVolumeClaims: default/test-pvc`,
21602163
},
2164+
{
2165+
name: "Node has volumes attached according to volumeattachments (but ignored because feature gate is disabled)",
2166+
node: &corev1.Node{
2167+
ObjectMeta: metav1.ObjectMeta{
2168+
Name: nodeName,
2169+
},
2170+
Status: corev1.NodeStatus{
2171+
Conditions: []corev1.NodeCondition{
2172+
{
2173+
Type: corev1.NodeReady,
2174+
Status: corev1.ConditionTrue,
2175+
},
2176+
},
2177+
},
2178+
},
2179+
remoteObjects: []client.Object{
2180+
volumeAttachment,
2181+
persistentVolume,
2182+
},
2183+
featureGateDisabled: true,
2184+
expected: ctrl.Result{},
2185+
},
21612186
{
21622187
name: "Node has volumes attached according to volumeattachments but without a pv",
21632188
node: &corev1.Node{
@@ -2339,6 +2364,10 @@ func TestShouldWaitForNodeVolumes(t *testing.T) {
23392364
t.Run(tt.name, func(t *testing.T) {
23402365
g := NewWithT(t)
23412366

2367+
if tt.featureGateDisabled {
2368+
utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachineWaitForVolumeDetachConsiderVolumeAttachments, false)
2369+
}
2370+
23422371
fakeClient := fake.NewClientBuilder().WithObjects(testCluster).Build()
23432372

23442373
var remoteObjects []client.Object

0 commit comments

Comments
 (0)