Skip to content

Commit

Permalink
Merge pull request #1949 from kubernetes-sigs/fix-rc-taint
Browse files Browse the repository at this point in the history
Ensure CSINode allocatable count is set on node before removing startup taint
  • Loading branch information
k8s-ci-robot authored Feb 29, 2024
2 parents a1aeff3 + 23ce499 commit 916729b
Show file tree
Hide file tree
Showing 6 changed files with 455 additions and 7 deletions.
3 changes: 3 additions & 0 deletions charts/aws-ebs-csi-driver/templates/clusterrole-csi-node.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ rules:
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get"]
3 changes: 3 additions & 0 deletions deploy/kubernetes/base/clusterrole-csi-node.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ rules:
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get"]
1 change: 1 addition & 0 deletions hack/update-mockgen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ BIN="$(dirname "$(realpath "${BASH_SOURCE[0]}")")/../bin"
"${BIN}/mockgen" -package driver -destination=./pkg/driver/mock_k8s_client.go -mock_names='Interface=MockKubernetesClient' k8s.io/client-go/kubernetes Interface
"${BIN}/mockgen" -package driver -destination=./pkg/driver/mock_k8s_corev1.go k8s.io/client-go/kubernetes/typed/core/v1 CoreV1Interface,NodeInterface
"${BIN}/mockgen" -package driver -destination=./pkg/driver/mock_k8s_storagev1.go k8s.io/client-go/kubernetes/typed/storage/v1 VolumeAttachmentInterface,StorageV1Interface
"${BIN}/mockgen" -package driver -destination=./pkg/driver/mock_k8s_storagev1_csinode.go k8s.io/client-go/kubernetes/typed/storage/v1 CSINodeInterface

# Fixes "Mounter Type cannot implement 'Mounter' as it has a non-exported method and is defined in a different package"
# See https://github.com/kubernetes/mount-utils/commit/a20fcfb15a701977d086330b47b7efad51eb608e for context.
Expand Down
178 changes: 178 additions & 0 deletions pkg/driver/mock_k8s_storagev1_csinode.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 30 additions & 1 deletion pkg/driver/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8stypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/volume"
)
Expand Down Expand Up @@ -68,6 +69,8 @@ var (
csi.NodeServiceCapability_RPC_GET_VOLUME_STATS,
}

// taintRemovalInitialDelay is the initial delay for node taint removal
taintRemovalInitialDelay = 1 * time.Second
// taintRemovalBackoff is the exponential backoff configuration for node taint removal
taintRemovalBackoff = wait.Backoff{
Duration: 500 * time.Millisecond,
Expand Down Expand Up @@ -103,7 +106,9 @@ func newNodeService(driverOptions *DriverOptions) nodeService {

// Remove taint from node to indicate driver startup success
// This is done at the last possible moment to prevent race conditions or false positive removals
go removeTaintInBackground(cloud.DefaultKubernetesAPIClient, removeNotReadyTaint)
time.AfterFunc(taintRemovalInitialDelay, func() {
removeTaintInBackground(cloud.DefaultKubernetesAPIClient, removeNotReadyTaint)
})

return nodeService{
metadata: metadata,
Expand Down Expand Up @@ -896,6 +901,11 @@ func removeNotReadyTaint(k8sClient cloud.KubernetesAPIClient) error {
return err
}

err = checkAllocatable(clientset, nodeName)
if err != nil {
return err
}

var taintsToKeep []corev1.Taint
for _, taint := range node.Spec.Taints {
if taint.Key != AgentNotReadyNodeTaintKey {
Expand Down Expand Up @@ -936,6 +946,25 @@ func removeNotReadyTaint(k8sClient cloud.KubernetesAPIClient) error {
return nil
}

func checkAllocatable(clientset kubernetes.Interface, nodeName string) error {
csiNode, err := clientset.StorageV1().CSINodes().Get(context.Background(), nodeName, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("isAllocatableSet: failed to get CSINode for %s: %w", nodeName, err)
}

for _, driver := range csiNode.Spec.Drivers {
if driver.Name == DriverName {
if driver.Allocatable != nil && driver.Allocatable.Count != nil {
klog.InfoS("CSINode Allocatable value is set", "nodeName", nodeName, "count", *driver.Allocatable.Count)
return nil
}
return fmt.Errorf("isAllocatableSet: allocatable value not set for driver on node %s", nodeName)
}
}

return fmt.Errorf("isAllocatableSet: driver not found on node %s", nodeName)
}

func recheckFormattingOptionParameter(context map[string]string, key string, fsConfigs map[string]fileSystemConfig, fsType string) (value string, err error) {
v, ok := context[key]
if ok {
Expand Down
Loading

0 comments on commit 916729b

Please sign in to comment.