This is a stable example. It should successfully build out of the box
This example is built on Construct Libraries marked "Stable" and does not have any infrastructure prerequisites to build.
This is a CDK example in Java that creates a private EKS cluster isolated from the Internet. This CDK application deploys a VPC with only Isolated Subnets. There is no Internet Gateway, NAT Gateway, or any proxy to the internet in the VPC. The cluster will have one worker node to run the pods and one client EC2 instance for kubectl. The EC2 instances will be accessible through AWS Systems Manager. The private connection to the AWS services will be through VPC Endpoints.
A private EKS cluster setup is commonly used in enterprise setup or highly regulated environments where there are strict requirements to not allow internet connectivity to the deployed workloads.
The cluster stack setup will create the following VPC endpoints.
- S3 -
s3 - ECR -
ecr.api,ecr.dkr - EC2 -
ec2 - EKS -
eks - Security Token Service -
sts - Cloudwatch -
logs,monitoring - Systems Manager -
ec2messages,ssm,ssmmessages - Lambda -
lambda - Step Functions -
states,sync-states
In the console, you will see Endpoints created in each Isolated subnet with the Service Name prefixed with com.amazonaws.[region]. e.g. com.amazonaws.ap-southeast-1.s3.
The S3 endpoint is used to download the assets, artifacts, and tools stored in S3 buckets. The ECR endpoint is to pull container images in private repos and even in public repos in upstream registries via ECR pull through caches. The EC2 endpoint is used to call the EC2 services when creating the worker nodes and client instance. The EKS endpoint is to call the EKS API for cluster creation. The CloudWatch endpoints are for logging and monitoring. The Lambda and Step Function endpoints are required by the Custom Resource cluster handler of CDK in creating the EKS cluster.
Also see the required endpoints for Systems Manager here.
After deployment, as you add applications to the cluster requiring other services, you will need to add their respective VPC endpoints. The full list can be found here.
Note that you will be billed for each hour that your VPC endpoint remains provisioned in each Availability Zone. Data processing charges also apply. Please refer to its pricing here.
-
Go the root directory of this example
cd ./eks-private-cluster -
Synthesize the code
cdk synth -
Deploy
cdk deployThis will take about 25 mins. It includes the creation of the EKS cluster, the VPC endpoints, and the Lambda functions required by CDK to monitor the cluster lifecycle. The functions are deployed in the VPC and is configured in the cluster's
placeClusterHandlerInVpcset totrue. See the EKS Construct Library for more details. -
After a successful deployment, note the output of CDK on the cluster's name, the
kubeconfigsettings, thekubectl-clientinstance id, and the master IAM role of the cluster.Example output:
Outputs: EksPrivateCluster.eksClusterNameXXXXXXXX = eks-private EksPrivateCluster.eksConfigCommandXXXXXXXX = aws eks update-kubeconfig --name eks-private --region ap-southeast-1 --role-arn arn:aws:iam::111111111111:role/EksPrivateCluster-clusteradminxxxxxxxx-xxxxxxxxxxxx EksPrivateCluster.eksGetTokenCommandXXXXXXXX = aws eks get-token --cluster-name eks-private --region ap-southeast-1 --role-arn arn:aws:iam::111111111111:role/EksPrivateCluster-clusteradminxxxxxxxx-xxxxxxxxxxxx EksPrivateCluster.eksMastersRoleArnXXXXXXXX = arn:aws:iam::111111111111:role/EksPrivateCluster-clusteradminxxxxxxxx-xxxxxxxxxxxx EksPrivateCluster.kubectlclientBastionHostXXXXXXXX = i-000000000aaaaaaaa
- Login to the AWS Console and go to the EC2 Service. Find and select the instance created by CDK with the name
kubectl-client. ClickConnect. ChooseSession Manager. - Optional. Update the Session Manager Preferences to use bash and set alias for kubectl.
/bin/bash alias k=kubectl export AWS_STS_REGIONAL_ENDPOINTS=regional cd $HOME
Amazon Linux repositories are hosted in Amazon Simple Storage Service (Amazon S3) buckets. Installing or updating packages from these repositories will work even in an isolated environment. See this AWS re:Post entry. The CDK we just deployed used Amazon Linux instances and has an S3 VPC gateway endpoint. For example, we can access this repository to install docker.
sudo yum update -y
sudo amazon-linux-extras install docker
sudo service docker start
For other packages or tools like kubectl, create an S3 bucket accessible from the isolated environment to store these assets. You can use AWS CloudShell to download the assets and upload them in the asset bucket. Follow the steps here to install kubectl in the kubectl-client instance.
Sample cloudshell session:
[cloudshell-user@ip-10-2-84-204 ~]$ curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.34.2/2025-11-13/bin/linux/amd64/kubectl
[cloudshell-user@ip-10-2-84-204 ~]$ aws s3 cp kubectl s3://my-bucket/kubectl-1.34.2
upload: ./kubectl to s3://my-bucket/kubectl-1.34.2
To access the EKS cluster, SSM to the kubectl-client instance
Update the kubeconfig. Get the settings from the cdk deploy output you noted earlier.
[ssm-user@ip-10-0-0-240 bin]$ aws eks update-kubeconfig --name eks-private --region ap-southeast-1 --role-arn arn:aws:iam::111111111111:role/EksPrivateCluster-clusteradminxxxxxxxx-xxxxxxxxxxxx
Added new context arn:aws:eks:ap-southeast-1:111111111111:cluster/eks-private to /home/ssm-user/.kube/config
Test the access to the EKS cluster. Get pods and nodes
[ssm-user@ip-10-0-0-240 ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-10-0-0-60.ap-southeast-1.compute.internal Ready <none> 19h v1.34.2-eks-ecaa3a6
[ssm-user@ip-10-0-0-240 ~]$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system aws-node-9sqcb 2/2 Running 2 (4h39m ago) 19h
kube-system coredns-6787556b84-cg29g 1/1 Running 1 (4h39m ago) 19h
kube-system coredns-6787556b84-q98ks 1/1 Running 1 (4h39m ago) 19h
kube-system kube-proxy-m9ms4 1/1 Running 1 (4h39m ago) 19h
cdk destroy
