RMIT University

COSC2767 · Systems Deployment and Operations

Week 11: Elastic Kubernetes Service (EKS) on AWS Lab Guide

Create and manage Kubernetes workloads in AWS using EKS, eksctl, kubectl, and the course cloud environment.

🎯 Objective

Week tutorial screenshot from page 1

In this lab, we will learn about the concepts and tools needed for creating and working with an Amazon EKS cluster.

Screenshot illustrating EKS cluster.

The above diagram provides a conceptual overview of how EKS works. It's crucial to understand the two main parts:

  • EKS Control Plane (in EKS VPC) : This is the "brain" of your Kubernetes cluster. It's fully managed by AWS in a separate, secure AWS-managed Virtual Private Cloud (VPC). You don't have direct access to these master nodes, but you interact with them via the Kubernetes API. This is the core value of EKS – AWS handles the complexity, availability, and scaling of the control plane for you.

  • Customer VPC: This is your VPC where your applications run.

    • EC2 Worker Nodes: These are the EC2 instances that you launch and manage (or have EKS manage for you). Your application containers (pods) will run on these nodes. They are grouped into an Autoscaling group to automatically scale the number of nodes up or down based on workload.

    • ENI (Elastic Network Interface): The control plane communicates with your worker nodes through these network interfaces that are placed in your VPC's subnets. This is the secure bridge between the AWS-managed VPC and your VPC.

    • Load Balancer: When you want to expose your application to the internet, Kubernetes works with AWS to automatically provision a Load Balancer. This directs external traffic from clients to the correct worker nodes running your application.

    • kubectl : This is the command-line tool you will use on your local machine or a bastion host (a dedicated management server) to send commands to the EKS Control Plane's API server.

☁️ Amazon EKS lab overview

Screenshot illustrating Instructions for EKS on AWS

For this session, we will learn how to set up a basic Elastic Kubernetes Service (EKS) on AWS. EKS is a managed container service to run and scale Kubernetes applications in the cloud or on-premises.

Getting started with Amazon EKS is easy:

Screenshot illustrating Getting started with Amazon EKS is easy:
  1. Create an Amazon EKS cluster in the AWS Management Console.

  2. Launch managed or self-managed Amazon EC2 nodes.

  3. When your cluster is ready, you can configure your favorite Kubernetes tools, such as kubectl, to communicate with your cluster.

  4. Deploy and manage workloads on your Amazon EKS cluster the same way that you would with any other Kubernetes environment. You can also view information about your workloads using the AWS Management Console.

Alright! Let's get started!

1. Understand the LabRole IAM role

  • The AWS learner lab does mention that we need to use the IAM role “LabRole” to manage/control EKS.

Screenshot illustrating manage/control EKS.

[Explanation] It suggests that Amazon EKS in this lab environment has the permissions necessary to function via the LabRole IAM role. This is the constraint of this specific learner lab environment. Both the EKS control plane and the worker nodes need permissions to interact with other AWS services. For example, the control plane needs to create Load Balancers, and worker nodes need to pull container images from ECR (Elastic Container Registry). The LabRole is an identity with a set of permissions that EKS will "assume" to perform these actions on your behalf. The screenshots confirm that in this specific lab environment, EKS is configured to use this role.

  • Let's find more information about this special IAM role “LabRole”:

Screenshot illustrating Let's find more information about this special IAM role “LabRole”: (1 of 2)Screenshot illustrating Let's find more information about this special IAM role “LabRole”: (2 of 2)
  • If you look closely at all permissions of LabRole, you can see the permission to access EKS services:

Screenshot illustrating services:

[Explanation] As you can see that, our special LabRole got these very special permission policies which are AWS managed IAM policies that grant necessary permissions for operating Amazon Elastic Kubernetes Service (EKS) clusters:

  • AmazonEKSClusterPolicy: This policy is attached to the Cluster IAM role. It grants the EKS control plane permissions to manage AWS resources required by the cluster, such as creating Elastic Load Balancers (ELBs) and managing network interfaces (ENIs).

  • AmazonEKSWorkerNodePolicy: This policy is attached to the Node IAM role (the role for the EC2 worker nodes). It grants the worker nodes the necessary permissions to connect to the EKS control plane and perform actions like fetching container images.

You need two distinct sets of permissions: one for the cluster's brain (control plane) and one for its muscles (worker nodes). In this lab, the LabRole conveniently has both.

That's good enough for this IAM role “LabRole” to create an EKS cluster now!

2. Prepare the EKS management instance

Now, let's create an EKS cluster!

  • You can check out the Elastic Kubernetes Service (EKS) dashboard here:

Screenshot illustrating You can check out the Elastic Kubernetes Service (EKS) dashboard here:
  • Click “Add cluster” ➜ Create to create a new EKS cluster!

