Grant EKS Pods Access to S3

Use EKS Pod Identity to give pods scoped S3 access without hardcoded credentials.

Introduction

30 Second Summary

Imagine a delivery driver who needs to pick up a package from a locked warehouse. They can't just walk in. Someone has to verify their identity and hand them the right key for the right door. Your Kubernetes pods face the same problem when they need to access AWS services.

In this project, you will deploy a pod to an Amazon EKS cluster and watch it fail to access a private S3 bucket. Then you will wire up EKS Pod Identity so the pod receives temporary AWS credentials automatically, with zero hardcoded secrets.

What You'll Build

By the end, you can exec into a pod, run an S3 download command, and watch a file from your private bucket print to the terminal. No credentials pasted anywhere.

By the end of this project, you'll have:

  • A running pod that reads files from a private S3 bucket using only temporary credentials delivered by Pod Identity.
  • A working IAM role with a least-privilege S3 policy, trusted exclusively by the EKS Pod Identity service principal.
  • A Pod Identity association binding a Kubernetes service account to the IAM role, proving you understand the modern credential-delivery pattern for EKS.
  • Secret Mission: Lock down the trust policy with condition keys so only a specific namespace and service account can assume the role.

Are there any prerequisites?

This project assumes you have a running EKS cluster with kubectl configured and the AWS CLI installed. If you have completed the "Launch a Kubernetes Cluster" NextWork project, you are ready to go.

Before We Start

Before any hands-on work, let's lock in what you're about to build and why it matters. Your pods need AWS credentials to access services like S3, but hardcoding those credentials is a security disaster waiting to happen.

Set Up Your Environment

Your EKS cluster from the prerequisite project can run pods, but it currently has no mechanism to deliver AWS credentials to those pods. Without credentials, any pod that tries to call an AWS service gets an immediate Access Denied.

In this step, you'll install the EKS Pod Identity Agent add-on to enable credential delivery. You'll also create an S3 bucket with a test file that your future pod will try to read.

In this step, get ready to:
  • Verify your existing cluster connection is working.
  • Install the EKS Pod Identity Agent add-on on your cluster.
  • Create an S3 bucket with a test file for later access testing.
Verify your cluster connection

Your prerequisite project left you with a configured AWS CLI and kubectl pointing at your EKS cluster. Before installing anything new, confirm both still work.

  • Confirm your AWS CLI identity by running this command:
aws sts get-caller-identity

You should see a JSON response with your Account, UserId, and Arn fields populated.

  • Confirm your cluster is reachable by running:
kubectl get nodes

You should see one or more nodes with a Ready status.

Not seeing Ready nodes or getting errors?

If aws sts get-caller-identity fails, your AWS CLI session may have expired. Re-authenticate using the same method you used in the prerequisite project.

If kubectl get nodes fails with a connection error, update your kubeconfig by running:

aws eks update-kubeconfig --name [[CLUSTER_NAME="your-cluster-name"]] --region [[AWS_REGION="your-region"]]

help me fix my kubectl connection to my EKS cluster

Install the EKS Pod Identity Agent add-on

The Pod Identity Agent runs as a DaemonSet on every node in your cluster. It intercepts credential requests from pods and supplies temporary AWS credentials from IAM roles you configure.

  • Install the Pod Identity Agent add-on by running this command:
aws eks create-addon --cluster-name [[CLUSTER_NAME="your-cluster-name"]] --addon-name eks-pod-identity-agent

What does this command do?

This tells EKS to deploy the Pod Identity Agent as a managed add-on on your cluster. AWS handles the agent lifecycle (upgrades, restarts) so you don't have to manage it manually.

The agent listens on a link-local address (169.254.170.23) so that any pod on the node can reach it to request credentials.

The add-on takes a moment to deploy. Wait about 30 seconds, then check its status.

  • Check the add-on status by running:
aws eks describe-addon --cluster-name [[CLUSTER_NAME="your-cluster-name"]] --addon-name eks-pod-identity-agent --query "addon.status"

You should see "ACTIVE" in the output. If you see "CREATING", wait another 30 seconds and run the command again.

Before you run the next command, what do you expect to see running in the kube-system namespace now that the agent is installed?

  • Verify the agent pods are running by running:
kubectl get pods -n kube-system | grep eks-pod-identity-agent

You should see one eks-pod-identity-agent pod per node, each in Running state. If you have two nodes, you'll see two agent pods.

