Amazon Elastic Kubernetes Service (Amazon EKS) is a managed service that you can use to run Kubernetes on AWS without needing to install, operate, and maintain your own Kubernetes control plane or nodes. Kubernetes is an open-source system for automating the deployment, scaling, and management of containerized applications.
In this article I'll help you to create a simple, default cluster without expanding into all of the available options. By using infrastructure as a code tool (IAC) HashiCorp Terraform
Prerequisites:
1- Terraform Tool: An IAC tool, use version >= 0.13.1.
2- AWS CLI: A command line tool for working with Amazon EKS.
3- kubectl
: A command line tool for working with Kubernetes clusters.
I've created the all next steps in my GitHub repo please follow the Getting started part in the readme to see how to use it.
Steps to create your first EKS cluster:
1- Create VPC and subnets that meet Amazon EKS requirements
2- Create Amazon EKS cluster with required IAM role.
3- Create Amazon EKS node group with required IAM role.
4- Run the code
5- Get into the cluster
6- Clean up
So lets start with the first step..
1-Create VPC and subnets
When you create a cluster, you specify a VPC and at least two subnets that are in different Availability Zones.
VPC requirements and considerations:
in the vpc.tf file I called the VPC module created by terraform with the required parameters to create VPC that meets the requirements of EKS cluster creation.
locals {
region = data.aws_region.current.name
}
module "vpc" {
source = "git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git?ref=v3.16.0"
name = var.vpc_name
cidr = var.vpc_cidr
azs = ["${local.region}a", "${local.region}b"]
public_subnets = cidrsubnets(var.vpc_cidr, 1, 1)
enable_dns_hostnames = true
enable_dns_support = true
map_public_ip_on_launch = true
tags = {
Name = var.vpc_name
}
public_subnet_tags = {
Name = "public subnet"
"kubernetes.io/role/elb" = "1"
"kubernetes.io/cluster/${var.cluster_name}" = "shared"
}
}
- The VPC must have a sufficient number of IP addresses available for the cluster, any nodes, and other Kubernetes resources that you want to create.
- The VPC must have DNS hostname and DNS resolution support. Otherwise, nodes can't register to your cluster.
- The VPC might require VPC endpoints using AWS PrivateLink. we need this in cases if we want to create a private cluster but for simplicity, I'll create a public cluster so there is no need for this now. However, AWS recommends creating a private cluster for the production workload.read more about public and private cluster
Subnets requirements and considerations:
- The subnets must have enough available IP addresses to deploy all of your nodes and Kubernetes resources to. AWS recommend at least 16 IP addresses.
- The subnets can be a public or private in our case will create public subnets.
- The public subnet must auto-assign IPv4 because we will deploy the nodes on it.
- If you want to deploy load balancers to a subnet, the subnet must have the following tag:
Key Value
kubernetes.io/role/elb 1
- If you use Version 2.1.1 or earlier of the AWS Load Balancer Controller requires the following tag:
Key Value
kubernetes.io/cluster/my-cluster shared
at the end of this step, we will have vpc created with 2 public subnets in a different availability zone, public route table and internet gateway.
2-Create Amazon EKS cluster with required IAM role
- Kubernetes clusters managed by Amazon EKS make calls to other AWS services on your behalf to manage the resources that you use with the service. Before you can create Amazon EKS clusters, you must create an IAM role with the following IAM policies:
"arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
"arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
- Create a default cluster (public) and specify the subnet ids to be the public subnet.
and that all in eks-cluster.tf
resource "aws_iam_role" "eksClusterRole" {
name = "eksClusterRole"
assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "eks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
POLICY
}
resource "aws_iam_role_policy_attachment" "AmazonEKSClusterPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
role = aws_iam_role.eksClusterRole.name
}
resource "aws_iam_role_policy_attachment" "AmazonEKSVPCResourceController" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
role = aws_iam_role.eksClusterRole.name
}
resource "aws_eks_cluster" "this" {
name = var.cluster_name
role_arn = aws_iam_role.eksClusterRole.arn
vpc_config {
subnet_ids = module.vpc.public_subnets
}
# Ensure that IAM Role permissions are created before and deleted after EKS Cluster handling.
# Otherwise, EKS will not be able to properly delete EKS managed EC2 infrastructure such as Security Groups.
depends_on = [
aws_iam_role_policy_attachment.AmazonEKSClusterPolicy,
aws_iam_role_policy_attachment.AmazonEKSVPCResourceController,
]
}
3- Create Amazon EKS node group with required IAM role
- The Amazon EKS node kubelet daemon makes calls to AWS APIs on your behalf. Nodes receive permissions for these API calls through an IAM instance profile and associated policies. Before you can launch nodes and register them into a cluster, you must create an IAM role for those nodes to use when they are launched,So you must create an IAM role with the following IAM policies:
"arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
"arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
- Create a node group in the public subnet and with it's configration(max, min,and desired size) and instance type.
and all that in eks-node-group.tf
resource "aws_iam_role" "eksWorkerNodeRole" {
name = "eksWorkerNodeRole"
assume_role_policy = jsonencode({
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}]
Version = "2012-10-17"
})
}
resource "aws_iam_role_policy_attachment" "AmazonEKSWorkerNodePolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
role = aws_iam_role.eksWorkerNodeRole.name
}
resource "aws_iam_role_policy_attachment" "AmazonEKS_CNI_Policy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
role = aws_iam_role.eksWorkerNodeRole.name
}
resource "aws_iam_role_policy_attachment" "AmazonEC2ContainerRegistryReadOnly" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
role = aws_iam_role.eksWorkerNodeRole.name
}
resource "aws_eks_node_group" "this" {
cluster_name = var.cluster_name
node_group_name = "${var.cluster_name}-nodeGroup"
node_role_arn = aws_iam_role.eksWorkerNodeRole.arn
subnet_ids = module.vpc.public_subnets
instance_types = var.instance_types
scaling_config {
desired_size = var.desired_size
max_size = var.max_size
min_size = var.min_size
}
update_config {
max_unavailable = 1
}
# Ensure that IAM Role permissions are created before and deleted after EKS Node Group handling.
# Otherwise, EKS will not be able to properly delete EC2 Instances and Elastic Network Interfaces.
depends_on = [
aws_eks_cluster.this,
aws_iam_role_policy_attachment.AmazonEKSWorkerNodePolicy,
aws_iam_role_policy_attachment.AmazonEKS_CNI_Policy,
aws_iam_role_policy_attachment.AmazonEC2ContainerRegistryReadOnly,
]
}
4- Run the code
git clone https://github.com/Noura98Houssien/simple-EKS-cluster.git
cd simple-EKS-cluster
create a file with name terraform.tfvars and copy past the values as in terraform.tfvars.tmpl in example folder.
vpc_name = "my-VPC1"
vpc_cidr = "10.0.0.0/16"
cluster_name = "my-EKS1"
desired_size = 2
max_size = 2
min_size = 1
instance_types = ["t3.medium"]
terraform init
terraform plan
-
terraform apply
as you can see there are 17 resource will be added. and there are some outputs will known after apply. It takes around 10 mins to create. after the creation your environment will be like that
5- Get into the cluster
- Update
kubectl
config file by using that command.
aws eks update-kubeconfig --region region-code --name my-cluster
The example output is as follows.
Added new context arn:aws:eks:region-code:111122223333:cluster/my-cluster to /home/username/.kube/config
- Confirm communication with your cluster by running the following command.
kubectl get svc
The example output is as follows.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 172.20.0.1 <none> 443/TCP 15m
- Confirm the worker nodes created successfully by running the following command.
kubectl get nodes
The example output is as follow.
NAME STATUS ROLES AGE VERSION
ip-10-0-171-51.ec2.internal Ready <none> 12m v1.23.9-eks-ba74326
ip-10-0-94-160.ec2.internal Ready <none> 12m v1.23.9-eks-ba74326
6- Clean up
- run that command to remove all resources
terraform destroy
The example output is as follows.
Plan: 0 to add, 0 to change, 17 to destroy.
summary:
In this article, we learned how to create a simple EKS cluster using Terraform, which is a powerful infrastructure as a code tool.
Hopefully, this has added new value to your knowledge.
Our next step is to deploy the application into the cluster and make it accessible through the internet. I have explained the process in detail here.
Top comments (1)
Very good post