Screenshot illustrating Click “Add cluster” ➜ Create to create a new EKS cluster!
  • Let’s create a cluster with following information:

    • Choose Custom configuration:

      • Turn off the EKS Auto Mode.

    • Name cluster: devops-eks-cluster.

    • Cluster service role: LabRole.

    • VPC: your default VPC.

    • Subnets:

      • us-east-1a

      • us-east-1b

      • us-east-1c

    • Let’s select our cluster endpoint access to be public!

    • Other settings: leave their default values.

  • Turn off EKS Auto Mode: This is because the LabRole lacks the specific permissions for this feature.

Screenshot illustrating feature.
  • Cluster IAM role: You are selecting the LabRole you investigated earlier. This tells EKS which permissions it can use to manage AWS resources.

Screenshot illustrating permissions it can use to manage AWS resources.
Screenshot illustrating permissions it can use to manage AWS resources.
  • Subnets : Selecting subnets across three different Availability Zones (us-east-1a, us-east-1b, us-east-1c) is a best practice for high availability. If one data center (AZ) has an issue, your cluster's control plane remains operational in the other two:

Screenshot illustrating cluster's control plane remains operational in the other two:

[Explanation] Choosing the right subnets for your Amazon EKS cluster is crucial for security, performance, and cost management. Here are some best practices to consider when selecting subnets for your EKS cluster:

  • Use Multiple Availability Zones: Deploy your EKS cluster across multiple Availability Zones (AZs) by selecting a subnet in each desired AZ. This ensures high availability and fault tolerance. If one zone goes down, your cluster can continue operating in the other zones.

  • For the purpose of learning: we would like to keep it simple by selecting three zones us-east-1a, us-east-1b, and us-east-1c which are usually available for the AWS Learner Lab.

  • Please create a security group in EC2 as following:

Screenshot illustrating Please create a security group in EC2 as following:
  • Select that security group for our Kubernetes cluster:

Screenshot illustrating Select that security group for our Kubernetes cluster:
  • Cluster endpoint access: The "Public" option is selected. This means the Kubernetes API server endpoint is accessible from the internet. This is necessary so you can run kubectl commands from your management instance. There are also "Private" options for higher security scenarios where the API is only accessible from within the VPC.

Screenshot illustrating where the API is only accessible from within the VPC.
  • Creation Process: The note correctly states that cluster creation takes time (around 15-20 minutes). This is because AWS is provisioning a highly available, multi-node control plane in the background.

    • This process of creating an EKS cluster will take around 20 minute s to complete to please wait around for it to finish!

Screenshot illustrating please wait around for it to finish!
  • Meanwhile, you can try to complete other things first by adding the access to the cluster!

    • While the cluster is being created, you can configure who has access to it. This is a great time-saving tip.

Screenshot illustrating time-saving tip.
  • This step is about mapping an AWS identity (the LabRole) to a Kubernetes identity.

    • IAM principal ARN: You are telling EKS, "Any user or process that assumes the LabRole should be allowed to interact with this cluster's API."

    • Username - Optional: The note "Leave it be!" is good advice. If you leave this blank, EKS automatically maps the IAM role to a username within Kubernetes. This is the standard and recommended practice.

    • This process is part of EKS's native integration with IAM, which simplifies authentication compared to older methods that required managing a ConfigMap manually.

Screenshot illustrating compared to older methods that required managing a ConfigMap manually.
  • After telling EKS who can access the cluster (the LabRole), this step defines what they can do. These are pre-defined EKS access policies that correspond to standard Kubernetes RBAC (Role-Based Access Control) roles:

    • AmazonEKSClusterAdminPolicy : This is the highest level of permission, equivalent to cluster-admin in Kubernetes. It grants full control over all resources in the cluster.

    • AmazonEKSAdminPolicy , AmazonEKSEditPolicy , AmazonEKSViewPolicy : These provide progressively fewer permissions, useful for assigning roles with the principle of least privilege.

By adding these, you are granting the LabRole the ability to act as a full administrator of the Kubernetes cluster.

Screenshot illustrating cluster.
  • After that, you can confirm these four roles have been associated with our LabRole to be able to manage our EKS cluster properly. When managing an EKS cluster, these roles and policies help delineate responsibility and control access to the cluster's resources:

Screenshot illustrating delineate responsibility and control access to the cluster's resources:
  • This is a verification step. It should show that the LabRole now has an access entry and is associated with the four policies you just added. You can also see other default entries, like the one for the AWSServiceRoleForAmazonEKS, which is used by EKS internally. This confirms that your permissions are set up correctly before you proceed.

