Skip to main content

EKS and AKS Deployment Guide - Lessons from GKE

This document provides comprehensive guidance for deploying to AWS EKS and Azure AKS, incorporating all lessons learned from GKE deployment troubleshooting to prevent similar issues.

Table of Contents


Overview

This guide ensures that the 11 issues encountered during GKE deployment do not occur on EKS or AKS deployments.

GKE Issues Resolved

  1. ✅ Pre-commit Python version mismatch (3.11 vs 3.12)
  2. ✅ Docker build disk space exhaustion
  3. ✅ External Secrets Operator CRD API version mismatch (v1beta1 vs v1)
  4. ✅ RBAC permission denied errors (unused Role/RoleBinding resources)
  5. ✅ GKE Autopilot CPU constraints (pod anti-affinity requires 500m minimum)
  6. ✅ Environment variable value/valueFrom conflict (Kustomize merge issue)
  7. ✅ Client-side vs server-side kubectl validation (CRDs not recognized)
  8. ✅ Namespace creation ordering (must exist before resources)
  9. ✅ ConfigMap generator behavior (create vs merge)
  10. ✅ External Secrets Operator installation permissions
  11. ✅ Unused RBAC resources requiring elevated IAM permissions

Critical Lessons from GKE

1. kubectl Validation: Always Use Server-Side Dry-Run

  • WRONG (Client-side - doesn’t see CRDs):
  • CORRECT (Server-side - validates against actual cluster):
Why: Client-side validation only uses kubectl’s built-in schemas. It cannot validate:
  • Custom Resource Definitions (CRDs)
  • External Secrets Operator resources
  • Any custom operators
Applies to: ✅ EKS, ✅ AKS, ✅ All Kubernetes platforms

2. External Secrets Operator: Check API Version

  • WRONG (Assumes v1beta1):
  • CORRECT (Verify installed version first):
Prevention:
  1. Always check installed CRD version: kubectl api-resources | grep <resource-type>
  2. Match manifest API version to cluster API version
  3. ESO v0.9+ uses v1 (not v1beta1)
Applies to: ✅ EKS, ✅ AKS (if using External Secrets Operator)

3. Environment Variables: Use ConfigMap Patches, Not Deployment Values

  • WRONG (Creates value/valueFrom conflict):
  • CORRECT (Override ConfigMap data):
Why: When base deployment uses valueFrom: configMapKeyRef and overlay adds value:, Kustomize merges both creating invalid Kubernetes manifest (cannot have both value and valueFrom). Applies to: ✅ EKS, ✅ AKS, ✅ All Kustomize-based deployments

4. RBAC Resources: Remove Unused Kubernetes RBAC

  • WRONG (Include unused RBAC resources):
Problem: If application doesn’t use Kubernetes API, these resources:
  • Require elevated IAM permissions to deploy (container.admin, EKS Cluster Admin, AKS RBAC Admin)
  • Violate least privilege principle
  • Increase attack surface
  • CORRECT (Only include ServiceAccount):
Why:
  • Application uses External Secrets Operator (ESO handles secret access)
  • Application doesn’t use Kubernetes API directly
  • No need for in-cluster RBAC permissions
How to Verify:
  1. Search codebase for kubernetes.client or @kubernetes/client-node
  2. If not found, remove Role and RoleBinding
  3. Keep only ServiceAccount with workload identity annotations
IAM Permissions Required (after RBAC removal):
  • GCP: roles/container.developer (sufficient for workload deployment)
  • AWS: AmazonEKSWorkerNodePolicy + ECR access
  • Azure: Azure Kubernetes Service Cluster User Role
Applies to: ✅ EKS, ✅ AKS, ✅ All platforms (universal best practice)

5. Namespace Creation: Always Create Before Validation

  • WRONG (Namespace created during deployment):
  • CORRECT (Namespace created before validation):
Why:
  • Enables rollback (namespace exists even if deployment fails)
  • Allows validation to succeed (resources reference the namespace)
  • Idempotent (--dry-run=client -o yaml | kubectl apply won’t fail if exists)
Applies to: ✅ EKS, ✅ AKS, ✅ All Kubernetes platforms

6. Managed Kubernetes CPU/Memory Constraints

GKE Autopilot:
  • Minimum 500m CPU when using pod anti-affinity
  • Minimum 250m CPU otherwise
  • Validates via admission webhook (GKE Warden)
EKS Fargate:
  • Minimum 250m CPU
  • CPU/memory must match specific combinations
  • Validates at pod scheduling time
AKS:
  • More flexible, but validate resource quotas
  • Check node pool constraints
Prevention:
Applies to: ✅ EKS (Fargate), ✅ AKS, ✅ All managed Kubernetes

EKS Deployment Guide

Prerequisites

  1. AWS IAM Configuration:
  2. IRSA (IAM Roles for Service Accounts):
  3. External Secrets Operator:

Workflow Template (.github/workflows/deploy-staging-eks.yaml)

Key Differences from GKE:
  • Authentication: configure-aws-credentials instead of google-github-actions/auth
  • Kubeconfig: aws eks update-kubeconfig instead of get-gke-credentials
  • Image registry: ECR instead of Artifact Registry
  • ServiceAccount annotation: eks.amazonaws.com/role-arn instead of iam.gke.io/gcp-service-account
Same Critical Patterns (from GKE fixes):
  • ✅ Server-side validation (--dry-run=server)
  • ✅ Namespace creation before validation
  • ✅ ESO verification (not installation)
  • ✅ Kustomize installation

AKS Deployment Guide

