Create Amazon EKS Cluster from scratch using eksctl.

Pankaj Thapliyal (Server Geek)
5 min readSep 20, 2022

Before we start learning how to build an EKS cluster, let us first understand what is k8s?

Kubernetes, also known as k8s, is an open-source container orchestration system to run microservice applications on a cluster of hosts. The k8s system automates the software deployment, scaling, and management of cloud-native applications using on-premises infrastructure or public cloud platforms. It distributes application workloads across a k8s cluster and automates dynamic container networking needs. Kubernetes also allocates storage and persistent volumes to running containers, provides automatic scaling, and works continuously to maintain the desired state of applications, providing resiliency.

Let's install some prerequisites.

  1. First You have to launch one ec2 machine in your AWS account which we will use as the launchpad for the EKS cluster. We are using Amazon Linux 2 here.
  2. Install kubectl in your launchpad machine so that Kubernetes Client can communicate with the Kubernetes API Server.

curl -o kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.23.7/2022-06-29/bin/linux/amd64/kubectl
chmod +x ./kubectl
mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/bin
After Install check the version
kubectl version — short — client

3. Install eksctl in your launchpad machine. It’s the official Amazon EKS CLI, used to create and manage multiple EKS Clusters.

curl — silent — location “https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz” | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
eksctl version

4. Install AWS CLI in the launchpad machine. it’s required to access the AWS service through the cli.

curl “https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o “awscliv2.zip”
unzip awscliv2.zip
sudo ./aws/install
To confirm the installed version
aws — version

Now create your first EKS cluster

First, create an IAM role and attach the below custom policy.