Screenshot illustrating your permissions are set up correctly before you proceed.
  • To be able to proceed to the next step, you need to wait for this cluster to be created first (it could take up to 20 minutes)!

Screenshot illustrating could take up to 20 minutes)!
Screenshot illustrating could take up to 20 minutes)!
  • Therefore, please wait until the status of our cluster to be “Active”!

    • This is a simple but important milestone. It means the EKS control plane is fully provisioned and ready to accept commands. However, the cluster is not yet useful because it has no worker nodes to run any applications. This page serves as a transition to the next logical step: creating the node group.

Screenshot illustrating to the next logical step: creating the node group.
  • Next, we need to create a worker node group so our cluster can control later on!

    • Compute Tab : This is where you manage the compute resources (the worker nodes) for your cluster.

    • Add node group: This starts the wizard to create a group of EC2 instances that will register themselves with your EKS control plane.

Screenshot illustrating register themselves with your EKS control plane.
  • Please create a worker node group with configurations as below screenshots:

    • Node group name: A descriptive name like devops-workers-group is chosen.

    • Node IAM role : You are again selecting LabRole. This is the role the EC2 instances themselves will assume to get the permissions defined in the AmazonEKSWorkerNodePolicy (e.g., to communicate with the control plane).

Screenshot illustrating AmazonEKSWorkerNodePolicy (e.g., to communicate with the control plane).
  • This section defines the properties of the EC2 instances in your node group:

    • AMI type: Amazon Linux 2023 is selected. This is an EKS-optimized Amazon Machine Image that comes pre-configured with necessary software like the container runtime (containerd) and the kubelet.

    • Capacity type : On-Demand is chosen, which means you pay a fixed hourly rate for the instances. The alternative is Spot, which can be much cheaper but instances can be terminated with short notice.

    • Instance types: t3.medium is selected. This defines the vCPU, memory, and network capacity of your worker nodes.

    • Disk size: 20 GiB is allocated for the root volume of each EC2 instance.

Screenshot illustrating Disk size: 20 GiB is allocated for the root volume of each EC2 instance.
  • These settings below allow you to define the scaling parameters for a group of worker nodes within the cluster:

    • Desired size : This is the number of worker nodes you want in the node group at the outset. The system will aim to maintain this number of nodes as the desired state. In the screenshot, it's set to 2 nodes.

    • Minimum size : This is the lowest number of nodes that the group can scale down to. This ensures that there is a minimum level of resources available for workloads at all times. Here, it's also set to 2 nodes, meaning scaling down below this number is not allowed.

    • Maximum size : This sets the upper limit of nodes that the group can scale up to. It's a ceiling for the scaling operation to ensure that the cluster doesn't grow beyond a manageable size or incur unexpected costs. The maximum size here is set to 2 nodes, indicating that the group should not scale up beyond this point.

    • The configuration is such that the node group is set to operate with exactly 2 nodes at all times, as the desired, minimum, and maximum sizes are all the same. This kind of configuration might be used in scenarios where predictable performance is needed, and the workload does not have significant fluctuations that would require scaling the number of nodes up or down.

  • Note : The most important part is the explanation of the scaling parameters. Here, Desired, Minimum, and Maximum size are all set to 2. This creates a fixed-size node group that will always have exactly two worker nodes. It will not scale up or down. This is simple for a lab but in a production environment, you would typically set min lower and max higher to allow for autoscaling.

Screenshot illustrating autoscaling.
  • [Explanation] These settings below allow us to manage the node group as a set of EC2 instances that are registered as nodes in a Kubernetes cluster managed by Amazon EKS:

    • Subnets: You are selecting the subnets where the worker nodes will be launched. These should be the same subnets you chose for the cluster control plane ENIs to ensure they can communicate.

    • Configure remote access to nodes: This is enabled to allow SSH access.

    • EC2 Key Pair: A key pair (devops_key) is selected. This is essential for being able to SSH into the worker nodes for troubleshooting.

    • Allow remote access from: Set to "All". As mentioned before, this is insecure for production but acceptable for a temporary lab.

Screenshot illustrating production but acceptable for a temporary lab. (1 of 2)Screenshot illustrating production but acceptable for a temporary lab. (2 of 2)
  • After that, you should be done with worker node setup! It’s time to wait some more for it to be created!

    • When you create a node group, EKS uses an Auto Scaling Group to launch the requested number of EC2 instances.

Screenshot illustrating number of EC2 instances.
  • The cool thing is that you can go to the EC2 dashboard and see two EC2 instances are created as worker nodes in our EKS cluster! Nice!

    • The image confirms that the worker nodes have been created, have successfully registered with the EKS control plane, and are ready to accept workloads.