Windows terminal without grep

If you're using Windows Command Prompt or PowerShell without grep, run kubectl get pods -n kube-system without the pipe and look for pods whose names start with eks-pod-identity-agent.

Not seeing agent pods in Running state?

If the add-on status is "CREATE_FAILED", your cluster's platform version may be too old. EKS Pod Identity requires Kubernetes 1.28 or later. Check your cluster version with kubectl version.

If pods show CrashLoopBackOff, verify your node IAM role includes the AmazonEKSWorkerNodePolicy managed policy. This policy grants the eks-auth:AssumeRoleForPodIdentity permission the agent needs.

help me troubleshoot my EKS Pod Identity Agent installation

Create an S3 bucket with a test file

You need a private S3 bucket with a file in it so you can test whether your pod can actually read from AWS. This bucket is your proof-of-access target.

  • Create a new S3 bucket by running this command:
aws s3 mb s3://pod-identity-test-[[AWS_ACCOUNT_ID="your-account-id"]]

You should see make_bucket: pod-identity-test-... confirming the bucket was created.

Why include your account ID in the bucket name?

S3 bucket names are globally unique across all AWS accounts. Including your account ID ensures no naming collision with other AWS users.

  • Create a test file and upload it to your bucket by running these commands:
echo "Hello from S3!" > hello.txt
aws s3 cp hello.txt s3://pod-identity-test-[[AWS_ACCOUNT_ID="your-account-id"]]/hello.txt

You should see an upload: line confirming the file was copied to S3.

What do you expect to see when you list the bucket contents?

  • Verify the file is in your bucket by running:
aws s3 ls s3://pod-identity-test-[[AWS_ACCOUNT_ID="your-account-id"]]/

You should see hello.txt listed with its size and upload timestamp. Your bucket is ready for the access test.

Bucket creation failed?

If you see a BucketAlreadyExists error, another AWS account already owns that bucket name. Double-check that you replaced the account ID placeholder with your actual 12-digit AWS account ID.

If you see an AccessDenied error, your IAM user or role may lack S3 permissions. Confirm your CLI identity has the s3:CreateBucket permission.

help me fix my S3 bucket creation error

Your environment is ready. You have a cluster with the Pod Identity Agent listening for credential requests, and an S3 bucket waiting to be accessed. Next up, you'll deploy a pod and watch it fail to reach that bucket.

Deploy a Pod and Attempt S3 Access

Your cluster has the Pod Identity Agent running and a test bucket ready to go. But here's the question: can a pod actually reach that bucket on its own?

In this step, you'll deploy a pod with the AWS CLI pre-installed and try to list your S3 bucket from inside it. The result reveals an important truth about Kubernetes security that the rest of this project is built around.

In this step, get ready to:
  • Deploy a test pod running the AWS CLI image.
  • Attempt to read from your S3 bucket from inside the pod and observe the result.
Create a test pod manifest

A Pod in Kubernetes is the smallest deployable unit. You'll define one using a YAML manifest that tells Kubernetes which container image to run and what command to execute inside it.

  • Create a file named test-pod.yaml with the following content:
apiVersion: v1
kind: Pod
metadata:
  name: aws-cli-test
spec:
  containers:
  - name: aws-cli
    image: public.ecr.aws/aws-cli/aws-cli:latest
    command: ["tail", "-f", "/dev/null"]

What does this manifest do?

  • image: public.ecr.aws/aws-cli/aws-cli:latest pulls a container with the AWS CLI pre-installed from Amazon's public registry.
  • command: ["tail", "-f", "/dev/null"] keeps the pod running indefinitely so you can exec into it interactively.
  • No serviceAccountName is specified, so the pod uses the default service account. This means no special permissions are attached.
  • Save test-pod.yaml.

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

Your test-pod.yaml should look exactly like this:

apiVersion: v1
kind: Pod
metadata:
  name: aws-cli-test
spec:
  containers:
  - name: aws-cli
    image: public.ecr.aws/aws-cli/aws-cli:latest
    command: ["tail", "-f", "/dev/null"]
Deploy the pod and attempt S3 access

Now you'll send this manifest to your cluster and try to access S3 from inside the running pod.

  • Deploy the pod to your cluster by running this command:
kubectl apply -f test-pod.yaml
  • Wait a moment for the image to pull, then check if the pod is running:
kubectl get pods

You should see aws-cli-test with a status of Running.

