2.1. Automation: Deploying Your Infrastructure with AWS CloudFormation (Template Deep Dive)

Kubernetes on AWS: Automating Your Infrastructure with CloudFormation (Template Deep Dive)
Okay, you've decided to dive into Kubernetes on AWS. Great choice! But setting up all the necessary infrastructure - VPCs, subnets, security groups, EC2 instances, etc. - can be a daunting task. Doing it manually is time-consuming and prone to errors. That's where automation comes to the rescue.
And when it comes to automating infrastructure on AWS, CloudFormation is your best friend.
Think of CloudFormation as a recipe book for your infrastructure. You write a recipe (the template), give it to AWS, and CloudFormation magically cooks up all the ingredients (the resources) and assembles them according to your instructions.
In this post, we'll deep dive into a CloudFormation template example specifically tailored for deploying the foundational infrastructure needed for a Kubernetes cluster on AWS.
What is CloudFormation?
CloudFormation is an Infrastructure as Code (IaC) service provided by AWS. It allows you to define your infrastructure in a declarative way using a template file. This template describes the desired state of your infrastructure, and CloudFormation provisions and manages the resources accordingly.
Why Use CloudFormation for Kubernetes?
Repeatability: Deploy the same infrastructure consistently across different environments (dev, staging, production).
Consistency: Eliminate configuration drift and ensure all resources are set up correctly.
Version Control: Treat your infrastructure as code, track changes, and revert to previous configurations.
Efficiency: Automate the entire deployment process, saving time and effort.
Deep Dive: A Basic Kubernetes CloudFormation Template
Let's look at a simplified example of a CloudFormation template. While a complete Kubernetes deployment would be much more complex, this template will give you a good understanding of the basics. We'll focus on creating a simple VPC, subnets, and an internet gateway.
AWSTemplateFormatVersion: '2010-09-09'
Description: A basic CloudFormation template for a VPC, Subnets, and an Internet Gateway
Parameters:
VpcCIDR:
Type: String
Description: CIDR block for the VPC
Default: 10.0.0.0/16
PublicSubnet1CIDR:
Type: String
Description: CIDR block for the Public Subnet 1
Default: 10.0.1.0/24
PublicSubnet2CIDR:
Type: String
Description: CIDR block for the Public Subnet 2
Default: 10.0.2.0/24
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCIDR
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
Tags:
- Key: Name
Value: MyKubernetesVPC
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: !Ref PublicSubnet1CIDR
MapPublicIpOnLaunch: 'true' # Important for nodes to get public IPs
AvailabilityZone: !Select [ 0, !GetAZs '' ] # Automatically gets the first AZ in the region
Tags:
- Key: Name
Value: MyKubernetesPublicSubnet1
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: !Ref PublicSubnet2CIDR
MapPublicIpOnLaunch: 'true' # Important for nodes to get public IPs
AvailabilityZone: !Select [ 1, !GetAZs '' ] # Automatically gets the second AZ in the region
Tags:
- Key: Name
Value: MyKubernetesPublicSubnet2
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: MyKubernetesInternetGateway
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MyVPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyVPC
Tags:
- Key: Name
Value: MyKubernetesPublicRouteTable
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0 # Route all traffic
GatewayId: !Ref InternetGateway
Subnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
Subnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
Outputs:
VPCId:
Description: The ID of the VPC
Value: !Ref MyVPC
Export:
Name: !Sub "${AWS::StackName}-VPCId"
PublicSubnet1Id:
Description: The ID of the Public Subnet 1
Value: !Ref PublicSubnet1
Export:
Name: !Sub "${AWS::StackName}-PublicSubnet1Id"
PublicSubnet2Id:
Description: The ID of the Public Subnet 2
Value: !Ref PublicSubnet2
Export:
Name: !Sub "${AWS::StackName}-PublicSubnet2Id"
Breaking Down the Template:
AWSTemplateFormatVersion: Specifies the version of the CloudFormation template format.Description: A brief description of what the template does.Parameters: Allows you to customize the template by providing values when you create the stack. Think of these as customizable ingredients in your recipe. Here, we define parameters for the VPC CIDR block and subnet CIDR blocks.Resources: This is the heart of the template. It defines the AWS resources you want to create. Each resource has aType(e.g.,AWS::EC2::VPCfor a VPC,AWS::EC2::Subnetfor a subnet) andProperties(e.g.,CidrBlockfor the VPC,VpcIdfor the subnet).!Ref: This intrinsic function refers to the logical ID of another resource. For example,!Ref MyVPCrefers to the VPC resource defined earlier. It's like saying "add a cup of the VPC you just made" in your recipe.!GetAZs '': Gets a list of Availability Zones in the current region.!Select [ 0, ... ]: Selects an item from a list. In this case, it selects the first and second Availability Zone for the subnets.
Outputs: Defines values that are returned after the stack is created. These values can be used by other CloudFormation templates or applications. TheExportsection is crucial for cross-stack referencing, allowing other stacks (like your Kubernetes cluster stack) to use resources created in this stack.
Real-World Example: Building a Kubernetes Control Plane
This basic VPC template forms the foundation for your Kubernetes cluster. You can then create another CloudFormation template to deploy the Kubernetes control plane (master nodes) within this VPC and these subnets. This second template would import the VPC and Subnet IDs using the Outputs section of the first template, referencing them in the Properties of the EC2 instances that will act as your Kubernetes masters.
Challenge: Hardcoding Availability Zones
One challenge is hardcoding Availability Zones (AZs). What if you want to deploy to a different region where the AZs are different?
Solution: Dynamic AZ Selection
Instead of hardcoding the AZs, use the !GetAZs intrinsic function and !Select to dynamically select them:
AvailabilityZone: !Select [ 0, !GetAZs '' ] # Selects the first AZ in the region
This ensures your template will work in any region without modification.
Architectural Diagram:
+-----------------------+
| CloudFormation |
| (Template) |
+-----------------------+
|
| (Creates/Updates)
V
+-----------------------+ +-----------------------+
| AWS VPC |---| AWS Subnets |
| (MyKubernetesVPC) | | (PublicSubnet1, 2) |
+-----------------------+ +-----------------------+
| | ^ ^
| | | |
+------------------>-------+-------+
|
V
+-----------------------+
| Internet Gateway |
| (MyKubernetesInternetGateway)|
+-----------------------+
Key Takeaways:
CloudFormation automates infrastructure provisioning on AWS.
Templates define the desired state of your infrastructure.
Resources,Parameters, andOutputsare key sections of a CloudFormation template.CloudFormation allows you to build reusable and scalable infrastructure for your Kubernetes deployments.
By using CloudFormation, you can significantly simplify the process of deploying and managing your Kubernetes clusters on AWS. Start with small, modular templates and gradually build up to more complex deployments. Happy automating!




