Skip to main content
Version: Develop

Provisioning and Managing S3 Buckets

This chapter describes how to provision and manage AWS S3 buckets using Klutch.

Pre-requisite

You can verify their presence with:

kubectl get crds

Example output:

NAME                                     CREATED AT
apiservicebindings.klutch.anynines.com 2025-10-15T23:14:44Z
objectstoragebindings.anynines.com 2025-10-15T23:15:28Z
objectstorageinstances.anynines.com 2025-10-15T23:14:46Z

These CRDs allow developers to request, bind, and consume AWS S3 object storage through Klutch.

Using Klutch to provision AWS S3 buckets

After verifying that the app cluster is properly configured with the necessary CRDs and can communicate with the control plane cluster, you can start by requesting S3 buckets.

Step 1: Request an S3 Bucket

To create an S3 bucket, use the object storage claim template below, or apply the provided example file.

  apiVersion: anynines.com/v1
kind: ObjectStorageInstance
metadata:
name: <name>
namespace: <namespace>
spec:
service: aws-s3 # must be aws-s3
plan: <plan-name>
region: <region-name>
compositionRef:
name: <composition-name> # to be supplied by a platform operator
# Optional
parameters:
tags:
TagName: <tag-value>
deletionPolicy: <EmptyBucketAndDelete/DeleteInstanceKeepBucket>
encryption:
type: <kms/aes256> # Defaults to aes256
key: # <-- Required only if type is 'kms'
# Option A: Have Klutch create a Managed Key
managed:
alias: <alias-name> # Optional, e.g. "my-key-alias"
# Option B: Use an Existing Key
existing:
id: <arn:aws:kms:...> # The ARN of your key

Note: If you specify an encryption key, AWS KMS will be used. Provide exactly one of managed or existing under the key block. This is not required if type is aes256 or the encryption block is omitted.

Deploy the resource:

kubectl apply -f <your-file-name>

What Klutch does:

The Klutch control plane provisions an S3 bucket in the specified region. The AWS bucket name is derived from the object storage claim name, with a unique suffix appended to ensure uniqueness and prevent naming collisions, as required by S3 (for example, example-aws-s3-xyz12).

Check that the ObjectStorageInstance was created successfully:

kubectl get objectstorageinstance

Example output:

NAME                SYNCED   READY   CONNECTION-SECRET   AGE
s3-bucket-example True True 10s

If you want to see more details about the resource (e.g. the actual name of the bucket created on AWS) you can use the command below and look for the status field.

kubectl describe objectstorageinstance <name>
Expand for more details about the ObjectStorageInstance's spec fields
FieldTypeRequiredDescriptionSupported Values
servicestringYesSpecifies the object storage service backend.aws-s3
planstringYesDefines the service plan. Values match AWS S3 storage classes.standard, infrequentaccess, intelligent, archiveinstant, archiveflexible, archivedeep
regionstringYesSpecifies the region where the object storage will be created.All AWS regions supported by Klutch. See here.
parametersobjectNoOptional parameters to customize the instance.tags, deletionPolicy, encryption
parameters.tagsobjectNoKey/value map of tags to apply to the provisioned resource.Keys must be alphanumeric and can include spaces, dashes (-), and underscores (_). Values must be ≤256 characters.
parameters.deletionPolicystringNoControls what happens to the bucket and its data when the instance is deleted.DeleteInstanceKeepBucket (default), EmptyBucketAndDelete
parameters.encryptionobjectNoConfigures server-side encryption. Cannot be changed after creation.type and key
parameters.encryption.typestringNoThe type of encryption to use. Defaults to aes256 if omitted.aes256, kms
parameters.encryption.keyobjectConditionally requiredAWS KMS key configuration. Required if type is kms. Must contain either managed or existing.Must contain one of managed or existing
parameters.encryption.key.managedobjectNoConfigures a new KMS key to be created by Klutch.Contains alias
parameters.encryption.key.managed.aliasstringNoAlias for the managed KMS key. Immutable. Must not start with aws/.1–250 alphanumeric characters, /, _, -
parameters.encryption.key.existingobjectNoConfigures the bucket to use a pre-existing KMS key.Contains id (Key ARN)
parameters.encryption.key.existing.idstringNoARN of the existing AWS KMS key. Immutable.Must match arn:aws:kms:[region]:[account]:key/...

For details on behaviors and limitations of AWS S3 buckets, see the official AWS S3 documentation.

Step 2: Bind the Bucket to Get Access Credentials

Once the ObjectStorageInstance is ready, create an ObjectStorageBinding to get access and use the bucket.

  apiVersion: anynines.com/v1
kind: ObjectStorageBinding
metadata:
name: <name>
namespace: <namespace>
spec:
instanceRef: <objectStorageInstance-name>
compositionRef:
name: <composition-name> # to be supplied by a platform operator
writeConnectionSecretToRef:
name: <secret-name>
# Optional
permissions: <permissions> # Optional, defaults to readWrite
scopedAccess:
- prefix: <prefix>
permissions: <permissions>

Deploy the resource:

kubectl apply -f <your-file-name>

What Klutch does:

Klutch creates an IAM user with a tightly scoped policy following the principle of least privilege. The access credentials are stored in the Kubernetes secret specified in writeConnectionSecretToRef. When KMS encryption is used, Klutch also assigns only the required KMS permissions based on the specified access level.

Check that the binding to the bucket was created successfully:

kubectl get objectstoragebinding

Example output:

NAME                      SYNCED   READY   CONNECTION-SECRET                     AGE
example-storage-binding True True example-storage-binding-credentials 11s

Once the binding is ready, you can deploy an application that uses the provisioned S3 bucket.

Expand for more details about the ObjectStorageBinding's spec fields
FieldTypeRequiredDescriptionSupported Values
instanceRefstringYesThe name of the target object storage instance to bind to.n.a.
permissionsstringNoThe default permission level for the entire bucket. Applies to both S3 actions and KMS actions if the bucket is encrypted.listOnly, readOnly, writeOnly, readWrite (Default), admin
scopedAccessarrayNoFine-grained permissions for specific S3 prefixes (folders) within the bucket.Same values as permissions field. Maximum 10 entries.
writeConnectionSecretToRefobjectYesDefines the Kubernetes secret where the access credentials for the instance will be stored.The object must include a name field.

More information on permissions values:

  • listOnly: Allows listing object names but not reading their content.
  • readOnly: Allows listing objects and reading their content.
  • writeOnly: Allows creating and deleting objects.
  • readWrite: Allows listing, reading, creating, and deleting objects.
  • admin: Grants full permissions on all objects (s3:*Object).

Note: If the bucket is encrypted with KMS, the specified permissions are also applied to the corresponding KMS operations.

Cleanup

To remove the ObjectStorageInstance and ObjectStorageBinding resources, use the standard kubectl delete <resource-type> <resource-name> command. If you deployed the example manifests, run the following commands to delete the corresponding objects.

To delete the binding for the S3 bucket:

kubectl delete objectstoragebinding storage-binding-example

To delete the s3 bucket:

kubectl delete objectstorageinstance s3-bucket-example