DEV Community

Cover image for 9 Ways to Spin Up an EKS Cluster - Way 4 - CloudFormation
Ant(on) Weiss for AWS Community Builders

Posted on • Updated on • Originally published at perfectscale.io

9 Ways to Spin Up an EKS Cluster - Way 4 - CloudFormation

I cheated for this one! Read on to see how:

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 :)

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

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

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}::ClusterSecurityGroupId'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  1. Change into the cloudformation folder:
cd 9-ways-2-EKS/way-4-cloudformation
Enter fullscreen mode Exit fullscreen mode
  1. Generate an ssh key:
ssh-keygen  -f ./id_rsa -N '' -C eks-way4
Enter fullscreen mode Exit fullscreen mode
  1. 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
Enter fullscreen mode Exit fullscreen mode

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 AAAAC3NzaC1lZDI1NTE5AAAAIMgmzvgvz7NENY5X25QFLFlMHVCp7U98ykm1s3+JYftI eks-way4
Enter fullscreen mode Exit fullscreen mode
  1. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

If this returns the names of our 2 stacks:

[
    "eks-way4-ng",
    "eks-way4"
]
Enter fullscreen mode Exit fullscreen mode

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?

Top comments (0)