Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure CSINode allocatable count is set on node before removing startup taint #1949

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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() {
ConnorJC3 marked this conversation as resolved.
Show resolved Hide resolved
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
Loading