August 7, 2024

9 Ways to Spin Up an EKS Cluster: CloudFormation

Anton Weiss

AWS Cloudformation is a robust Infrastructure-As-Code tool. It's well-supported and allows us to write templates in JSON or YAML. And it is also used behind the scenes by a number of tools in the cloud native ecosystem. For example kops. But more importantly for this post - it's used by eksctl!

In my previous post I used eksctl to spin up a cluster complete with Karpenter and a few more add-ons.

So for this post - instead of starting from scratch I decided to just reuse the stack template created by eksctl.

Yes, I could have used one of the quickstart stacks provided by AWS but this repo has so many options that I got lost reading the docs.

So instead I just opted to export the template from the existing stack. That's the cheating part :)

This article is part of series "How to Spin Up an AWS Cluster".

Take a look at the different methods:

Way 1 - Create an EKS Cluster in AWS Management Console

Way 2 - Create an EKS Cluster in AWS cli

Way 3 - Create an EKS Cluster with eksctl

Way 4 - Create an EKS Cluster with CloudFormation

Way 5 - Create an EKS Cluster with python and boto3

Way 6 - Create an EKS Cluster with AWS CDK

Way 7 - Create an EKS Cluster with Terraform

Way 8 - Create an EKS Cluster with Pulumi

Way 9 - Create an EKS Cluster with Crossplane

Exporting the CloudFormation template

But how does one export a CloudFormation template from eksctl? As I found out - this was requested repeatedly, but never implemented. See here for example.
So instead I went to the CloudFormation console in AWS, clicked on the stacks the I wanted (the ones eksctl generated) and went to the 'Template' tab.

Image description
Exporting the CloudFormation template

But as you can notice - this only gives us JSON. Now I'm a YAML engineer, so I wanted yaml. For which I clicked on 'View in Application Composer' - and when there - 'Template' and switched the toggle to 'YAML'. Voila - I can now copy the template text and continue editing it on my laptop.

Image description
Exporting the CloudFormation template

In its basic form eksctl creates 2 stacks:

  • one for the EKS control plane
  • another one for the managed nodegroup

I could've bundled both stacks into one file but this separation actually makes a lot of sense. We may want more than one node group in our EKS, or we may decide to let go of node groups and opt to manage nodes with Karpenter. (You should!)

So I created 2 template files - eks.yaml (for the control plane) and ng.yaml (for the node group).
I've edited them both so they have no hard-coded resource names. Everything is based on the stack name you chose.

Second stack receives the name of the first stack as a parameter and uses some of its exports like this:


# the parameter:
Parameters:
  ClusterStack:
    Description: Name of the ClusterStack
    Type: String
    Default: eks-way4
# and the reference:
SecurityGroupIds:
          - Fn::ImportValue: !Sub '${ClusterStack}::ClusterSecurityGroupI


I'm also defining SSH access to the nodes with an imported SSH key.
You could of course skip the whole SSH stuff, but I tend to believe it's important - especially when bringing up clusters for learning purposes.

Spinning Up EKS iwth CloudFormation

Here's how to use this:

1. Clone the example repo:

git clone https://github.com/antweiss/9-ways-2-EKS.git

2. Change into the cloudformation folder:

cd 9-ways-2-EKS/way-4-cloudformation

3. Generate an ssh key:

ssh-keygen  -f ./id_rsa -N '' -C eks-way4

4. Insert the public key into the node group template: I'm saving the original file with bak extension.

sed -ibak "s/SSH_KEY/$(cat id_rsa.pub)/g" ng.yaml

The result should look something like (ng.yaml line 15):


ImportedKeyPair:
    Type: AWS::EC2::KeyPair
    Properties:
      KeyName: !Ref AWS::StackName
     # this was PublicKeyMaterial: SSH_KEY
      PublicKeyMaterial: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMgmzvgvz7NEN

5. And finally run the deploy.sh script with 2 parameters - the desired name of the cluster and the AWS region:


./deploy.sh eks-way4 eu-central-1

Inside the script this is translated into the following 2 CFN (cloudformation) invocations:


aws cloudformation create-stack --stack-name $1 \
                                --region $2 \
                                --template-body file://eks.yaml \
                                --capabilities CAPABILITY_NAMED_IAM
aws cloudformation create-stack --stack-name $1-ng \
                                --parameters ParameterKey=ClusterStack,ParameterValue=$1 \
                                --region $2 \
                                --template-body file://ng.yaml \
                                --capabilities CAPABILITY_NAMED_IAM

Things to note here: the necessary capability CAPABILITY_NAMED_IAM
and the parameter named ClusterStack that I'm passing to the second stack.

After a short while we can verify the state of our stacks:


aws cloudformation list-stacks --stack-status-filter CREATE_COMPLETE --region eu-central-1 --max-items=2 --query "StackSummaries[*].StackName"

If this returns the names of our 2 stacks:


[
    "eks-way4-ng",
    "eks-way4"
]


then we're great! If not - proceed to the CloudFormation UI in AWS console to find the reasons why your stack creation failed.

Summary

CloudFormation is a great IaC tool if you're fine with AWS vendor-lock. It's definitely possible to create an EKS cluster with CloudFormation and that's what such tools as kops and eksctl do under the hood.
While writing CloudFormation from scratch is no fun - we can use the templates generated by eksctl - as I did. Or we can build the templates ourselves in the AWS Application Composer. But then we need to take into the account everything necessary for the cluster operation - security groups, gateways, routing rules, IAM policies. And that's a lot to take care of.

Are you using pure CloudFormation as your IaC tool?

PerfectScale Lettermark

Reduce your cloud bill and improve application performance today

Install in minutes and instantly receive actionable intelligence.
Subscribe to our newsletter
In part 4 of our series 9 Ways Spin Up an AWS Cluster, we show you how create an EKS Cluster with CloudFormation
This is some text inside of a div block.
This is some text inside of a div block.

About the author

This is some text inside of a div block.
more from this author
By clicking “Accept”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.