Skip to content

Commit

Permalink
Merge pull request #1600 from rdpsin/modify-volume
Browse files Browse the repository at this point in the history
Enable volume modification through annotations
  • Loading branch information
k8s-ci-robot authored May 15, 2023
2 parents cdaa6d3 + 1560d54 commit d47ee59
Show file tree
Hide file tree
Showing 13 changed files with 429 additions and 12 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,6 @@ The EBS CSI Driver is compatible with Kubernetes versions v1.17+ and implements
* [Driver Launch Options](docs/options.md)
* [StorageClass Parameters](docs/parameters.md)
* [Volume Tagging](docs/tagging.md)
* [Volume Modification](docs/modify-volume.md)
* [Kubernetes Examples](/examples/kubernetes)
* [Development and Contributing](CONTRIBUTING.md)
44 changes: 44 additions & 0 deletions charts/aws-ebs-csi-driver/templates/controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,50 @@ spec:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
{{- if (.Values.controller.volumeModificationFeature).enabled }}
- name: volumemodifier
image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.volumemodifier.image.repository .Values.sidecars.volumemodifier.image.tag }}
imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.volumemodifier.image.pullPolicy }}
args:
- --csi-address=$(ADDRESS)
- --v={{ .Values.sidecars.volumemodifier.logLevel }}
- --leader-election={{ .Values.sidecars.volumemodifier.leaderElection.enabled | required "leader election state for csi-volumemodifier is required, must be set to true || false." }}
{{- if .Values.sidecars.volumemodifier.leaderElection.enabled }}
{{- if .Values.sidecars.volumemodifier.leaderElection.leaseDuration }}
- --leader-election-lease-duration={{ .Values.sidecars.volumemodifier.leaderElection.leaseDuration }}
{{- end }}
{{- if .Values.sidecars.volumemodifier.leaderElection.renewDeadline}}
- --leader-election-renew-deadline={{ .Values.sidecars.volumemodifier.leaderElection.renewDeadline }}
{{- end }}
{{- if .Values.sidecars.volumemodifier.leaderElection.retryPeriod }}
- --leader-election-retry-period={{ .Values.sidecars.volumemodifier.leaderElection.retryPeriod }}
{{- end }}
{{- end }}
env:
- name: ADDRESS
value: /var/lib/csi/sockets/pluginproxy/csi.sock
{{- if .Values.proxy.http_proxy }}
{{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }}
{{- end }}
{{- with .Values.sidecars.volumemodifier.env }}
{{- . | toYaml | nindent 12 }}
{{- end }}
envFrom:
{{- with .Values.controller.envFrom }}
{{- . | toYaml | nindent 12 }}
{{- end }}
volumeMounts:
- name: socket-dir
mountPath: /var/lib/csi/sockets/pluginproxy/
{{- with default .Values.controller.resources .Values.sidecars.volumemodifier.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.sidecars.volumemodifier.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
- name: csi-resizer
image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.resizer.image.repository .Values.sidecars.resizer.image.tag }}
imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.resizer.image.pullPolicy }}
Expand Down
21 changes: 21 additions & 0 deletions charts/aws-ebs-csi-driver/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,25 @@ sidecars:
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
volumemodifier:
env: []
image:
pullPolicy: IfNotPresent
repository: public.ecr.aws/ebs-csi-driver/volume-modifier-for-k8s
tag: "v0.1.0"
leaderElection:
enabled: true
# Optional values to tune lease behavior.
# The arguments provided must be in an acceptable time.ParseDuration format.
# Ref: https://pkg.go.dev/flag#Duration
# leaseDuration: "15s"
# renewDeadline: "10s"
# retryPeriod: "5s"
logLevel: 2
resources: {}
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false

proxy:
http_proxy:
Expand All @@ -110,6 +129,8 @@ nameOverride:
fullnameOverride:

controller:
volumeModificationFeature:
enabled: false
additionalArgs: []
sdkDebugLog: false
loggingFormat: text
Expand Down
202 changes: 202 additions & 0 deletions docs/modify-volume.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# Volume Modification

The EBS CSI Driver (starting from v1.19.0) supports volume modification through PVC annotations. This allows users to modify volume properties (e.g., volume type, IOPS, and throughput).

## Installation
This feature is opt-in.

To install this feature through the Helm chart, users must set `controller.volumeModificationFeature.enabled` in `values.yaml` to `true`.

This will install an additional sidecar (`volumemodifier`) that watches the Kubernetes API server for changes to PVC annotations and triggers an RPC call against the CSI driver.

