Skip to main content
Source

This page is generated from skills/eks-build/references/addon-catalog.md. Edit the source, not this page.

Addon Catalog

All addons supported by this framework, organized by category. Each addon is toggled via YAML configuration -- no Terraform code changes required.

Addon Summary Table

CategoryAddonConfig KeyPattern 1Pattern 2DefaultAuth
EKS ManagedVPC CNIeks_addons.vpc-cniTerraformTerraformOnNode role
CoreDNSeks_addons.corednsTerraformTerraformOnNode role
kube-proxyeks_addons.kube-proxyTerraformTerraformOnNode role
EBS CSI Drivereks_addons.aws-ebs-csi-driverTerraformTerraformOnPod Identity
EFS CSI Drivereks_addons.aws-efs-csi-driverTerraformTerraformOffPod Identity
Pod Identity Agenteks_addons.eks-pod-identity-agentTerraformTerraformOnNode role
NetworkingAWS LB Controlleraws_load_balancer_controllerTerraformArgoCDOnIRSA
ingress-nginxingress_nginxTerraformArgoCDOff--
External DNSexternal_dnsTerraformArgoCDOffIRSA
Gateway API Controlleraws_gateway_api_controllerTerraformArgoCDOffIRSA
AutoscalingCluster Autoscalercluster_autoscalerTerraformArgoCDOnIRSA
Karpenterkarpenter (dedicated submodule)TerraformArgoCDOffPod Identity
Metrics Servermetrics_serverTerraformArgoCDOn--
Securitycert-managercert_managerTerraformArgoCDOff--
External Secretsexternal_secretsTerraformArgoCDOffIRSA
GatekeepergatekeeperTerraformArgoCDOff--
KyvernokyvernoTerraformArgoCDOff--
ObservabilityCloudWatch Metricscloudwatch_metricsTerraform--OffIRSA
Fluent BitfluentbitTerraform--OffIRSA
PrometheusprometheusTerraform--Off--
StorageFSx CSI Driverfsx_csiTerraform--OffPod Identity
BackupVeleroveleroTerraformArgoCDOffIRSA/PodId
CapabilitiesACKcapabilities.ackTerraformTerraformOffIAM role
KROcapabilities.kroTerraformTerraformOff--
CustomPrisma Cloudcustom_addons.prisma_defenderTerraformArgoCD*Off--
New Reliccustom_addons.new_relicTerraformArgoCD*Off--
Flux CDcustom_addons.fluxTerraformArgoCD*Off--
Multus CNIcustom_addons.multusTerraformArgoCD*Off--
AWS PCA Issuercustom_addons.pca_issuerTerraformArgoCD*OffIRSA

* In Pattern 2, custom addons deploy via gitops/custom-addons/ directory-based ApplicationSet.

EKS Managed Addons

Deployed through the EKS API (not Helm), managed identically in both patterns. Configure under eks_addons in addons.yaml:

eks_addons:
vpc-cni:
most_recent: true
before_compute: true # MANDATORY -- prevents NodeCreationFailure
coredns:
most_recent: true
kube-proxy:
most_recent: true
aws-ebs-csi-driver:
most_recent: true
aws-efs-csi-driver:
most_recent: true
eks-pod-identity-agent:
most_recent: true
before_compute: true # MANDATORY -- for Pod Identity workloads

before_compute Requirements

AddonNeeds before_computeReason
vpc-cniYesNodes need CNI for Pod IPs and health checks
eks-pod-identity-agentYesPods need agent DaemonSet for Pod Identity
corednsNoDNS runs as Deployment; nodes work without it initially
kube-proxyNoIptables rules set up on node join
aws-ebs-csi-driverNoStorage driver only needed when PVCs are created

Pod Identity for EKS Managed Addons

EKS managed addons (EBS CSI, EFS CSI, FSx CSI, Mountpoint S3 CSI, CloudWatch) use Pod Identity instead of IRSA. IAM roles are created by terraform-aws-modules/eks-pod-identity/aws modules. Associations are separate aws_eks_pod_identity_association resources -- not inline in addon config.

Why separate resources (not inline pod_identity_association):

  1. Terraform v1.14's strict for_each rejects unknown module outputs in the upstream EKS module's filter expression
  2. Separate resources create correct destroy ordering -- associations destroyed before IAM roles
# IAM role (no association -- created separately)
module "ebs_csi_pod_identity" {
source = "terraform-aws-modules/eks-pod-identity/aws"
version = "<LOOK_UP>" # Look up latest from Terraform Registry
name = "${local.cluster_config.name}-ebs-csi"
use_name_prefix = false
attach_aws_ebs_csi_policy = true
aws_ebs_csi_policy_name = "${local.cluster_config.name}-EBS_CSI" # Avoid cross-project collision
tags = local.tags
}

# Separate association (depends on both cluster and IAM role)
resource "aws_eks_pod_identity_association" "ebs_csi" {
cluster_name = module.eks_cluster.cluster_name
namespace = "kube-system"
service_account = "ebs-csi-controller-sa"
role_arn = module.ebs_csi_pod_identity[0].iam_role_arn
}