Screenshot illustrating registered with the EKS control plane, and are ready to accept workloads.
  • After some time, the worker node group is created with the status “Ready” for all of the worker nodes!

Screenshot illustrating nodes!

2a. Create the EC2 management instance

  • Let's create an EC2 instance which contains AWS CLI (to control AWS services), eksctl (to create EKS clusters) and kubectl (to control the cluster):

In this experiment, we only need one single EC2 instance:

Screenshot illustrating In this experiment, we only need one single EC2 instance:
  • Here are the settings of the EC2:

    • Name: eksctl_kubectl_server

    • OS: Amazon Linux 2023 AMI (Latest one)

    • Instance Type: t3.micro (Free-tier)

    • Key pair: create a new key or reuse the old key.

    • Storage: Default 8 GB is plenty enough!

    • Security Group:

      • Optional Name: eksctl_kubectl_server_security_group

      • Source Type: Anywhere

      • Open only one port:

        • 22 for SSH

2b. Attach the LabRole IAM role

  • Let’s wait for the EC2 instance state to be “Running” first. After that, let's attach the IAM role “LabRole" to this EC2 instance so this EC2 can execute commands as “LabRole”:

    • Why attach a role?

      • By attaching the LabRole (or in this case, a similar LabInstanceProfile) to the EC2 instance, you grant the AWS CLI running on that instance the permissions of that role.

      • This means you don't need to configure static AWS access keys (aws configure). The instance automatically retrieves temporary credentials, which is a much more secure practice.

      • Now, any aws or eksctl command you run from this instance will be authenticated as the LabRole, which has the necessary permissions to interact with your EKS cluster.

Screenshot illustrating with your EKS cluster.
Screenshot illustrating with your EKS cluster.
Screenshot illustrating with your EKS cluster.

2c. Set the EC2 hostname

  • After the EC2 instance is running, please SSH to that EC2 instance “eksctl_kubectl_server” you just created:

Screenshot illustrating just created:
  • Also, please change the hostname of this instance to “eksctl-kubectl-server” to keep it organized like so:

sudo nano /etc/hostname
Screenshot illustrating sudo nano /etc/hostname
  • Reboot the EC2 instance so the new hostname is updated:

sudo reboot
Screenshot illustrating sudo reboot
  • To keep things simple without dealing with permission, let’s login as a root user and change our current directory to /root:

sudo su -

2d. Verify the AWS CLI

  • We can check the current version of AWS CLI:

aws --version
Screenshot illustrating aws --version

So the default version of AWS CLI is 2.17.18 which is good enough to meet the requirement to use eksctl which requires AWS CLI version >= 2.2.37. Nice!!!

2e. Install kubectl

  • Let’s install kubectl which is the standard, open-source command-line tool for any Kubernetes cluster. It's used for deploying applications, inspecting resources, and managing the cluster's state.

  • Next, let's install kubectl so please refer to this documentation:

  • At this point of writing, the latest version of kubectl is 1.31 so let's install it!

  • Download the kubectl binary for your cluster's Kubernetes version from Amazon S3:

curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.31.2/2024-11-15/bin/linux/amd64/kubectl
  • Apply execute permissions to the binary:

chmod +x ./kubectl
  • Copy the binary to a folder in your PATH.

mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/bin
  • Add the $HOME/bin path to your shell initialization file so that it is configured when you open a shell.

echo 'export PATH=$PATH:$HOME/bin' >> ~/.bashrc
  • After you install kubectl, you can verify its version with the following command:

kubectl version --client
Screenshot illustrating kubectl version --client

2f. Install eksctl

  • Let’s install eksctl which is a popular open-source tool sponsored by AWS that simplifies many EKS-specific tasks. While you created the cluster through the console, eksctl is excellent for creating clusters, node groups, and other resources from the command line.

  • Next, let's install eksctl so please refer to this documentation:

  • Download and extract the latest release of eksctl with the following command.

curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
  • Move the extracted binary to /usr/local/bin.

sudo mv /tmp/eksctl /usr/local/bin
  • Test that your installation was successful with the following command.

eksctl version
Screenshot illustrating eksctl version

3. Connect kubectl to the EKS cluster

  • Alright, now we are ready to connect an EKS cluster!

  • But first, we need to figure out what is our current Availability Zone of our EC2 instance:

Screenshot illustrating But first, we need to figure out what is our current Availability Zone of our EC2 instance:
Screenshot illustrating But first, we need to figure out what is our current Availability Zone of our EC2 instance:

So it is clear we are currently in the zone “us-east-1" of US East (North Virginia)!

  • The template command to connect an existing EKS cluster is:

aws eks update-kubeconfig --name <cluster-name> --region <zone-name>

