Introduction: Building Your First EKS Cluster

In the previous lesson, you prepared your environment by installing the aws, kubectl, and eksctl command-line tools. Now, you'll use those tools to create your first EKS cluster. This is the foundational step for the rest of the course, as you need a running cluster before you can deploy any applications.

By the end of this lesson, you'll have a fully functional, two-node Kubernetes cluster running on AWS. You will define the cluster's configuration in a YAML file, create it with a single eksctl command, connect to it with kubectl, verify its status, and finally, learn how to delete it to avoid extra costs. We use a configuration file because it provides a clear, reproducible, and versionable specification for your infrastructure, which is far more reliable than typing a long series of command-line flags.

Understanding the Cluster Configuration

A cluster configuration file is a structured document that describes exactly what you want your EKS cluster to look like. We use YAML format because it's human-readable and widely used in the Kubernetes ecosystem. YAML uses indentation to show structure, similar to how Python uses indentation, and it's designed to be easy to read and write by hand.

The configuration file has two main sections that work together to define your cluster. The first section contains metadata about the cluster itself, such as its name, which AWS region it should run in, and which version of Kubernetes to use. The second section describes your node groups, which are the worker nodes where your containers will actually run. Each section serves a distinct purpose, and eksctl uses both sections to create all the necessary AWS resources.

When you run eksctl create cluster with a configuration file, it doesn't just create a Kubernetes cluster. Behind the scenes, it creates a complete AWS infrastructure: a VPC with public and private subnets, security groups that control network access, IAM roles with appropriate permissions, the EKS control plane, and EC2 instances configured as Kubernetes worker nodes. All of these resources are created and configured to work together seamlessly. This is why using eksctl is so much easier than trying to set everything up manually with the aws CLI.

Breaking Down the Cluster Specification

Let's look at a complete cluster configuration file and understand each part. Here's the configuration you'll use to create your first cluster:

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: dev-eks-cluster
  region: us-east-1
  version: "1.29"

managedNodeGroups:
  - name: ng-1
    desiredCapacity: 2
    minSize: 2
    maxSize: 2
    instanceTypes: ["t3.small"]
    amiFamily: AmazonLinux2
    iam:
      withAddonPolicies:
        imageBuilder: false
        albIngress: false
        cloudWatch: true
        ebs: true
        efs: false
        fsx: false
        xRay: false
    tags:
      purpose: learning

# Note: eksctl attaches AmazonEC2ContainerRegistryReadOnly to nodes,
# allowing pulls from private ECR in the same account/region.
# eksctl also creates public subnets by default, enabling internet access
# for pulling images. In production with private subnets, you'd need
# NAT gateways or VPC endpoints for ECR.

This file declaratively defines every important aspect of your cluster. Let's examine the key components of this configuration.

  • apiVersion and kind: These fields tell eksctl that this is a ClusterConfig file and which version of the configuration schema to use. This is a standard pattern in Kubernetes configuration.
  • metadata: This section defines the cluster's core identity. It includes the name (dev-eks-cluster), the AWS region (us-east-1), and the Kubernetes version ("1.29"). The version is quoted to ensure it is passed as a string literal to the API, avoiding potential floating-point precision issues and ensuring the schema validation receives the exact version string expected.
  • managedNodeGroups: This section defines your worker nodes. "Managed" means AWS handles patching and maintenance of the underlying EC2 instances.
  • Capacity Settings: desiredCapacity, minSize, and maxSize are all set to 2. This creates a fixed-size node group with two worker nodes, which is simple and predictable for learning.
  • Instance Configuration: instanceTypes specifies the EC2 instance size (t3.small), which is cost-effective for this course. amiFamily sets the operating system to AmazonLinux2, which is optimized for EKS.
  • IAM Add-on Policies: The iam section grants worker nodes specific permissions to interact with other AWS services. We enable cloudWatch for logging and ebs for persistent storage, which are common requirements for real applications.

By defining these settings in one file, you create a single source of truth for your cluster's architecture. The comment at the bottom highlights that eksctl automatically adds permissions for nodes to pull images from Amazon ECR and creates public subnets by default, which provides the internet connectivity needed for pulling container images.

Creating the Cluster with eksctl

Now that you understand the configuration file, let's create the cluster. Save the configuration shown above to a file named cluster.yaml. Then run the following command:

eksctl create cluster -f cluster.yaml

The -f flag tells eksctl to read the configuration from a file. The creation process takes 20 to 30 minutes because eksctl is provisioning a significant amount of infrastructure on your behalf. Here's a breakdown of the critical actions eksctl performs:

  • CloudFormation Stacks: It creates AWS CloudFormation stacks to manage all resources as a single unit. This ensures that creation and deletion are atomic and reliable.
  • VPC and Networking: It builds a new, production-ready Virtual Private Cloud (VPC) with public and private subnets across multiple availability zones for high availability.
  • EKS Control Plane: It provisions the highly available Kubernetes control plane, which is managed by AWS. This is the "brain" of your cluster.
  • Worker Nodes: It creates a separate CloudFormation stack for the managed node group, launching and configuring the EC2 instances to securely connect to the control plane.

