aws-s3-eks
AWS S3 + EKS Pod Identity
Provision S3 buckets and configure EKS Pod Identity so services running on EKS can access S3 without static AWS credentials.
Prerequisites
Verify tools are installed before proceeding:
aws --version # AWS CLI v2
kubectl version # kubectl
eksctl version # eksctl (for pod identity association)
Quick Start
For a complete setup (bucket + IAM role + pod identity), run the bundled script:
scripts/create-s3-bucket.sh \
--bucket my-app-uploads \
--region us-east-1 \
--cluster my-cluster \
--namespace my-app \
--service-account my-app-api
This single command:
- Creates the S3 bucket with encryption + versioning
- Creates an IAM role with a trust policy for
pods.eks.amazonaws.com - Attaches an S3 access policy to the role
- Creates/annotates the Kubernetes ServiceAccount
- Creates the EKS Pod Identity Association
Workflow
Step 1: Create S3 Bucket
scripts/create-s3-bucket.sh \
--bucket <BUCKET_NAME> \
--region <REGION>
Pass --bucket-only to skip IAM/pod identity setup.
Options:
--versioning— Enable versioning (default: enabled)--lifecycle-days N— Add lifecycle rule to expire objects after N days--public-read— Apply a public-read policy (for serving file URLs directly)--cors-origins "https://example.com"— Configure CORS allowed origins
Step 2: Set Up EKS Pod Identity
scripts/setup-pod-identity.sh \
--cluster <CLUSTER_NAME> \
--namespace <NAMESPACE> \
--service-account <SA_NAME> \
--bucket <BUCKET_NAME> \
--region <REGION>
Options:
--role-name— Custom IAM role name (default:<cluster>-<namespace>-<sa>-s3-role)--read-only— Grant only s3:GetObject/s3:ListBucket (no write)--prefix "uploads/"— Restrict access to a key prefix
Step 3: Verify Access
After pod identity is configured, verify from within a pod:
kubectl run s3-test --rm -it \
--image=amazon/aws-cli \
--serviceaccount=<SA_NAME> \
--namespace=<NAMESPACE> \
-- s3 ls s3://<BUCKET_NAME>/
If it lists objects (or shows empty), pod identity is working. The AWS SDK credential chain automatically picks up the injected AWS_CONTAINER_CREDENTIALS_FULL_URI env var.
Step 4: Configure Your Service
Set the bucket name and region in your application's environment variables:
S3_BUCKET: "my-app-uploads"
S3_REGION: "us-east-1"
# No access key / secret key needed — Pod Identity handles credentials
The AWS SDK default credential chain (boto3, aioboto3, aws-sdk-js, etc.) picks up credentials automatically via the injected AWS_CONTAINER_CREDENTIALS_FULL_URI env var.
How EKS Pod Identity Works
Unlike IRSA (which requires an OIDC provider), Pod Identity uses the EKS Pod Identity Agent DaemonSet:
- IAM role trusts
pods.eks.amazonaws.comservice principal CreatePodIdentityAssociationlinks the role to a K8s ServiceAccount- Pod Identity Agent (link-local
169.254.170.23:80) injects STS credentials - AWS SDKs detect
AWS_CONTAINER_CREDENTIALS_FULL_URIand use those credentials
No OIDC provider, no annotation-based IRSA. Works on EKS 1.24+.
Reference Files
- IAM policies: See references/iam-policies.md for full IAM policy JSON templates (read-only, read-write, prefix-scoped)
- K8s manifests: See references/k8s-manifests.md for ServiceAccount, Deployment patches, and ConfigMap examples
- S3 API spec: See references/openapi.yaml for the full S3 OpenAPI 3.2.0 spec
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
NoCredentialProviders |
Pod Identity Agent not installed | eksctl create addon --name eks-pod-identity-agent --cluster <cluster> |
AccessDenied on S3 call |
IAM policy missing or wrong bucket | Check aws iam get-role-policy and verify bucket ARN |
403 Forbidden |
Pod Identity Association not created | aws eks list-pod-identity-associations --cluster <cluster> |
| Credentials work in test pod but not app | ServiceAccount name mismatch | Verify spec.serviceAccountName in Deployment matches the association |
ExpiredTokenException |
Stale cached credentials | Restart the pod — agent injects fresh credentials on start |
More from deepparser/skills
exa.ai-websearch-api
A skill that equips you with real-time, source-grounded web search and content retrieval using the Exa API—optimized for balanced relevance and speed (type="auto") and full-text extraction for downstream reasoning, RAG, and code assistance. Powering agents with fast, high-quality web search by Exa.AI.
14oas-api-spec-generator
Generate OpenAPI 3.2.0 specifications for third-party APIs (OpenAI, Anthropic, Google, Microsoft, Stripe, GitHub, Slack, AWS, and more)
8eks-cluster
Create and manage Amazon EKS clusters, managed node groups, and EC2 instances. Use when: (1) Provisioning a new EKS cluster from scratch, (2) Adding or modifying managed node groups, (3) Choosing EC2 instance types for workloads, (4) Installing EKS addons (CoreDNS, kube-proxy, VPC CNI, EBS CSI, Pod Identity Agent), (5) Setting up VPC networking for EKS, (6) Configuring cluster autoscaling with Karpenter or Cluster Autoscaler, (7) Deploying services to EKS, (8) Troubleshooting EKS node or cluster issues. Requires: aws CLI v2, eksctl, kubectl.
6design-apple
Apply Apple's design system (colors, typography, components, layout, shadows) when building UI. Use when the user wants to create interfaces styled like Apple.
3azure-bot
Create and manage Azure Bot resources using the Azure CLI. Covers the full lifecycle: identity creation, bot registration, channel configuration (Teams, Slack, Telegram, Direct Line, and more), and deployment to Azure App Service. ESPECIALLY for OpenClaw agents.
3design-miro
Apply Miro's design system (colors, typography, components, layout, shadows) when building UI. Use when the user wants to create interfaces styled like Miro.
1