Deploy Backend with Kubernetes

Welcome to the final project in our Kubernetes x AWS series!

Introduction

⚡️ 30 second Summary

Welcome to part FOUR of your four-part Kubernetes with AWS series.

In the first three projects of this series, you've learnt how to:

  1. Deploy an EKS cluster, which is a group of containers that EKS (Elastic Kubernetes Service) will manage.
  2. Build a container image, which packages up an app's backend code that you want to deploy into a format that Kubernetes can run.
  3. Set up manifest files, which are instructions that tell Kubernetes how to deploy and run your container image on your EKS cluster.

In the final part of this series, it's finally time to deploy that backend with Kubernetes!

In this project, get ready to...

  • 🚢 Set up the backend of an app for deployment.
  • ⬇️ Install kubectl.
  • 🚀 Deploy the backend on a Kubernetes cluster.
  • 💎 (Secret Mission) Track your Kubernetes deployment using EKS.

🎬 Want a complete demo of this project, from start to finish? Check out our walkthrough with Natasha

If you're up for a bit of a challenge, quiz yourself on the key concepts up ahead in this project.

This project is part of a series:

  1. Part 1: Launch a Kubernetes Cluster
  2. Part 2: Set Up Kubernetes Deployment
  3. Part 3: Create Kubernetes Manifests

Before we start Step #1...

Before we get started, it's important that you know what we're trying to do today...

First things first, have you done Projects #1-3 of the Kubernetes series?

Note

Yes, I deleted my resources

Perfect! Welcome back to the Kubernetes series, and it's awesome to have you here again.

See you in 🛠️ Step 1!

Yes, I kept all my resources

If you've completed all the previous projects and kept your resources, you can skip the setup steps.

TIP

If you can, we recommend doing all the questions and screenshots in the set up steps anyway. It'll make your project documentation look AMAZING!

Jump straight to 🚀 Step #6! See you thereeeeee.

Nooo, I haven't!

Haven't tried those projects yet? That's okay - you can still do this project!

Give yourself some extra time to go through 🛠️ Step #1 slowly...

You'll make the most out of this project if you go slow and build a strong understanding of Kubernetes and EKS over the first few steps :)

Set up your EKS cluster

Let's kick things off by setting up a cluster with Amazon EKS! To do this, we'll launch an EC2 instance, and then connect to that instance to run commands for creating the EKS cluster.

What is EKS?

Amazon EKS (Elastic Kubernetes Service) is a service that helps you use Kubernetes to manage containers you create on AWS.

Setting up Kubernetes from scratch can be quite a time consuming and complex thing to do, because you'd need to set up networking, scaling, and security settings on your own. Amazon EKS handles these tasks for you and helps you integrate Kubernetes with other AWS services.

In this step, get ready to:

  • Launch and connect to an EC2 instance.
  • Set up eksctl and your instance's AWS credentials.
  • Create an EKS cluster.

p.s. This step revisits the first project in our Kubernetes series. You can check out that project to learn more about the concepts covered in this step, or if you get stuck!

Launch and Connect to an EC2 Instance

  • Head to the EC2 console.
  • Check that you're using the AWS Region that's closest to you.
  • Click Launch instances.
  • Name your EC2 instance nextwork-eks-instance
  • For the Amazon Machine Image, select Amazon Linux 2023 AMI.
  • For the Instance type, select t3.micro.
  • For the Key pair, Select Proceed without a key pair (not recommended).
  • In the Network settings section, we'll keep the default security group for now.

Extra for Experts: Is using the default security group security best practice?

We wouldn't do this for production environments or long-term use. For now, the default security group makes it easier to connect to our EC2 instance using EC2 Instance Connect.

If we don't use the default security group, we'd have to manually edit our instance's inbound rules to allow an SSH connection through Instance Connect.

Feeling up for a challenge? Try editing your security group's settings to make it more secure (without stopping you from using EC2 Instance Connect later on). If you get stuck, ask the NextWork community!

  • Select Launch instance.
  • In your EC2 console's Instances page, select your new instance.
  • Select Connect. Welcome to EC2 Instance Connect! EC2 Instance Connect is a tool that makes it easy to connect to your instance directly from your browser.
  • Select Connect again in your EC2 Instance Connect page.