This automation is the primary benefit of eksctl, as it handles dozens of complex steps that would be tedious and error-prone to perform manually. The output you'll see looks something like this:

2026-01-15 10:23:45 [ℹ]  eksctl version 0.156.0
2026-01-15 10:23:45 [ℹ]  using region us-east-1
2026-01-15 10:23:46 [ℹ]  setting availability zones to [us-east-1a us-east-1b]
2026-01-15 10:23:46 [ℹ]  subnets for us-east-1a - public:192.168.0.0/19 private:192.168.64.0/19
2026-01-15 10:23:46 [ℹ]  subnets for us-east-1b - public:192.168.32.0/19 private:192.168.96.0/19
2026-01-15 10:23:46 [ℹ]  using Kubernetes version 1.29
2026-01-15 10:23:46 [ℹ]  creating EKS cluster "dev-eks-cluster" in "us-east-1" region with managed nodes
2026-01-15 10:23:46 [ℹ]  will create 2 separate CloudFormation stacks for cluster itself and the initial managed nodegroup
2026-01-15 10:23:46 [ℹ]  if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=us-east-1 --cluster=dev-eks-cluster'
2026-01-15 10:23:46 [ℹ]  Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "dev-eks-cluster" in "us-east-1"
2026-01-15 10:23:46 [ℹ]  CloudWatch logging will not be enabled for cluster "dev-eks-cluster" in "us-east-1"
2026-01-15 10:23:46 [ℹ]  you can enable it with 'eksctl utils update-cluster-logging --enable-types={SPECIFY-YOUR-LOG-TYPES-HERE (e.g. all)} --region=us-east-1 --cluster=dev-eks-cluster'
2026-01-15 10:23:46 [ℹ]  
2 sequential tasks: { create cluster control plane "dev-eks-cluster", 
    2 sequential sub-tasks: { 
        wait for control plane to become ready,
        create managed nodegroup "ng-1",
    } 
}
2026-01-15 10:23:46 [ℹ]  building cluster stack "eksctl-dev-eks-cluster-cluster"
2026-01-15 10:23:47 [ℹ]  deploying stack "eksctl-dev-eks-cluster-cluster"
2026-01-15 10:24:17 [ℹ]  waiting for CloudFormation stack "eksctl-dev-eks-cluster-cluster"
...
2026-01-15 10:38:52 [ℹ]  waiting for CloudFormation stack "eksctl-dev-eks-cluster-nodegroup-ng-1"
2026-01-15 10:39:23 [ℹ]  waiting for the control plane to become ready
2026-01-15 10:39:23 [✔]  saved kubeconfig as "/home/user/.kube/config"
2026-01-15 10:39:23 [ℹ]  no tasks
2026-01-15 10:39:23 [✔]  all EKS cluster resources for "dev-eks-cluster" have been created
2026-01-15 10:39:24 [ℹ]  nodegroup "ng-1" has 2 node(s)
2026-01-15 10:39:24 [ℹ]  node "ip-192-168-18-234.ec2.internal" is ready
2026-01-15 10:39:24 [ℹ]  node "ip-192-168-45-123.ec2.internal" is ready
2026-01-15 10:39:24 [ℹ]  waiting for at least 2 node(s) to become ready in "ng-1"
2026-01-15 10:39:24 [ℹ]  nodegroup "ng-1" has 2 node(s)
2026-01-15 10:39:24 [ℹ]  node "ip-192-168-18-234.ec2.internal" is ready
2026-01-15 10:39:24 [ℹ]  node "ip-192-168-45-123.ec2.internal" is ready
2026-01-15 10:39:24 [✔]  EKS cluster "dev-eks-cluster" in "us-east-1" region is ready

This output shows each step of the process. You can see when the control plane is being created, when it becomes ready, when the node group is being created, and finally when the nodes join the cluster and become ready. The checkmarks indicate successful completion of each major step. While you're waiting for the cluster to be created, you can open the AWS console and watch the CloudFormation stacks being created, or you can check the EKS console to see your cluster appearing.

Connecting kubectl to Your Cluster

Once your cluster is created, you need to configure kubectl so it knows how to connect to it. kubectl uses a configuration file (called kubeconfig), typically located at ~/.kube/config, that contains connection details for your clusters.

When eksctl creates your cluster, it automatically updates your kubeconfig file, which is why you saw the message "saved kubeconfig" in the output above. However, if you're working on a different machine or if the kubeconfig wasn't updated for some reason, you can manually update it using the AWS CLI:

aws eks update-kubeconfig --name dev-eks-cluster --region us-east-1