Pod stuck in ContainerCreating or ErrImagePull?

  • If the pod is stuck in ContainerCreating, the image is still being pulled. Wait 30-60 seconds and run kubectl get pods again.
  • If you see ErrImagePull or ImagePullBackOff, your nodes may not have internet access to pull from the public ECR registry. Check that your node group's subnet has a NAT gateway or internet gateway.

help me troubleshoot my pod not reaching Running state

Now for the key moment. Before you run the next command, make a prediction: do you think the pod will be able to list your S3 bucket contents? Why or why not?

  • Attempt to list your S3 bucket from inside the pod by running:
kubectl exec -it aws-cli-test -- aws s3 ls s3://[[BUCKET_NAME="pod-identity-test-your-account-id"]]/

The command fails. You'll see an error message like:

Unable to locate credentials. You can configure credentials by running "aws configure".

This is the expected result. The pod has zero AWS credentials because no one gave it any.

Why does the pod have no AWS permissions?

Pods in EKS do not automatically inherit permissions from the node or cluster. The EC2 nodes your pods run on have an IAM role, but Kubernetes deliberately isolates pod workloads from node-level credentials.

This is a security feature, not a bug. If every pod inherited the node's permissions, a single compromised container could access every AWS service the node can reach. Pods start with nothing and only receive permissions you explicitly grant.

Seeing a different error?

  • If you see An error occurred (AccessDenied) instead, that's also expected. Some cluster configurations surface a different error message, but the outcome is the same: the pod cannot access S3.
  • If the command hangs or times out, make sure you typed kubectl exec -it (with the -it flags for interactive mode).

help me troubleshoot unexpected errors when running aws s3 ls inside my EKS pod

You've just proven firsthand that EKS pods start with zero AWS permissions. In the next step, you'll create an IAM role with the exact S3 permissions your pod needs and a trust policy that lets the Pod Identity service deliver those credentials automatically.

Create an IAM Role for Pod Identity

The Access Denied error from the previous step told you something important. Your pod has absolutely zero AWS credentials, so it cannot reach any AWS service.

The fix is an IAM role that the EKS Pod Identity service can assume on behalf of your pod. You'll write a trust policy that only the Pod Identity service can use, then attach the minimum S3 permissions your workload actually needs.

In this step, get ready to:
  • Create a trust policy that allows the EKS Pod Identity service to assume a role.
  • Create an IAM role and attach a least-privilege S3 read policy.
Create the Pod Identity trust policy

A trust policy tells IAM who is allowed to assume a role. For Pod Identity, the trusted principal is not a user or another AWS account. It is the pods.eks.amazonaws.com service itself.

  • Create a new file named trust-policy.json in your current directory and paste the following content:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowEksAuthToAssumeRoleForPodIdentity",
            "Effect": "Allow",
            "Principal": {
                "Service": "pods.eks.amazonaws.com"
            },
            "Action": [
                "sts:AssumeRole",
                "sts:TagSession"
            ]
        }
    ]
}

What does this trust policy do?

The Principal field names pods.eks.amazonaws.com as the only entity allowed to assume this role. No user, no other service can use it.

sts:AssumeRole lets the Pod Identity service get temporary credentials for the role. sts:TagSession lets it attach metadata (like the namespace and service account name) as session tags.

  • Save trust-policy.json.
  • Confirm the file exists by running:
ls trust-policy.json

You should see trust-policy.json listed in the output.

File not found?

Make sure you saved the file in your current working directory (the same directory where you ran the ls command). Run pwd to confirm where you are.

Help me find where my trust-policy.json file was saved.

Create the IAM role and attach an S3 read policy

With the trust policy ready, you can create the IAM role that references it. This role is what your pod will eventually assume to get S3 permissions.

  • Create the IAM role by running this command:
aws iam create-role --role-name pod-s3-reader-role --assume-role-policy-document file://trust-policy.json --description "Allows pods to read S3 via Pod Identity"

What does this command do?

  • --role-name pod-s3-reader-role gives the role a descriptive name you can reference later.
  • --assume-role-policy-document file://trust-policy.json attaches the trust policy you just created, locking the role to the Pod Identity service.

You should see JSON output containing the role ARN and the trust policy document, confirming the role was created successfully.

Seeing EntityAlreadyExists?

This means a role named pod-s3-reader-role already exists in your account. If it is from a previous attempt, delete it first with aws iam delete-role --role-name pod-s3-reader-role and try again.