Install eksctl

What is eksctl?

Our goal for this step is to set up an EKS cluster, and eksctl is one of the simplest command-line tools you can use to do this.

When you create an EKS cluster with eksctl, it will detect the resources you'll need and automates the set up process for you. This saves you from having to run lots of commands to set up your cluster, which would be the case if you used other command-line options like AWS CLI.

  • Run the following command in your EC2 instance's terminal to download, extract, and install eksctl.
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv -v /tmp/eksctl /usr/local/bin
  • Verify that you've installed eksctl:
eksctl version
  • You should spot a version number in the terminal output.

I don't see a version number

Try running command to install eksctl again. Make sure there aren't any errors in the terminal response.

Stuck? Ask the NextWork community!

Set up IAM role for your EC2 Instance

Let's create a new IAM role for your EC2 instance! If you've done this before in the first project of this series, you might still have it in your AWS account...

Do you need to create a new IAM role?

TIP

If you're not sure whether you've got the IAM role, search nextwork-eks-instance-role in your IAM console's Role page.

I need to create a new IAM role

  • Head to the IAM console.
  • Select Roles.
  • Select Create role.
  • Under Trusted entity type, select AWS service to tell AWS that we're setting up this role for a AWS service (Amazon EC2).

Why do we need to set up an IAM role?

Your EC2 instance starts off as a blank slate, so it doesn't actually have the permission to do anything in your AWS account yet! Your instance would fail to use eksctl to create any EKS clusters.

You need to give your instance the permission to work with AWS services, and you can grant this using roles.

  • Under Use case, select EC2.
  • Select Next.
  • Under Permissions policies, we'll grant our EC2 instance AdministratorAccess.

Extra for Experts: Is granting AdministratorAccess best practice?

Great question! Granting AdministratorAccess is powerful but not ideal for long-term use. We’re using it now because we don’t know all the services your EC2 instance will access for this project yet.

In a real-world scenario, you’d follow the principle of least privilege - giving user/services/apps just enough permissions for the job to minimize security risks. In a real-world scenario, you’d follow the principle of least privilege - giving user/services/apps just enough permissions for the job to minimize security risks.

  • Make sure the AdministratorAccess option is checked, and select Next.
  • Let's give this role a straightforward name - nextwork-eks-instance-role
  • Enter a short description:
Grants an EC2 instance AdministratorAccess to my AWS account. Created during NextWork's Kubernetes project.
  • Select Create role.

Great! Your new role is born. Now let's attach this role to your EC2 instance.

I already have the IAM role

Perfect! If you already have nextwork-eks-instance-role, you can head straight to attaching the IAM role to your EC2 instance below.

Attach IAM role to EC2 instance

  • Head back to the Amazon EC2 console.
  • Select Instances from the left hand sidebar.
  • Select the checkbox next to your nextwork-eks-instance EC2 instance.
  • Select the Actions dropdown, and then Security -> Modify IAM role.
  • Under IAM role, select your new nextwork-eks-instance-role role.
  • Select Update IAM role.

Create EKS Cluster

  • Back to EC2 Instance Connect, run the following command to create your EKS cluster.
  • Make sure to replace your-region-code with your AWS region's code e.g. us-west-2:
eksctl create cluster \
  --name nextwork-eks-cluster \
  --nodegroup-name nextwork-nodegroup \
  --node-type t3.micro \
  --nodes 3 \
  --nodes-min 1 \
  --nodes-max 3 \
  --version 1.33 \
  --region [[AWS_REGION="your-region-code"]]
  • Check: Have you replaced your-region-code with your AWS region's code?
  • Creating your EKS cluster can take some time (around 15-20 minutes), in the meantime...

Why are we launching an EKS cluster?

In this project, your goal is to deploy and manage a containerized application (specifically, its backend) using Kubernetes.

The EKS cluster acts like a command center: it tells your EC2 instances (called “nodes”) when to start, stop, or scale your containers and keeps them connected to the internet. It keeps your app's deployment running smoothly while you focus on writing code.

