DirectorySecurity AdvisoriesPricing
Sign in
Directory
aws-ebs-csi-driver logoHELM

aws-ebs-csi-driver

Helm chart
Last changed
Request a free trial

Contact our team to test out this Helm chart and related images for free. Please also indicate any other images you would like to evaluate.

Overview
Chart tags
Default values
Chart metadata
Images

AWS EBS CSI Driver

Chainguard's redistribution of the AWS EBS CSI Driver Helm chart, pre-configured with hardened Chainguard Images.

Prerequisites

Authentication is required to access this chart and its images. First, authenticate with Chainguard and configure your environment:

chainctl auth login
chainctl auth configure-docker --pull-token --save
helm registry login cgr.dev

Create an image pull secret for the cluster:

kubectl create secret docker-registry cgr-pull-secret \
  --docker-server=cgr.dev \
  --docker-username="$(echo cgr.dev | docker-credential-cgr get | jq -r '.Username')" \
  --docker-password="$(echo cgr.dev | docker-credential-cgr get | jq -r '.Secret')" \
  --namespace kube-system

Installation

helm install aws-ebs-csi-driver oci://cgr.dev/ORGANIZATION/charts/aws-ebs-csi-driver \
  --namespace kube-system \
  --set imagePullSecrets[0].name=cgr-pull-secret

About This Chart

This is a redistribution of the upstream AWS EBS CSI Driver Helm chart. All upstream configuration options and documentation apply.

For full documentation, see: https://github.com/kubernetes-sigs/aws-ebs-csi-driver

Chainguard Customizations

The chart's values schema accepts two values that the upstream schema lacks: k8sVersion, which EKS passes when it installs the chart as an add-on, and useAwsAddonSelectors, described under Taking over from AWS's EBS CSI add-on below. This chart provides an aws_mp_addon_parameters.json file that defines the IAM permissions required when deploying this product as an EKS Addon. It also provides an aws_mp_configuration_schema.json file, described under EKS add-on configuration values below.

EKS add-on configuration values

EKS validates the --configuration-values of aws eks create-addon and aws eks update-addon against aws_mp_configuration_schema.json at the chart root, and aws eks describe-addon-configuration returns it.

The schema starts from the schema of AWS's own aws-ebs-csi-driver add-on v1.67.2-eksbuild.1 (driver 1.67.2), so a customer moving from AWS's add-on can pass the same settings in the same shape, except those in the next two sections. Its defaults are this chart's, which can differ from AWS's.

AWS settings the schema leaves out

The chart ignores these settings of AWS's add-on, so the schema leaves them out rather than accept a setting that does nothing:

AWS settingWhy the chart ignores it

node.envFrom

No template reads it; node pods read controller.envFrom.

additionalDaemonSets.<name>.envFrom

No template reads envFrom under node.

additionalDaemonSets.<name>.enablePrometheusAnnotations

Only the node metrics Service reads it, and only from node.

additionalDaemonSets.<name>.serviceMonitor.forceEnable and additionalDaemonSets.<name>.serviceMonitor.labels

Only the node ServiceMonitor reads them, and only from node.

additionalDaemonSets.<name>.serviceAccount.automountServiceAccountToken

Only the node service account reads it, and only from node.

AWS settings the schema narrows

In their open form, these settings could reach something that no schema exposes, such as an image, a security context, or RBAC rules, or they accept values that Kubernetes or the driver rejects, that the chart ignores, or that the chart renders twice.

AWS settingAcceptedWhy

controller.podAnnotations