We need to change “cluster-name” to be the name of our cluster created before, “region-name” to be the name of the region we want to create our cluster.

  • Let's run this aws eks update-kubeconfig command to connect an EKS cluster:

aws eks update-kubeconfig --name devops-eks-cluster --region us-east-1
Screenshot illustrating aws eks update-kubeconfig --name devops-eks-cluster --region us-east-1
  • The file “/root/.kube/config” is very important. Whoever got that file will have the permission to control our EKS cluster! Let's check out the config file of our EKS cluster to learn more about this file:

    • The screenshot shows that the server URL and the certificate-authority-data in the file are the same as what's displayed in the AWS EKS console.

    • This confirms that your management instance is now fully configured to communicate with your EKS cluster.

cat /root/.kube/config
Screenshot illustrating cat /root/.kube/config
Screenshot illustrating cat /root/.kube/config

4. Deploy and manage workloads on EKS

4a. Inspect the EKS cluster

  • Let's display info of nodes in our cluster:

    • The kubectl get nodes command is the "hello world" of cluster management. Seeing your two nodes with a Ready status is the final confirmation that your cluster is fully operational.

kubectl get nodes
Screenshot illustrating kubectl get nodes

We can see these two of our EC2 worker nodes are ready to listen to our command!

  • Using the kubectl get all command we can list down all the pods, services:

kubectl get all
Screenshot illustrating kubectl get all

Initially, there is no other service yet!

  • Install git and clone the Github voting application repo:

yum install git -y
git clone https://github.com/TomHuynhSG/Simple-Voting-Application-Docker
Screenshot illustrating yum install git -y git clone https://github.com/TomHuynhSG/Simple-Voting-Application-Docker
  • Change the current directory to be inside k8s-specifications folder where all of our k8s yaml files are located:

cd Simple-Voting-Application-Docker/aws-eks-example/k8s-specifications/
Screenshot illustrating cd Simple-Voting-Application-Docker/aws-eks-example/k8s-specifications/
  • Run these K8s yaml files to create deployments and services to launch the voting application:

    • The series of kubectl create -f <filename>.yaml commands is the core of deploying an application. Each command reads a YAML file and tells the Kubernetes API to create the resources defined within it (Deployments, Services, etc.). The explanation correctly breaks down the purpose of each component: a frontend (voting-app), a backend database (postgres), a cache (redis), a processor (worker-app), and a results viewer (result-app).

kubectl create -f voting-app-deploy.yaml
kubectl create -f voting-app-service.yaml
kubectl create -f redis-deploy.yaml
kubectl create -f redis-service.yaml
kubectl create -f postgres-deploy.yaml
kubectl create -f postgres-service.yaml
kubectl create -f worker-app-deploy.yaml
kubectl create -f result-app-deploy.yaml
kubectl create -f result-app-service.yaml
Screenshot illustrating kubectl create -f voting-app-deploy.yaml kubectl create -f voting-app-service.yaml kubectl create -f redis-deploy.yaml kubectl create -f redis-service.yaml kubectl create

[Alternative] Instead of running each yaml file, you can also keep it simple by running “kubectl create -f .”

[Explanation] Each command uses a .yaml file to create different resources within the Kubernetes cluster:

  • kubectl create -f voting-app-service.yaml & kubectl create -f voting-app-deploy.yaml : These commands launch the front-end part of the voting application. The voting-app-service.yaml defines the service that exposes the voting app to the users through a web interface. The voting-app-deploy.yaml defines a deployment, which manages the creation and scaling of the voting app pods.

  • kubectl create -f redis-deploy.yaml & kubectl create -f redis-service.yaml : These commands are for deploying Redis, an in-memory data store used as a database, cache, and message broker. The redis-deploy.yaml creates the deployment for the Redis containers, while redis-service.yaml exposes Redis to the other components of the application that require it.

  • kubectl create -f postgres-deploy.yaml & kubectl create -f postgres-service.yaml : These commands deploy a PostgreSQL database, which is a relational database used to persist data. The postgres-deploy.yaml handles the deployment of the PostgreSQL containers, and postgres-service.yaml makes the database accessible to other parts of the application that need to store or retrieve data.

  • kubectl create -f worker-app-deploy.yaml : This command launches a background worker that processes tasks in the voting application, such as compiling and updating vote counts. The worker-app-deploy.yaml defines how this worker operates and scales within the Kubernetes environment.

  • kubectl create -f result-app-deploy.yaml & kubectl create -f result-app-service.yaml : These commands are for the component that displays the results of the voting. The result-app-deploy.yaml sets up the deployment for the results application, and result-app-service.yaml defines the service to expose the results to users or other applications.