Pull the Code for your Backend

While we wait for the cluster to finish setting up, let's find the app that we want to deploy.

Your team member has pushed the code for an app's backend into a GitHub repository, so we'll start there!

What is 'backend'?

The backend is the "brain" of an application. It's how your app processes user requests and stores and retrieves data. In other words, the backend makes sure your app does what it's supposed to do (e.g. load a new page) when a user does things like clicking on buttons.

Unlike frontend code, which is what users see and interact with, backend code works on the server side so it runs in the background.

In this step, get ready to:

  • Make a copy of the backend code in GitHub.

If you get stuck in this step, check out the second project of this Kubernetes series for a detailed explanation of each part.

  • While your EC2 instance is busy with creating your cluster, head back to the EC2 console.
  • Select your EC2 instance nextwork-eks-instance-role, and select Connect again.
  • Start a new EC2 Instance Connect session with your instance.

Woah, I can run two Instance Connect sessions with the same instance?

Yup, you can have multiple SSH sessions to the same instance at the same time.

This can be super helpful when you want to multitask, and running a command in a new session doesn’t pause your progress in any other windows.

  • In your new EC2 Instance Connect tab, run the command to install Git:
sudo dnf update
sudo dnf install git -y

What is Git?

Git is a version control system, which means it tracks changes to our code. You can also use it to get specific versions of other people's code, which is why we're installing it for this project!

  • Verify you've downloaded Git by checking for its version:
git --version
  • Configure Git by running the command below. Make sure to replace the placeholder values with your name and email:
git config --global user.name "[[YOURNAME="yourname"]]"
git config --global user.email "[[EMAIL="email"]]"

Let's clone our team member's backend repository.

What does cloning mean?

Cloning in Git means creating a full copy of a repository's code. The code you're copying is usually stored remotely (in this case, in GitHub), and your copy will live in your local machine (in this case, our EC2 instance).

Cloning is a super handy feature of Git because you get a copy of someone else's files and code without having to manually copy and paste.

If you're new to Git and GitHub, you can also check out our Connect a GitHub Repo with AWS project.

  • Select Code to reveal the instructions for cloning their repository.
  • Copy the HTTPS URL.
  • Head back to your EC2 Instance Connect tab.
  • In the terminal, run the command to clone your team member's repository. Replace your-github-url with the HTTPS URL you've copied:
git clone [[GITHUB_URL="your-github-url"]]

What am I cloning?

You are cloning a GitHub repository called nextwork-flask-backend. This repository contains all the backend code that your team member created, including files like app.py, Dockerfile, and requirements.txt.

Once you've cloned the repository, you'll see a new folder in your EC2 instance with the entire repository's files inside.

  • Run ls, which is the Linux command to list all files and subdirectories in your current directory.
  • Confirm that you have a new folder called nextwork-flask-backend in your EC2 instance.

Why does the repository name say 'flask'?

Your team member named the repository with flask to reference that they used the Flask framework to build the backend code.

A framework is a set of tools and guidelines that help developers build software. Flask is a framework that comes with pre-built components and tools for building web applications in Python.

Nice work, seeing the folder means you've successfully cloned your team member's backend code!

  • Navigate into the application directory and run the command that lists everything inside:
cd nextwork-flask-backend
ls
  • Nice - the terminal should show you all the files inside nextwork-flask-backend!

Build a Container Image for Your Backend

Great, we've got our team member's code sitting in our EC2 instance. On to deployment?! 👀

Not so fast. When you deploy a containerized app to Kubernetes, Kubernetes needs to pull the app from a container image that it can access.

What is a container image?

A container image is like a blueprint that contains all the instructions, code, libraries, and dependencies needed to run your application. Note that on the other hand, a container is the running instance created from that image, bringing the application to life and running it in an environment.

Kubernetes is running not just a single container, but entire clusters that could represent tens or hundreds of containers. That's why it needs a container image as a template every time it creates a new container. When containers are created in the same way, your application will also behave the same way when you deploy it in development, testing, and production environments. This makes your application reliable and easier to manage at scale.