Note: Do not assign administrator full access policy to the IAM role

  1. AmazonEC2FullAccess (AWS Managed Policy)
    {
    “Version”: “2012–10–17”,
    “Statement”: [
    {
    “Action”: “ec2:*”,
    “Effect”: “Allow”,
    “Resource”: “*”
    },
    {
    “Effect”: “Allow”,
    “Action”: “elasticloadbalancing:*”,
    “Resource”: “*”
    },
    {
    “Effect”: “Allow”,
    “Action”: “cloudwatch:*”,
    “Resource”: “*”
    },
    {
    “Effect”: “Allow”,
    “Action”: “autoscaling:*”,
    “Resource”: “*”
    },
    {
    “Effect”: “Allow”,
    “Action”: “iam:CreateServiceLinkedRole”,
    “Resource”: “*”,
    “Condition”: {
    “StringEquals”: {
    “iam:AWSServiceName”: [
    “autoscaling.amazonaws.com”,
    “ec2scheduled.amazonaws.com”,
    “elasticloadbalancing.amazonaws.com”,
    “spot.amazonaws.com”,
    “spotfleet.amazonaws.com”,
    “transitgateway.amazonaws.com”
    ]
    }
    }
    }
    ]
    }
  2. AWSCloudFormationFullAccess (AWS Managed Policy)
    {
    “Version”: “2012–10–17”,
    “Statement”: [
    {
    “Effect”: “Allow”,
    “Action”: [
    “cloudformation:*”
    ],
    “Resource”: “*”
    }
    ]
    }
  3. EksAllAccess
    {
    “Version”: “2012–10–17”,
    “Statement”: [
    {
    “Effect”: “Allow”,
    “Action”: “eks:*”,
    “Resource”: “*”
    },
    {
    “Action”: [
    “ssm:GetParameter”,
    “ssm:GetParameters”
    ],
    “Resource”: [
    “arn:aws:ssm:*:<account_id>:parameter/aws/*”,
    “arn:aws:ssm:*::parameter/aws/*”
    ],
    “Effect”: “Allow”
    },
    {
    “Action”: [
    “kms:CreateGrant”,
    “kms:DescribeKey”
    ],
    “Resource”: “*”,
    “Effect”: “Allow”
    },
    {
    “Action”: [
    “logs:PutRetentionPolicy”
    ],
    “Resource”: “*”,
    “Effect”: “Allow”
    }
    ]
    }
  4. IamLimitedAccess
    {
    “Version”: “2012–10–17”,
    “Statement”: [
    {
    “Effect”: “Allow”,
    “Action”: [
    “iam:CreateInstanceProfile”,
    “iam:DeleteInstanceProfile”,
    “iam:GetInstanceProfile”,
    “iam:RemoveRoleFromInstanceProfile”,
    “iam:GetRole”,
    “iam:CreateRole”,
    “iam:DeleteRole”,
    “iam:AttachRolePolicy”,
    “iam:PutRolePolicy”,
    “iam:ListInstanceProfiles”,
    “iam:AddRoleToInstanceProfile”,
    “iam:ListInstanceProfilesForRole”,
    “iam:PassRole”,
    “iam:DetachRolePolicy”,
    “iam:DeleteRolePolicy”,
    “iam:GetRolePolicy”,
    “iam:GetOpenIDConnectProvider”,
    “iam:CreateOpenIDConnectProvider”,
    “iam:DeleteOpenIDConnectProvider”,
    “iam:TagOpenIDConnectProvider”,
    “iam:ListAttachedRolePolicies”,
    “iam:TagRole”,
    “iam:GetPolicy”,
    “iam:CreatePolicy”,
    “iam:DeletePolicy”,
    “iam:ListPolicyVersions”
    ],
    “Resource”: [
    “arn:aws:iam::<account_id>:instance-profile/eksctl-*”,
    “arn:aws:iam::<account_id>:role/eksctl-*”,
    “arn:aws:iam::<account_id>:policy/eksctl-*”,
    “arn:aws:iam::<account_id>:oidc-provider/*”,
    “arn:aws:iam::<account_id>:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup”,
    “arn:aws:iam::<account_id>:role/eksctl-managed-*”
    ]
    },
    {
    “Effect”: “Allow”,
    “Action”: [
    “iam:GetRole”
    ],
    “Resource”: [
    “arn:aws:iam::<account_id>:role/*”
    ]
    },
    {
    “Effect”: “Allow”,
    “Action”: [
    “iam:CreateServiceLinkedRole”
    ],
    “Resource”: “*”,
    “Condition”: {
    “StringEquals”: {
    “iam:AWSServiceName”: [
    “eks.amazonaws.com”,
    “eks-nodegroup.amazonaws.com”,
    “eks-fargate.amazonaws.com”
    ]
    }
    }
    }
    ]
    }

Once you have created the IAM role and linked the policy to the role, assign this role to your eks launchpad ec2 machine.

Now login to launchpad machine to create dev-cluster.yaml file to launch eks cluster.

e.g dev-cluster.yaml

— -
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: My-First-Cluster
region: us-east-1
version: ‘1.23’
privateCluster:
enabled: false
iam:
vpcResourceControllerPolicy: true
withOIDC: false
################################################Autoscaling clusters###########################################################
nodeGroups:
- name: On-demand-app-ng1
instanceType: t3.xlarge
volumeSize: 40
volumeType: gp3
minSize: 4
maxSize: 8
desiredCapacity: 4
privateNetworking: true
labels: {role: worker-node}
iam:
attachPolicyARNs:
— arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
— arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
— arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess
— arn:aws:iam::aws:policy/AmazonS3FullAccess #you can create policy specfic for bucket created
withAddonPolicies:
autoScaler: true
ebs: true
externalDNS: true
albIngress: true
xRay: true
imageBuilder: true
cloudWatch: true
ssh:
allow: true
publicKeyName: ‘demo-cluster’
tags:
k8s.io/cluster-autoscaler/enabled: ‘true’
availabilityZones: [‘us-east-1a’, ‘us-east-1b’, ‘us-east-1c’, ‘us-east-1d’]
vpc:
id: “vpc-075a63507f2a578e7” # This is the id of your VPC in AWS.
subnets: # In this section, include all the subnets of your AWS VPC. Follow the example format below.
private: # Private subnet details. Add an entry for each region of your VPC.
us-east-1a: { id: subnet-0e3a478421e235fc2 } # Change to be the subnet region and subnet id.
us-east-1b: { id: subnet-04019ba1467e7f3c9 } # Change to be the subnet region and subnet id.
us-east-1c: { id: subnet-043bbca9ac7acb074 } # Change to be the subnet region and subnet id.
us-east-1d: { id: subnet-0d05c652b989c63dc } # Change to be the subnet region and subnet id.
public: # Public subnet details. Add an entry for each region of your VPC.
us-east-1a: { id: subnet-096138922cffa5906 } # Change to be the subnet region and subnet id.
us-east-1b: { id: subnet-0ee35eebd0b001843 } # Change to be the subnet region and subnet id.
us-east-1c: { id: subnet-0732ac66b08939a5b } # Change to be the subnet region and subnet id.

Now run the command with dry run it will help you identify any errors on the config files or related to your permission

eksctl create cluster -f dev-cluster.yaml — dry-run

Once the dry run is successful without any error run the command to launch the eks cluster

eksctl create cluster -f dev-cluster.yaml

It will take a few minutes for CloudFormation Stack to launch on your account. After successfully deploying the EKS cluster you can check the node group you have created.

kubectl get node

To clean the EKS cluster Setup

if you want to delete the cluster then run the below command

eksctl delete cluster dev-cluster.yaml

To install the autoscaler & ingress controller follows the below link.

--

--