Help me resolve the EntityAlreadyExists error when creating my IAM role.

The role exists, but it has no permissions yet. Now you'll define what the role is actually allowed to do. This is a separate policy from the trust policy.

  • Create a new file named s3-read-policy.json and paste the following content:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::[[BUCKET_NAME=\"pod-identity-test-YOUR-ACCOUNT-ID\"]]"
        },
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[[BUCKET_NAME=\"pod-identity-test-YOUR-ACCOUNT-ID\"]]/*"
        }
    ]
}

What does this policy grant?

  • s3:ListBucket allows listing the contents of your specific bucket.
  • s3:GetObject allows downloading objects from that bucket.
  • Both are scoped to your single bucket ARN. The role can only read from one bucket and nothing else. This is least-privilege access.
  • Save s3-read-policy.json.
  • Attach this policy to the role by running:
aws iam put-role-policy --role-name pod-s3-reader-role --policy-name S3ReadAccess --policy-document file://s3-read-policy.json

What does this command do?

This attaches the S3 permission policy as an inline policy named S3ReadAccess directly on the role. The command produces no output on success. If you see no error, the policy attached correctly.

Before you run the next command, think about this: what should appear in the trust policy document when you query the role? Which service principal should be listed?

  • Verify the full role setup by running:
aws iam get-role --role-name pod-s3-reader-role --query "Role.AssumeRolePolicyDocument"

You should see pods.eks.amazonaws.com listed as the service principal, with actions sts:AssumeRole and sts:TagSession. This confirms your role is correctly configured for Pod Identity.

Seeing NoSuchEntity?

This means the role was not created successfully in the earlier step. Re-run the aws iam create-role command and check for errors in the output. Confirm trust-policy.json is valid JSON by pasting it into an online JSON validator.

Help me debug why my IAM role was not created.

✔️ Awesome, I've got everything!

Great. Make sure you have saved both trust-policy.json and s3-read-policy.json.

ⓧ I'd like to double check the full code

Here is the full content for trust-policy.json:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowEksAuthToAssumeRoleForPodIdentity",
            "Effect": "Allow",
            "Principal": {
                "Service": "pods.eks.amazonaws.com"
            },
            "Action": [
                "sts:AssumeRole",
                "sts:TagSession"
            ]
        }
    ]
}

And here is s3-read-policy.json (remember to replace the bucket name with your actual bucket):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::[[BUCKET_NAME=\"pod-identity-test-YOUR-ACCOUNT-ID\"]]"
        },
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[[BUCKET_NAME=\"pod-identity-test-YOUR-ACCOUNT-ID\"]]/*"
        }
    ]
}

Your IAM role is ready and waiting with the right trust policy and S3 permissions. Next, you'll wire it up to a Kubernetes service account so your pod can actually use these credentials.

Wire Up Pod Identity and Verify Access

In the previous step, you created an IAM role with the right permissions and a trust policy that lets pods.eks.amazonaws.com assume it.

The missing piece is the connection between your pod and that role. Right now, no pod knows the role exists. You need to create a Kubernetes service account, bind it to the IAM role via a Pod Identity association, and deploy a new pod that uses that service account.

In this step, get ready to:
  • Create a Kubernetes service account and a Pod Identity association linking it to your IAM role.
  • Deploy a new pod that uses the service account.
  • Verify the pod can read from S3 without any hardcoded credentials.
Create a Kubernetes service account and Pod Identity association

A Kubernetes service account is an identity you attach to a pod. The Pod Identity association then tells EKS which IAM role to inject when a pod runs with that service account.

  • Create the service account by running this command:
kubectl create serviceaccount s3-reader-sa

What does this command do?

This creates a service account named s3-reader-sa in the default namespace. Unlike IRSA (IAM Roles for Service Accounts), Pod Identity does not require any annotation on the service account. The association is managed entirely on the AWS side.

  • Now create the Pod Identity association that binds this service account to your IAM role by running:
aws eks create-pod-identity-association --cluster-name [[CLUSTER_NAME="your-cluster-name"]] --role-arn arn:aws:iam::[[AWS_ACCOUNT_ID="123456789012"]]:role/pod-s3-reader-role --namespace default --service-account s3-reader-sa

What does this command do?

This tells EKS: when a pod in the default namespace uses the s3-reader-sa service account, inject temporary credentials for the pod-s3-reader-role IAM role.

