EKS End-to-End Scenario: Pod Identity with AWS Services
This scenario demonstrates deploying a web application on Amazon EKS that interacts with AWS S3 and DynamoDB using EKS Pod Identity for secure, fine-grained IAM access.
Use Case Overview
- Deploy a Python Flask app in EKS.
- App stores/retrieves files in S3 and reads/writes data in DynamoDB.
- Access to AWS services is managed using EKS Pod Identity—no static AWS credentials in pods.
Step 1: Prerequisites
- AWS CLI and kubectl installed and configured.
- eksctl installed.
- An AWS account with permissions to create EKS clusters, IAM roles, S3, and DynamoDB.
Step 2: Create the EKS Cluster
eksctl create cluster \
--name eks-pod-identity-demo \
--region us-west-2 \
--nodes 2 \
--node-type t3.medium
Step 3: Enable EKS Pod Identity
- Associate Pod Identity with your cluster:
eksctl utils associate-iam-oidc-provider \
--region us-west-2 \
--cluster eks-pod-identity-demo \
--approve
- Install the EKS Pod Identity Agent:
kubectl apply -f https://github.com/aws/amazon-eks-pod-identity-webhook/releases/latest/download/deployment.yaml
Step 4: Create AWS Resources
-
S3 Bucket:
- Create a bucket (e.g.,
eks-pod-identity-demo-bucket).
- Create a bucket (e.g.,
-
DynamoDB Table:
- Create a table (e.g.,
EKSAppTable) with a primary key (id).
- Create a table (e.g.,
Step 5: Create IAM Role for Service Account (IRSA)
- Create an IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::eks-pod-identity-demo-bucket/*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:GetItem"
],
"Resource": "arn:aws:dynamodb:us-west-2:YOUR_ACCOUNT_ID:table/EKSAppTable"
}
]
}
- Create the IAM role and associate with Kubernetes service account:
eksctl create iamserviceaccount \
--name eks-app-sa \
--namespace default \
--cluster eks-pod-identity-demo \
--attach-policy-arn arn:aws:iam::YOUR_ACCOUNT_ID:policy/eks-app-policy \
--approve
Step 6: Deploy the Application
- Create a Kubernetes deployment using the service account:
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-app
spec:
replicas: 2
selector:
matchLabels:
app: flask-app
template:
metadata:
labels:
app: flask-app
spec:
serviceAccountName: eks-app-sa
containers:
- name: flask-app
image: YOUR_ECR_REPO/flask-app:latest
env:
- name: S3_BUCKET
value: eks-pod-identity-demo-bucket
- name: DDB_TABLE
value: EKSAppTable
ports:
- containerPort: 5000
- Expose the app via a LoadBalancer:
apiVersion: v1
kind: Service
metadata:
name: flask-app-service
spec:
type: LoadBalancer
selector:
app: flask-app
ports:
- protocol: TCP
port: 80
targetPort: 5000
Step 7: Application Logic (Python Example)
import boto3
import os
from flask import Flask, request
app = Flask(__name__)
s3 = boto3.client('s3')
ddb = boto3.resource('dynamodb')
bucket = os.environ['S3_BUCKET']
table = ddb.Table(os.environ['DDB_TABLE'])
@app.route('/upload', methods=['POST'])
def upload():
file = request.files['file']
s3.upload_fileobj(file, bucket, file.filename)
table.put_item(Item={'id': file.filename, 'status': 'uploaded'})
return 'Uploaded', 200
@app.route('/download/<filename>', methods=['GET'])
def download(filename):
s3.download_file(bucket, filename, f'/tmp/{filename}')
return open(f'/tmp/{filename}', 'rb').read(), 200
if __name__ == '__main__':
app.run(host='0.0.0.0')
Step 8: Test the Setup
- Upload and download files via the app endpoint.
- Check S3 and DynamoDB for data.
- Confirm no AWS credentials are present in the pod—access is via Pod Identity.
Summary Table
| Component | AWS Service | Purpose | Access Managed By |
|---|---|---|---|
| EKS Cluster | EKS | Orchestrates containers | eksctl |
| Storage | S3 | File storage | Pod Identity (IRSA) |
| Database | DynamoDB | Key-value data store | Pod Identity (IRSA) |
| App Deployment | EKS | Runs Flask app in pods | K8s Service Account |
This workflow demonstrates a secure, production-grade pattern for cloud-native applications on AWS using EKS, Pod Identity, and tightly scoped IAM permissions—no hardcoded credentials, all access is managed by Kubernetes-native identities.
⁂
can you use cdk to set uthi up
Yes, you can use AWS CDK (Cloud Development Kit) to set up the entire EKS scenario—including the cluster, Pod Identity, IAM roles, S3 bucket, DynamoDB table, and Kubernetes resources. CDK enables you to define your infrastructure as code in Python, TypeScript, or other supported languages.
Below is a high-level outline of how you would implement this scenario using CDK (Python example):
1. Initialize Your CDK Project
cdk init app --language python
pip install aws-cdk-lib constructs
2. Define the Stack in CDK
a. Create the EKS Cluster
from aws_cdk import (
Stack,
aws_eks as eks,
aws_iam as iam,
aws_s3 as s3,
aws_dynamodb as dynamodb,
)
from constructs import Construct
class EksPodIdentityStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs):
super().__init__(scope, construct_id, **kwargs)
# S3 bucket
bucket = s3.Bucket(self, "EksAppBucket")
# DynamoDB table
table = dynamodb.Table(
self, "EksAppTable",
partition_key=dynamodb.Attribute(name="id", type=dynamodb.AttributeType.STRING)
)
# EKS cluster
cluster = eks.Cluster(
self, "EksCluster",
version=eks.KubernetesVersion.V1_29,
default_capacity=2,
)
# IAM policy for pod access
policy = iam.PolicyStatement(
actions=[
"s3:GetObject", "s3:PutObject",
"dynamodb:PutItem", "dynamodb:GetItem"
],
resources=[
bucket.bucket_arn + "/*",
table.table_arn
]
)
# Service account with IAM role (Pod Identity)
sa = cluster.add_service_account("EksAppServiceAccount")
sa.add_to_principal_policy(policy)
# Output values
self.bucket = bucket
self.table = table
self.cluster = cluster
self.sa = sa
b. Deploy the Stack
cdk deploy
3. Deploy Your Application to EKS
- Build and push your Docker image to ECR.
- Use CDK to apply a Kubernetes manifest (or use
kubectl):
app_manifest = {
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {"name": "flask-app"},
"spec": {
"replicas": 2,
"selector": {"matchLabels": {"app": "flask-app"}},
"template": {
"metadata": {"labels": {"app": "flask-app"}},
"spec": {
"serviceAccountName": sa.service_account_name,
"containers": [{
"name": "flask-app",
"image": "YOUR_ECR_REPO/flask-app:latest",
"env": [
{"name": "S3_BUCKET", "value": bucket.bucket_name},
{"name": "DDB_TABLE", "value": table.table_name}
],
"ports": [{"containerPort": 5000}]
}]
}
}
}
}
cluster.add_manifest("FlaskAppDeployment", app_manifest)
- Similarly, add a manifest for the LoadBalancer service.
4. Summary
- All AWS resources (EKS, S3, DynamoDB, IAM roles) are provisioned via CDK.
- Pod Identity (IAM role for service account) is set up with least-privilege permissions.
- Kubernetes manifests can be deployed via CDK or post-deployment with
kubectl.
This approach gives you a fully automated, repeatable infrastructure deployment using modern infrastructure-as-code best practices.
⁂
can you use python
Yes, you can use Python with AWS CDK to set up your EKS cluster, configure Pod Identity, and provision all supporting AWS resources. The AWS CDK natively supports Python as one of its primary languages, allowing you to define and automate your infrastructure using Python code12345.
Key Points
- AWS CDK supports Python: You can define EKS clusters, IAM roles, S3 buckets, DynamoDB tables, and Kubernetes manifests directly in Python code12345.
- Full automation: Using Python with CDK, you can automate the entire lifecycle of your infrastructure, including cluster creation, IAM role association for Pod Identity, and application deployment1345.
-
Example Workflow:
- Initialize your CDK project with
cdk init app --language python45. - Use the
aws_cdk.aws_eksmodule to define your EKS cluster and add Kubernetes resources35. - Define IAM roles and policies in Python and associate them with Kubernetes service accounts for Pod Identity.
- Use CDK to deploy S3, DynamoDB, and other AWS resources as needed.
- Deploy Kubernetes manifests (such as Deployments and Services) using
cluster.add_manifest()in your Python CDK code35.
- Initialize your CDK project with
Example CDK Project Structure (Python)
mkdir eks
cd eks
mkdir cluster cdk8s
cd cluster
cdk init app --language=python
This sets up your Python-based CDK project for EKS provisioning45.
Documentation and Guides
- The AWS EKS Construct Library documentation provides Python examples for defining clusters and applying Kubernetes manifests3.
- Tutorials and guides, such as those on AWS and developer blogs, demonstrate end-to-end EKS automation using Python and CDK, including integration with Helm and other tools45.
In summary: Python is a fully supported and commonly used language for AWS CDK, enabling you to automate EKS and related AWS resource setup, including Pod Identity, entirely in Python code12345.
⁂
where is the python code
Here is a concise Python AWS CDK example that provisions:
- An EKS cluster
- An S3 bucket
- A DynamoDB table
- An IAM role for Pod Identity (IRSA) and a Kubernetes service account
- Deploys a simple app using that service account
This is a minimal, illustrative example. You can expand it for production use.
from aws_cdk import (
core,
aws_eks as eks,
aws_iam as iam,
aws_s3 as s3,
aws_dynamodb as dynamodb,
)
class EksPodIdentityStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs):
super().__init__(scope, id, **kwargs)
# S3 bucket
bucket = s3.Bucket(self, "EksAppBucket")
# DynamoDB table
table = dynamodb.Table(
self, "EksAppTable",
partition_key=dynamodb.Attribute(name="id", type=dynamodb.AttributeType.STRING)
)
# EKS Cluster
cluster = eks.Cluster(
self, "EksCluster",
version=eks.KubernetesVersion.V1_29,
default_capacity=2,
)
# IAM policy for pod access
policy = iam.PolicyStatement(
actions=[
"s3:GetObject", "s3:PutObject",
"dynamodb:PutItem", "dynamodb:GetItem"
],
resources=[
bucket.bucket_arn + "/*",
table.table_arn
]
)
# Service account with IAM role (Pod Identity)
sa = cluster.add_service_account("EksAppServiceAccount")
sa.add_to_principal_policy(policy)
# Deploy your app (placeholder manifest)
app_manifest = {
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {"name": "flask-app"},
"spec": {
"replicas": 2,
"selector": {"matchLabels": {"app": "flask-app"}},
"template": {
"metadata": {"labels": {"app": "flask-app"}},
"spec": {
"serviceAccountName": sa.service_account_name,
"containers": [{
"name": "flask-app",
"image": "YOUR_ECR_REPO/flask-app:latest",
"env": [
{"name": "S3_BUCKET", "value": bucket.bucket_name},
{"name": "DDB_TABLE", "value": table.table_name}
],
"ports": [{"containerPort": 5000}]
}]
}
}
}
}
cluster.add_manifest("FlaskAppDeployment", app_manifest)
# Expose the app (placeholder manifest)
service_manifest = {
"apiVersion": "v1",
"kind": "Service",
"metadata": {"name": "flask-app-service"},
"spec": {
"type": "LoadBalancer",
"selector": {"app": "flask-app"},
"ports": [{"protocol": "TCP", "port": 80, "targetPort": 5000}]
}
}
cluster.add_manifest("FlaskAppService", service_manifest)
Usage:
- Place this in your CDK app (e.g.,
app.pyandeks_pod_identity_stack.py). - Replace
"YOUR_ECR_REPO/flask-app:latest"with your actual container image. - Run
cdk deploy.
References:
⁂
-
https://isjem.com/download/from-code-to-cloud-automating-continuous-deployment-with-aws-cloud-development-kit-cdk-and-infrastructure-as-code-iac/ ↩
-
https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_eks/README.html ↩
-
https://aws.amazon.com/tutorials/deploy-webapp-eks/module-one/ ↩
-
https://dev.to/marocz/automating-eks-deployment-and-nginx-setup-using-helm-with-aws-cdk-in-python-27mn ↩
-
https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_eks/README.html ↩
-
https://aws.plainenglish.io/deploying-an-eks-cluster-with-aws-cloud-development-kit-cdk-afdb96ce3a83 ↩

Top comments (0)