In this step, get ready to:

  • Build a container image of the backend code.

Install and Configure Docker

  • Install Docker:
sudo yum install -y docker

What is Docker?

Docker is the tool we're using to build the container image of our backend. In general, you'd use Docker to create containers and container images, and then you'd use Kubernetes to coordinate clusters of containers that are running the same/related applications.

If you're new to Docker or container images, check out our intro project to Docker!

  • Start Docker:
sudo service docker start

Give User Access to Docker

  • To confirm which user you're using in the terminal, run the command whoami
  • You should see ec2-user in the terminal response.

What is ec2-user?

The user you're using to log into the EC2 instance - ec2-user - is different from your AWS account user. Think of it as having a separate login for each server, and your EC2 instance credentials are not tied to your AWS account credentials.

When you launch an EC2 instance using an AMI like Amazon Linux 2023, the AMI automatically sets up ec2-user and makes it your default user for SSH access. When you access your instance as ec2-user, it’s like logging into an AWS account as an IAM Admin user - you’ve got a lot of control but not the absolute top level.

Right now, ec2-user can't run Docker commands on its own because Docker requires root user access. We could install Docker and start the service before because we added sudo to our commands, which lets us run commands as if we were the system's root user. But, using sudo all the time can be a hassle. The moment we forget to add sudo, we'd run into errors.

  • Add ec2-user to the Docker group:
sudo usermod -a -G docker ec2-user

What is the Docker group?

The Docker group is a group in Linux systems that gives users the permission to run Docker commands. When you add a user (e.g., ec2-user) to the Docker group, it lets that user run Docker commands without having to type sudo every time.

This makes your command line work faster and simpler, and is considered better security practice.

💡 What does this command do?

The command sudo usermod -a -G docker ec2-user adds the ec2-user to the docker group.

  • usermod is used to modify a user's account in the system. It lets you update attributes like their groups, home directory, login name, and more.
  • The -a flag (append) makes sure your user doesn't get removed from any other groups they might already belong to. Without -a, the user would be removed from all groups not listed in the command.
  • The -G flag (group) specifies the groups a user should be added to. In this case, it's the docker group.
  • Restart your EC2 Instance Connect session by refreshing your current tab.

Why are we refreshing our tab?

User group changes don’t take effect until you start a new session. Reconnecting to your EC2 instance makes sure your ec2-user picks up the new docker group permissions.

  • Make sure your ec2-user has been added to the Docker group:
groups ec2-user

What does this command do?

This command will list all the groups that ec2-user is a part of.

If you see docker listed, then ec2-user is in the Docker group. Nice work - you can run Docker commands without using sudo!

  • We'll jump back into the application directory. We'll also run the ls command again to list everything inside, so we can double check we're at the right place:
cd nextwork-flask-backend
ls
  • Run the command for building your Docker image:
docker build -t nextwork-flask-backend .

What does building an image mean?

When your team member prepared the app's backend, they wrote a file called a Dockerfile and stored it inside the GitHub repository that they shared with you. A Dockerfile contains instructions on how to build a container image that packages up an app (in this case, the backend) and all its dependencies.

Building an image means you're creating a container image using the Dockerfile that your team member prepared. When you ran the docker build command, you were asking Docker to read the instructions in the Dockerfile and build the container image for you accordingly.

The container image lets Kubernetes set up multiple, identical containers so your application runs consistently across different environments. Whether you're deploying in development, testing, or production, your app behaves the same way because Kubernetes refers to your image each time a new instance/node needs to be created.

💡 What do these commands do?

-t nextwork-flask-backend names your container image nextwork-flask-backend, and the . tells Docker to find the Dockerfile in the current directory.

Push Your Container Image to Amazon ECR

Now that your container image is all built, where should Kubernetes find your container image?

Container registries, like Amazon ECR (Elastic Container Registry), are storage spaces for container images. They give container images somewhere to live so they can be accessed by Kubernetes/other services.

In this step, get ready to:

  • Store the Docker image of your backend in a repository.
  • Create a new Amazon ECR repository using this command:
