86 types
The aws-eks-v2 module is a rewrite of the existing aws-eks module (https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_eks-readme.html). This new iteration leverages native L1 CFN resources, replacing the previous custom resource approach for creating EKS clusters and Fargate Profiles.
Compared to the original EKS module, it has the following major changes:
Here is the minimal example of defining an AWS EKS cluster
cluster = AWSCDK::EKSv2::Cluster.new(self, "hello-eks", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
+-----------------+
kubectl | |
+------------>| Kubectl Handler |
| | (Optional) |
| +-----------------+
+-------------------------------------+-------------------------------------+
| EKS Cluster (Auto Mode) |
| AWS::EKS::Cluster |
| |
| +---------------------------------------------------------------------+ |
| | Auto Mode Compute (Managed by EKS) (Default) | |
| | | |
| | - Automatically provisions EC2 instances | |
| | - Auto scaling based on pod requirements | |
| | - No manual node group configuration needed | |
| | | |
| +---------------------------------------------------------------------+ |
| |
+---------------------------------------------------------------------------+
In a nutshell:
cluster = AWSCDK::EKSv2::Cluster.new(self, "AutoModeCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
You can also define Fargate Profiles that determine which pods or namespaces run on Fargate infrastructure.
cluster = AWSCDK::EKSv2::Cluster.new(self, "ManagedNodeCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::NODEGROUP,
})
# Add a Fargate Profile for specific workloads (e.g., default namespace)
cluster.add_fargate_profile("FargateProfile", {
selectors: [
{namespace: "default"},
],
})
cluster = AWSCDK::EKSv2::FargateCluster.new(self, "FargateCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
cluster = AWSCDK::EKSv2::Cluster.new(self, "SelfManagedCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
# Add self-managed Auto Scaling Group
cluster.add_auto_scaling_group_capacity("self-managed-asg", {
instance_type: AWSCDK::EC2::InstanceType.of(AWSCDK::EC2::InstanceClass::T3, AWSCDK::EC2::InstanceSize::MEDIUM),
min_capacity: 1,
max_capacity: 5,
})
kubectl commands (like apply or patch) during deployment.
Regardless of the capacity mode, this handler may still be created to apply Kubernetes manifests as part of CDK provisioning.Creating a new cluster is done using the Cluster constructs. The only required property is the kubernetes version.
AWSCDK::EKSv2::Cluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
You can also use FargateCluster to provision a cluster that uses only fargate workers.
AWSCDK::EKSv2::FargateCluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
Note: Unlike the previous EKS cluster, Kubectl Handler will not
be created by default. It will only be deployed when kubectl_provider_options
property is used.
require 'aws-cdk-lambda-layer-kubectl-v35'
AWSCDK::EKSv2::Cluster.new(self, "hello-eks", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
kubectl_provider_options: {
kubectl_layer: AWSCDK::LambdaLayerKubectlV35::KubectlV35Layer.new(self, "kubectl"),
},
})
Amazon EKS Auto Mode extends AWS management of Kubernetes clusters beyond the cluster itself, allowing AWS to set up and manage the infrastructure that enables the smooth operation of your workloads.
While aws-eks uses DefaultCapacityType.NODEGROUP by default, aws-eks-v2 uses DefaultCapacityType.AUTOMODE as the default capacity type.
Auto Mode is enabled by default when creating a new cluster without specifying any capacity-related properties:
# Create EKS cluster with Auto Mode implicitly enabled
cluster = AWSCDK::EKSv2::Cluster.new(self, "EksAutoCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
You can also explicitly enable Auto Mode using default_capacity_type:
# Create EKS cluster with Auto Mode explicitly enabled
cluster = AWSCDK::EKSv2::Cluster.new(self, "EksAutoCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::AUTOMODE,
})
When Auto Mode is enabled, the cluster comes with two default node pools:
system: For running system components and add-onsgeneral-purpose: For running your application workloadsThese node pools are managed automatically by EKS. You can configure which node pools to enable through the compute property:
cluster = AWSCDK::EKSv2::Cluster.new(self, "EksAutoCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::AUTOMODE,
compute: {
node_pools: ["system", "general-purpose"],
},
})
For more information, see Create a Node Pool for EKS Auto Mode.
You can disable the default node pools entirely by setting an empty array for node_pools. This is useful when you want to use Auto Mode features but manage your compute resources separately:
cluster = AWSCDK::EKSv2::Cluster.new(self, "EksAutoCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::AUTOMODE,
compute: {
node_pools: [],
},
})
When node pools are disabled this way, no IAM role will be created for the node pools, preventing deployment failures that would otherwise occur when a role is created without any node pools.
If you prefer to manage your own node groups instead of using Auto Mode, you can use the traditional node group approach by specifying default_capacity_type as NODEGROUP:
# Create EKS cluster with traditional managed node group
cluster = AWSCDK::EKSv2::Cluster.new(self, "EksCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::NODEGROUP,
default_capacity: 3,
# Number of instances
default_capacity_instance: AWSCDK::EC2::InstanceType.of(AWSCDK::EC2::InstanceClass::T3, AWSCDK::EC2::InstanceSize::LARGE),
})
You can also create a cluster with no initial capacity and add node groups later:
cluster = AWSCDK::EKSv2::Cluster.new(self, "EksCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::NODEGROUP,
default_capacity: 0,
})
# Add node groups as needed
cluster.add_nodegroup_capacity("custom-node-group", {
min_size: 1,
max_size: 3,
instance_types: [AWSCDK::EC2::InstanceType.of(AWSCDK::EC2::InstanceClass::T3, AWSCDK::EC2::InstanceSize::LARGE)],
})
Read Managed node groups for more information on how to add node groups to the cluster.
You can combine Auto Mode with traditional node groups for specific workload requirements:
cluster = AWSCDK::EKSv2::Cluster.new(self, "Cluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::AUTOMODE,
compute: {
node_pools: ["system", "general-purpose"],
},
})
# Add specialized node group for specific workloads
cluster.add_nodegroup_capacity("specialized-workload", {
min_size: 1,
max_size: 3,
instance_types: [AWSCDK::EC2::InstanceType.of(AWSCDK::EC2::InstanceClass::C5, AWSCDK::EC2::InstanceSize::XLARGE)],
labels: {
workload: "specialized",
},
})
default_capacity or default_capacity_instance.Amazon EKS managed node groups automate the provisioning and lifecycle management of nodes (Amazon EC2 instances) for Amazon EKS Kubernetes clusters. With Amazon EKS managed node groups, you don't need to separately provision or register the Amazon EC2 instances that provide compute capacity to run your Kubernetes applications. You can create, update, or terminate nodes for your cluster with a single operation. Nodes run using the latest Amazon EKS optimized AMIs in your AWS account while node updates and terminations gracefully drain nodes to ensure that your applications stay available.
For more details visit Amazon EKS Managed Node Groups.
By default, when using DefaultCapacityType.NODEGROUP, this library will allocate a managed node group with 2 m5.large instances (this instance type suits most common use-cases, and is good value for money).
AWSCDK::EKSv2::Cluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::NODEGROUP,
})
At cluster instantiation time, you can customize the number of instances and their type:
AWSCDK::EKSv2::Cluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::NODEGROUP,
default_capacity: 5,
default_capacity_instance: AWSCDK::EC2::InstanceType.of(AWSCDK::EC2::InstanceClass::M5, AWSCDK::EC2::InstanceSize::SMALL),
})
To access the node group that was created on your behalf, you can use cluster.defaultNodegroup.
Additional customizations are available post instantiation. To apply them, set the default capacity to 0, and use the cluster.addNodegroupCapacity method:
cluster = AWSCDK::EKSv2::Cluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
default_capacity_type: AWSCDK::EKSv2::DefaultCapacityType::NODEGROUP,
default_capacity: 0,
})
cluster.add_nodegroup_capacity("custom-node-group", {
instance_types: [AWSCDK::EC2::InstanceType.new("m5.large")],
min_size: 4,
disk_size: 100,
})
By default, managed node groups that do not set ami_type use AL2_X86_64 (or AL2_ARM_64 for
ARM instances). Amazon Linux 2 EKS-optimized AMIs reached end of support on November 26, 2025.
AL2023 is the AWS-recommended default.
New applications should enable the @aws-cdk/aws-eks:defaultToAL2023 feature flag in cdk.json:
{
"context": {
"@aws-cdk/aws-eks:defaultToAL2023": true
}
}
When the flag is enabled, the default AMI type for x86_64 instances becomes
AL2023_X86_64_STANDARD, and for ARM instances it becomes AL2023_ARM_64_STANDARD. GPU
instances continue to default to AL2_X86_64_GPU because AL2023 splits GPU support into
separate NVIDIA and Neuron AMI variants — GPU users must pick a variant explicitly.
Migration for existing applications. Enabling this flag on an existing app will cause managed node groups that previously defaulted to AL2 to be replaced with AL2023 on the next deploy, which terminates running pods. To roll out safely, pin every existing node group to its current AMI type first, and only then enable the flag as shown below. Then gradually unpin the AMI for the nodes you want to upgrade.
cluster = nil # AWSCDK::EKSv2::Cluster
# Pin existing node groups to AL2 explicitly before enabling the flag.
cluster.add_nodegroup_capacity("workers", {
instance_types: [AWSCDK::EC2::InstanceType.new("m5.large")],
ami_type: AWSCDK::EKSv2::NodegroupAmiType::AL2_X86_64,
})
Explicitly setting ami_type will pin it — it is not affected by the feature flag.
AWS Fargate is a technology that provides on-demand, right-sized compute capacity for containers. With AWS Fargate, you no longer have to provision, configure, or scale groups of virtual machines to run containers. This removes the need to choose server types, decide when to scale your node groups, or optimize cluster packing.
You can control which pods start on Fargate and how they run with Fargate Profiles, which are defined as part of your Amazon EKS cluster.
See Fargate Considerations in the AWS EKS User Guide.
You can add Fargate Profiles to any EKS cluster defined in your CDK app
through the add_fargate_profile() method. The following example adds a profile
that will match all pods from the "default" namespace:
cluster = nil # AWSCDK::EKSv2::Cluster
cluster.add_fargate_profile("MyProfile", {
selectors: [{namespace: "default"}],
})
You can also directly use the FargateProfile construct to create profiles under different scopes:
cluster = nil # AWSCDK::EKSv2::Cluster
AWSCDK::EKSv2::FargateProfile.new(self, "MyProfile", {
cluster: cluster,
selectors: [{namespace: "default"}],
})
To create an EKS cluster that only uses Fargate capacity, you can use FargateCluster.
The following code defines an Amazon EKS cluster with a default Fargate Profile that matches all pods from the "kube-system" and "default" namespaces. It is also configured to run CoreDNS on Fargate.
cluster = AWSCDK::EKSv2::FargateCluster.new(self, "MyCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
FargateCluster will create a default FargateProfile which can be accessed via the cluster's default_profile property. The created profile can also be customized by passing options as with add_fargate_profile.
NOTE: Classic Load Balancers and Network Load Balancers are not supported on pods running on Fargate. For ingress, we recommend that you use the ALB Ingress Controller on Amazon EKS (minimum version v1.1.4).
Self-managed capacity gives you the most control over your worker nodes by allowing you to create and manage your own EC2 Auto Scaling Groups. This approach provides maximum flexibility for custom AMIs, instance configurations, and scaling policies, but requires more operational overhead.
You can add self-managed capacity to any cluster using the add_auto_scaling_group_capacity method:
cluster = AWSCDK::EKSv2::Cluster.new(self, "Cluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
cluster.add_auto_scaling_group_capacity("self-managed-nodes", {
instance_type: AWSCDK::EC2::InstanceType.of(AWSCDK::EC2::InstanceClass::T3, AWSCDK::EC2::InstanceSize::MEDIUM),
min_capacity: 1,
max_capacity: 10,
desired_capacity: 3,
})
You can specify custom subnets for the Auto Scaling Group:
vpc = nil # AWSCDK::EC2::VPC
cluster = nil # AWSCDK::EKSv2::Cluster
cluster.add_auto_scaling_group_capacity("custom-subnet-nodes", {
vpc_subnets: {subnets: vpc.private_subnets},
instance_type: AWSCDK::EC2::InstanceType.of(AWSCDK::EC2::InstanceClass::T3, AWSCDK::EC2::InstanceSize::MEDIUM),
min_capacity: 2,
})
When you create a new cluster, Amazon EKS creates an endpoint for the managed Kubernetes API server that you use to communicate with your cluster (using Kubernetes management tools such as kubectl)
You can configure the cluster endpoint access by using the endpoint_access property:
cluster = AWSCDK::EKSv2::Cluster.new(self, "hello-eks", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
endpoint_access: AWSCDK::EKSv2::EndpointAccess.PRIVATE,
})
The default value is eks.EndpointAccess.PUBLIC_AND_PRIVATE. Which means the cluster endpoint is accessible from outside of your VPC, but worker node traffic and kubectl commands issued by this library stay within your VPC.
Some Kubernetes resources are commonly implemented on AWS with the help of the ALB Controller.
From the docs:
AWS Load Balancer Controller is a controller to help manage Elastic Load Balancers for a Kubernetes cluster.
- It satisfies Kubernetes Ingress resources by provisioning Application Load Balancers.
- It satisfies Kubernetes Service resources by provisioning Network Load Balancers.
To deploy the controller on your EKS cluster, configure the alb_controller property:
AWSCDK::EKSv2::Cluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
alb_controller: {
version: AWSCDK::EKSv2::ALBControllerVersion.V3_2_2,
},
})
To provide additional Helm chart values supported by alb_controller in CDK, use the additional_helm_chart_values property. For example, the following code snippet shows how to set the enable_waf_v2 flag:
require 'aws-cdk-lambda-layer-kubectl-v35'
AWSCDK::EKSv2::Cluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
alb_controller: {
version: AWSCDK::EKSv2::ALBControllerVersion.V3_2_2,
additional_helm_chart_values: {
enable_wafv2: false,
},
},
})
To overwrite an existing ALB controller service account, use the overwrite_service_account property:
AWSCDK::EKSv2::Cluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
alb_controller: {
version: AWSCDK::EKSv2::ALBControllerVersion.V3_2_2,
overwrite_service_account: true,
},
})
The alb_controller requires default_capacity or at least one nodegroup. If there's no default_capacity or available
nodegroup for the cluster, the alb_controller deployment would fail.
Querying the controller pods should look something like this:
❯ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
aws-load-balancer-controller-76bd6c7586-d929p 1/1 Running 0 109m
aws-load-balancer-controller-76bd6c7586-fqxph 1/1 Running 0 109m
...
...
Every Kubernetes manifest that utilizes the ALB Controller is effectively dependent on the controller. If the controller is deleted before the manifest, it might result in dangling ELB/ALB resources. Currently, the EKS construct library does not detect such dependencies, and they should be done explicitly.
For example:
cluster = nil # AWSCDK::EKSv2::Cluster
manifest = cluster.add_manifest("manifest", {})
if cluster.alb_controller
manifest.node.add_dependency(cluster.alb_controller)
end
You can specify the VPC of the cluster using the vpc and vpc_subnets properties:
vpc = nil # AWSCDK::EC2::VPC
AWSCDK::EKSv2::Cluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
vpc: vpc,
vpc_subnets: [{subnet_type: AWSCDK::EC2::SubnetType::PRIVATE_WITH_EGRESS}],
})
If you do not specify a VPC, one will be created on your behalf, which you can then access via cluster.vpc. The cluster VPC will be associated to any EKS managed capacity (i.e Managed Node Groups and Fargate Profiles).
Please note that the vpc_subnets property defines the subnets where EKS will place the control plane ENIs. To choose
the subnets where EKS will place the worker nodes, please refer to the Provisioning clusters section above.
If you allocate self managed capacity, you can specify which subnets should the auto-scaling group use:
vpc = nil # AWSCDK::EC2::VPC
cluster = nil # AWSCDK::EKSv2::Cluster
cluster.add_auto_scaling_group_capacity("nodes", {
vpc_subnets: {subnets: vpc.private_subnets},
instance_type: AWSCDK::EC2::InstanceType.new("t2.medium"),
})
There is an additional components you might want to provision within the VPC.
The KubectlHandler is a Lambda function responsible to issuing kubectl and helm commands against the cluster when you add resource manifests to the cluster.
The handler association to the VPC is derived from the endpoint_access configuration. The rule of thumb is: If the cluster VPC can be associated, it will be.
Breaking this down, it means that if the endpoint exposes private access (via EndpointAccess.PRIVATE or EndpointAccess.PUBLIC_AND_PRIVATE), and the VPC contains private subnets, the Lambda function will be provisioned inside the VPC and use the private subnets to interact with the cluster. This is the common use-case.
If the endpoint does not expose private access (via EndpointAccess.PUBLIC) or the VPC does not contain private subnets, the function will not be provisioned within the VPC.
If your use-case requires control over the IAM role that the KubeCtl Handler assumes, a custom role can be passed through the ClusterProps (as kubectl_lambda_role) of the EKS Cluster construct.
You can choose to have CDK create a Kubectl Handler - a Python Lambda Function to
apply k8s manifests using kubectl apply. This handler will not be created by default.
To create a Kubectl Handler, use kubectl_provider_options when creating the cluster.
kubectl_layer is the only required property in kubectl_provider_options.
require 'aws-cdk-lambda-layer-kubectl-v35'
AWSCDK::EKSv2::Cluster.new(self, "hello-eks", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
kubectl_provider_options: {
kubectl_layer: AWSCDK::LambdaLayerKubectlV35::KubectlV35Layer.new(self, "kubectl"),
},
})
Kubectl Handler created along with the cluster will be granted admin permissions to the cluster.
If you want to use an existing kubectl provider function, for example with tight trusted entities on your IAM Roles - you can import the existing provider and then use the imported provider when importing the cluster:
handler_role = AWSCDK::IAM::Role.from_role_arn(self, "HandlerRole", "arn:aws:iam::123456789012:role/lambda-role")
# get the serviceToken from the custom resource provider
function_arn = AWSCDK::Lambda::Function.from_function_name(self, "ProviderOnEventFunc", "ProviderframeworkonEvent-XXX").function_arn
kubectl_provider = AWSCDK::EKSv2::KubectlProvider.from_kubectl_provider_attributes(self, "KubectlProvider", {
service_token: function_arn,
role: handler_role,
})
cluster = AWSCDK::EKSv2::Cluster.from_cluster_attributes(self, "Cluster", {
cluster_name: "cluster",
kubectl_provider: kubectl_provider,
})
You can configure the environment of this function by specifying it at cluster instantiation. For example, this can be useful in order to configure an http proxy:
require 'aws-cdk-lambda-layer-kubectl-v35'
cluster = AWSCDK::EKSv2::Cluster.new(self, "hello-eks", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
kubectl_provider_options: {
kubectl_layer: AWSCDK::LambdaLayerKubectlV35::KubectlV35Layer.new(self, "kubectl"),
environment: {
"http_proxy" => "http://proxy.myproxy.com",
},
},
})
The kubectl handler uses kubectl, helm and the aws CLI in order to
interact with the cluster. These are bundled into AWS Lambda layers included in
the @aws-cdk/lambda-layer-awscli and @aws-cdk/lambda-layer-kubectl modules.
The version of kubectl used must be compatible with the Kubernetes version of the
cluster. kubectl is supported within one minor version (older or newer) of Kubernetes
(see Kubernetes version skew policy).
Depending on which version of kubernetes you're targeting, you will need to use one of
the @aws-cdk/lambda-layer-kubectl-vXY packages.
require 'aws-cdk-lambda-layer-kubectl-v35'
cluster = AWSCDK::EKSv2::Cluster.new(self, "hello-eks", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
kubectl_provider_options: {
kubectl_layer: AWSCDK::LambdaLayerKubectlV35::KubectlV35Layer.new(self, "kubectl"),
},
})
By default, the kubectl provider is configured with 1024MiB of memory. You can use the memory option to specify the memory size for the AWS Lambda function:
require 'aws-cdk-lambda-layer-kubectl-v35'
AWSCDK::EKSv2::Cluster.new(self, "MyCluster", {
kubectl_provider_options: {
kubectl_layer: AWSCDK::LambdaLayerKubectlV35::KubectlV35Layer.new(self, "kubectl"),
memory: AWSCDK::Size.gibibytes(4),
},
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
Instance types with ARM64 architecture are supported in both managed nodegroup and self-managed capacity. Simply specify an ARM64 instance_type (such as m6g.medium), and the latest
Amazon Linux 2 AMI for ARM64 will be automatically selected.
cluster = nil # AWSCDK::EKSv2::Cluster
# add a managed ARM64 nodegroup
cluster.add_nodegroup_capacity("extra-ng-arm", {
instance_types: [AWSCDK::EC2::InstanceType.new("m6g.medium")],
min_size: 2,
})
# add a self-managed ARM64 nodegroup
cluster.add_auto_scaling_group_capacity("self-ng-arm", {
instance_type: AWSCDK::EC2::InstanceType.new("m6g.medium"),
min_capacity: 2,
})
When you create a cluster, you can specify a masters_role. The Cluster construct will associate this role with AmazonEKSClusterAdminPolicy through Access Entry.
role = nil # AWSCDK::IAM::Role
AWSCDK::EKSv2::Cluster.new(self, "HelloEKS", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
masters_role: role,
})
If you do not specify it, you won't have access to the cluster from outside of the CDK application.
When you create an Amazon EKS cluster, envelope encryption of Kubernetes secrets using the AWS Key Management Service (AWS KMS) can be enabled. The documentation on creating a cluster can provide more details about the customer master key (CMK) that can be used for the encryption.
You can use the secrets_encryption_key to configure which key the cluster will use to encrypt Kubernetes secrets. By default, an AWS Managed key will be used.
This setting can only be specified when the cluster is created and cannot be updated.
secrets_key = AWSCDK::KMS::Key.new(self, "SecretsKey")
cluster = AWSCDK::EKSv2::Cluster.new(self, "MyCluster", {
secrets_encryption_key: secrets_key,
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
You can also use a similar configuration for running a cluster built using the FargateCluster construct.
secrets_key = AWSCDK::KMS::Key.new(self, "SecretsKey")
cluster = AWSCDK::EKSv2::FargateCluster.new(self, "MyFargateCluster", {
secrets_encryption_key: secrets_key,
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
})
The Amazon Resource Name (ARN) for that CMK can be retrieved.
cluster = nil # AWSCDK::EKSv2::Cluster
cluster_encryption_config_key_arn = cluster.cluster_encryption_config_key_arn
When you create an Amazon EKS cluster, you can configure it to leverage the EKS Hybrid Nodes feature, allowing you to use your on-premises and edge infrastructure as nodes in your EKS cluster. Refer to the Hyrid Nodes networking documentation to configure your on-premises network, node and pod CIDRs, access control, etc before creating your EKS Cluster.
Once you have identified the on-premises node and pod (optional) CIDRs you will use for your hybrid nodes and the workloads running on them, you can specify them during cluster creation using the remote_node_networks and remote_pod_networks (optional) properties:
require 'aws-cdk-lambda-layer-kubectl-v35'
AWSCDK::EKSv2::Cluster.new(self, "Cluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
remote_node_networks: [
{
cidrs: ["10.0.0.0/16"],
},
],
remote_pod_networks: [
{
cidrs: ["192.168.0.0/16"],
},
],
})
Amazon EKS automatically installs self-managed add-ons such as the Amazon VPC CNI plugin for Kubernetes, kube-proxy, and CoreDNS for every cluster. You can change the default configuration of the add-ons and update them when desired. If you wish to create a cluster without the default add-ons, set bootstrap_self_managed_addons as false. When this is set to false, make sure to install the necessary alternatives which provide functionality that enables pod and service operations for your EKS cluster.
Changing the value of
bootstrap_self_managed_addonsafter the EKS cluster creation will result in a replacement of the cluster.
In the new EKS module, ConfigMap is deprecated. Clusters created by the new module will use API as authentication mode. Access Entry will be the only way for granting permissions to specific IAM users and roles.
An access entry is a cluster identity—directly linked to an AWS IAM principal user or role that is used to authenticate to an Amazon EKS cluster. An Amazon EKS access policy authorizes an access entry to perform specific cluster actions.
Access policies are Amazon EKS-specific policies that assign Kubernetes permissions to access entries. Amazon EKS supports only predefined and AWS managed policies. Access policies are not AWS IAM entities and are defined and managed by Amazon EKS. Amazon EKS access policies include permission sets that support common use cases of administration, editing, or read-only access to Kubernetes resources. See Access Policy Permissions for more details.
Use AccessPolicy to include predefined AWS managed policies:
# AmazonEKSClusterAdminPolicy with `cluster` scope
AWSCDK::EKSv2::AccessPolicy.from_access_policy_name("AmazonEKSClusterAdminPolicy", {
access_scope_type: AWSCDK::EKSv2::AccessScopeType::CLUSTER,
})
# AmazonEKSAdminPolicy with `namespace` scope
AWSCDK::EKSv2::AccessPolicy.from_access_policy_name("AmazonEKSAdminPolicy", {
access_scope_type: AWSCDK::EKSv2::AccessScopeType::NAMESPACE,
namespaces: ["foo", "bar"],
})
Use grant_access() to grant the AccessPolicy to an IAM principal:
require 'aws-cdk-lambda-layer-kubectl-v35'
vpc = nil # AWSCDK::EC2::VPC
cluster_admin_role = AWSCDK::IAM::Role.new(self, "ClusterAdminRole", {
assumed_by: AWSCDK::IAM::ARNPrincipal.new("arn_for_trusted_principal"),
})
eks_admin_role = AWSCDK::IAM::Role.new(self, "EKSAdminRole", {
assumed_by: AWSCDK::IAM::ARNPrincipal.new("arn_for_trusted_principal"),
})
cluster = AWSCDK::EKSv2::Cluster.new(self, "Cluster", {
vpc: vpc,
masters_role: cluster_admin_role,
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
kubectl_provider_options: {
kubectl_layer: AWSCDK::LambdaLayerKubectlV35::KubectlV35Layer.new(self, "kubectl"),
memory: AWSCDK::Size.gibibytes(4),
},
})
# Cluster Admin role for this cluster
cluster.grant_access("clusterAdminAccess", cluster_admin_role.role_arn, [
AWSCDK::EKSv2::AccessPolicy.from_access_policy_name("AmazonEKSClusterAdminPolicy", {
access_scope_type: AWSCDK::EKSv2::AccessScopeType::CLUSTER,
}),
])
# EKS Admin role for specified namespaces of this cluster
cluster.grant_access("eksAdminRoleAccess", eks_admin_role.role_arn, [
AWSCDK::EKSv2::AccessPolicy.from_access_policy_name("AmazonEKSAdminPolicy", {
access_scope_type: AWSCDK::EKSv2::AccessScopeType::NAMESPACE,
namespaces: ["foo", "bar"],
}),
])
You can optionally specify an access entry type when granting access. This is particularly useful for EKS Auto Mode clusters with custom node roles, which require the EC2 type:
cluster = nil # AWSCDK::EKSv2::Cluster
node_role = nil # AWSCDK::IAM::Role
# Grant access with EC2 type for Auto Mode node role
cluster.grant_access("nodeAccess", node_role.role_arn, [
AWSCDK::EKSv2::AccessPolicy.from_access_policy_name("AmazonEKSAutoNodePolicy", {
access_scope_type: AWSCDK::EKSv2::AccessScopeType::CLUSTER,
}),
], {access_entry_type: AWSCDK::EKSv2::AccessEntryType::EC2})
The following access entry types are supported:
STANDARD - Default type for standard IAM principals (default when not specified)FARGATE_LINUX - For Fargate profilesEC2_LINUX - For EC2 Linux worker nodesEC2_WINDOWS - For EC2 Windows worker nodesEC2 - For EKS Auto Mode node rolesHYBRID_LINUX - For EKS Hybrid NodesHYPERPOD_LINUX - For Amazon SageMaker HyperPodNote: Access entries with type EC2, HYBRID_LINUX, or HYPERPOD_LINUX cannot have access policies attached per AWS EKS API constraints. For these types, use the AccessEntry construct directly with an empty access policies array.
By default, the cluster creator role will be granted the cluster admin permissions. You can disable it by setting
bootstrap_cluster_creator_admin_permissions to false.
Note - Switching
bootstrap_cluster_creator_admin_permissionson an existing cluster would cause cluster replacement and should be avoided in production.
With services account you can provide Kubernetes Pods access to AWS resources.
require 'aws-cdk-lib'
cluster = nil # AWSCDK::EKSv2::Cluster
# add service account
service_account = cluster.add_service_account("MyServiceAccount")
bucket = AWSCDK::S3::Bucket.new(self, "Bucket")
bucket.grant_read_write(service_account)
mypod = cluster.add_manifest("mypod", {
api_version: "v1",
kind: "Pod",
metadata: {name: "mypod"},
spec: {
service_account_name: service_account.service_account_name,
containers: [
{
name: "hello",
image: "paulbouwer/hello-kubernetes:1.5",
ports: [{container_port: 8080}],
},
],
},
})
# create the resource after the service account.
mypod.node.add_dependency(service_account)
# print the IAM role arn for this service account
AWSCDK::CfnOutput.new(self, "ServiceAccountIamRole", {value: service_account.role.role_arn})
Note that using serviceAccount.serviceAccountName above does not translate into a resource dependency.
This is why an explicit dependency is needed. See https://github.com/aws/aws-cdk/issues/9910 for more details.
It is possible to pass annotations and labels to the service account.
cluster = nil # AWSCDK::EKSv2::Cluster
# add service account with annotations and labels
service_account = cluster.add_service_account("MyServiceAccount", {
annotations: {
"eks.amazonaws.com/sts-regional-endpoints" => "false",
},
labels: {
"some-label" => "with-some-value",
},
})
You can also add service accounts to existing clusters.
To do so, pass the open_id_connect_provider property when you import the cluster into the application.
require 'aws-cdk-lib'
# or create a new one using an existing issuer url
issuer_url = nil
require 'aws-cdk-lambda-layer-kubectl-v35'
# you can import an existing provider
provider = AWSCDK::EKSv2::OidcProviderNative.from_oidc_provider_arn(self, "Provider", "arn:aws:iam::123456:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/AB123456ABC")
provider2 = AWSCDK::EKSv2::OidcProviderNative.new(self, "Provider", {
url: issuer_url,
})
cluster = AWSCDK::EKSv2::Cluster.from_cluster_attributes(self, "MyCluster", {
cluster_name: "Cluster",
open_id_connect_provider: provider,
kubectl_provider_options: {
kubectl_layer: AWSCDK::LambdaLayerKubectlV35::KubectlV35Layer.new(self, "kubectl"),
},
})
service_account = cluster.add_service_account("MyServiceAccount")
bucket = AWSCDK::S3::Bucket.new(self, "Bucket")
bucket.grant_read_write(service_account)
Note that adding service accounts requires running kubectl commands against the cluster which requires you to provide kubectl_provider_options in the cluster props to create the kubectl provider. See Kubectl Support
eks.OpenIdConnectProvider creates an IAM OIDC (OpenId Connect) provider using a custom resource while eks.OidcProviderNative uses the CFN L1 (AWS::IAM::OidcProvider) to create the provider. It is recommended for new and existing projects to use eks.OidcProviderNative.
To migrate without temporarily removing the OIDCProvider, follow these steps:
removal_policy of cluster.openIdConnectProvider to RETAIN. require 'aws-cdk-lib'
cluster = nil # AWSCDK::EKSv2::Cluster
AWSCDK::RemovalPolicies.of(cluster.open_id_connect_provider).apply(AWSCDK::RemovalPolicy::RETAIN)
cdk diff to verify the changes are expected then cdk deploy.context field of your cdk.json to enable the feature flag that creates the native oidc provider. "@aws-cdk/aws-eks:useNativeOidcProvider": true,
cdk diff and ensure the changes are expected. Example of an expected diff: Resources
[-] Custom::AWSCDKOpenIdConnectProvider TestCluster/OpenIdConnectProvider/Resource TestClusterOpenIdConnectProviderE18F0FD0 orphan
[-] AWS::IAM::Role Custom::AWSCDKOpenIdConnectProviderCustomResourceProvider/Role CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65 destroy
[-] AWS::Lambda::Function Custom::AWSCDKOpenIdConnectProviderCustomResourceProvider/Handler CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0 destroy
[+] AWS::IAM::OIDCProvider TestCluster/OidcProviderNative TestClusterOidcProviderNative0BE3F155
cdk import --force and provide the ARN of the existing OpenIdConnectProvider when prompted. You will get a warning about pending changes to existing resources which is expected.cdk deploy to apply any pending changes. This will apply the destroy/orphan changes in the above example.If you are creating the OpenIdConnectProvider manually via new eks.OpenIdConnectProvider, follow these steps:
removal_policy of the existing OpenIdConnectProvider to RemovalPolicy.RETAIN. require 'aws-cdk-lib'
# Step 1: Add retain policy to existing provider
existing_provider = AWSCDK::EKSv2::OpenIdConnectProvider.new(self, "Provider", {
url: "https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLE",
removal_policy: AWSCDK::RemovalPolicy::RETAIN,
})
cdk deploy
OpenIdConnectProvider with OidcProviderNative in your code. # Step 3: Replace with native provider
native_provider = AWSCDK::EKSv2::OidcProviderNative.new(self, "Provider", {
url: "https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLE",
})
cdk diff and verify the changes are expected. Example of an expected diff: Resources
[-] Custom::AWSCDKOpenIdConnectProvider TestCluster/OpenIdConnectProvider/Resource TestClusterOpenIdConnectProviderE18F0FD0 orphan
[-] AWS::IAM::Role Custom::AWSCDKOpenIdConnectProviderCustomResourceProvider/Role CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65 destroy
[-] AWS::Lambda::Function Custom::AWSCDKOpenIdConnectProviderCustomResourceProvider/Handler CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0 destroy
[+] AWS::IAM::OIDCProvider TestCluster/OidcProviderNative TestClusterOidcProviderNative0BE3F155
cdk import --force to import the existing OIDC provider resource by providing the existing ARN.cdk deploy to apply any pending changes. This will apply the destroy/orphan operations in the example diff above.When you create an Amazon EKS cluster, a cluster security group is automatically created as well. This security group is designed to allow all traffic from the control plane and managed node groups to flow freely between each other.
The ID for that security group can be retrieved after creating the cluster.
cluster = nil # AWSCDK::EKSv2::Cluster
cluster_security_group_id = cluster.cluster_security_group_id
To apply kubernetes resource, kubectl provider needs to be created for the cluster. You can use kubectl_provider_options to create the kubectl Provider.
The library supports several popular resource deployment mechanisms, among which are:
The KubernetesManifest construct or cluster.addManifest method can be used
to apply Kubernetes resource manifests to this cluster.
When using
cluster.addManifest, the manifest construct is defined within the cluster's stack scope. If the manifest contains attributes from a different stack which depend on the cluster stack, a circular dependency will be created and you will get a synth time error. To avoid this, directly usenew KubernetesManifestto create the manifest in the scope of the other stack.
The following examples will deploy the paulbouwer/hello-kubernetes service on the cluster:
cluster = nil # AWSCDK::EKSv2::Cluster
app_label = {app: "hello-kubernetes"}
deployment = {
api_version: "apps/v1",
kind: "Deployment",
metadata: {name: "hello-kubernetes"},
spec: {
replicas: 3,
selector: {match_labels: app_label},
template: {
metadata: {labels: app_label},
spec: {
containers: [
{
name: "hello-kubernetes",
image: "paulbouwer/hello-kubernetes:1.5",
ports: [{container_port: 8080}],
},
],
},
},
},
}
service = {
api_version: "v1",
kind: "Service",
metadata: {name: "hello-kubernetes"},
spec: {
type: "LoadBalancer",
ports: [{port: 80, target_port: 8080}],
selector: app_label,
},
}
# option 1: use a construct
AWSCDK::EKSv2::KubernetesManifest.new(self, "hello-kub", {
cluster: cluster,
manifest: [deployment, service],
})
# or, option2: use `addManifest`
cluster.add_manifest("hello-kub", service, deployment)
The KubernetesManifest construct can detect ingress resources inside your manifest and automatically add the necessary annotations
so they are picked up by the ALB Controller.
See Alb Controller
To that end, it offers the following properties:
ingress_alb - Signal that the ingress detection should be done.ingress_alb_scheme - Which ALB scheme should be applied. Defaults to internal.The following example will deploy the resource manifest hosting on remote server:
// This example is only available in TypeScript
import * as yaml from 'js-yaml';
import * as request from 'sync-request';
declare const cluster: eks.Cluster;
const manifestUrl = 'https://url/of/manifest.yaml';
const manifest = yaml.safeLoadAll(request('GET', manifestUrl).getBody());
cluster.addManifest('my-resource', manifest);
There are cases where Kubernetes resources must be deployed in a specific order. For example, you cannot define a resource in a Kubernetes namespace before the namespace was created.
You can represent dependencies between KubernetesManifests using
resource.node.addDependency():
cluster = nil # AWSCDK::EKSv2::Cluster
namespace = cluster.add_manifest("my-namespace", {
api_version: "v1",
kind: "Namespace",
metadata: {name: "my-app"},
})
service = cluster.add_manifest("my-service", {
metadata: {
name: "myservice",
namespace: "my-app",
},
spec: {},
})
service.node.add_dependency(namespace)
NOTE: when a KubernetesManifest includes multiple resources (either directly
or through cluster.addManifest()) (e.g. cluster.addManifest('foo', r1, r2, r3,...)), these resources will be applied as a single manifest via kubectl
and will be applied sequentially (the standard behavior in kubectl).
Since Kubernetes manifests are implemented as CloudFormation resources in the
CDK. This means that if the manifest is deleted from your code (or the stack is
deleted), the next cdk deploy will issue a kubectl delete command and the
Kubernetes resources in that manifest will be deleted.
When a resource is deleted from a Kubernetes manifest, the EKS module will
automatically delete these resources by injecting a prune label to all
manifest resources. This label is then passed to kubectl apply --prune.
Pruning is enabled by default but can be disabled through the prune option
when a cluster is defined:
AWSCDK::EKSv2::Cluster.new(self, "MyCluster", {
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
prune: false,
})
The kubectl CLI supports applying a manifest by skipping the validation.
This can be accomplished by setting the skip_validation flag to true in the KubernetesManifest props.
cluster = nil # AWSCDK::EKSv2::Cluster
AWSCDK::EKSv2::KubernetesManifest.new(self, "HelloAppWithoutValidation", {
cluster: cluster,
manifest: [{foo: "bar"}],
skip_validation: true,
})
The HelmChart construct or cluster.addHelmChart method can be used
to add Kubernetes resources to this cluster using Helm.
When using
cluster.addHelmChart, the manifest construct is defined within the cluster's stack scope. If the manifest contains attributes from a different stack which depend on the cluster stack, a circular dependency will be created and you will get a synth time error. To avoid this, directly usenew HelmChartto create the chart in the scope of the other stack.
The following example will install the NGINX Ingress Controller to your cluster using Helm.
cluster = nil # AWSCDK::EKSv2::Cluster
# option 1: use a construct
AWSCDK::EKSv2::HelmChart.new(self, "NginxIngress", {
cluster: cluster,
chart: "nginx-ingress",
repository: "https://helm.nginx.com/stable",
namespace: "kube-system",
})
# or, option2: use `addHelmChart`
cluster.add_helm_chart("NginxIngress", {
chart: "nginx-ingress",
repository: "https://helm.nginx.com/stable",
namespace: "kube-system",
})
Helm charts will be installed and updated using helm upgrade --install, where a few parameters
are being passed down (such as repo, values, version, namespace, wait, timeout, etc).
This means that if the chart is added to CDK with the same release name, it will try to update
the chart in the cluster.
Additionally, the chart_asset property can be an aws-s3-assets.Asset. This allows the use of local, private helm charts.
require 'aws-cdk-lib'
cluster = nil # AWSCDK::EKSv2::Cluster
chart_asset = AWSCDK::S3Assets::Asset.new(self, "ChartAsset", {
path: "/path/to/asset",
})
cluster.add_helm_chart("test-chart", {
chart_asset: chart_asset,
})
Nested values passed to the values parameter should be provided as a nested dictionary:
cluster = nil # AWSCDK::EKSv2::Cluster
cluster.add_helm_chart("ExternalSecretsOperator", {
chart: "external-secrets",
release: "external-secrets",
repository: "https://charts.external-secrets.io",
namespace: "external-secrets",
values: {
install_cr_ds: true,
webhook: {
port: 9443,
},
},
})
Helm chart can come with Custom Resource Definitions (CRDs) defined that by default will be installed by helm as well. However in special cases it might be needed to skip the installation of CRDs, for that the property skip_crds can be used.
cluster = nil # AWSCDK::EKSv2::Cluster
# option 1: use a construct
AWSCDK::EKSv2::HelmChart.new(self, "NginxIngress", {
cluster: cluster,
chart: "nginx-ingress",
repository: "https://helm.nginx.com/stable",
namespace: "kube-system",
skip_crds: true,
})
OCI charts are also supported.
Also replace the ${VARS} with appropriate values.
cluster = nil # AWSCDK::EKSv2::Cluster
# option 1: use a construct
AWSCDK::EKSv2::HelmChart.new(self, "MyOCIChart", {
cluster: cluster,
chart: "some-chart",
repository: "oci://${ACCOUNT_ID}.dkr.ecr.${ACCOUNT_REGION}.amazonaws.com/${REPO_NAME}",
namespace: "oci",
version: "0.0.1",
})
Helm charts are implemented as CloudFormation resources in CDK.
This means that if the chart is deleted from your code (or the stack is
deleted), the next cdk deploy will issue a helm uninstall command and the
Helm chart will be deleted.
When there is no release defined, a unique ID will be allocated for the release based
on the construct path.
By default, all Helm charts will be installed concurrently. In some cases, this
could cause race conditions where two Helm charts attempt to deploy the same
resource or if Helm charts depend on each other. You can use
chart.node.addDependency() in order to declare a dependency order between
charts:
cluster = nil # AWSCDK::EKSv2::Cluster
chart1 = cluster.add_helm_chart("MyChart", {
chart: "foo",
})
chart2 = cluster.add_helm_chart("MyChart", {
chart: "bar",
})
chart2.node.add_dependency(chart1)
You can also compose a few stock cdk8s+ constructs into your own custom construct. However, since mixing scopes between aws-cdk and cdk8s is currently not supported, the Construct class
you'll need to use is the one from the constructs module, and not from aws-cdk-lib like you normally would.
This is why we used new cdk8s.App() as the scope of the chart above.
require 'constructs'
require 'cdk8s'
require 'cdk8s-plus-25'
app = CDK8s::App.new
chart = CDK8s::Chart.new(app, "my-chart")
class LoadBalancedWebService < Constructs::Construct
def initialize(scope, id, props)
super(scope, id)
deployment = CDK8sPlus25::Deployment.new(chart, "Deployment", {
replicas: props.replicas,
containers: [CDK8sPlus25::Container.new({image: props.image})],
})
deployment.expose_via_service({
ports: [
{port: props.port},
],
service_type: CDK8sPlus25::ServiceType::LOAD_BALANCER,
})
end
end
If you find yourself unable to use cdk8s+, or just like to directly use the k8s native objects or CRD's, you can do so by manually importing them using the cdk8s-cli.
See Importing kubernetes objects for detailed instructions.
The KubernetesPatch construct can be used to update existing kubernetes
resources. The following example can be used to patch the hello-kubernetes
deployment from the example above with 5 replicas.
cluster = nil # AWSCDK::EKSv2::Cluster
AWSCDK::EKSv2::KubernetesPatch.new(self, "hello-kub-deployment-label", {
cluster: cluster,
resource_name: "deployment/hello-kubernetes",
apply_patch: {spec: {replicas: 5}},
restore_patch: {spec: {replicas: 3}},
})
The KubernetesObjectValue construct can be used to query for information about kubernetes objects,
and use that as part of your CDK application.
For example, you can fetch the address of a LoadBalancer type service:
cluster = nil # AWSCDK::EKSv2::Cluster
# query the load balancer address
my_service_address = AWSCDK::EKSv2::KubernetesObjectValue.new(self, "LoadBalancerAttribute", {
cluster: cluster,
object_type: "service",
object_name: "my-service",
json_path: ".status.loadBalancer.ingress[0].hostname",
})
# pass the address to a lambda function
proxy_function = AWSCDK::Lambda::Function.new(self, "ProxyFunction", {
handler: "index.handler",
code: AWSCDK::Lambda::Code.from_inline("my-code"),
runtime: AWSCDK::Lambda::Runtime.NODEJS_LATEST,
environment: {
my_service_address: my_service_address.value,
},
})
Specifically, since the above use-case is quite common, there is an easier way to access that information:
cluster = nil # AWSCDK::EKSv2::Cluster
load_balancer_address = cluster.get_service_load_balancer_address("my-service")
Add-ons is a software that provides supporting operational capabilities to Kubernetes applications. The EKS module supports adding add-ons to your cluster using the eks.Addon class.
cluster = nil # AWSCDK::EKSv2::Cluster
AWSCDK::EKSv2::Addon.new(self, "Addon", {
cluster: cluster,
addon_name: "coredns",
addon_version: "v1.11.4-eksbuild.2",
# whether to preserve the add-on software on your cluster but Amazon EKS stops managing any settings for the add-on.
preserve_on_delete: false,
configuration_values: {
replica_count: 2,
},
})
The EKS library allows defining Kubernetes resources such as Kubernetes manifests and Helm charts on clusters that are not defined as part of your CDK app.
First you will need to import the kubectl provider and cluster created in another stack
handler_role = AWSCDK::IAM::Role.from_role_arn(self, "HandlerRole", "arn:aws:iam::123456789012:role/lambda-role")
kubectl_provider = AWSCDK::EKSv2::KubectlProvider.from_kubectl_provider_attributes(self, "KubectlProvider", {
service_token: "arn:aws:lambda:us-east-2:123456789012:function:my-function:1",
role: handler_role,
})
cluster = AWSCDK::EKSv2::Cluster.from_cluster_attributes(self, "Cluster", {
cluster_name: "cluster",
kubectl_provider: kubectl_provider,
})
Then, you can use add_manifest or add_helm_chart to define resources inside
your Kubernetes cluster.
cluster = nil # AWSCDK::EKSv2::Cluster
cluster.add_manifest("Test", {
api_version: "v1",
kind: "ConfigMap",
metadata: {
name: "myconfigmap",
},
data: {
Key: "value",
Another: "123454",
},
})
EKS supports cluster logging for 5 different types of events:
You can enable logging for each one separately using the cluster_logging
property. For example:
cluster = AWSCDK::EKSv2::Cluster.new(self, "Cluster", {
# ...
version: AWSCDK::EKSv2::KubernetesVersion.V1_34,
cluster_logging: [
AWSCDK::EKSv2::ClusterLoggingTypes::API,
AWSCDK::EKSv2::ClusterLoggingTypes::AUTHENTICATOR,
AWSCDK::EKSv2::ClusterLoggingTypes::SCHEDULER,
],
})
You can enable Managed Node Group auto-repair config using enable_node_auto_repair
property. For example:
cluster = nil # AWSCDK::EKSv2::Cluster
cluster.add_nodegroup_capacity("NodeGroup", {
enable_node_auto_repair: true,
})