## Usage

Users can specify the following PVC annotations:

- `ebs.csi.aws.com/volumeType`: to update the volume type
- `ebs.csi.aws.com/iops`: to update the IOPS
- `ebs.csi.aws.com/throughput`: to update the throughput

## Considerations

- Keep in mind the [6 hour cooldown period](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyVolume.html) for EBS ModifyVolume. Multiple ModifyVolume calls for the same volume within a 6 hour period will fail.
- It is not yet possible to update both the annotations and capacity of the PVC at the same time. This results in multiple RPC calls to the driver, and only one of them will succeed (due to the cooldown period). A future release of the driver will lift this restriction.
- Ensure that the desired volume properties are permissible. The driver does minimum client side validation.

## Example

#### 1) Create a PVC.


```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ebs-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: ebs-sc
resources:
requests:
storage: 100Gi
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: centos
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: ebs-claim
```

#### 2) Verify the PVC is created.

```
$ k describe pvc ebs-claim
Name: ebs-claim
Namespace: default
StorageClass: ebs-sc
Status: Bound
Volume: pvc-20c5ddec-5913-4b8d-a2fc-bfd0943b966d
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
volume.beta.kubernetes.io/storage-provisioner: ebs.csi.aws.com
volume.kubernetes.io/selected-node: ip-192-168-32-79.ec2.internal
volume.kubernetes.io/storage-provisioner: ebs.csi.aws.com
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 100Gi
Access Modes: RWO
VolumeMode: Filesystem
Used By: app
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ProvisioningFailed 6s persistentvolume-controller storageclass.storage.k8s.io "ebs-sc" not found
Normal Provisioning 5s ebs.csi.aws.com_ebs-csi-controller-b84fbbd88-5z66k_d2cb941a-aee8-41d6-aea5-8f4a40c7c82c External provisioner is provisioning volume for claim "default/ebs-claim"
Normal ExternalProvisioning 4s (x2 over 5s) persistentvolume-controller waiting for a volume to be created, either by external provisioner "ebs.csi.aws.com" or manually created by system administrator
Normal ProvisioningSucceeded 1s ebs.csi.aws.com_ebs-csi-controller-b84fbbd88-5z66k_d2cb941a-aee8-41d6-aea5-8f4a40c7c82c Successfully provisioned volume pvc-20c5ddec-5913-4b8d-a2fc-bfd0943b966d
```

#### 3) (Optional) Verify volume properties in EBS.

```
$ pv=$(k get -o json pvc ebs-claim | jq -r '.spec | .volumeName')
$ volumename=$(k get -o json pv $pv | jq -r '.spec | .csi | .volumeHandle')
$ aws ec2 describe-volumes —volume-id $volumename | jq '.Volumes[] | "\(.VolumeType) \(.Iops) \(.Throughput)"'
"gp3 3000 125"
```

#### 4) Edit the PVC with annotations.

```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ebs-claim
annotations:
ebs.csi.aws.com/volumeType: "io2"
ebs.csi.aws.com/iops: "4000"
spec:
accessModes:
- ReadWriteOnce
storageClassName: ebs-sc
resources:
requests:
storage: 100Gi
```

#### 5) Verify the volume has been updated successfully.


```
$ k describe pvc ebs-claim
Name: ebs-claim
Namespace: default
StorageClass: ebs-sc
Status: Bound
Volume: pvc-6bff47f9-1843-4576-ba15-158c73491e8c
Labels: <none>
Annotations: ebs.csi.aws.com/iops: 4000
ebs.csi.aws.com/volumeType: io2
pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
volume.beta.kubernetes.io/storage-provisioner: ebs.csi.aws.com
volume.kubernetes.io/selected-node: ip-192-168-88-208.us-east-2.compute.internal
volume.kubernetes.io/storage-provisioner: ebs.csi.aws.com
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 100Gi
Access Modes: RWO
VolumeMode: Filesystem
Used By: app
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ProvisioningFailed 7m51s persistentvolume-controller storageclass.storage.k8s.io "ebs-sc" not found
Normal WaitForPodScheduled 7m49s persistentvolume-controller waiting for pod app to be scheduled
Normal ExternalProvisioning 7m49s (x2 over 7m49s) persistentvolume-controller waiting for a volume to be created, either by external provisioner "ebs.csi.aws.com" or manually created by system administrator
Normal Provisioning 7m49s ebs.csi.aws.com_ebs-csi-controller-6bb6b754f7-kqpzm_27524e89-857b-4197-b801-e48576823e89 External provisioner is provisioning volume for claim "default/ebs-claim"
Normal ProvisioningSucceeded 7m46s ebs.csi.aws.com_ebs-csi-controller-6bb6b754f7-kqpzm_27524e89-857b-4197-b801-e48576823e89 Successfully provisioned volume pvc-6bff47f9-1843-4576-ba15-158c73491e8c
Normal VolumeModificationStarted 4s volume-modifier-for-k8s-ebs.csi.aws.com External modifier is modifying volume pvc-6bff47f9-1843-4576-ba15-158c73491e8c
Normal VolumeModificationSuccessful 1s volume-modifier-for-k8s-ebs.csi.aws.com External modifier has successfully modified volume pvc-6bff47f9-1843-4576-ba15-158c73491e8c
```