Annotation keys, and as values: strings with no {{ and no control characters other than tab and line feed, integers from -999999 to 999999, or booleans

The chart runs every key and value through Helm's tpl, so template code could change the controller's image or security context. A template action starts only at {{, so single braces and }} are accepted, and JSON values such as {"a":{"b":1}} work. The chart turns a number into a string, and writes 1,000,000 as 1e+06 and 0.00001 as 1e-05; pass such a value as a string.

Every string, including map keys and list items, for example proxy.http_proxy, node.kubeletPath, and each additionalArgs entry

No control characters and no NEL, LS, or PS line separators, except tab and line feed in annotation values and EnvVar values

Helm's YAML writer keeps these separators raw and nindent re-indents only after line feeds, so where the chart renders a string with toYaml a separator can add keys outside the value. Quoted settings get the rule too, in case an upstream change stops quoting one.

customLabels

Label keys, except keys under rbac.authorization.k8s.io/ and keys named aggregate-to-*

The chart puts these labels on its ClusterRoles, where an aggregation label adds their rules to other roles, such as the built-in view role.

customLabels, controller.podLabels, node.podLabels, and the podLabels of each additionalDaemonSets entry

Label keys other than app, app.kubernetes.io/name, and app.kubernetes.io/instance

The chart's Deployment, DaemonSet, and PodDisruptionBudget selectors use these keys, and the chart writes these maps into the same pod template labels. A different value there leaves the pods outside their own Deployment or DaemonSet, which Kubernetes rejects.

customLabels, controller.podLabels, node.podLabels, and the podLabels of each additionalDaemonSets entry

Label keys other than app.kubernetes.io/managed-by, app.kubernetes.io/component, app.kubernetes.io/version, and helm.sh/chart

The chart's labels helper sets these labels and then writes customLabels, and each pod template writes podLabels after the helper, so the same key renders twice in one map. Which value applies then depends on how the manifest is parsed, and app.kubernetes.io/managed-by is the label Helm reads to decide whether it owns an object.

controller.extraVolumeTags

Keys with no , or = that do not start or end with a space, and values with no ,. Not the keys CSIVolumeName and CSIVolumeSnapshotName, or keys that start with kubernetes.io or ebs.csi.aws.com/.

The chart joins the tags into one --extra-tags=k=v,k2=v2 argument, and the driver splits it at each , and at the first = of each pair, then trims the spaces around each key and value. The driver reserves those keys and prefixes, and exits at startup when a tag uses one.

additionalDaemonSets keys

Lowercase letters, digits, -, and ., starting and ending with a letter or digit, at most 50 characters, and not windows or ending in -windows

The key becomes part of two DaemonSet names and of the selector label value ebs-csi-node-<key>, which Kubernetes limits to 63 characters. The key windows would name a second DaemonSet ebs-csi-node-windows, and the key x-windows would name a DaemonSet ebs-csi-node-x-windows, the name of the key x's Windows DaemonSet.

controller.podDisruptionBudget

maxUnavailable and minAvailable: an integer from 1 to 999999, a string holding an integer from 0 to 999999, or a percentage from 0% to 100%. unhealthyPodEvictionPolicy: IfHealthyBudget or AlwaysAllow.

Kubernetes rejects any other value in the PodDisruptionBudget. It also rejects both counts set at once, which the schema does not check. The chart ignores the integer 0 and renders its default budget, which allows one unavailable pod with 2 or fewer replicas, so pass "0" as a string to set 0.

controller.priorityClassName, node.priorityClassName, and the priorityClassName of each additionalDaemonSets entry

Empty, or a DNS subdomain of at most 253 characters, such as system-node-critical

Kubernetes rejects a pod whose priority class name is not a DNS subdomain.

nodeAllocatableUpdatePeriodSeconds

-1, 0, or 10 to 999999

Where Kubernetes keeps the field, it requires at least 10. It keeps the field on Kubernetes 1.35, and on 1.33 and 1.34 only with the MutableCSINodeAllocatableCount feature gate on.

controller.replicaCount, every logLevel, and the revisionHistoryLimit, terminationGracePeriodSeconds, volumeAttachLimit, and reservedVolumeAttachments settings, including the additionalDaemonSets copies

At most 999999, every logLevel at least -999999, and a revisionHistoryLimit at least 0

The chart writes these numbers into the manifests and arguments without quotes, and Helm writes 1,000,000 or more as 1e+06, and -1,000,000 or less as -1e+06, which neither Kubernetes nor the driver reads as an integer. Kubernetes rejects a negative revisionHistoryLimit.

sidecars.nodeDriverRegistrar.healthPort

1 to 65535

It becomes a container port.

node.kubeletPath and the kubeletPath of each additionalDaemonSets entry

An absolute path with no .. element

The node pods mount it from the host and into their containers. Kubernetes rejects an empty host path or mount path, and a host path with a .. element.

controller.serviceAccount.automountServiceAccountToken and node.serviceAccount.automountServiceAccountToken

true only, the default

The chart writes the field only when it is true. With false it leaves the field unset, and Kubernetes still mounts the token.

customLabels, podLabels, nodeSelector, node.serviceMonitor.labels, and the podAnnotations maps other than controller.podAnnotations, and the deploymentAnnotations and daemonSetAnnotations maps

Label or annotation keys, and string values. An annotation key prefix, such as example.com in example.com/owner, must be lowercase, which is stricter than Kubernetes; a later version may widen this if customers need it. The values of customLabels, podLabels, nodeSelector, and node.serviceMonitor.labels are label values: at most 63 characters, starting and ending with a letter or digit, or empty.

Kubernetes accepts only strings here and rejects any other label value, and a line separator in a key or value could add keys outside the map.

affinity, tolerations, topologySpreadConstraints, resources, dnsConfig, env, envFrom, volumes, and volumeMounts, wherever they appear

The Kubernetes types, with only the fields that work on every Kubernetes version from 1.29 to 1.35, no unknown fields, and no null at any field inside them, and with the required fields, allowed values, bounds, and formats that Kubernetes validation enforces on one field at a time

AWS's add-on accepts any object here, and a string inside an open object could carry a line separator. A value that Kubernetes would reject when the chart applies it, such as a pod affinity term with no topologyKey, a toleration effect of Never, or a memory limit of lots, is rejected when EKS validates the configuration values instead. The schema leaves out four kinds of Kubernetes rule: rules that tie one field to another, such as a toleration with no key needing the Exists operator; rules across objects or list items, such as a volume mount naming one of the pod's volumes; required fields that a chart default fills, because Helm merges a customer's map into that default, so nodeSelectorTerms needs at least one term but is not required; and some single-field rules not yet written, such as the formats of container resource names, downward API field paths, the iSCSI iqn and initiatorName, a claim's storageClassName, and the CSI nodePublishSecretRef name. It also leaves out each field behind a feature gate that is off by default on some version from 1.29 to 1.35, such as matchLabelKeys and mismatchLabelKeys in pod affinity terms, recursiveReadOnly on volume mounts, the projected clusterTrustBundle source, and the env fileKeyRef source. Some rules are stricter than Kubernetes: annotation key prefixes must be lowercase, nameservers take no IPv4 address with leading zeros and no IPv6 address with an embedded IPv4 address, a quantity cannot be . or a bare +, an envFrom ConfigMap or Secret name cannot end in -, csi.driver takes ASCII letters only, and env var names and DNS search domains follow the stricter rule where Kubernetes changed it within that range. resources takes limits and requests only: a container's claims must name one of the pod's resource claims, which no setting exposes. A null inside one of these objects is rejected everywhere, so that one rule covers every field; a later version may accept null where a customer needs it. An env entry may not set an AWS SDK credential or identity variable: AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_SESSION_NAME, AWS_ACCESS_KEY_ID, AWS_ACCESS_KEY, AWS_SECRET_ACCESS_KEY, AWS_SECRET_KEY, AWS_SESSION_TOKEN, AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, AWS_CONTAINER_AUTHORIZATION_TOKEN, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, AWS_PROFILE, AWS_DEFAULT_PROFILE, AWS_SHARED_CREDENTIALS_FILE, and AWS_CONFIG_FILE. The AWS SDK would read these instead of the add-on's own credentials, which replaces the service account identity. AWS_REGION and AWS_USE_FIPS_ENDPOINT are accepted. The endpoint variables, such as AWS_ENDPOINT_URL, AWS_ENDPOINT_URL_STS, AWS_EC2_METADATA_SERVICE_ENDPOINT, and the driver's AWS_EC2_ENDPOINT, are also accepted, as in AWS's add-on. They change the hosts that the driver sends AWS requests to, and AWS_ENDPOINT_URL_STS and AWS_EC2_METADATA_SERVICE_ENDPOINT change where the SDK gets credentials, so an env entry can still send the service account token or the node role's credentials to another host. A later version may reject them. envFrom can still set the denied names from the keys of a ConfigMap or Secret, which the schema cannot see.

controller.affinity, node.affinity, controller.resources, node.resources, the fields under them that the chart sets, controller.defaultFsType, and nodeAllocatableUpdatePeriodSeconds

Any value except null

A setting accepts null only where a null renders the same as leaving the setting out, once null fields are dropped, and Chainguard's build-time check renders every null that the schema accepts. Here a null deletes the chart's default: a null node.affinity lets node pods run on Fargate, EKS Auto Mode, and hybrid nodes, a null resources drops the memory limits, and a null nodeAllocatableUpdatePeriodSeconds drops the CSIDriver's 10-second update period. Pass "" to leave defaultFsType unset, and 0 to drop the update period. The affinity and resources defaults can be changed but not removed, because Helm merges a map into the default key by key and a Kubernetes quantity cannot be null: the controller's default 256Mi memory limit can be raised but not dropped. Inside an additionalDaemonSets entry every setting rejects null, because a null there deletes the value that the entry would take from node.

The limits and requests of each sidecar's resources; the values of controller.podAnnotations; the nameservers, searches, and options of dnsConfig; the requiredDuringSchedulingIgnoredDuringExecution and preferredDuringSchedulingIgnoredDuringExecution terms of podAffinity, and of podAntiAffinity under node; and controller.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms. The dnsConfig and affinity fields are rejected inside additionalDaemonSets entries too.

Any value except null

These are empty or unset by default, but a null there still renders. Under a sidecar's resources, a null turns off the sidecar's fallback to controller.resources or to the chart's built-in values, so the sidecar runs with no requests or limits. A null annotation value becomes an empty annotation; pass "" for that. Under nodeSelectorTerms, a null renders a node selector with no terms, which Kubernetes rejects at apply. The others, under dnsConfig and the affinity terms, render only an empty object, which has no effect on the pod; they are rejected so that one rule covers every null, and a later version may accept them. A non-empty sidecar resources replaces the inherited values as a whole, so set every request and limit that the sidecar needs.

Every annotation map, including the additionalDaemonSets copies and the annotations of an ephemeral volume's claim

Keys other than container.apparmor.security.beta.kubernetes.io/<container>, seccomp.security.alpha.kubernetes.io/pod, and container.seccomp.security.alpha.kubernetes.io/<container>

Kubernetes 1.30 and later still copy the AppArmor annotation into the container's AppArmor profile, which is a security context. The seccomp annotations do nothing since Kubernetes 1.27, and are rejected so that every Chainguard EKS add-on has the same rule.

The image volume source in controller.volumes

Not accepted

It mounts a container image's contents, and the product decides which images the add-on uses.

The gitRepo volume source in controller.volumes

Not accepted

It pulls content that the product does not decide. Kubernetes deprecated it in v1.11 and dropped its driver after v1.35.

The secret, rbd, and quobyte volume sources in controller.volumes, and the secret, serviceAccountToken, and podCertificate projected sources

Not accepted

Chainguard's build-time check rejects settings by words in their names (secret, service account, token, certificate, image, registry), although a volume that names a Secret carries none of its contents. So a Secret-backed volume that AWS's add-on accepts, such as a CA bundle, is rejected here; mount it from a ConfigMap instead. The rbd and quobyte in-tree drivers are also deprecated or no longer documented upstream.

The gcePersistentDisk, azureDisk, azureFile, cinder, vsphereVolume, photonPersistentDisk, portworxVolume, flocker, glusterfs, scaleIO, storageos, flexVolume, and cephfs volume sources in controller.volumes

Not accepted

Kubernetes has deprecated each of these in-tree volume types, or no longer provides it. Mount such storage through its CSI driver with the csi or ephemeral source instead. Every Chainguard EKS add-on schema leaves out the same sources.

Settings inside additionalDaemonSets entries

The chart merges each entry over node, key by key at every level. A setting that the entry leaves out, or sets to an empty map, keeps its value from node. Any other value replaces it, including false, 0, an empty string, and an empty list, so an entry can turn off enableLinux, enableWindows, or tolerateAllTaints, which node turns on by default. Null is rejected in an entry, because it deletes the value from node.

Taking over from AWS's EBS CSI add-on

useAwsAddonSelectors (default false) drops the app.kubernetes.io/instance label from every object and label selector. The controller Deployment, the node DaemonSets, and the PodDisruptionBudget then use the selectors of AWS's own add-on, so this add-on can take those objects over. Selectors cannot change on an existing object, so:

  • Set useAwsAddonSelectors: true on the first install that replaces AWS's add-on, and keep it set.
  • On a cluster that never ran AWS's add-on, the setting is not needed.
  • Never change the setting on an existing install, because the update fails.

A failed update can still change the PodDisruptionBudget, because its selector can change. Turning the setting off on an install that took over AWS's objects adds app.kubernetes.io/instance to that selector, while the controller pods still lack the label. If the budget is updated before the Deployment update fails, it selects no pods, and nothing limits evictions of the controller pods until the setting is turned back on. Turning the setting on for an existing Chainguard install leaves the pods matched, because their labels still include the narrower selector's keys.

With the setting on, the kubectl get pod command in the install notes still filters on app.kubernetes.io/instance and lists no pods. Filter on app.kubernetes.io/name=aws-ebs-csi-driver instead.

A Chainguard patch to the chart's selector labels helper adds the setting. With it unset, the chart renders exactly what it rendered before.

Chart versions
  • 2.67.2-fips

    Latest
  • 2.67.2

  • 2.67.1-fips

  • 2.67.1

View all chart versions

Images

Helm charts contain references to Chainguard Container images. The following images are referenced in the chart:

aws-ebs-csi-driver-fips logoFIPS

aws-ebs-csi-driver-fips


The trusted source for open source

Talk to an expert
PrivacyTerms

Product

Chainguard ContainersChainguard LibrariesChainguard VMsChainguard OS PackagesChainguard ActionsChainguard Agent SkillsIntegrationsPricing
© 2026 Chainguard, Inc. All Rights Reserved.
Chainguard® and the Chainguard logo are registered trademarks of Chainguard, Inc. in the United States and/or other countries.
The other respective trademarks mentioned on this page are owned by the respective companies and use of them does not imply any affiliation or endorsement.