AWS CDK (Python) How to Create EKS Cluster

In my previous post, I have discussed about how to create vpc, subnets, internet gateway, nat gateway using AWS CDK(Python). In this post, we will be discussing about how to create EKS (k8s) cluster. This is requested by many of my followers, so I would like to write a blog to help the community.

Create a new stack called EKSStack and use existing vpc from other stack (vpc: ec2.Vpc)

class EKSStack(core.Stack):

    def __init__(self, scope: core.Construct, construct_id: str, vpc: ec2.Vpc, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

Create an IAM role for worker groups and kubernetes RBAC configuration

eks_role = iam.Role(self, "eksadmin", assumed_by=iam.ServicePrincipal(service='ec2.amazonaws.com'),
                            role_name='eks-cluster-role', managed_policies=
                            [iam.ManagedPolicy.from_aws_managed_policy_name(managed_policy_name='AdministratorAccess')])
        eks_instance_profile = iam.CfnInstanceProfile(self, 'instanceprofile',
                                                      roles=[eks_role.role_name],
                                                      instance_profile_name='eks-cluster-role')

Once the role is created, let us create EKS Cluster and attach the role as masters_role.

 cluster = eks.Cluster(self, 'prod', cluster_name='eks-demo-cluster',
                              version=eks.KubernetesVersion.V1_19,
                              vpc=vpc,
                              vpc_subnets=[ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE)],
                              default_capacity=0,
                              masters_role=eks_role)

In the above code, you can see that I’m using version 1.9, cluster will use private subnets and the IAM role that was created will be used. I used default_capacity = 0 since, I do not want EKS to create default node group. I will be creating node groups separately and will use SPOT instances for worker nodes in this case. This is all about control plane definition.

Now, let us create node group.

nodegroup = cluster.add_nodegroup_capacity('eks-nodegroup',
                                                   instance_types=[ec2.InstanceType('t3.large'),
                                                                   ec2.InstanceType('m5.large'),
                                                                   ec2.InstanceType('c5.large')],
                                                   disk_size=50,
                                                   min_size=2,
                                                   max_size=2,
                                                   desired_size=2,
                                                   subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE),
                                                   remote_access=eks.NodegroupRemoteAccess(
                                                       ssh_key_name='eks-ssh-keypair'),
                                                   capacity_type=eks.CapacityType.SPOT)

I’ve used multiple instance types for SPOT for different worker nodes. Disk size for the nodes to set to 50GB and two nodes will be created. you can adjust these parameters based on your requirement.

Now, let’s call the stack.

from mycdkproject.eks_stack import EKSStack
app = core.App()
vpc_stack = VPCStack(app, "mycdkproject")
eks_stack = EKSStack(app,'eks',vpc=vpc_stack.vpc)
app.synth()

you need to update requirements.txt file to import modules for iam and eks. you can install these modules using pip install -r requirements.txt


aws-cdk.aws-iam
aws-cdk.aws-eks

now, let’s run cdk ls to see howmany stacks we can see. we should expect to see two stacks.

Now, let’s Synthesize an AWS CloudFormation template for the app, as follows.

(.venv) C:\Rama\MyProjects\mycdkproject>cdk synth
Successfully synthesized to C:\Rama\MyProjects\mycdkproject\cdk.out
Supply a stack id (mycdkproject, eks) to display its template.

Now, let’s deploy

cdk deploy eks --profile cdkprofile