You will notice that the annotations have been applied to the PV as well.

```
$ k describe pv
Name: pvc-6bff47f9-1843-4576-ba15-158c73491e8c
Labels: <none>
Annotations: ebs.csi.aws.com/iops: 4000
ebs.csi.aws.com/volumeType: io2
pv.kubernetes.io/provisioned-by: ebs.csi.aws.com
volume.kubernetes.io/provisioner-deletion-secret-name:
volume.kubernetes.io/provisioner-deletion-secret-namespace:
Finalizers: [kubernetes.io/pv-protection external-attacher/ebs-csi-aws-com]
StorageClass: ebs-sc
Status: Bound
Claim: default/ebs-claim
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 100Gi
Node Affinity:
Required Terms:
Term 0: topology.ebs.csi.aws.com/zone in [us-east-2b]
Message:
Source:
Type: CSI (a Container Storage Interface (CSI) volume source)
Driver: ebs.csi.aws.com
FSType: ext4
VolumeHandle: vol-02cb54d01c685b919
ReadOnly: false
VolumeAttributes: storage.kubernetes.io/csiProvisionerIdentity=1684161810754-8081-ebs.csi.aws.com
Events: <none>
```

Do **NOT** delete these annotations. These annotations are used by the sidecar to reconcile the PVC's state when modifying annotations.

#### 6) (Optional) Validate the volume has been modified in EBS.
```
$ aws ec2 describe-volumes --volume-id $volumename | jq '.Volumes[] | "\(.VolumeType) \(.Iops) \(.Throughput)"'
"io2 4000 null"
```

13 changes: 7 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module github.com/kubernetes-sigs/aws-ebs-csi-driver

require (
github.com/aws/aws-sdk-go v1.44.218
github.com/awslabs/volume-modifier-for-k8s v0.1.0
github.com/container-storage-interface/spec v1.8.0
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.5.9
Expand All @@ -13,12 +14,12 @@ require (
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.2
golang.org/x/sys v0.6.0
google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.29.0
k8s.io/api v0.26.2
k8s.io/apimachinery v0.26.2
google.golang.org/grpc v1.54.0
google.golang.org/protobuf v1.30.0
k8s.io/api v0.27.1
k8s.io/apimachinery v0.27.1
k8s.io/client-go v1.22.11
k8s.io/component-base v0.26.2
k8s.io/component-base v0.27.1
k8s.io/klog/v2 v2.90.1
k8s.io/kubernetes v1.26.2
k8s.io/mount-utils v0.26.2
Expand Down Expand Up @@ -108,7 +109,7 @@ require (
k8s.io/cloud-provider v0.26.0 // indirect
k8s.io/component-helpers v0.26.2 // indirect
k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a // indirect
k8s.io/kubectl v0.0.0 // indirect
k8s.io/kubectl v0.27.1 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
Expand Down
10 changes: 6 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.44.218 h1:p707+xOCazWhkSpZOeyhtTcg7Z+asxxvueGgYPSitn4=
github.com/aws/aws-sdk-go v1.44.218/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/awslabs/volume-modifier-for-k8s v0.1.0 h1:MwV01UuG1/AxE5fcCal6rqbW79W/27kSgsr8wtWJHB4=
github.com/awslabs/volume-modifier-for-k8s v0.1.0/go.mod h1:i2vmtVyjDVQEV1NfGJ0p6eett8LY03mzsB1gy0zbzfA=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down Expand Up @@ -707,8 +709,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
Expand All @@ -724,8 +726,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0=
google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
Loading

0 comments on commit d47ee59

Please sign in to comment.