Blueprints Addons (Pattern 1)

The aws-ia/eks-blueprints-addons module deploys these as Helm releases. Each addon has an enabled flag and optional config block:

aws_load_balancer_controller:
enabled: true
config:
wait: true # Required for Phase 1 webhook ordering
chart_version: "<LOOK_UP>" # Always override module default
set:
- name: vpcId
value: "vpc-0abc123" # Explicit -- IMDS fallback can fail
- name: replicaCount
value: "2"

Critical: Two-Phase Module Architecture

LBC and Gatekeeper must deploy in Phase 1 (with wait: true) before all other addons in Phase 2. See lessons-learned.md for details.

ArgoCD-Managed Addons (Pattern 2)

Addon enable flags pass to ArgoCD via the GitOps Bridge metadata secret. ArgoCD reads enable_<addon_name> annotations and conditionally creates Helm Applications.

Karpenter in Pattern 2 (validated): Terraform creates the IAM roles and Pod Identity associations via the dedicated submodule. The Helm chart deploys via ArgoCD Application (OCI chart: oci://public.ecr.aws/karpenter/karpenter). NodePool/EC2NodeClass CRDs can be deployed via a custom-addons chart. Discovery tags must be applied by Terraform before ArgoCD syncs.

addons:
aws_load_balancer_controller:
enabled: true
metrics_server:
enabled: true
cluster_autoscaler:
enabled: true

Tenant Workloads (Pattern 2)

Tenants use a Kustomize-based ApplicationSet with a Git Directory Generator that auto-discovers tenant overlay directories (gitops/tenants/*/overlays/*). Each tenant gets its own AppProject for RBAC isolation.

Custom Addons

Prisma Cloud Defender

Runtime container security agent from Palo Alto Networks.

custom_addons:
prisma_defender:
enabled: true
chart: twistlock-defender
chart_version: "<LOOK_UP>"
repository: "https://<REGISTRY_URL>"
namespace: twistlock

New Relic

Infrastructure monitoring bundle (K8s integration, Prometheus agent, logging).

custom_addons:
new_relic:
enabled: true
chart: nri-bundle
chart_version: "<LOOK_UP>" # Look up from https://artifacthub.io/packages/helm/newrelic/nri-bundle
repository: https://helm-charts.newrelic.com
namespace: newrelic
set:
- name: global.licenseKey
value: "<YOUR_LICENSE_KEY>"

Flux CD

GitOps toolkit. Installs Flux controllers; configure GitRepository and Kustomization CRDs separately.

custom_addons:
flux:
enabled: true
chart: flux2
chart_version: "<LOOK_UP>" # Look up from https://artifacthub.io/packages/helm/fluxcd-community/flux2
repository: https://fluxcd-community.github.io/helm-charts
namespace: flux-system

Multus CNI -- BROKEN

Do NOT enable. Thick-plugin has a pod-lookup race condition that blocks ALL new pod creation.

custom_addons:
multus:
enabled: false # BROKEN: thick-plugin pod-lookup race

AWS PCA Issuer

Bridges cert-manager with AWS Private Certificate Authority for org-trusted TLS.

custom_addons:
pca_issuer:
enabled: true
chart: aws-privateca-issuer
chart_version: "<LOOK_UP>" # Look up from https://artifacthub.io/packages/helm/cert-manager/aws-privateca-issuer
repository: https://cert-manager.github.io/aws-privateca-issuer
namespace: cert-manager
service_account_role_arn: "arn:aws:iam::<ACCOUNT_ID>:role/pca-issuer-role"
cluster_issuer_arn: "arn:aws:acm-pca:<REGION>:<ACCOUNT_ID>:certificate-authority/<CA_ID>"
cluster_issuer_name: pca-cluster-issuer

Adding a New Custom Addon

Pattern 1 (Terraform)

  1. Add a module block in modules/custom-addons/main.tf:
module "my_addon" {
count = try(var.custom_addons_config.my_addon.enabled, false) ? 1 : 0
source = "aws-ia/eks-blueprints-addon/aws"
version = "<LOOK_UP>" # Look up from Terraform Registry

chart = try(var.custom_addons_config.my_addon.chart, "my-addon")
chart_version = try(var.custom_addons_config.my_addon.chart_version, "<LOOK_UP>")
repository = try(var.custom_addons_config.my_addon.repository, "https://charts.example.com")
namespace = try(var.custom_addons_config.my_addon.namespace, "my-addon")
create_namespace = true

values = try(var.custom_addons_config.my_addon.values, [])
set = try(var.custom_addons_config.my_addon.set, [])
tags = var.tags
}
  1. Add config in addons.yaml:
custom_addons:
my_addon:
enabled: true
chart: my-addon
chart_version: "<LOOK_UP>"
repository: "https://charts.example.com"
namespace: my-addon

Pattern 2 (ArgoCD)

  1. Create gitops/custom-addons/charts/my-addon/ with Chart.yaml + values.yaml.
  2. The directory-based ApplicationSet auto-discovers and deploys it.