aws ecr create-repository \
  --repository-name nextwork-flask-backend \
  --image-scanning-configuration scanOnPush=true \

Why are we using ECR?

Amazon ECR (Elastic Container Registry) is a container registry service by AWS, which means you use it to securely store, share, and deploy container images.

ECR is an excellent choice because it's also an AWS service, which lets Elastic Kubernetes Service (EKS) find and deploy your container image with minimal authentication setup.

Tip: If you're new to container registries, we'd recommend checking out our project on using Amazon ECR.

Woah! What does the terminal's response mean?

This response confirms that you've created an ECR repository - it's ready for you to push Docker images!

💡 Extra for Experts: Here's a breakdown of the terminal response

  • repositoryArn: The Amazon Resource Name (ARN) i.e. unique ID for your ECR repository.
  • repositoryUri: Where your images will be stored. This is also the URL you'll use to push and pull container images.
  • repositoryName: Your repository's name - in this case, nextwork-flask-backend.
  • imageTagMutability: Whether image tags are mutable or immutable. "MUTABLE" means you can overwrite which image has a tag e.g. the latest tag can be taken by a newer image at any time.
  • imageScanningConfiguration: Whether images will be scanned for vulnerabilities when pushed.
  • encryptionConfiguration: Your images are encrypted using AES256 for security.
  • In a new tab, head to the ECR console.
  • Confirm that you can see a new repository called nextwork-flask-backend.

Nice, our Amazon ECR repository is live. We're ready to push our container image into ECR!

Push your container image to ECR

  • Select your new repository.
  • Select View push commands.

What is a push command?

A push command in Amazon ECR is used to upload your container images to an ECR repository.

  • Copy the first command.
  • Run the command in your EC2 Instance Connect window.

What's that warning about? Is this an error?

No, that's not an error! It's just a warning from Docker about how it stores your login credentials.

Docker keeps your ECR login info on your local machine, so you don’t need to authenticate to ECR every time you run an ECR command. It’s super convenient, but not the most secure approach. For better security, your credentials should live somewhere safer, like a dedicated credentials manager.

P.S. If you want to try out AWS’s credentials manager for yourself, check out our project: Secure Secrets with Secrets Manager

  • Head back to your ECR console's push commands window.
  • We'll skip the second command - we've already built our container image!
  • Copy the last two push commands.
  • Run the last two commands in your EC2 Instance Connect terminal to tag and push your container image.

What does tagging do?

Since your ECR repository can hold many versions of the same container image, tags help you keep things organized. Tagging your Docker image is like giving it a nickname so you can easily refer to a specific version.

Here, we're tagging our Docker image with latest so Kubernetes knows where it can find the latest container image version when it’s time to deploy.

  • Head back to the ECR console.
  • Close the push commands window.
  • Select the refresh button to refresh your console.
  • Wooo! Confirm that a new container image is in your console now.

Does my container image need to be in a repository?

Nope, Kubernetes doesn’t have to pull container images from a remote repository like ECR.

But, using a container registry is a great way to deploy containerized apps and is best practice. Your cluster can pull whatever is the latest image in your repository on demand, which makes deployments stay consistent across all your nodes automatically.

If you didn't use a container registry, you’d need to preload every node in your Kubernetes cluster with your image. You'd also need to update each node manually with every change to your container image.

Set Up Your App for Deployment

With our image safely stored in ECR, we're ready to deploy our application to our EKS cluster. We'll use Kubernetes manifests to tell Kubernetes how we want it to deploy our application.

What are Kubernetes manifests?

Just like how a Dockerfile gives Docker instructions on building a container image, Kubernetes manifest files tell Kubernetes how to run your application in a cluster.

They act as blueprints that define the desired state of your app, like which container images to use and how to make your app available to end users or other services.

In this step, get ready to:

  • Create the Deployment manifest, which gives Kubernetes instructions on deploying your containerized backend to your Kubernetes cluster.
  • Create the Service manifest, which tells Kubernetes how to expose your application and route traffic to it.

If you get stuck in this step, check out the third project of this Kubernetes series for a detailed explanation of each part.