Prerequisites

  1. Azure Workload Identity:
  2. RBAC Permissions:
  3. External Secrets Operator:

Workflow Template (.github/workflows/deploy-staging-aks.yaml)

Key Differences from GKE:
  • Authentication: azure/login@v2 instead of Google auth
  • Kubeconfig: az aks get-credentials instead of get-gke-credentials
  • Image registry: ACR instead of Artifact Registry
  • ServiceAccount annotation: azure.workload.identity/client-id instead of GKE annotation
Same Critical Patterns (from GKE fixes):
  • ✅ Server-side validation (--dry-run=server)
  • ✅ Namespace creation before validation
  • ✅ ESO verification (not installation)
  • ✅ Kustomize installation

Common Kubernetes Issues

Issue 1: ConfigMap Generator Behavior

  • WRONG (Merge when no base ConfigMap):
  • CORRECT (Create new ConfigMap):
Applies to: ✅ EKS, ✅ AKS, ✅ All Kustomize deployments

Issue 2: Disk Space for Docker Builds

Enhanced Cleanup (.github/workflows/ci.yaml):
Applies to: ✅ Universal (all platforms use same GitHub Actions runners)

Issue 3: Pre-commit Python Version

Align with GitHub Actions Runner:
Applies to: ✅ Universal (all platforms use same runners)

Issue 4: Strategic Merge Patch for Namespaces

  • WRONG (Namespace in both base and overlay resources):
  • CORRECT (Namespace as patch):
Applies to: ✅ EKS, ✅ AKS, ✅ All Kustomize deployments

Prevention Checklist

Use this checklist when creating EKS/AKS deployment workflows:

Workflow Configuration

  • Use server-side validation: kubectl apply --dry-run=server
  • Create namespace before validation
  • Install kustomize tool
  • Verify External Secrets Operator is installed (if using)
  • Check ESO API version matches cluster (kubectl api-resources)
  • Set proper RBAC permissions (cluster admin, not just developer)
  • Configure platform-specific authentication (IRSA for EKS, Workload Identity for AKS)

Kustomize Configuration

  • Use strategic merge patches for namespaces (not resources)
  • Use correct ConfigMap generator behavior (create vs merge)
  • Put env var overrides in ConfigMap patches, not deployment patches
  • Avoid value/valueFrom conflicts in environment variables
  • Set explicit resource requests/limits (minimum 500m CPU for safety)

CI/CD Pipeline

  • Include enhanced disk cleanup for Docker builds
  • Align pre-commit Python version with runners (3.12)
  • Use Trivy SARIF fallback for compliance scans
  • Fix TruffleHog base reference for secret scanning
  • Set actual project/account IDs (no placeholders)

External Secrets Operator

  • Install ESO during infrastructure setup (not in CI/CD)
  • Use correct API version (v1 for ESO 0.9+, check with kubectl api-resources)
  • Verify CRDs are installed before deployment
  • Configure provider-specific auth (Workload Identity for GCP, IRSA for AWS, Managed Identity for Azure)

Resource Specifications

  • Set minimum 500m CPU for containers with pod anti-affinity
  • Define resources for init containers
  • Check platform-specific constraints (GKE Autopilot, EKS Fargate, AKS quotas)
  • Validate with actual cluster (server-side dry-run)

Platform-Specific Quick Reference


Testing Before Deployment

Local Validation

Pre-Deployment Verification


Summary of Applicable Fixes

UNIVERSAL (Apply to ALL platforms)

  1. Pre-commit Python 3.12 - Already applied globally
  2. Enhanced disk cleanup - Already in ci.yaml
  3. Trivy/TruffleHog fixes - Already in gcp-compliance-scan.yaml
  4. ConfigMap env overrides - Pattern for all Kustomize deployments
  5. Remove unused RBAC resources - Security best practice (Issue #11)

KUBERNETES-SPECIFIC (Apply to GKE, EKS, AKS)

  1. Server-side validation - CRITICAL for all platforms
  2. Namespace pre-creation - Required for all platforms
  3. Kustomize installation - Required for all platforms
  4. ESO verification - If using External Secrets
  5. ConfigMap generator behavior - All Kustomize deployments
  6. Resource specifications - Check platform-specific constraints
  7. Minimal IAM permissions - No RBAC creation needed after removing unused resources

GCP-ONLY (Different for EKS/AKS)

  1. Workload Identity - Use IRSA (EKS) or Managed Identity (AKS)
  2. GCP project values - Use AWS Account ID or Azure Subscription ID
  3. Artifact Registry - Use ECR (EKS) or ACR (AKS)
  4. GKE Autopilot constraints - Different for EKS Fargate and AKS

Conclusion

All 11 critical lessons from GKE troubleshooting have been documented and templates provided for EKS and AKS. When creating actual EKS/AKS deployment workflows, use the templates above and follow the prevention checklist to avoid all issues encountered with GKE. Key Takeaways:
  1. Always use server-side validation for CRD support
  2. Create namespace before validation for proper error handling
  3. Use ConfigMap patches for environment variable overrides
  4. Check ESO API version matches cluster
  5. Remove unused RBAC resources - verify application needs before including
  6. Grant minimal IAM permissions - only what’s needed for deployment
  7. Set explicit resource requests meeting platform constraints
Next Steps (when ready to deploy):
  1. Create EKS overlay directory: deployments/overlays/staging-eks/
  2. Create AKS overlay directory: deployments/overlays/staging-aks/
  3. Copy templates from this guide
  4. Adapt ServiceAccount annotations for IRSA/Managed Identity
  5. Test with kubectl apply --dry-run=server before committing