Each .yaml file contains the configuration for a specific part of the application and its related Kubernetes resources. Together, they work to create a distributed, scalable voting application.

  • List out the deployment and services (svc) resources in the Kubernetes cluster:

    • The kubectl get deployments,svc command is used to check the status of the deployment. The key thing to look for is the EXTERNAL-IP for the services of type: LoadBalancer . This is the public DNS name of the AWS Elastic Load Balancer that EKS automatically created for you. This is the URL you will use to access the application.

kubectl get deployments,svc
Screenshot illustrating kubectl get deployments,svc

These above screenshots are the payoff! They show the voting and result websites being accessed via the Load Balancer URLs. The bottom image connects the abstract DNS name to a concrete "Load Balancer" resource in the EC2 dashboard, reinforcing the link between Kubernetes and the underlying AWS services.

[Explanation]

  • The first table of deployment shows the list of deployment resources in the Kubernetes cluster. Deployments are responsible for creating and updating instances of your application. We can see four deployments with names such as postgres-deploy, redis-deploy, etc.

  • The second table of deployment shows the services in the Kubernetes cluster. Services in Kubernetes are an abstraction that defines a logical set of pods and a policy by which to access them, often via a network. The TYPE column indicates the kind of service, for example, ClusterIP which is a default type providing a service inside a cluster that other apps inside your cluster can access, and LoadBalancer which exposes the service externally to the cluster by using a cloud provider's load balancer. The EXTERNAL-IP for result-service and voting-service shows that these services are exposed outside of the cluster, likely allowing web traffic to reach the application. The red boxes highlight that the applications are accessible via the load balancers with external IP addresses and ports specified, suggesting that these services are reachable from outside the Kubernetes cluster. This is a common setup for web applications that need to be accessible to users or external systems.

  • You can copy and paste the URL of these load balancers to access the voting website and the result website like below here:

    • Note: make sure your url has the http protocol like http:// … Otherwise the websites won’t be loaded without the correct URLs.

Screenshot illustrating won’t be loaded without the correct URLs.
Screenshot illustrating won’t be loaded without the correct URLs.
  • Also, you can investigate further in the load balancer by going to the load balancer dashboard to look for the right balancer with the same DNS name like so:

Screenshot illustrating look for the right balancer with the same DNS name like so:
Screenshot illustrating look for the right balancer with the same DNS name like so:
  • This screenshot below shows the details of the AWS Load Balancer. The key takeaway is the "Listeners" section. It shows that the load balancer is listening for traffic on port 80 (standard HTTP) and forwarding it to a TCP port on the worker nodes (in this case, 30790). Kubernetes manages this port mapping automatically.

Screenshot illustrating manages this port mapping automatically.
  • Let’s retrieve and list all resources (like pods, services, and deployments) in a Kubernetes cluster for further investigate:

    • The kubectl get all c ommand provides a comprehensive view of all the resources created. The explanation correctly identifies the four main types of objects:

    • Pods: The actual running instances of your application containers.

    • Services: The networking layer that exposes your pods.

    • Deployments: The controller that manages the Pods and ensures the desired number of replicas are running.

    • ReplicaSets : A lower-level controller managed by the Deployment, responsible for maintaining a stable set of replica Pods.

kubectl get all
Screenshot illustrating kubectl get all

[Explanation]

  • Pods : The first section lists the pods, which are the smallest deployable units that can be created and managed in Kubernetes. Each pod represents a running process on your cluster. In this case, there are pods for PostgreSQL, Redis, a result app, and a worker app, each of which is running (1/1 READY) and has not been restarted since they were deployed (0 RESTARTS).

  • Services : The second section lists the services, which provide stable endpoints for connecting to the pods. The services shown are for the database (db), Kubernetes itself (kubernetes), Redis, and two services related to the voting application (result-service and voting-service). The result-service and voting-service are exposed externally (LoadBalancer), which means they can be accessed from outside the Kubernetes cluster. External IP addresses are provided for these services, indicating where the services can be accessed.

  • Deployments : The third section shows the deployments, which provide declarative updates to applications. A deployment allows you to describe an application’s life cycle, such as which images to use for the app, the number of pods, and the way to update them, among other aspects. There are deployments for PostgreSQL, Redis, the result app, and the worker app, all up-to-date and available.

  • ReplicaSets : The last section lists the replica sets, which ensure that a specified number of pod replicas are running at any given time. This is useful for scaling and self-healing of the application. Each of the replica sets corresponds to one of the deployments and shows the desired count of replicas, which is 1 in this case, and the current count, which matches the desired count.

  • The nice thing about EKS is to allow you to use EKS cluster dashboard with the “Resources” tab to monitor and check the components inside your cluster:

    • These below screenshots show the graphical equivalent of the kubectl commands. The AWS EKS console provides a user-friendly way to view the status of your Pods , Deployments , Services , and other Kubernetes resources. This can be very helpful for quick visual checks and for users who are less comfortable with the command line.