Create a Directory for Kubernetes Manifests

  • Head back into your EC2 Instance Connect tab.
  • Create a new directory from your instance's root called manifests. Run the following commands:
cd ..
mkdir manifests
cd manifests

What are Kubernetes manifests?

Think of a Kubernetes manifest as a set of instructions that tells Kubernetes how to run your app. Kubernetes uses it to know what your app needs, like which containers to run, how many copies to create, and how much memory to allocate.

Without manifests, Kubernetes wouldn’t know how to set up and manage your app automatically. You'd have to manually configure each container every time you deploy, which would be confusing, error-prone, and hard to repeat. Manifests make deployment much more simple and consistent.

Tip: In general (even outside of Kubernetes), a manifest is an instruction/manual that tells a system how to set up and manage something.

💡 What was the command I just ran?

The commands you ran did three things:

  1. cd .. navigates the terminal out of the nextwork-flask-backend folder and back to the root.
  2. mkdir manifests creates a new directory called manifests.
  3. cd manifests navigates the terminal into the new manifests directory.
  • Create the Deployment manifest file by running the following command:
cat << EOF > flask-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextwork-flask-backend
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nextwork-flask-backend
  template:
    metadata:
      labels:
        app: nextwork-flask-backend
    spec:
      containers:
        - name: nextwork-flask-backend
          image: [[YOUR_ECR_IMAGE_URI="your-ecr-image-url"]]
          ports:
            - containerPort: 8080
EOF
  • Notice the third to last line... don't forget to replace the placeholder for your-ecr-image-url

What should I be replacing your-ecr-image-url with?

Replace your-ecr-image-url with the URI of the Docker image you pushed to Amazon ECR. This lets Kubernetes know where to pull the container image from when it deploys your application.

💡 Extra for Experts: What does the containers section of this file mean?

The containers section tells Kubernetes how it should set up each container that will run inside the pods created by this deployment. It includes:

  • The name of the container.
  • The container image to use.
  • The ports that the container will use, which lets the application communicate within the cluster and with external traffic.

Can you find and replace the image URI by yourself?

Yup! Got it all sorted!

Nice work! Once you've replaced the URI placeholder, don't forget to run the command in your terminal.

Hmmmm, can you show me how?

  • Head back into your ECR console
  • Copy the URI of your image tagged latest.
  • Now paste that URI into the your-ecr-image-url placeholder.
  • Copy the entire code block and run it in your terminal!

What is a Deployment manifest?

When you deploy an app with Kubernetes, Kubernetes' job is to manage several copies of your app across multiple containers in your cluster. It does this using a Deployment resource, which is a piece of software inside your cluster. The Deployment resource handles creating and replacing groups of containers, scaling your app, and rolling out updates.

A Deployment manifest tells Kubernetes exactly how to manage these tasks. It includes details like the number of copies of your code that Kubernetes should run across your cluster, and which settings to apply (e.g. CPU limits, container image, or network settings).

We’re only deploying the backend of our app, but a Deployment manifest can manage multiple components, like frontend servers, databases, and other services.

💡 How does this command create the Deployment manifest?

The cat command in Linux is a quick way to see what's inside a file or create a new one without opening a text editor.

When you use cat with << EOF, like cat << EOF > flask-deployment.yaml, you're telling the system: "Take the content I type here and save it in a new file called flask-deployment.yaml."

💡 Extra for Experts: What are resources in Kubernetes?

A Kubernetes cluster can be broken down into different parts, each playing a specific role in making deployment and container management successful. These parts are called resources, and their jobs make up Kubernetes' functionalities.

For example, the Deployment resource's job is to makes sure your app stays running, scales correctly, and updates smoothly.

  • Run nano flask-deployment.yaml in your terminal to see your work.

Woah! Where am I, how did that happen?

You’re now in nano, a built-in text editor within the terminal! Unlike a regular text editor, nano doesn’t use a mouse – you’ll navigate and edit with your keyboard.

p.s. nano is a software that usually comes pre-installed in Linux and Unix systems, like this EC2 instance. You'd have to install it manually if you want to use it in a Windows computer!

  • Use the arrow keys on your keyboard to navigate down the file.
  • Press Ctrl + S on your keyboard to save your work.
  • Press Ctrl + X to exit out of the file.