if you have encountered an error as eks failed: Error: This stack uses assets, so the toolkit stack must be deployed to the environment (Run “cdk bootstrap aws://unknown-account/unknown-region”)

you can fix this by running cdk bootstrap aws://accountnumber/region

(.venv) C:\Rama\MyProjects\mycdkproject>cdk deploy eks --profile cdkprofile
Including dependency stacks: mycdkproject
mycdkproject
mycdkproject: deploying...

 ✅  mycdkproject (no changes)

Outputs:
mycdkproject.ExportsOutputRefdemovpcF2DCF540F486AA93 = vpc-0a28afc429ef12e7d
mycdkproject.ExportsOutputRefdemovpcPrivateSubnetSubnet1Subnet7F4868328AE74887 = subnet-01d19280e1eca62f5
mycdkproject.ExportsOutputRefdemovpcPrivateSubnetSubnet2Subnet4FD8659B8BB1175E = subnet-05cedf7ea3c9a2d1a

Stack ARN:
arn:aws:cloudformation:eu-west-1:604035856224:stack/mycdkproject/ced8f3a0-7791-11eb-8a02-02fbd2f362b9
eks
eks: deploying...
[0%] start: Publishing 50e10880d134a01b440991fc77d217f39f01c2d56945215ee9a3b81187c6f3b1:current
[14%] success: Published 50e10880d134a01b440991fc77d217f39f01c2d56945215ee9a3b81187c6f3b1:current
[14%] start: Publishing c691172cdeefa2c91b5a2907f9d81118e47597634943344795f1a844192dd49c:current
[28%] success: Published c691172cdeefa2c91b5a2907f9d81118e47597634943344795f1a844192dd49c:current
[28%] start: Publishing 299e5262386e9f084fcd72906b8282f5c3cb1885c39d0912db1670b472873fb5:current
[42%] success: Published 299e5262386e9f084fcd72906b8282f5c3cb1885c39d0912db1670b472873fb5:current
[42%] start: Publishing e9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68:current
[57%] success: Published e9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68:current
[57%] start: Publishing 844c1a4b13479b359ea0e607dccb4a04b73e22cf88cf9b64feed2c5f0de213c0:current
[71%] success: Published 844c1a4b13479b359ea0e607dccb4a04b73e22cf88cf9b64feed2c5f0de213c0:current
[71%] start: Publishing 7f9c09e9e3ebb8ac17932545378ebfc732075bc1529c3f5294d1220ab938c1a8:current
[85%] success: Published 7f9c09e9e3ebb8ac17932545378ebfc732075bc1529c3f5294d1220ab938c1a8:current
[85%] start: Publishing 53fdcf13d33580b64d5d493f823aa68fa304539df464fedc629ad48b949244ad:current
[100%] success: Published 53fdcf13d33580b64d5d493f823aa68fa304539df464fedc629ad48b949244ad:current
eks: creating CloudFormation changeset...
  0/15 | 12:50:35 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack            | eks User Initiated
  0/15 | 12:50:40 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack            | eks User Initiated
  0/15 | 12:51:09 PM | CREATE_IN_PROGRESS   | AWS::EC2::SecurityGroup               | prod/ControlPlaneSecurityGroup (prodControlPlaneSecurityGroup7CE46782)
  0/15 | 12:51:09 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | eksadmin (eksadminBEE25D8E)
  0/15 | 12:51:09 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | prod/Resource/CreationRole (prodCreationRole5E247585)
  0/15 | 12:51:09 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                    | @aws-cdk--aws-eks.ClusterResourceProvider/CDKMetadata/Default (CDKMetadata)
  0/15 | 12:51:09 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | prod/Role (prodRoleD997707D)
  0/15 | 12:51:09 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | prod/Nodegroupeks-nodegroup/NodeGroupRole (prodNodegroupeksnodegroupNodeGroupRoleB635EB43)
  0/15 | 12:51:09 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | prod/Resource/CreationRole (prodCreationRole5E247585) Resource creation Initiated
  0/15 | 12:51:09 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | prod/Role (prodRoleD997707D) Resource creation Initiated
  0/15 | 12:51:09 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | prod/Nodegroupeks-nodegroup/NodeGroupRole (prodNodegroupeksnodegroupNodeGroupRoleB635EB43)
Resource creation Initiated
  0/15 | 12:51:10 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | eksadmin (eksadminBEE25D8E) Resource creation Initiated
  2/15 | 12:51:11 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                    | @aws-cdk--aws-eks.ClusterResourceProvider/CDKMetadata/Default (CDKMetadata) Resource creati
on Initiated
  2/15 | 12:51:12 PM | CREATE_COMPLETE      | AWS::CDK::Metadata                    | @aws-cdk--aws-eks.ClusterResourceProvider/CDKMetadata/Default (CDKMetadata)
  2/15 | 12:51:13 PM | CREATE_IN_PROGRESS   | AWS::EC2::SecurityGroup               | prod/ControlPlaneSecurityGroup (prodControlPlaneSecurityGroup7CE46782) Resource creation In
itiated
  2/15 | 12:51:15 PM | CREATE_COMPLETE      | AWS::EC2::SecurityGroup               | prod/ControlPlaneSecurityGroup (prodControlPlaneSecurityGroup7CE46782)
  6/15 | 12:51:26 PM | CREATE_COMPLETE      | AWS::IAM::Role                        | prod/Resource/CreationRole (prodCreationRole5E247585)
  6/15 | 12:51:26 PM | CREATE_COMPLETE      | AWS::IAM::Role                        | prod/Role (prodRoleD997707D)
  6/15 | 12:51:27 PM | CREATE_COMPLETE      | AWS::IAM::Role                        | prod/Nodegroupeks-nodegroup/NodeGroupRole (prodNodegroupeksnodegroupNodeGroupRoleB635EB43)
  6/15 | 12:51:27 PM | CREATE_COMPLETE      | AWS::IAM::Role                        | eksadmin (eksadminBEE25D8E)
  6/15 | 12:51:30 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack            | @aws-cdk--aws-eks.ClusterResourceProvider.NestedStack/@aws-cdk--aws-eks.ClusterResourceProv
ider.NestedStackResource (awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454) 
  6/15 | 12:51:30 PM | CREATE_IN_PROGRESS   | AWS::IAM::InstanceProfile             | instanceprofile
  6/15 | 12:51:31 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy                      | prod/Resource/CreationRole/DefaultPolicy (prodCreationRoleDefaultPolicy46633E70)
  6/15 | 12:51:31 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack            | @aws-cdk--aws-eks.ClusterResourceProvider.NestedStack/@aws-cdk--aws-eks.ClusterResourceProv
ider.NestedStackResource (awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454) Resource creation Initiated
  6/15 | 12:51:31 PM | CREATE_IN_PROGRESS   | AWS::IAM::InstanceProfile             | instanceprofile Resource creation Initiated
  6/15 | 12:51:32 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy                      | prod/Resource/CreationRole/DefaultPolicy (prodCreationRoleDefaultPolicy46633E70) Resource c
reation Initiated
  7/15 | 12:51:48 PM | CREATE_COMPLETE      | AWS::IAM::Policy                      | prod/Resource/CreationRole/DefaultPolicy (prodCreationRoleDefaultPolicy46633E70)
 7/15 Currently in progress: eks, awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454, instanceprofile
  8/15 | 12:53:32 PM | CREATE_COMPLETE      | AWS::IAM::InstanceProfile             | instanceprofile
 8/15 Currently in progress: eks, awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454
  9/15 | 12:54:09 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack            | @aws-cdk--aws-eks.ClusterResourceProvider.NestedStack/@aws-cdk--aws-eks.ClusterResourceProv
ider.NestedStackResource (awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454) 
  9/15 | 12:54:13 PM | CREATE_IN_PROGRESS   | Custom::AWSCDK-EKS-Cluster            | prod/Resource/Resource/Default (prod3363F4D9)
 9/15 Currently in progress: eks, prod3363F4D9
 10/15 | 1:07:36 PM | CREATE_IN_PROGRESS   | Custom::AWSCDK-EKS-Cluster            | prod/Resource/Resource/Default (prod3363F4D9) Resource creation Initiated
 10/15 | 1:07:37 PM | CREATE_COMPLETE      | Custom::AWSCDK-EKS-Cluster            | prod/Resource/Resource/Default (prod3363F4D9)
 11/15 | 1:07:41 PM | CREATE_IN_PROGRESS   | AWS::SSM::Parameter                   | prod/KubectlReadyBarrier (prodKubectlReadyBarrier3183289D)
 11/15 | 1:07:41 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack            | @aws-cdk--aws-eks.KubectlProvider.NestedStack/@aws-cdk--aws-eks.KubectlProvider.NestedStackR
esource (awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B) 
 11/15 | 1:07:42 PM | CREATE_IN_PROGRESS   | AWS::EKS::Nodegroup                   | prod/Nodegroupeks-nodegroup (prodNodegroupeksnodegroupE8147B13)
 11/15 | 1:07:42 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack            | @aws-cdk--aws-eks.KubectlProvider.NestedStack/@aws-cdk--aws-eks.KubectlProvider.NestedStackR
esource (awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B) Resource creation Initiated
 11/15 | 1:07:42 PM | CREATE_IN_PROGRESS   | AWS::SSM::Parameter                   | prod/KubectlReadyBarrier (prodKubectlReadyBarrier3183289D) Resource creation Initiated
 11/15 | 1:07:43 PM | CREATE_COMPLETE      | AWS::SSM::Parameter                   | prod/KubectlReadyBarrier (prodKubectlReadyBarrier3183289D)
 11/15 | 1:07:46 PM | CREATE_IN_PROGRESS   | AWS::EKS::Nodegroup                   | prod/Nodegroupeks-nodegroup (prodNodegroupeksnodegroupE8147B13) Resource creation Initiated
11/15 Currently in progress: eks, awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B, prodNodegroupeksnodegroupE8147B13
 12/15 | 1:10:13 PM | CREATE_COMPLETE      | AWS::EKS::Nodegroup                   | prod/Nodegroupeks-nodegroup (prodNodegroupeksnodegroupE8147B13)
12/15 Currently in progress: eks, awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B
 13/15 | 1:12:57 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack            | @aws-cdk--aws-eks.KubectlProvider.NestedStack/@aws-cdk--aws-eks.KubectlProvider.NestedStackR
esource (awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B) 
 13/15 | 1:13:02 PM | CREATE_IN_PROGRESS   | Custom::AWSCDK-EKS-KubernetesResource | prod/AwsAuth/manifest/Resource/Default (prodAwsAuthmanifest0B7F1A5F)
 15/15 | 1:13:10 PM | CREATE_IN_PROGRESS   | Custom::AWSCDK-EKS-KubernetesResource | prod/AwsAuth/manifest/Resource/Default (prodAwsAuthmanifest0B7F1A5F) Resource creation Initi
ated
 15/15 | 1:13:10 PM | CREATE_COMPLETE      | Custom::AWSCDK-EKS-KubernetesResource | prod/AwsAuth/manifest/Resource/Default (prodAwsAuthmanifest0B7F1A5F)
 15/15 | 1:13:13 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack            | eks

 ✅  eks

Outputs:
eks.prodConfigCommand1B086551 = aws eks update-kubeconfig --name eks-cluster-demo --region eu-west-1 --role-arn arn:aws:iam::accountnumber:role/eks-cluster-role
eks.prodGetTokenCommand0CE8FF77 = aws eks get-token --cluster-name eks-cluster-demo --region eu-west-1 --role-arn arn:aws:iam::accountnumber:role/eks-cluster-role

Stack ARN:
arn:aws:cloudformation:eu-west-1:accountnumber:stack/eks/57cd8dd0-779a-11eb-9605-06cacdbbe755

That’s it. You can see that EKS cluster has been setup using AWS CDK (Python). You can find the EKSStack on my github repository here.

Hope you enjoyed the post.

Cheers

Ramasankar Molleti

LinkedIn

Published by Ramasankar

As a Principal Cloud Architect with over 18 years of experience, I am dedicated to revolutionizing IT landscapes through cutting-edge cloud solutions. My expertise spans Cloud Architecture, Security Architecture, Solution Design, Cloud Migration, Database Transformation, Development, and Big Data Analytics.Currently, I spearhead cloud initiatives with a focus on Infrastructure, Containerization, Security, Big Data, Machine Learning, and Artificial Intelligence. I collaborate closely with development teams to architect, build, and manage robust cloud ecosystems that drive business growth and technological advancement.Core Competencies: • Cloud Platforms: AWS, Google Cloud Platform, Microsoft Azure • Technologies: Kubernetes, Serverless Computing, Microservices • Databases: MS SQL Server, PostgreSQL, Oracle, MongoDB, Amazon Redshift, DynamoDB, Aurora • Industries: Finance, Retail, Manufacturing. Throughout my career, I’ve had the privilege of working with industry leaders such as OCC, Gate Gourmet, Walgreens, and Johnson Controls, gaining invaluable insights across diverse sectors.As a lifelong learner and knowledge sharer, I take pride in being the first in my organization to complete all major AWS certifications. I am passionate about mentoring and guiding fellow professionals in their cloud journey, fostering a culture of continuous learning and innovation.Let’s connect and explore how we can leverage cloud technologies to transform your business: • LinkedIn: https://www.linkedin.com/in/ramasankar-molleti-23b13218/ • Book a mentorship session: [1:1] Together, let’s architect the future of cloud computing and drive technological excellence. Disclaimer The views expressed on this website/blog are mine alone and do not reflect the views of my company. All postings on this blog are provided “AS IS” with no warranties, and confers no rights. The owner of https://ramasankarmolleti.com will not be liable for any errors or omissions in this information nor for the availability of this information. The owner will not be liable for any losses, injuries, or damages from the display or use of this information.

Leave a comment