The Pod Identity Agent (running as a DaemonSet on your nodes) intercepts the pod's credential requests and delivers short-lived tokens automatically.

  • Verify the association was created by running:
aws eks list-pod-identity-associations --cluster-name [[CLUSTER_NAME="your-cluster-name"]]

You should see a JSON response with an associations array containing an entry with namespace: "default" and serviceAccount: "s3-reader-sa".

Not seeing your association?

Make sure your --cluster-name matches the exact name of your EKS cluster. You can check with aws eks list-clusters.

If you see an error about the role ARN, double-check that pod-s3-reader-role exists by running aws iam get-role --role-name pod-s3-reader-role.

Help me troubleshoot my Pod Identity association

Deploy a new pod that uses the service account

Your existing aws-cli-test pod uses the default service account and has no AWS permissions. You need a new pod that specifies serviceAccountName: s3-reader-sa so the Pod Identity Agent knows to inject credentials.

  • Create a file named pod-with-identity.yaml and paste the following content:
apiVersion: v1
kind: Pod
metadata:
  name: aws-cli-pod-identity
spec:
  serviceAccountName: s3-reader-sa
  containers:
  - name: aws-cli
    image: public.ecr.aws/aws-cli/aws-cli:latest
    command: ["tail", "-f", "/dev/null"]

What does this manifest do?

The key addition is serviceAccountName: s3-reader-sa. This tells Kubernetes to associate the pod with your service account. The Pod Identity Agent then automatically mounts a token and sets environment variables so the AWS CLI inside the pod can retrieve temporary credentials.

The rest is the same as your test pod: the public.ecr.aws/aws-cli/aws-cli:latest image with tail -f /dev/null to keep it running for interactive testing.

  • Deploy the pod by running:
kubectl apply -f pod-with-identity.yaml
  • Wait for the pod to reach Running state by running:
kubectl get pods

You should see aws-cli-pod-identity with status Running. This may take 15-30 seconds.

Pod stuck in Pending or ContainerCreating?

Run kubectl describe pod aws-cli-pod-identity and check the Events section at the bottom. Common causes include image pull issues or the node not having capacity.

Help me debug my pod that won't start

Test S3 access from the new pod

This is the moment of truth. Your previous pod got Access Denied. This pod should succeed because it has the Pod Identity credentials.

Before you run the next command, what do you think will happen? Will this pod be able to list the bucket contents, or will it get the same Access Denied error?

  • List the bucket contents from inside the pod by running:
kubectl exec -it aws-cli-pod-identity -- aws s3 ls s3://pod-identity-test-[[AWS_ACCOUNT_ID="your-account-id"]]/

You should see hello.txt listed in the output. Your pod can now read from S3.

  • Download the test file to confirm full read access by running:
kubectl exec -it aws-cli-pod-identity -- aws s3 cp s3://pod-identity-test-[[AWS_ACCOUNT_ID="your-account-id"]]/hello.txt -

You should see Hello from S3! printed directly to your terminal. No credentials were hardcoded anywhere. The Pod Identity Agent delivered them automatically.

  • Verify the Pod Identity token is mounted inside the pod by running:
kubectl describe pod aws-cli-pod-identity | grep AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE

What should I see?

You should see a line showing AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE set to /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token. This is the projected token that the Pod Identity Agent uses to fetch temporary IAM credentials on behalf of your pod.

On Windows, replace grep with findstr in the command above.

Still getting Access Denied?

Pod Identity associations may take several seconds to propagate. If you deployed the pod immediately after creating the association, delete the pod and redeploy it:

  • Run kubectl delete pod aws-cli-pod-identity then kubectl apply -f pod-with-identity.yaml again.
  • Make sure the Pod Identity Agent is running: kubectl get pods -n kube-system | grep eks-pod-identity-agent.
  • Confirm your association matches the correct namespace and service account: aws eks list-pod-identity-associations --cluster-name [[CLUSTER_NAME="your-cluster-name"]].

Help me fix my Pod Identity credentials

Your pod is reading from S3 with zero hardcoded credentials. Next up, the Secret Mission challenges you to lock down the trust policy so only a specific namespace and service account can assume the role.

Secret mission

Lock Down with Condition Keys

Your trust policy currently allows any service account in any namespace on your cluster to assume the IAM role. In production, that's too broad. Can you restrict the role so only your specific namespace and service account can use it?

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. The EKS cluster control plane costs $0.10/hr while running, and your node group incurs EC2 charges.

