-
Notifications
You must be signed in to change notification settings - Fork 77
PodMounter: Add Mountpoint Pod Sharing Support #439
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
Merged
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
e7651b3
Add Pod Sharing
yerzhan7 0ba8d12
Add `{{- if .Values.experimental.podMounter -}}` wrapper to CRD
yerzhan7 1e1e761
Make Expectations private, fix comments
yerzhan7 8a53b09
Reconcile fixes
yerzhan7 75ec928
Rename CRD version from v1 to v1beta
yerzhan7 19ebfa1
PodMounter fixes
yerzhan7 161ea2d
Add mppod_lock unit test
yerzhan7 3fd56c0
Add expectations unit test
yerzhan7 faa33e6
Add PodMounter unit tests
yerzhan7 5ae555f
Add PodUnmounter unit tests
yerzhan7 8fde1c4
Improve PodSharing e2e tests
yerzhan7 87f4edb
Add more e2e tests
yerzhan7 75892bd
Add attachment time to CRD
yerzhan7 d192ded
Add StaleAttachmentCleaner
yerzhan7 84b88cf
Fix controller test after changing CRD
yerzhan7 a5887d0
Fix CI tests
yerzhan7 b6bd5ce
Fix MountOptions controller test
yerzhan7 183e517
Add needs-unmount annotation logic
yerzhan7 d04d8d1
Conditionally support selectable fields
yerzhan7 845b508
Add sleep in controller for IRSA role change test
yerzhan7 f224240
Merge remote-tracking branch 'upstream/main' into mppodsharing
yerzhan7 26dc0d8
Further refactoring, add more doc comments
yerzhan7 258e0c8
go mod tidy
yerzhan7 9dfd816
Node: Handle shutdown signal
yerzhan7 c52f321
Merge remote-tracking branch 'upstream/main' into mppodsharing
yerzhan7 e4bcdb1
Merge remote-tracking branch 'upstream/main' into mppodsharing
yerzhan7 ab6e260
Merge remote-tracking branch 'upstream/main' into mppodsharing
yerzhan7 eeb1699
Address small comments
yerzhan7 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
charts/aws-mountpoint-s3-csi-driver/templates/mountpoints3podattachments-crd.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| # Auto-generated file via `make generate`. Do not edit. | ||
| {{- if .Values.experimental.podMounter -}} | ||
| --- | ||
| apiVersion: apiextensions.k8s.io/v1 | ||
| kind: CustomResourceDefinition | ||
| metadata: | ||
| annotations: | ||
| controller-gen.kubebuilder.io/version: v0.17.3 | ||
| name: mountpoints3podattachments.s3.csi.aws.com | ||
| spec: | ||
| group: s3.csi.aws.com | ||
| names: | ||
| kind: MountpointS3PodAttachment | ||
| listKind: MountpointS3PodAttachmentList | ||
| plural: mountpoints3podattachments | ||
| shortNames: | ||
| - s3pa | ||
| singular: mountpoints3podattachment | ||
| scope: Cluster | ||
| versions: | ||
| - name: v1beta | ||
| schema: | ||
| openAPIV3Schema: | ||
| description: MountpointS3PodAttachment is the Schema for the mountpoints3podattachments | ||
| API. | ||
| properties: | ||
| apiVersion: | ||
| description: |- | ||
| APIVersion defines the versioned schema of this representation of an object. | ||
| Servers should convert recognized schemas to the latest internal value, and | ||
| may reject unrecognized values. | ||
| More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | ||
| type: string | ||
| kind: | ||
| description: |- | ||
| Kind is a string value representing the REST resource this object represents. | ||
| Servers may infer this from the endpoint the client submits requests to. | ||
| Cannot be updated. | ||
| In CamelCase. | ||
| More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | ||
| type: string | ||
| metadata: | ||
| type: object | ||
| spec: | ||
| description: MountpointS3PodAttachmentSpec defines the desired state of | ||
| MountpointS3PodAttachment. | ||
| properties: | ||
| authenticationSource: | ||
| description: Authentication source taken from volume attribute field | ||
| `authenticationSource`. | ||
| type: string | ||
| mountOptions: | ||
| description: Comma separated mount options taken from volume. | ||
| type: string | ||
| mountpointS3PodAttachments: | ||
| additionalProperties: | ||
| items: | ||
| description: WorkloadAttachment represents the attachment details | ||
| of a workload pod to a Mountpoint S3 pod. | ||
| properties: | ||
| attachmentTime: | ||
| description: AttachmentTime represents when the workload pod | ||
| was attached to the Mountpoint S3 pod | ||
| format: date-time | ||
| type: string | ||
| workloadPodUID: | ||
| description: WorkloadPodUID is the unique identifier of the | ||
| attached workload pod | ||
| type: string | ||
| required: | ||
| - attachmentTime | ||
| - workloadPodUID | ||
| type: object | ||
| type: array | ||
| description: Maps each Mountpoint S3 pod name to its workload attachments | ||
| type: object | ||
| nodeName: | ||
| description: Name of the node. | ||
| type: string | ||
| persistentVolumeName: | ||
| description: Name of the Persistent Volume. | ||
| type: string | ||
| volumeID: | ||
| description: Volume ID. | ||
| type: string | ||
| workloadFSGroup: | ||
| description: Workload pod's `fsGroup` from pod security context | ||
| type: string | ||
| workloadNamespace: | ||
| description: 'Workload pod''s namespace. Exists only if `authenticationSource: | ||
| pod`.' | ||
| type: string | ||
| workloadServiceAccountIAMRoleARN: | ||
| description: 'EKS IAM Role ARN from workload pod''s service account | ||
| annotation (IRSA). Exists only if `authenticationSource: pod` and | ||
| service account has `eks.amazonaws.com/role-arn` annotation.' | ||
| type: string | ||
| workloadServiceAccountName: | ||
| description: 'Workload pod''s service account name. Exists only if | ||
| `authenticationSource: pod`.' | ||
| type: string | ||
| required: | ||
| - authenticationSource | ||
| - mountOptions | ||
| - mountpointS3PodAttachments | ||
| - nodeName | ||
| - persistentVolumeName | ||
| - volumeID | ||
| - workloadFSGroup | ||
| type: object | ||
| type: object | ||
| selectableFields: | ||
| - jsonPath: .spec.nodeName | ||
| served: true | ||
| storage: true | ||
| subresources: | ||
| status: {} | ||
| {{- end -}} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| package csicontroller | ||
|
|
||
| import ( | ||
| "sort" | ||
| "strings" | ||
| "sync" | ||
|
|
||
| "sigs.k8s.io/controller-runtime/pkg/client" | ||
| ) | ||
|
|
||
| // expectations is a structure that manages pending expectations for Kubernetes resources. | ||
| // It uses field filters as keys to track resources that are expected to be created | ||
| // helping with eventual consistency, reducing unnecessary processing and API server load. | ||
| type expectations struct { | ||
| pending sync.Map | ||
| } | ||
|
|
||
| // newExpectations creates and returns a new Expectations instance. | ||
| func newExpectations() *expectations { | ||
| return &expectations{} | ||
| } | ||
|
|
||
| // setPending marks a resource as pending based on the given field filters. | ||
| // This is typically used when a create operation is initiated. | ||
| func (e *expectations) setPending(fieldFilters client.MatchingFields) { | ||
| key := deriveExpectationKeyFromFilters(fieldFilters) | ||
| e.pending.Store(key, struct{}{}) | ||
| } | ||
|
|
||
| // isPending checks if a resource is marked as pending based on the given field filters. | ||
| // Returns true if the resource is pending, false otherwise. | ||
| func (e *expectations) isPending(fieldFilters client.MatchingFields) bool { | ||
| key := deriveExpectationKeyFromFilters(fieldFilters) | ||
| _, ok := e.pending.Load(key) | ||
| return ok | ||
| } | ||
|
|
||
| // clear removes the pending mark for a resource based on the given field filters. | ||
| // This is typically called when an expected operation has been confirmed as completed. | ||
| func (e *expectations) clear(fieldFilters client.MatchingFields) { | ||
| key := deriveExpectationKeyFromFilters(fieldFilters) | ||
| e.pending.Delete(key) | ||
| } | ||
|
|
||
| // deriveExpectationKeyFromFilters generates a deterministic string key from a map of field filters. | ||
| // It creates a consistent string representation of the filters by: | ||
| // 1. Sorting the filter keys alphabetically | ||
| // 2. Concatenating each key-value pair in the format "key=value;" | ||
| // | ||
| // For example, given filters {"foo": "bar", "baz": "qux"}, it will produce "baz=qux;foo=bar;" | ||
| // | ||
| // Parameters: | ||
| // - fieldFilters: A map of field names to their values used for filtering Kubernetes resources | ||
| // | ||
| // Returns: | ||
| // - A string that uniquely represents the combination of field filters | ||
| func deriveExpectationKeyFromFilters(fieldFilters client.MatchingFields) string { | ||
| keys := make([]string, 0, len(fieldFilters)) | ||
| for k := range fieldFilters { | ||
| keys = append(keys, k) | ||
| } | ||
| sort.Strings(keys) | ||
| var sb strings.Builder | ||
| for _, k := range keys { | ||
| sb.WriteString(k) | ||
| sb.WriteRune('=') | ||
| sb.WriteString(fieldFilters[k]) | ||
| sb.WriteRune(';') | ||
| } | ||
| return sb.String() | ||
| } |
105 changes: 105 additions & 0 deletions
105
cmd/aws-s3-csi-controller/csicontroller/expectations_test.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| package csicontroller | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/awslabs/aws-s3-csi-driver/pkg/util/testutil/assert" | ||
| "sigs.k8s.io/controller-runtime/pkg/client" | ||
| ) | ||
|
|
||
| func TestDeriveExpectationKeyFromFilters(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| fieldFilters client.MatchingFields | ||
| want string | ||
| }{ | ||
| { | ||
| name: "empty filters", | ||
| fieldFilters: client.MatchingFields{}, | ||
| want: "", | ||
| }, | ||
| { | ||
| name: "single filter", | ||
| fieldFilters: client.MatchingFields{ | ||
| "key1": "value1", | ||
| }, | ||
| want: "key1=value1;", | ||
| }, | ||
| { | ||
| name: "multiple filters", | ||
| fieldFilters: client.MatchingFields{ | ||
| "key2": "value2", | ||
| "key1": "value1", | ||
| "key3": "value3", | ||
| }, | ||
| want: "key1=value1;key2=value2;key3=value3;", | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| got := deriveExpectationKeyFromFilters(tt.fieldFilters) | ||
| assert.Equals(t, tt.want, got) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestExpectations(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| fieldFilters client.MatchingFields | ||
| operations func(*expectations) | ||
| wantPending bool | ||
| }{ | ||
| { | ||
| name: "set and check pending", | ||
| fieldFilters: client.MatchingFields{ | ||
| "key1": "value1", | ||
| }, | ||
| operations: func(e *expectations) { | ||
| e.setPending(client.MatchingFields{"key1": "value1"}) | ||
| }, | ||
| wantPending: true, | ||
| }, | ||
| { | ||
| name: "set and clear pending", | ||
| fieldFilters: client.MatchingFields{ | ||
| "key1": "value1", | ||
| }, | ||
| operations: func(e *expectations) { | ||
| e.setPending(client.MatchingFields{"key1": "value1"}) | ||
| e.clear(client.MatchingFields{"key1": "value1"}) | ||
| }, | ||
| wantPending: false, | ||
| }, | ||
| { | ||
| name: "check non-existent pending", | ||
| fieldFilters: client.MatchingFields{ | ||
| "key1": "value1", | ||
| }, | ||
| operations: func(e *expectations) {}, | ||
| wantPending: false, | ||
| }, | ||
| { | ||
| name: "multiple operations", | ||
| fieldFilters: client.MatchingFields{ | ||
| "key1": "value1", | ||
| "key2": "value2", | ||
| }, | ||
| operations: func(e *expectations) { | ||
| e.setPending(client.MatchingFields{"key1": "value1", "key2": "value2"}) | ||
| e.clear(client.MatchingFields{"key1": "value1"}) // Different key, shouldn't affect the test | ||
| }, | ||
| wantPending: true, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| e := newExpectations() | ||
| tt.operations(e) | ||
| got := e.isPending(tt.fieldFilters) | ||
| assert.Equals(t, tt.wantPending, got) | ||
| }) | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.