End-to-End Encryption Architecture for AWS EKS with Istio Ambient Mesh
Architecture Overview
This architecture implements comprehensive end-to-end encryption for applications running on Amazon EKS using Istio Ambient Mesh, following AWS best practices for security and compliance.
Key Components
- AWS Application Load Balancer (ALB) - TLS termination at edge with ACM certificates
- AWS Certificate Manager (ACM) - Automated certificate lifecycle management
- Istio Ambient Mesh - Sidecar-less service mesh with layered security
- ztunnel - Node-level L4 proxy providing mTLS and zero-trust networking
- Waypoint Proxies - Optional L7 Envoy proxies for advanced traffic management
- AWS KMS - Encryption of Kubernetes secrets at rest
Architecture Diagram

Encryption Layers
Layer 1: Internet to ALB (North-South Traffic)
- Protocol: HTTPS with TLS 1.2/1.3
- Certificate: ACM-managed public certificate
- Termination: ALB terminates TLS and validates client requests
- Best Practice: Use ACM for automatic certificate renewal and AWS-managed security
Layer 2: ALB to EKS Cluster
- Protocol: Re-encrypted HTTPS or mTLS
- Options:
- Option A: ALB re-encrypts traffic to backend targets (recommended)
- Option B: ALB passes through encrypted traffic to ztunnel
- Certificate: ACM Private CA or self-signed certificates for backend encryption
Layer 3: ztunnel Layer (L4 Secure Overlay)
- Protocol: HBONE (HTTP-Based Overlay Network Environment)
- Encryption: Automatic mTLS between all mesh workloads
- Deployment: DaemonSet on every node
- Features:
- Zero-trust tunnel for all pod traffic
- L4 authorization policies
- Transparent traffic capture and encryption
- No application changes required
Layer 4: Waypoint Proxies (L7 Processing)
- Protocol: mTLS with full L7 capabilities
- Deployment: Per-namespace or per-service account
- Features:
- Advanced traffic routing (VirtualService, DestinationRule)
- L7 authorization policies
- Request/response manipulation
- Circuit breaking and retries
Layer 5: Pod-to-Pod (East-West Traffic)
- Protocol: mTLS via ztunnel
- Encryption: All inter-pod communication encrypted by default
- Identity: SPIFFE-based workload identity
- Zero Trust: Deny-by-default with explicit authorization policies
Layer 6: Data at Rest
- EKS Secrets: Encrypted using AWS KMS customer-managed keys
- etcd: Envelope encryption with KMS
- EBS Volumes: Encrypted with KMS keys
- Best Practice: Use separate KMS keys for different data classifications
Implementation Guide
Prerequisites
# Required tools
- AWS CLI v2
- kubectl v1.28+
- helm v3.12+
- istioctl v1.28+Step 1: Create EKS Cluster with Encryption
# Create KMS key for EKS secrets encryption
aws kms create-key \
--description "EKS secrets encryption key" \
--region us-east-1
# Create key alias
aws kms create-alias \
--alias-name alias/eks-secrets \
--target-key-id <key-id>
# Create EKS cluster with encryption enabled
eksctl create cluster \
--name istio-ambient-cluster \
--region us-east-1 \
--version 1.28 \
--nodegroup-name standard-workers \
--node-type t3.large \
--nodes 3 \
--nodes-min 3 \
--nodes-max 6 \
--encryption-config-key-arn arn:aws:kms:us-east-1:ACCOUNT_ID:key/KEY_ID \
--managedStep 2: Install Istio Ambient Mesh
# Download Istio
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.28.3 sh -
cd istio-1.28.3
export PATH=$PWD/bin:$PATH
# Install Istio with ambient profile
istioctl install --set profile=ambient -y
# Verify installation
kubectl get pods -n istio-systemExpected output:
NAME READY STATUS RESTARTS AGE
istiod-xxx 1/1 Running 0 2m
ztunnel-xxx 1/1 Running 0 2m
ztunnel-yyy 1/1 Running 0 2m
ztunnel-zzz 1/1 Running 0 2mStep 3: Configure ACM Certificate for ALB
# Request public certificate from ACM
aws acm request-certificate \
--domain-name "*.example.com" \
--subject-alternative-names "example.com" \
--validation-method DNS \
--region us-east-1
# Note the certificate ARN for ALB configurationStep 4: Deploy AWS Load Balancer Controller
# Create IAM policy for Load Balancer Controller
curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://iam-policy.json
# Create service account
eksctl create iamserviceaccount \
--cluster=istio-ambient-cluster \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--attach-policy-arn=arn:aws:iam::ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \
--approve
# Install Load Balancer Controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=istio-ambient-cluster \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controllerStep 5: Enable Ambient Mesh for Namespace
# Create application namespace
kubectl create namespace app-1
# Enable ambient mesh
kubectl label namespace app-1 istio.io/dataplane-mode=ambient
# Verify ztunnel is capturing traffic
kubectl get pods -n app-1 -o jsonpath='{.items[*].metadata.annotations.ambient\.istio\.io/redirection}'Step 6: Deploy Waypoint Proxy (Optional - for L7 features)
# Deploy waypoint proxy for namespace
istioctl x waypoint apply -n app-1
# Verify waypoint deployment
kubectl get pods -n app-1 -l gateway.istio.io/managed=istio.io-mesh-controller
# Label namespace to use waypoint
kubectl label namespace app-1 istio.io/use-waypoint=waypointStep 7: Deploy Sample Application with ALB Ingress
# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app
namespace: app-1
spec:
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: app
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: sample-app
namespace: app-1
spec:
selector:
app: sample-app
ports:
- port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sample-app-ingress
namespace: app-1
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:ACCOUNT_ID:certificate/CERT_ID
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06
alb.ingress.kubernetes.io/backend-protocol: HTTPS
alb.ingress.kubernetes.io/healthcheck-protocol: HTTPS
spec:
ingressClassName: alb
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: sample-app
port:
number: 80kubectl apply -f app-deployment.yamlStep 8: Configure mTLS Policies
# peer-authentication.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: app-1
spec:
mtls:
mode: STRICT
---
# authorization-policy.yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-ingress
namespace: app-1
spec:
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/istio-system/sa/ztunnel"]
to:
- operation:
methods: ["GET", "POST"]kubectl apply -f peer-authentication.yaml
kubectl apply -f authorization-policy.yamlStep 9: Verify End-to-End Encryption
# Check ztunnel logs for mTLS connections
kubectl logs -n istio-system -l app=ztunnel --tail=50
# Verify mTLS is enabled
istioctl x describe pod <pod-name> -n app-1
# Test connectivity
kubectl exec -n app-1 <pod-name> -- curl -v https://sample-app.app-1.svc.cluster.localStep 10: Enable Network Policies (Defense in Depth)
# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: app-1
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: app-1
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-traffic
namespace: app-1
spec:
podSelector:
matchLabels:
app: sample-app
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: istio-system
ports:
- protocol: TCP
port: 80# Enable VPC CNI network policy support
kubectl set env daemonset aws-node -n kube-system ENABLE_NETWORK_POLICY=true
kubectl apply -f network-policy.yamlSecurity Best Practices
1. Certificate Management
- Use ACM for public-facing certificates (automatic renewal)
- Use ACM Private CA for internal service-to-service certificates
- Rotate certificates before expiration
- Monitor certificate expiration with CloudWatch alarms
2. KMS Key Management
- Use separate KMS keys for different security domains
- Enable automatic key rotation
- Implement least-privilege IAM policies for key access
- Enable CloudTrail logging for key usage
3. Network Security
- Deploy EKS in private subnets
- Use security groups to restrict ALB access
- Enable VPC Flow Logs for traffic analysis
- Implement network policies for defense in depth
4. Istio Security
- Enable STRICT mTLS mode for all namespaces
- Implement authorization policies (deny-by-default)
- Use separate waypoint proxies per namespace for isolation
- Regularly update Istio to latest stable version
5. Monitoring and Observability
- Enable Istio telemetry for traffic metrics
- Configure CloudWatch Container Insights
- Set up alerts for certificate expiration
- Monitor ztunnel and waypoint proxy health
6. Compliance
- Enable audit logging for EKS control plane
- Use AWS Config rules for compliance checking
- Implement pod security standards
- Regular security assessments and penetration testing
Traffic Flow Details
Ingress Traffic (North-South)
- Client → Route 53: DNS resolution to ALB endpoint
- Client → ALB: TLS 1.3 handshake with ACM certificate
- ALB → ztunnel: Re-encrypted HTTPS or mTLS connection
- ztunnel → Waypoint: HBONE tunnel with mTLS
- Waypoint → Pod: mTLS connection with L7 policy enforcement
- Pod: Application processes request
East-West Traffic (Pod-to-Pod)
- Source Pod: Initiates connection to destination service
- ztunnel (source node): Intercepts traffic, establishes mTLS
- HBONE Tunnel: Encrypted tunnel across nodes
- ztunnel (dest node): Terminates tunnel, forwards to waypoint
- Waypoint: Applies L7 policies, routes to destination
- Destination Pod: Receives encrypted request
Certificate Flow
- istiod: Acts as Certificate Authority (CA)
- ztunnel: Requests certificates from istiod
- Waypoint: Requests certificates from istiod
- Workloads: Receive SPIFFE identities
- Rotation: Automatic certificate rotation (default: 24h lifetime)
Monitoring and Troubleshooting
Verify mTLS is Working
# Check if ambient is enabled
kubectl get namespace app-1 -o jsonpath='{.metadata.labels.istio\.io/dataplane-mode}'
# Verify ztunnel is running
kubectl get daemonset -n istio-system ztunnel
# Check mTLS status
istioctl x describe pod <pod-name> -n app-1 | grep -i mtls
# View ztunnel logs
kubectl logs -n istio-system -l app=ztunnel -fCommon Issues
Issue: Pods not receiving traffic
# Check if namespace is labeled for ambient
kubectl get namespace app-1 --show-labels
# Verify ztunnel is capturing traffic
kubectl get pods -n app-1 -o yaml | grep ambient.istio.io/redirectionIssue: Certificate errors
# Check istiod logs
kubectl logs -n istio-system -l app=istiod
# Verify certificate chain
istioctl proxy-config secret <pod-name> -n app-1Issue: ALB health checks failing
# Ensure backend protocol is set correctly
kubectl get ingress -n app-1 -o yaml | grep backend-protocol
# Check target group health
aws elbv2 describe-target-health --target-group-arn <tg-arn>Performance Considerations
ztunnel Performance
- Written in Rust for high performance and low memory footprint
- Handles L4 traffic with minimal latency overhead (<1ms)
- Scales horizontally with node count (DaemonSet)
Waypoint Performance
- Only deployed when L7 features are needed
- Can be scaled independently based on traffic
- Use HPA for automatic scaling
ALB Optimization
- Use target type
ipfor direct pod routing - Enable connection draining for graceful shutdowns
- Configure appropriate health check intervals
Cost Optimization
- Selective Waypoint Deployment: Only deploy waypoints for namespaces requiring L7 features
- ALB Sharing: Use single ALB with host-based routing for multiple applications
- KMS Key Reuse: Share KMS keys across similar security domains
- Right-sizing: Monitor and adjust waypoint proxy resources based on actual usage
Migration Strategy
From Sidecar to Ambient
- Install Istio with ambient support
- Keep existing sidecar workloads running
- Gradually migrate namespaces to ambient mode
- Remove sidecar injection labels
- Verify traffic flow and policies
- Decommission sidecar infrastructure
From No Mesh to Ambient
- Start with ztunnel only (L4 encryption)
- Validate mTLS is working
- Add waypoint proxies for namespaces needing L7 features
- Incrementally add authorization policies
- Enable STRICT mTLS mode
References
- AWS EKS Best Practices - Network Security
- AWS EKS Encryption Best Practices
- Istio Ambient Mesh Documentation
- AWS Certificate Manager Integration
- AWS Load Balancer Controller
Conclusion
This architecture provides comprehensive end-to-end encryption for EKS workloads using Istio Ambient Mesh, following AWS best practices:
✅ TLS termination at ALB with ACM-managed certificates
✅ Re-encryption from ALB to cluster
✅ Automatic mTLS for all pod-to-pod traffic via ztunnel
✅ L7 security policies via waypoint proxies
✅ Secrets encryption at rest with AWS KMS
✅ Zero-trust networking with deny-by-default policies
✅ No application changes required (sidecar-less)
✅ Incremental adoption with layered security model
The ambient mesh architecture provides a more efficient and operationally simpler approach compared to traditional sidecar-based service meshes, while maintaining the same security guarantees.