Screenshot illustrating quick visual checks and for users who are less comfortable with the command line.
Screenshot illustrating quick visual checks and for users who are less comfortable with the command line.
Screenshot illustrating quick visual checks and for users who are less comfortable with the command line.
Screenshot illustrating quick visual checks and for users who are less comfortable with the command line.
Screenshot illustrating quick visual checks and for users who are less comfortable with the command line.
  • Let’s clean up everything by deleting all resources in this kubernetes!

  • Before deleting, you might want to list all the resources in the default namespace to review what will be deleted.

kubectl get all --namespace=default
Screenshot illustrating kubectl get all --namespace=default
  • You can delete all resources in the default namespace using the following command. This command deletes pods, services, deployments, replicasets, etc.

kubectl delete all --all --namespace=default
Screenshot illustrating kubectl delete all --all --namespace=default
  • [Optional] If you want to delete specific types of resources only (like pods or services), you can specify the resource type.

kubectl delete pods,services --all --namespace=default

Bonus activity: Practise with Nginx pods

Maybe the above voting application is a good way to show off what Kubernetes can do! However, if you find the above voting application is a bit too complex for you to understand then please continue these bonus activities which you will hand on a simple example with step by step to create yaml files as well. Hopefully, these bonus activities below are more friendly and suitable for beginners!

4b. Create one test pod

  • Let's create a pod in our cluster using the httpd image from DockerHub:

    • kubectl run is a simple, imperative way to create a single pod. It's great for quick tests.

kubectl run webapp --image=httpd
Screenshot illustrating kubectl run webapp --image=httpd
  • Let's check out if our pod is running:

kubectl get pods
Screenshot illustrating kubectl get pods

As you can see, the pod name “webapp" is running!

Awesome! Let's move on to the next section so we need to clean up this pod by deleting it!

kubectl delete pod webapp
Screenshot illustrating kubectl delete pod webapp
  • Let's check out if our pod is deleted:

kubectl get pods
Screenshot illustrating kubectl get pods

4c. Create multiple pods with a deployment

  • Deploying two pods contains Nginx container and expose these two pods at port 80:

    • This is a more robust imperative command that creates a Deployment, which in turn creates a ReplicaSet and the desired number of Pods (in this case, 2). This is the preferred imperative method for creating workloads.

kubectl create deployment demo-nginx --image=nginx --replicas=2 --port=80
Screenshot illustrating kubectl create deployment demo-nginx --image=nginx --replicas=2 --port=80
  • List all deployments of the cluster:

kubectl get deployment
Screenshot illustrating kubectl get deployment
  • List all replicasets of the cluster:

kubectl get replicaset
Screenshot illustrating kubectl get replicaset
  • List all pods of the cluster:

kubectl get pods
Screenshot illustrating kubectl get pods
  • List all resources in one go:

kubectl get all
Screenshot illustrating kubectl get all
  • So far, these two pods are only accessible within the internal IP addresses so we need to expose them.

  • Expose the deployment as a service. This will create an ELB in front of those 2 containers and allow us to publicly access them.

    • This is a key command. It creates a Service that "exposes" the pods managed by the deployment. By specifying --type=LoadBalancer, you are telling Kubernetes to provision an external AWS Load Balancer and configure it to send traffic to the Nginx pods. The diagram perfectly illustrates this relationship.

kubectl expose deployment demo-nginx --port=80 --type=LoadBalancer
Screenshot illustrating kubectl expose deployment demo-nginx --port=80 --type=LoadBalancer (1 of 2)Screenshot illustrating kubectl expose deployment demo-nginx --port=80 --type=LoadBalancer (2 of 2)

Here is the explanation:

  • When you deploy, you set the replicas to be 2 so the replica set will create two pods.

    • When you run the “expose" command, then you will attach a load balancer (SVC) to access these two pods and allow the browser to open the content inside those pods via the public DNS of your load balancer.

  • This is how you can verify the result of the expose command. You find the EXTERNAL-IP from kubectl get service, see the corresponding Load Balancer in the AWS console, and then access the Nginx welcome page using its DNS name. The kubectl describe service command provides detailed information, including the Events section which shows the progress of the load balancer creation.

kubectl get service
Screenshot illustrating kubectl get service
  • That created a load balancer in AWS to expose these two pods for us! Let’s check out the information in the AWS Load Balancer dashboard!

Screenshot illustrating information in the AWS Load Balancer dashboard!

The DNS name of the load balancer matches the External IP of our service in the cluster!

  • You can list out all events happening in the K8s cluster to see if the load balancer is ready:

kubectl get events --sort-by=.metadata.creationTimestamp
Screenshot illustrating kubectl get events --sort-by=.metadata.creationTimestamp
  • Or you can list out only events happening in a specific service to see if the load balancer is ready:

kubectl describe service demo-nginx
Screenshot illustrating kubectl describe service demo-nginx

These events show that our load balancer is ready!

  • Let’s open the browser and enter that DNS name / IP address:

Screenshot illustrating Let’s open the browser and enter that DNS name / IP address:

You should see the welcome page of nginx which is served by our load balancer!

  • You can check out about the port forwarding of the load balancer:

Screenshot illustrating You can check out about the port forwarding of the load balancer:
  • Let’s list out all the resources of our cluster again!

kubectl get all
Screenshot illustrating kubectl get all
  • Let's clean up everything to move on to the next section!

kubectl delete deployment demo-nginx
Screenshot illustrating kubectl delete deployment demo-nginx
kubectl delete service/demo-nginx
Screenshot illustrating kubectl delete service/demo-nginx

This takes some time to delete service as it will clean up resources and delete the load balancer also!

  • Let’s list out all the resources of our cluster again!

kubectl get all
Screenshot illustrating kubectl get all

All is gone! Nice!

4d. Create deployment and service manifests

  • Let’s create a “pod.yml” manifest file to create a pod

nano pod.yml
apiVersion: v1
kind: Pod
metadata:
 name: nginx-pod
 labels:
  app: demo-app
spec:
 containers:
 - name: nginx-container
  image: nginx
  ports:
  - name: nginx
  containerPort: 80
  • Create a pod by running that manifest yaml file:

kubectl apply -f pod.yml
Screenshot illustrating kubectl apply -f pod.yml
  • Let’s list out all the resources of our cluster!

kubectl get all
Screenshot illustrating kubectl get all
  • Next, let’s create a manifest yaml file “service.yml” to create a service:

nano service.yml
apiVersion: v1
kind: Service
metadata:
 name: demo-service
spec:
 ports:
 - name: demo-service
  port: 80
  targetPort: 80
 selector:
  app: demo-app
 type: LoadBalancer
  • Create a service by running that manifest yaml file:

kubectl apply -f service.yml
Screenshot illustrating kubectl apply -f service.yml
  • Let’s list out all the resources of our cluster!

kubectl get all
Screenshot illustrating kubectl get all
  • We can get more information of that service:

kubectl describe service/demo-service
Screenshot illustrating kubectl describe service/demo-service

Note: Did you realize we need to match the name “demo-app” for the selector of our balancer and the labels of our pod so that every traffic coming to the balancer will be redirected to the pods.

  • You can check out the details of our load balancer in the AWS dashboard:

Screenshot illustrating You can check out the details of our load balancer in the AWS dashboard:
  • Let’s open the browser and enter that DNS name / IP address:

Screenshot illustrating Let’s open the browser and enter that DNS name / IP address:
  • Display more information of the pod:

kubectl get pod -o wide
Screenshot illustrating kubectl get pod -o wide

You can even see the private ip address and the name of the EC2 instance running that pod!

  • Nice, now, let’s clean up everything!

kubectl delete service/demo-service
kubectl delete pod/nginx-pod
Screenshot illustrating kubectl delete service/demo-service kubectl delete pod/nginx-pod

After cleaning up, only the default kubernetes service is running!

  • To totally clean up everything, you should delete the worker node group and the EKS cluster as well like below!

    • Deleting the managed node group from the EKS console will trigger the termination of the associated EC2 worker nodes.

Screenshot illustrating the associated EC2 worker nodes.
Screenshot illustrating the associated EC2 worker nodes.
Screenshot illustrating the associated EC2 worker nodes.
Screenshot illustrating the associated EC2 worker nodes.
  • Once the node group is gone, you can delete the cluster itself. This de-provisions the entire EKS control plane.

Screenshot illustrating control plane.
Screenshot illustrating control plane.

It will take some time to clean up everything in the cluster! So wait for it!

That's it! Great job! What a great success to wrap things up!

Congrats for finishing the final lab for learning AWS EKS! This is an amazing journey of conquering DevOps together! Thank you for your hard work and patience to reach the finish line of this journey!

Note : keep in mind that EKS is very expensive to run because Amazon EKS requires running multiple underlying resources like EC2 worker nodes, load balancers, and networking components, even for small clusters, so you end up paying for all those supporting services in addition to the EKS control plane fee, which makes even short learning experiments costly. So try to wisely manage your resources with AWS EKS. Otherwise it will burn all of your AWS Learner Lab credits.

Screenshot illustrating EKS. Otherwise it will burn all of your AWS Learner Lab credits.

📚 Continue the course