Cost warning

Your EKS cluster control plane charges $0.10/hr whether or not you are using it. Your node group also incurs EC2 charges for each running instance. If you are not continuing to the next project immediately, pause or delete your resources to avoid unexpected costs.

Resources you used:

  • EKS Pod Identity Agent add-on (installed on your cluster).
  • S3 bucket pod-identity-test-your-account-id with a test file.
  • IAM role pod-s3-reader-role with inline policy S3ReadAccess.
  • Pod Identity association binding s3-reader-sa to the IAM role.
  • Kubernetes service account s3-reader-sa in the default namespace.
  • Test pods aws-cli-test and aws-cli-pod-identity in the default namespace.
  • Local files: test-pod.yaml, pod-with-identity.yaml, trust-policy.json, trust-policy-restricted.json, s3-read-policy.json, other-ns-pod.yaml.

Keep everything running

No action needed. Choose this if you plan to continue building on this cluster. The Pod Identity add-on, association, and service account have no running cost beyond the cluster itself.

  • Your EKS cluster control plane continues to charge $0.10/hr.
  • Your node group incurs EC2 charges for each running instance.
  • The S3 bucket storage cost is negligible (one small file).
  • The Pod Identity configuration persists and can be reused in future projects on this cluster.

Pause - I'll come back to this later

Stop your EKS node group to eliminate EC2 charges while keeping your configuration intact. The cluster control plane still costs $0.10/hr.

  • Scale your node group to zero instances in the EKS console under **Compute**, or use the AWS CLI to update the node group scaling config.
  • Your Pod Identity configuration, IAM role, S3 bucket, and service account all persist. When you scale the node group back up, everything works again.
  • To fully stop the $0.10/hr control plane charge, you must delete the cluster. There is no way to pause the control plane itself.

Delete - I don't want to use this again

Remove all project resources and start fresh. Follow these steps in order.

  • Delete the test pods by running:
kubectl delete pod aws-cli-test aws-cli-pod-identity
  • Get your Pod Identity association ID by running:
aws eks list-pod-identity-associations --cluster-name [[CLUSTER_NAME="your-cluster-name"]] --query "associations[?serviceAccount=='s3-reader-sa'].associationId" --output text
  • Delete the Pod Identity association using the ID from the previous command:
aws eks delete-pod-identity-association --cluster-name [[CLUSTER_NAME="your-cluster-name"]] --association-id [[ASSOCIATION_ID="your-association-id"]]
  • Delete the Kubernetes service account by running:
kubectl delete serviceaccount s3-reader-sa
  • Delete the IAM inline policy and role by running:
aws iam delete-role-policy --role-name pod-s3-reader-role --policy-name S3ReadAccess
aws iam delete-role --role-name pod-s3-reader-role
  • Empty and delete the S3 bucket by running:
aws s3 rm s3://pod-identity-test-[[AWS_ACCOUNT_ID="your-account-id"]]/ --recursive
aws s3 rb s3://pod-identity-test-[[AWS_ACCOUNT_ID="your-account-id"]]
  • Remove the Pod Identity Agent add-on by running:
aws eks delete-addon --cluster-name [[CLUSTER_NAME="your-cluster-name"]] --addon-name eks-pod-identity-agent
  • Delete the local project files by running:
rm test-pod.yaml pod-with-identity.yaml trust-policy.json trust-policy-restricted.json s3-read-policy.json other-ns-pod.yaml hello.txt
  • If you no longer need the EKS cluster at all, delete it through the AWS Management Console or follow the cleanup steps from the prerequisite project.

Nice Work!

Nice Work!

Nice work! You just granted an EKS pod secure, credential-free access to a private S3 bucket using Pod Identity.

You've learned how to:

  • Deployed a pod and proved firsthand that EKS pods have zero AWS permissions by default, then installed the Pod Identity Agent add-on to enable credential delivery.
  • Created an IAM role with a Pod Identity trust policy (pods.eks.amazonaws.com as trusted principal) and a least-privilege S3 read policy scoped to a specific bucket.
  • Bound a Kubernetes service account to the IAM role via a Pod Identity association and verified that a pod using that service account can read from S3 without any hardcoded credentials.
  • Secret Mission: Locked down the trust policy with condition keys so only a specific namespace and service account can assume the role.

Ready to quiz yourself?