Woohoo! That was your very first manifest file created. We still have one more...

Create your Service Manifest

What is a Service manifest?

A Service in Kubernetes is like a traffic controller that keeps traffic flowing to the right pods inside your app.

A Service manifest tells Kubernetes to create or update that traffic controller. In it, you list which pods to target, the kind of traffic to accept, and the ports to listen on.

In our case, the Service we defined sends external traffic to port 8080 on any pod labeled app:nextwork-flask-backend. That way, users outside the cluster can reach your app without knowing its internal details.

P.S. A pod is Kubernetes’ smallest work unit. Think of it as one or more containers that run side by side and share the same network address, so Kubernetes can manage them as a single piece.

💡 What's the difference between the Deployment and the Service manifests?

The Deployment manifest focuses on deploying and managing your app inside Kubernetes, while the Service manifest is what you use to expose your app to the outside world or other parts of your system. Both work together to create a fully functional application setup.

  • Create the flask-service.yaml file:
cat << EOF > flask-service.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: nextwork-flask-backend
spec:
  selector:
    app: nextwork-flask-backend
  type: NodePort
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
EOF

What does this Service manifest do?

This file creates a Service resource in Kubernetes to make nextwork-flask-backend accessible from outside the cluster.

  • Name: The Service is called nextwork-flask-backend.
  • Selector: It looks for pods (i.e. bundles of containers, which we'll learn more about in today's secret mission 💎) with the label app: nextwork-flask-backend to send traffic to.
  • Type: the type of Service you are creating in Kubernetes. In this case, the type is NodePort, which means the Service will make your app accessible by assigning a specific port (called a NodePort) on each node. You can then use the node's IP address and this NodePort to reach your app.
  • port: 8080: The port on the Service that will receive traffic. When users or other resources want to get to the deployed backend, they have to reach the Service first on this port.
  • targetPort: 8080: Once the Service receives external traffic, it identifies the pod that will handle/process this traffic and forwards the traffic to that pod's targetPort.

Simply put, this Service lets you access your backend using your node's IP and a port number. There are other ways to expose your app, like LoadBalancer (which gives you an external IP) or Ingress (for advanced traffic routing), but NodePort is a great option for testing or learning how Services work.

Nice! The manifest files were the final missing pieces for your Kubernetes deployment, so we're all ready for the grand finale!

Deploy Your Backend Application

Now for the moment you've been waiting for...

Let's deploy our backend application! We'll be using a command-line tool called kubectl to do this.

In this step, get ready to:

  • Install kubectl, a command-line tool for using Kubernetes.
  • Deploy your app with Kubernetes.
  • Apply the manifests:
kubectl apply -f flask-deployment.yaml
kubectl apply -f flask-service.yaml

What does it mean to 'apply' manifests?

Now that you've set up the manifest files, this command tells Kubernetes toto create or update resources (i.e. the Deployment and Service) based on the instructions in your manifest files.

Since this is our first time running apply, Kubernetes will create the Deployment and Service resources in the cluster.

The next time you run the same apply command with updated manifests, Kubernetes will recognize that these resources already exist and will update them to match the new configurations.

Ah... an error

If you've done the previous projects in this series, you might recognize this error message - you haven't installed the key tool you're using in this command, kubectl!

💡 What is kubectl?

kubectl is the command-line tool for interacting with Kubernetes resources (like Deployment or Service resources) once your cluster is up and running. We're using it to apply our manifests and deploy our application.

💡 Don't we already have another tool called eksctl?

Good question! eksctl, which you installed in Step #1 of this project, is great for setting up and deleting your EKS cluster and configuring its settings.

But, when it comes to deploying applications and managing resources within the cluster, kubectl is the tool to use.

  • Install kubectl:
sudo curl -o /usr/local/bin/kubectl \
https://s3.us-west-2.amazonaws.com/amazon-eks/1.31.0/2024-09-12/bin/linux/amd64/kubectl
  • Just like what you did with Docker, you'll need to give yourself the permission to use kubectl:
sudo chmod +x /usr/local/bin/kubectl
  • Check you've installed kubectl properly:
kubectl version

I ran into an error!

Hmmm! Did the error say The connection to the server localhost:8080 was refused?

Not to worry! When you ran kubectl version, the command first printed the version of kubectl installed on your computer. It then tries to contact your Kubernetes control-plane to fetch the cluster’s own version. To know where the cluster lives and how to log in, kubectl relies on a tiny file called a kubeconfig - a simple set of directions saved in ~/.kube/config.

  • Run the commands to apply your manifest files again. We've tried running both commands before, so you should know what they are!

I ran into an error!

No worries! You're likely to see an error that says error validating data: failed to download openapi:

This means kubectl was trying to talk to the Kubernetes API at localhost:8080... but nothing was running there! That's true. Our Kubernetes cluster isn't running at localhost, it's running in EKS. We'll have to tell kubectl to find your cluster in EKS.

Try solving this error by configuring kubeconfig:

aws eks update-kubeconfig --name [[CLUSTER_NAME="cluster-name"]] --region [[AWS_REGION="your-region-code"]]

Try applying your manifest files again, you should be able to run it with no errors. All it took was telling kubectl where to find your Kubernetes cluster!

Nice work! You've just used kubectl to apply your manifest files, which deploys your app across your cluster.

Wondering how you can check that you've deployed the app? Look no further than today's secret mission...

Secret mission

Welcome to your 🤫 exclusive 🤫 secret mission!

Your mission, should you choose to accept it, is to investigate your deployment's progress using Amazon EKS.

💎 Get ready to:

  • View your EKS cluster in the console.
  • Verify your backend's deployment in EKS.
  • Showcase your secret mission in your project documentation.

Verify your EKS deployment

Delete Your Resources

Delete Your Resources

Before diving into the steps for deleting your resources, why not challenge yourself to delete everything in this project on your own?

Keeping track of your resources and deleting them without any guidance is absolutely a skill that will help you protect you from unexpected charges!!

Yep, all done.

  • EKS cluster
  • EC2 instance
  • ECR Repository

I know, but also, I don't...

If you're feeling stuck (we've all been there!), here's a little guide:

  • Delete EKS Cluster
  • Delete your EKS cluster within the terminal:
eksctl delete cluster --name nextwork-eks-cluster --region [[AWS_REGION="your-region-code"]]

This command deletes the EKS cluster and all associated resources! It takes a bit of time before everything's gone, but you can move on to deleting other resources while you wait.

  • Terminate EC2 Instance
  • Head to the EC2 console.
  • Select the checkbox next to nextwork-eks-instance.
  • Select Instance state -> Terminate (delete) instance.
  • Delete ECR Repository
  • Head in the AWS console.
  • Select the nextwork-flask-backend repository.
  • Click Delete and confirm.

Please check - is your EKS cluster removed? Is everything in the CloudFormation stack deleted?

Please also check for an Elastic IP address in the EC2 console - some students have been charged by the Elastic IP still being in their account!

That's a wrap!

That's a wrap!

You've just deployed the backend of an app with Kubernetes!

You've learned how to:

  • 🐳 Build and push a container image of the backend of an app.
  • 📝 Write manifests that tell Kubernetes how you'd like to deploy the backend.
  • 🚢 Deploy the backend with Kubernetes using kubectl.

That's awesome, give yourself a pat on the back 😮‍💨 Are you ready to quiz yourself? 💪

Ready to keep learning about Kubernetes? This project wraps up the current Kubernetes series, but stay tuned for more Kubernetes projects that will get you too:

  • See your deployed backend in action.
  • Troubleshoot network issues.
  • Deploy the frontend for the same app!

p.s. Does it say "Still tasks to complete!" at the bottom of the screen?

This means you still have screenshots left to upload, or questions left to answer!

  1. Press Ctrl+F (Windows) or Command+F (Mac) on your keyboard.
  2. Search for the text Return to later.
  3. Jump straight to your incomplete tasks!
  4. 🙋‍♀️ Still stuck? Ask the community!