Amazon EKS — API Server Endpoint

2 minute read

API Server Endpoint Access

The API server endpoint determines who can reach your Kubernetes API and how nodes communicate with the control plane. Getting this wrong is a common security misconfiguration.


Three Access Modes

API Server Endpoint Options
┌────────────────────────────────────────────────────────────┐
│                                                            │
│  PUBLIC ONLY (default)          PUBLIC + PRIVATE            │
│  ┌──────────┐                   ┌──────────┐               │
│  │ Internet │──▶ API Server     │ Internet │──▶ API Server │
│  └──────────┘                   └──────────┘               │
│  ┌──────────┐                   ┌──────────┐               │
│  │  Nodes   │──▶ Internet ──▶   │  Nodes   │──▶ Private    │
│  └──────────┘    API Server     └──────────┘    ENIs       │
│                                                            │
│  PRIVATE ONLY                                              │
│  ┌──────────┐                                              │
│  │ VPN/DC   │──▶ Private ENIs ──▶ API Server               │
│  └──────────┘                                              │
│  ┌──────────┐                                              │
│  │  Nodes   │──▶ Private ENIs                              │
│  └──────────┘                                              │
└────────────────────────────────────────────────────────────┘

Comparison

Feature Public Only Public + Private Private Only
kubectl from internet ✅ Yes ✅ Yes ❌ No (VPN/DC required)
Node-to-API path Internet (NAT GW) Private (ENIs in VPC) Private (ENIs in VPC)
Security level Low Medium High
NAT GW for API traffic Required Not needed Not needed
Setup complexity Low Low High (VPN/bastion needed)
Recommendation Dev only Most production Strict compliance

Configure Endpoint Access

With eksctl

# cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: demo
  region: us-east-1

vpc:
  clusterEndpoints:
    publicAccess: true
    privateAccess: true     # Recommended for production

With AWS CLI

$ aws eks update-cluster-config \
    --name demo \
    --resources-vpc-config \
    endpointPublicAccess=true,endpointPrivateAccess=true

Restrict Public Access by CIDR

If you use public access, restrict it to your IP:

vpc:
  clusterEndpoints:
    publicAccess: true
    privateAccess: true
  publicAccessCIDRs:
    - 203.0.113.0/24     # Your office IP range
    - 198.51.100.10/32   # Your VPN exit IP
$ aws eks update-cluster-config \
    --name demo \
    --resources-vpc-config \
    publicAccessCidrs=["203.0.113.0/24","198.51.100.10/32"]

Public + Private — Best of Both Worlds

Developer laptop                     Worker Nodes
(anywhere)                           (in private subnets)
    │                                     │
    │ kubectl (public)                    │ kubelet (private)
    ▼                                     ▼
┌──────────┐                        ┌──────────┐
│ Public   │                        │ Private  │
│ Endpoint │                        │ ENIs     │
│ (NLB)    │                        │ (in VPC) │
└────┬─────┘                        └────┬─────┘
     │                                   │
     └──────────┐           ┌────────────┘
                ▼           ▼
           ┌──────────────────┐
           │   API Server     │
           │   (EKS managed)  │
           └──────────────────┘

Benefits:

  • Developers can kubectl from their laptops
  • Nodes talk to API server privately (no NAT GW costs for API traffic)
  • Faster node-to-API communication (no internet hop)
  • Can restrict public access to specific CIDRs

Common Mistakes

Mistake Impact
Public-only endpoint in production Nodes route to API via internet (slow, costs NAT GW)
Private-only without VPN setup Locked out of cluster
No CIDR restriction on public Anyone can attempt API authentication
Changing endpoint without testing Could lose kubectl access

Quick Reference

# Check current endpoint access
$ aws eks describe-cluster --name demo \
    --query 'cluster.resourcesVpcConfig.{Public:endpointPublicAccess, Private:endpointPrivateAccess}'

# Enable both
$ aws eks update-cluster-config --name demo \
    --resources-vpc-config endpointPublicAccess=true,endpointPrivateAccess=true

# Restrict public
$ aws eks update-cluster-config --name demo \
    --resources-vpc-config 'publicAccessCidrs=["YOUR_IP/32"]'

What’s Next?

Now let’s design the VPC properly: VPC Design.