This command retrieves the connection information for your cluster from AWS and adds it to your kubeconfig file. The "context" it creates is a combination of cluster, user, and namespace information that tells kubectl where to send commands. The kubeconfig file itself contains several key pieces of information to enable this secure connection.

  • API Server Endpoint: The URL where kubectl sends requests to the Kubernetes control plane.
  • Authentication Credentials: Information that proves you are authorized to access the cluster. For EKS, this typically involves using the AWS IAM Authenticator.
  • Certificate Authority Data: The certificate kubectl uses to verify it's talking to the real cluster and not a malicious imposter.

All of this information is managed automatically by eksctl and the aws CLI, so you don't need to worry about the details.

Verifying Everything Works

Now that your cluster is created and kubectl is configured, let's verify everything is working correctly. The first thing to check is whether your worker nodes are running and ready. Run the following command:

kubectl get nodes

This command asks the Kubernetes control plane to list all the nodes in your cluster. You should see output similar to this:

NAME                             STATUS   ROLES    AGE     VERSION
ip-192-168-18-234.ec2.internal   Ready    <none>   5m32s   v1.29.0-eks-5e0fdde
ip-192-168-45-123.ec2.internal   Ready    <none>   5m28s   v1.29.0-eks-5e0fdde

This output shows you have two nodes, both with a status of "Ready," which means they're healthy and ready to run containers. If you see both nodes with "Ready" status, your cluster is working correctly.

Next, let's check the namespaces in your cluster. Namespaces are a way to divide cluster resources between multiple users or applications. Run this command:

kubectl get ns

The ns is a shorthand for namespaces. You should see the default namespaces that Kubernetes creates automatically, each with a specific purpose.

  • default: The namespace where your applications will run if you don't specify another one.
  • kube-system: Contains Kubernetes system components like the DNS service and other critical add-ons.
  • kube-public: Readable by all users and typically used for cluster information that should be publicly accessible.
  • kube-node-lease: Used for node heartbeat data that helps the control plane detect node failures quickly.

If you see these namespaces and your nodes are ready, congratulations! You have a fully functional, production-grade Kubernetes cluster running on AWS.

Cleaning Up Your Cluster

When you're done experimenting, it's important to delete your cluster to avoid unnecessary AWS charges for the EKS control plane and EC2 worker nodes. Deleting an EKS cluster with eksctl is straightforward. Run the following command:

eksctl delete cluster --name dev-eks-cluster --region us-east-1

This command tells eksctl to delete the cluster and all associated resources, including any AWS load balancers created by Kubernetes. The deletion process takes about 10 to 15 minutes as eksctl carefully tears down the CloudFormation stacks in the correct order.

The output will show the progress of deletion:

2026-01-15 11:45:23 [ℹ]  deleting EKS cluster "dev-eks-cluster"
2026-01-15 11:45:24 [ℹ]  will drain 0 unmanaged nodegroup(s) in cluster "dev-eks-cluster"
2026-01-15 11:45:24 [ℹ]  starting parallel draining, max in-flight of 1
2026-01-15 11:45:25 [ℹ]  deleted 0 Fargate profile(s)
2026-01-15 11:45:26 [✔]  kubeconfig has been updated
2026-01-15 11:45:26 [ℹ]  cleaning up AWS load balancers created by Kubernetes objects of Kind Service or Ingress
2026-01-15 11:45:29 [ℹ]  
2 sequential tasks: { delete nodegroup "ng-1", delete cluster control plane "dev-eks-cluster" [async] 
}
2026-01-15 11:45:29 [ℹ]  will delete stack "eksctl-dev-eks-cluster-nodegroup-ng-1"
2026-01-15 11:45:29 [ℹ]  waiting for stack "eksctl-dev-eks-cluster-nodegroup-ng-1" to get deleted
...
2026-01-15 11:58:45 [ℹ]  will delete stack "eksctl-dev-eks-cluster-cluster"
2026-01-15 11:58:45 [✔]  all cluster resources were deleted

Using eksctl for deletion is crucial because it ensures a clean teardown. If you were to delete resources manually from the AWS console, you might leave behind orphaned resources like load balancers or security groups that would continue to incur charges.

Summary: What You've Accomplished

In this lesson, you created your first Amazon EKS cluster from scratch. You defined your cluster declaratively using a YAML configuration file and used eksctl to provision all the necessary AWS infrastructure automatically. You then configured kubectl to communicate with your new cluster, verified that the nodes were ready, and inspected the default namespaces. Finally, you learned the command to safely delete the cluster and all its resources to prevent unwanted costs.

The cluster you built is not just a toy—it's a real, production-grade Kubernetes cluster with the same architecture used to run large-scale applications. The skills you've developed here are directly applicable to managing production workloads.

Before practice: The practice exercises in this unit focus on understanding and configuring cluster YAML files. You can optionally create a real cluster using eksctl create cluster -f cluster.yaml if you want hands-on experience with the full creation process, but be aware that cluster creation takes 20-30 minutes. In the practices, we'll focus on reading, understanding, and modifying cluster configurations rather than executing the actual cluster creation commands.

In the next lesson, you'll build on this foundation by deploying your first containerized application to the cluster.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal