EKS
The EKS stack creates and manages an Amazon Elastic Kubernetes Service (EKS) cluster in your AWS account. Webscale deploys Helm charts to the EKS cluster through the Control Plane, and your own tools reach it with kubectl and Helm.
An EKS stack consists of:
- An EKS cluster with a public and a private API endpoint
- A fixed-size node group of Arm nodes
- The
vpc-cni,kube-proxy,coredns, andmetrics-serveradd-ons - External Secrets Operator with a ClusterSecretStore for AWS Secrets Manager (enabled by default)
- Karpenter node autoscaling (enabled by default)
- Supporting infrastructure (subnets and their route tables, a NAT gateway, IAM roles, and the security group rule, plus a VPC in the new VPC mode)
Network topology
The stack can be deployed in three modes:
- Data plane VPC (private nodes): Set
data_plane_vpcto the VPC ID of your dedicated data plane andnetwork_cidrto a free block of that VPC. The stack creates its subnets there, and the proxies reach the nodes over the VPC’s own routing. The nodes reach the internet through one NAT gateway, whose address thenat_ipoutput reports for allowlisting. The VPC must be in the same AWS account and region, with an internet gateway attached and DNS support and DNS hostnames enabled. - New VPC (public nodes): Set
public_nodesanddata_plane_cidr, which is0.0.0.0/0because the proxies reach public nodes from their public addresses. The stack creates a new VPC fromnetwork_cidrand gives each node a public address. It creates no NAT gateway, each node uses its own address, andnat_ipis null. - Existing network: Uses the subnets you list in
node_subnets. The stack creates no network. The subnets must already have a route to the internet, or the nodes cannot pull images. Setdata_plane_cidrto the network of the proxies, or the stack opens no port and deployments fail their reachability test. Connect the two networks yourself when the subnets are in another VPC.
The mode cannot change for the life of the EKS cluster, which cannot move between VPCs. A different mode needs a new stack.
Data plane
A data plane is a set of Webscale proxies that receive the traffic for your applications, and a dedicated data plane serves your account alone. Its proxies send traffic directly to the EKS cluster’s nodes on the node port of the release’s Service. Because the port can change with every deployment, the stack opens the whole NodePort range (30000-32767) to the network of the proxies. In a created network, private nodes need data_plane_vpc and public nodes need data_plane_cidr.
Variables
The stack name becomes the EKS cluster name and prefixes the IAM roles the stack creates. Use 3 to 47 characters from a-z, 0-9, and -, starting with a lowercase letter or a digit. Stacks that share an AWS account need unique names.
| Variable name | Type | Description |
|---|---|---|
region | string | (Required) (Permanent) The AWS region to create the EKS cluster in. |
kubernetes_version | string | Kubernetes version of the EKS cluster, its nodes, and its add-ons. Defaults to "1.36". A change upgrades all three. A version past standard support keeps running under EKS extended support, which AWS bills at a higher price. See Amazon EKS pricing
. |
network_cidr | string | (Permanent) Network the created subnets take. In a created VPC it is the whole VPC block, and inside the data plane’s VPC it is a free block of that VPC. Defaults to 192.168.0.0/16. Provide your own block when the EKS cluster must route to your other networks. Ignored when node_subnets is set. The EKS cluster cannot move between VPCs, and its NAT gateway cannot move between subnets. |
node_subnets | list(string) | (Permanent) Existing subnet IDs for the nodes in two or more availability zones. When set, the stack uses them and creates no network. See Network topology . |
data_plane_vpc | string | (Permanent) VPC ID of your dedicated data plane, required for private nodes in a created network. The stack builds its subnets inside that VPC and opens the NodePort range to its primary CIDR block unless data_plane_cidr is set. The VPC must be in the same AWS account and region, and network_cidr must be a free block inside it. With node_subnets, use data_plane_cidr instead, and setting both fails the update. See Data plane
. |
public_nodes | bool | Whether the nodes in the created subnets get public addresses. Defaults to false. Ignored when node_subnets is set. When true, the stack creates no NAT gateway, nat_ip is null, and data_plane_cidr is required, because the proxies reach the nodes from their public addresses. Do not change the value on a live EKS cluster. The existing nodes lose internet access until they are replaced, and this change does not replace them. |
data_plane_cidr | string | Network the data plane proxies reach the nodes from. When set, the EKS cluster’s security group opens the NodePort range to it. Use 0.0.0.0/0 for public nodes, which the proxies reach from their public addresses. For private nodes on subnets you list in node_subnets, use the network of the dedicated data plane. When not set and data_plane_vpc is set, the stack uses the primary CIDR block of that VPC. See Data plane
. |
public_access_cidrs | list(string) | Networks allowed to reach the public API endpoint. Open by default. The list must include the Webscale Control Plane addresses, or Webscale can no longer manage the EKS cluster or deploy to it. |
base_instance_type | string | Arm instance type of the base nodes, such as t4g.large (default) or m7g.large. A change builds a new node group before the stack removes the old one. |
base_node_count | number | Node count of the base node group. Defaults to 2. The group never scales. Karpenter adds temporary nodes on top when enabled. |
disk_size | number | Root disk size in GiB of every node. Defaults to 80. A change builds a new node group before the stack removes the old one. |
kubernetes_admins | list(string) | ARNs of IAM roles or users granted cluster admin. Empty by default. See Cluster access . |
enable_external_secrets | bool | Whether to install External Secrets Operator and its aws-secretsmanager store. Defaults to true. When false, a chart that declares an ExternalSecret fails to install. Setting it to false on a live EKS cluster deletes every ExternalSecret and the Secrets it created. See Secrets
. |
enable_karpenter | bool | Whether to install Karpenter node autoscaling. Defaults to true. When false, the EKS cluster stays at base_node_count nodes. See Node autoscaling
. |
karpenter_cpu_limit | number | Total vCPUs of the temporary nodes Karpenter may add. Defaults to 512. Karpenter stops adding nodes at the cap. |
karpenter_node_lifetime | string | Lifetime of each temporary node, a duration built from s, m, and h. Defaults to 720h. Karpenter replaces a node at this age, and Never disables the rotation. The base node group never expires. |
Example:
{
"type": "eks",
"environment": "/v2/environments/tu8aovkn7waj",
"service": "/v2/services/2tpkjj7e0b28",
"name": "production-eks",
"variables": {
"region": "us-east-1",
"network_cidr": "10.0.16.0/20",
"data_plane_vpc": "vpc-0123456789abcdef0",
"kubernetes_admins": ["arn:aws:iam::123456789012:role/PlatformAdmin"]
}
}
Outputs
| Output name | Description |
|---|---|
kubernetes_cluster_name | The name of the EKS cluster. Enter it in Cluster Name when you enable Use for Kubernetes on the AWS provider. |
nat_ip | Public address of the NAT gateway, the fixed address the nodes use to reach the internet. Null when node_subnets is set or public_nodes is true. |
Cluster access
The stack grants cluster admin through EKS access entries to the Webscale IAM user and to each ARN in kubernetes_admins. Webscale creates that user in your account during onboarding. Use kubernetes_admins for your own roles and users, and for a provider whose access key belongs to another user. The Webscale user and the stack’s own IAM roles already have entries, and listing one of them fails the stack update.
To deploy through Webscale, enable Use for Kubernetes on the AWS provider and enter the kubernetes_cluster_name output in Cluster Name. Then create a Kubernetes cluster
with a Helm blueprint. See Working with Providers
for the provider settings.
Secrets
When enable_external_secrets is true, the stack installs External Secrets Operator
in the external-secrets namespace and a ClusterSecretStore named aws-secretsmanager for AWS Secrets Manager. The operator reads each value directly from Secrets Manager, so no value passes through Webscale. It can read only secrets whose names start with webscale/. Your chart declares an ExternalSecret that names the secret, and the operator writes a Kubernetes Secret in the namespace of the deployment.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: example
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: aws-secretsmanager
target:
name: secret-to-be-created
dataFrom:
- extract:
key: webscale/acme-api/prod
Reference the Secret in the container spec of your Deployment with envFrom:
envFrom:
- secretRef:
name: secret-to-be-created
Containers read environment variables at start. A rotated value reaches the application on the next deployment.
Node autoscaling
When enable_karpenter is true, Karpenter
adds temporary nodes when pods do not fit on the existing nodes and removes them as demand falls. It launches on-demand Arm instances from the c, m, and r families, generation 3 or newer, size large or larger. They share the disk size, node role, and security group of the base nodes. karpenter_cpu_limit caps the total, and karpenter_node_lifetime sets when Karpenter replaces a node.
Karpenter evicts pods when it removes a node and honors a PodDisruptionBudget for up to 20 minutes, then deletes the remaining pods. Add a budget that selects each Deployment’s pods.
Deleting the stack
Delete the Kubernetes clusters that deploy to the EKS cluster before you delete the stack, and wait for Karpenter to remove its temporary nodes. Karpenter launches and terminates those instances itself, so the stack cannot delete them. If temporary nodes are still running, the delete waits for Karpenter to drain them, which can take up to 20 minutes. The stack releases the NAT address when you delete it, and a replacement stack gets a different one. The stack removes only the network pieces it created.
Last modified on September 2, 2026