Deploy Your First App on Kubernetes

Deploy, scale, and update a web app on a local Kubernetes cluster.

Introduction

30 Second Summary

Every time you stream a show or order food through an app, that app is running across dozens of containers managed automatically. If one crashes, something restarts it instantly.

In this project, you will deploy a web application to a local Kubernetes cluster using Minikube. You will scale it up, watch it self-heal after a failure, and perform a zero-downtime rolling update.

What You'll Build

A fully functional local Kubernetes environment where you write YAML manifests to deploy, expose, scale, and update a containerized web application.

By the end of this project, you'll have:

  • A running Kubernetes cluster on your own machine, powered by Minikube and Docker.
  • A Deployment and Service defined in YAML manifests that manage your application declaratively.
  • Hands-on experience with scaling, self-healing, and rolling updates that mirror how production systems work.
  • Secret Mission: Add resource limits and a liveness probe to make your deployment production-ready.

Are there any prerequisites?

You should be comfortable opening a terminal and running basic commands. You should also have a general understanding of what containers are, but you do not need Docker expertise.

Install Docker and Minikube

Before you can run Kubernetes locally, you need three tools on your machine.

Docker provides the container runtime that powers your cluster. Minikube creates the cluster itself. And kubectl is the command-line tool you use to talk to the cluster and manage everything running inside it.

In this step, get ready to:
  • Install Docker as your container runtime.
  • Install Minikube to run a local Kubernetes cluster.
  • Install kubectl to interact with your cluster from the terminal.
Install Docker Engine

Docker is the container runtime that Minikube uses as its driver. Minikube runs your Kubernetes cluster inside Docker containers, so Docker must be installed and running first.

  • Open your terminal.
  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
  • Check if Docker is already installed by running:
docker --version

✔️ I see a version number

Docker is ready to go. Move on to the next substep.

ⓧ Command not found

You need to install Docker. The easiest path is Docker Desktop, which works on macOS, Windows, and Linux.

  • Visit the official Docker install page:
  • https://docs.docker.com/get-started/get-docker/
  • Download and install Docker Desktop for your operating system.
  • Once installed, open Docker Desktop and wait for the Docker Engine to start (you will see the whale icon in your system tray turn steady).
  • After Docker Desktop is running, return to your terminal and run the version check again:
docker --version

You should now see a version number in the output.

Why Docker Desktop?

Docker Desktop bundles the Docker Engine along with a graphical interface for managing containers. It handles the background daemon automatically so you do not need to configure anything manually.

Minikube uses Docker as its "driver" to run Kubernetes cluster nodes as containers on your machine.

Install Minikube

Minikube is the tool that creates and manages a local Kubernetes cluster on your machine. The latest stable release is v1.38.1.

  • Check if Minikube is already installed by running:
minikube version

✔️ I see a version number

Minikube is installed. Move on to the next substep.

ⓧ Command not found

Install Minikube using the instructions for your operating system below.

macOS

  • Install Minikube with Homebrew by running:
brew install minikube

Windows

  • Install Minikube with the Windows Package Manager by running this in PowerShell:
winget install Kubernetes.minikube

Linux

  • Download and install the Minikube binary by running:
curl -LO https://github.com/kubernetes/minikube/releases/latest/download/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64
  • After installation, verify Minikube is on your PATH by running:
minikube version

You should see a version number in the output confirming the install worked.

Still seeing command not found?

On macOS, if which minikube fails after a Homebrew install, try unlinking and relinking:

brew unlink minikube
brew link minikube

On Windows, close and reopen your PowerShell window so the new PATH entry takes effect.

help me troubleshoot my Minikube installation

Install kubectl

kubectl is the Kubernetes command-line tool. You use it to deploy applications, inspect cluster resources, and manage everything running inside Kubernetes.

  • Check if kubectl is already installed by running:
kubectl version --client

✔️ I see a version number

kubectl is ready. You are all set for the next step.

ⓧ Command not found

Install kubectl using the instructions for your operating system below.

macOS

  • Install kubectl with Homebrew by running:
brew install kubectl

Windows

  • Install kubectl with the Windows Package Manager by running this in PowerShell:
winget install -e --id Kubernetes.kubectl

Linux

  • Download and install the kubectl binary by running:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
  • After installation, verify kubectl is working by running:
kubectl version --client

You should see client version information in the output.

What is kubectl?

kubectl communicates with the Kubernetes API server to carry out your commands. It is the primary way developers interact with any Kubernetes cluster, whether local or production.

It supports a +/- 1 minor version skew with the cluster. Since the install command grabs the latest stable release, it will be compatible with whatever Kubernetes version Minikube runs.

kubectl command not found after install?

On macOS, Homebrew installs may require a new terminal session. Close and reopen your terminal, then try again.

On Windows, close and reopen PowerShell to pick up the updated PATH.

On Linux, confirm the binary landed in the right place by running which kubectl. It should return /usr/local/bin/kubectl.

help me troubleshoot my kubectl installation

Your toolkit is ready. Next up, you will use these tools to start a real Kubernetes cluster on your machine.

Start Your Kubernetes Cluster

Your tools are all installed and verified. Now it's time to bring them to life by creating your very own Kubernetes cluster.

A cluster is the environment where your applications run, scale, and heal themselves. You'll spin one up locally using Minikube and confirm everything is healthy before deploying anything.

In this step, get ready to:
  • Start a local Kubernetes cluster with Minikube.
  • Verify the cluster node is healthy and in Ready state.
  • Open the Kubernetes Dashboard to see a visual overview of your cluster.
Start Minikube

Minikube creates a single-node Kubernetes cluster inside a Docker container on your machine. The --driver=docker flag tells Minikube to use Docker as the backend instead of a full virtual machine.

  • Start your cluster by running this command:
minikube start --driver=docker

This command takes a minute or two. You'll see progress messages as Minikube downloads components, creates the container, and bootstraps Kubernetes inside it.

What does this command do?

Minikube pulls a pre-built container image that includes all the Kubernetes components (API server, scheduler, controller manager, etcd). It starts that container with Docker, configures networking, and sets up kubectl to point at the new cluster automatically.

The --driver=docker flag means no hypervisor is needed. Your cluster runs as a regular Docker container, which is lightweight and fast.

When the command finishes, you should see a message confirming that kubectl is configured to use the minikube cluster.

Cluster failed to start?

Make sure Docker is running. Minikube needs an active Docker daemon to create the cluster container.

Confirm your system has at least 2 CPUs and 2GB of free memory available. Minikube requires these minimums to start.

If you see a permissions error, ensure your user is in the Docker group and can run docker commands without sudo.

Help me troubleshoot why minikube start --driver=docker is failing on my machine.

Verify the cluster

Your cluster should now be running. Let's confirm by checking the node status and the overall Minikube health.

  • Check that your Kubernetes node is ready by running:
kubectl get nodes

You should see one node named minikube with a STATUS of Ready. This means the node can accept workloads.

  • Check that all Minikube components are running by running:
minikube status

You should see the host, kubelet, and apiserver all listed as Running.

What is a node?

A node is a machine (physical or virtual) that runs your containerized applications. In a production cluster you'd have many nodes. Minikube gives you a single node that acts as both the control plane and the worker.

The Ready status confirms that the node has registered with the cluster, all required services are running, and it's prepared to schedule pods.

Node not showing Ready?

If the STATUS column shows NotReady, the cluster may still be initializing. Wait 30 seconds and run kubectl get nodes again.

If you see no output at all, confirm that minikube start completed successfully in the previous substep.

Help me figure out why my Minikube node is not in Ready state.

Explore the dashboard

Kubernetes includes a built-in web dashboard that gives you a visual overview of everything running in your cluster. Let's grab its URL so you can explore it.

  • Get the dashboard URL by running:
minikube dashboard --url

What does the --url flag do?

Without --url, Minikube would try to open your browser automatically. The --url flag tells it to print the URL in your terminal instead, so you can open it manually.

This command keeps running in the foreground to maintain the proxy connection. It will hold your terminal open until you press Ctrl+C to stop it.

  • Copy the URL from your terminal output and paste it into your browser.
  • You should see the Kubernetes Dashboard showing an empty cluster with no workloads deployed yet.
  • When you're done exploring, press Ctrl+C in the terminal to stop the dashboard proxy and get your terminal back.

No URL appearing?

The dashboard takes a few seconds to start. If nothing appears after 30 seconds, check that the cluster is running with minikube status.

If you see a timeout error, the dashboard pod may not have started yet. Wait a minute and try the command again.

Help me troubleshoot why minikube dashboard --url is not producing a URL.

Your cluster is alive and healthy. Next, you'll deploy your first application onto it.

Deploy Your Application

Your Kubernetes cluster is running and ready to accept workloads. Now it's time to put something on it.

In Kubernetes, you don't launch containers directly. Instead, you write a manifest file that describes your desired state, and Kubernetes figures out how to make it happen. In this step, you'll write your first manifest and deploy a multi-replica web application.

In this step, get ready to:
  • Write a Deployment manifest in YAML.
  • Apply the manifest to create pods on your cluster.
  • Inspect the running Deployment and its pods.
Create the Deployment manifest

A Deployment is the standard way to run application containers in Kubernetes. It manages a set of identical Pods and ensures the number you specify is always running.

You describe a Deployment in a YAML manifest file. Kubernetes reads this file and creates the resources to match your desired state.

  • Create a new file called app-deployment.yaml in the directory where your terminal is open (the same location where you ran minikube start).
  • Open app-deployment.yaml in any text editor and paste the following content:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-k8s
  labels:
    app: hello-k8s
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-k8s
  template:
    metadata:
      labels:
        app: hello-k8s
    spec:
      containers:
        - name: hello-k8s
          image: paulbouwer/hello-kubernetes:1.10
          ports:
            - containerPort: 8080

What does this manifest do?

  • apiVersion: apps/v1 tells Kubernetes which API group to use for Deployments.
  • replicas: 3 means Kubernetes will keep exactly 3 copies of your app running at all times.
  • selector and template.metadata.labels must match so the Deployment knows which Pods belong to it.
  • image: paulbouwer/hello-kubernetes:1.10 is a pre-built web app image that displays the pod name in your browser. It listens on port 8080.
  • Save app-deployment.yaml.
  • Confirm the file exists by running:
ls app-deployment.yaml

You should see app-deployment.yaml printed in the output.

File not found?

  • Make sure you saved the file in the same directory where your terminal is open. Run pwd to see your current directory and check that the file is there.
  • Check that the filename is exactly app-deployment.yaml with no extra spaces or extensions.

Why can't Kubernetes find my manifest file?

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

Here is the complete app-deployment.yaml file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-k8s
  labels:
    app: hello-k8s
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-k8s
  template:
    metadata:
      labels:
        app: hello-k8s
    spec:
      containers:
        - name: hello-k8s
          image: paulbouwer/hello-kubernetes:1.10
          ports:
            - containerPort: 8080
Apply the manifest to your cluster

With the manifest written, you can now hand it to Kubernetes. The kubectl apply command reads your file and creates the resources described in it.

  • Deploy your application by running this command:
kubectl apply -f app-deployment.yaml

You should see output similar to deployment.apps/hello-k8s created confirming the Deployment was created.

What does kubectl apply do?

The kubectl apply command is idempotent. If you run it again on the same file, Kubernetes compares your manifest with what already exists and only applies changes. This makes it safe to re-run whenever you update your manifest.

  • Watch your pods come up in real time by running:
kubectl get pods -w

You should see three pods appear, each with a name starting with hello-k8s- and a STATUS that transitions to Running.

  • Once all three pods show Running, press Ctrl+C to stop watching.

Pods stuck in Pending or ImagePullBackOff?

  • If pods show Pending, your cluster may still be allocating resources. Wait 30 seconds and check again.
  • If pods show ImagePullBackOff or ErrImagePull, check your internet connection. The image needs to be downloaded from Docker Hub.
  • Verify the image name in your YAML matches exactly: paulbouwer/hello-kubernetes:1.10.

Why are my pods not reaching Running status?

Inspect the Deployment

Your pods are running, but Kubernetes created more than just pods behind the scenes. A Deployment also creates a ReplicaSet that tracks which pods belong to it. Let's inspect what Kubernetes built.

  • View your Deployment's summary by running:
kubectl get deployments

You should see a table with your hello-k8s Deployment showing 3/3 in the READY column.

  • Get detailed information about your Deployment by running:
kubectl describe deployment hello-k8s

What should I see?

The describe output shows the full picture of your Deployment: its labels, selector, replica count, rolling update strategy, the pod template (image and port), and a list of events showing how Kubernetes created the pods.

Look for the Replicas line. It should show 3 desired | 3 updated | 3 total | 3 available. This confirms all three pods are healthy.

Seeing fewer than 3 available replicas?

  • Run kubectl get pods to check which pods are not in Running state.
  • If any pod shows an error status, run kubectl describe pod <pod-name> (replace <pod-name> with the actual name) to see the Events section for clues.

Help me figure out why my Deployment doesn't have 3 available replicas.

Your application is now running across three pods. Next up, you'll expose it to the network so you can access it in your browser.

Expose Your Application with a Service

Your pods are running, but they live inside the cluster's private network. There's no way to reach them from your browser yet.

In Kubernetes, a Service is the resource that gives your pods a stable network address and routes external traffic to them. In this step, you'll create a NodePort Service that maps a port on your cluster's node directly to your application pods.

In this step, get ready to:
  • Create a Service manifest that routes traffic to your pods.
  • Apply the Service and open the app in your browser.
  • Verify the Service is routing requests to your running pods.
Create the Service manifest

Your Deployment created the pods, but it did not define how to reach them from outside. A Service acts as a stable front door, forwarding incoming traffic to whichever pods match a label selector.

  • Create a new file called app-service.yaml in the same folder as your app-deployment.yaml by running:
touch app-service.yaml
  • Confirm the file was created by running:
ls

You should see both app-deployment.yaml and app-service.yaml in the output.

  • Open app-service.yaml in your text editor and paste the following YAML:
# Declares a NodePort Service to expose pods externally
apiVersion: v1
kind: Service
metadata:
  name: hello-k8s-svc
spec:
  # NodePort opens a port on the cluster node for external access
  type: NodePort
  # Routes traffic to pods with the label app: hello-k8s
  selector:
    app: hello-k8s
  ports:
      # The port the Service listens on inside the cluster
    - port: 80
      # The port your container is actually listening on
      targetPort: 8080

What does this manifest do?

  • type: NodePort tells Kubernetes to open a port on the cluster node itself, making the Service reachable from outside.
  • selector: app: hello-k8s matches the labels on your Deployment's pods. The Service sends traffic only to pods with this label.
  • port: 80 is the port the Service listens on. targetPort: 8080 is the port your container app actually accepts requests on.
  • Save app-service.yaml.

File not saving?

Make sure you saved to the same directory as app-deployment.yaml. If you're using a terminal-based editor, confirm you see both files when you run ls.

help me confirm my app-service.yaml file is saved correctly

Apply the Service and access your app

With the manifest written, you can now tell Kubernetes to create the Service. Then you'll use a Minikube helper command to open the app in your browser.

  • Apply the Service to your cluster by running:
kubectl apply -f app-service.yaml

What does this command do?

kubectl apply -f reads your YAML file and creates (or updates) the resource in the cluster. It's the same command you used for your Deployment. Kubernetes compares your file to what's already running and makes changes only where needed.

You should see output confirming the Service was created:

service/hello-k8s-svc created
  • Open the app in your browser by running:
minikube service hello-k8s-svc

This command finds the NodePort assigned to your Service and opens it in your default browser automatically.

You should see a web page with a Kubernetes logo and information about which pod handled your request.

Browser not opening?

Some environments don't auto-open a browser. Look for a URL in the terminal output (something like http://127.0.0.1:<port>) and paste it into your browser manually.

If you see a connection refused error, wait a few seconds and try the minikube service command again. The Service may still be starting up.

help me troubleshoot why minikube service isn't opening my app

Verify the Service is routing traffic

The web page you see is served by one of your three pods. You can confirm this by checking the Service details and matching the pod name shown on the page.

  • View your cluster's Services by running:
kubectl get services

You should see hello-k8s-svc listed with type NodePort and its port mapping shown in the PORT(S) column (for example, 80:3XXXX/TCP).

What do the ports mean?

The PORT(S) column shows port:nodePort/protocol. The first number (80) is your Service's internal cluster port. The second number (assigned automatically by Kubernetes) is the port opened on the node for external access.

Minikube's minikube service command handles this mapping for you, so you don't need to remember the NodePort number.

  • Look at the web page in your browser.
  • Find the pod name displayed on the page.
  • Refresh the page a few times. Depending on your browser and Kubernetes' load balancing, you may see different pod names appear.

Why does the page show a pod name?

The paulbouwer/hello-kubernetes image is designed specifically for learning. It prints the pod name, node name, and namespace so you can visually confirm which pod handled each request.

✔️ Awesome, I've got everything!

Great. Double check you've saved app-service.yaml and can still access the app in your browser.

ⓧ I'd like to double check the full code

Here is the complete app-service.yaml file:

apiVersion: v1
kind: Service
metadata:
  name: hello-k8s-svc
spec:
  type: NodePort
  selector:
    app: hello-k8s
  ports:
    - port: 80
      targetPort: 8080

Your app is now accessible from outside the cluster. Next up, you'll scale your Deployment to add more pods and watch Kubernetes automatically heal itself when things go wrong.

Scale and Self-Heal

Your application is running with 3 replicas behind a Service. In production, traffic spikes happen. You need more copies of your app to handle the load.

In this step, you will scale your Deployment up, watch Kubernetes automatically heal itself when a pod dies, and then scale back down. This is the power of declarative state management.

In this step, get ready to:
  • Scale the deployment up to 5 replicas.
  • Test self-healing by deleting a pod and watching Kubernetes recreate it.
  • Scale back down to 3 replicas.
Scale up your deployment

Your Deployment currently declares 3 replicas. You can change that number on the fly without editing the YAML file.

  • Scale the hello-k8s deployment to 5 replicas by running this command:
kubectl scale deployment hello-k8s --replicas=5
  • Watch the new pods come up in real time by running:
kubectl get pods -w

What does this command do?

The -w flag means "watch". It keeps the terminal updating as pods change status. You will see new pods appear with statuses like ContainerCreating and then Running.

Press **Ctrl+C** to stop watching once all 5 pods show Running.

  • Confirm you now have 5 pods by running:
kubectl get pods

You should see 5 pods listed, all with the status Running.

Pods stuck in Pending or ContainerCreating?

If pods stay in Pending, your Minikube node might not have enough resources. Check with kubectl describe pod <pod-name> and look at the Events section for scheduling errors.

If pods stay in ContainerCreating for more than a minute, the image might still be pulling. Wait a bit longer since Docker needs to download layers the first time.

Why are my pods stuck and not reaching Running status?

Test self-healing by deleting a pod

Kubernetes constantly compares the actual state of your cluster to the desired state you declared. If a pod disappears, Kubernetes notices the mismatch and creates a replacement automatically.

  • First, list your current pods and copy one of the pod names by running:
kubectl get pods

Each pod has a unique name like hello-k8s-xxxxxxxxxx-xxxxx. Copy any one of the pod names from the output.

  • Delete that pod by running this command (replacing the pod name with yours):
kubectl delete pod [[PODNAME="one of your pod names from the list above"]]
  • Immediately check the pods again to see Kubernetes self-heal by running:
kubectl get pods

You should still see 5 pods. One will be brand new (with a very low AGE value). Kubernetes detected the missing pod and created a replacement to maintain 5 replicas.

What is self-healing?

You told Kubernetes you want 5 replicas. That is your desired state. When you deleted a pod, the actual state dropped to 4. Kubernetes detected the drift and immediately spun up a new pod to bring it back to 5.

In production, this means crashed containers get replaced automatically without human intervention. Your application stays available even when individual pods fail.

Still seeing 4 pods instead of 5?

Run kubectl get pods again after a few seconds. The replacement pod might still be in ContainerCreating status. It should transition to Running within seconds.

Why didn't Kubernetes recreate my deleted pod?

Scale back down to 3 replicas

Now that you have proven scaling works, bring your deployment back to 3 replicas. Kubernetes will gracefully terminate the extra pods.

  • Scale the deployment down to 3 replicas by running:
kubectl scale deployment hello-k8s --replicas=3
  • Watch pods terminate gracefully by running:
kubectl get pods -w

You should see 2 pods transition to Terminating and then disappear, leaving exactly 3 pods in Running status. Press Ctrl+C to stop watching.

Why is graceful termination important?

Kubernetes does not kill pods instantly. It sends a termination signal and gives the container time to finish processing current requests. This prevents dropped connections during scale-down in production.

  • Confirm the final state by running:
kubectl get deployments

You should see hello-k8s with 3/3 in the READY column.

Pods not terminating?

If you see pods stuck in Terminating for more than 30 seconds, the container might be ignoring the shutdown signal. This is normal for some images. Wait up to 30 seconds for Kubernetes to force-kill the pod.

Why are my pods stuck in Terminating status?

You have scaled your application up and down, and proven that Kubernetes self-heals to maintain your desired state. Next up, you will perform a rolling update to deploy a new version of your app with zero downtime.

Perform a Rolling Update

Your deployment can scale up, scale down, and heal itself. Now for the real production test: how do you ship a new version of your application without taking it offline?

Kubernetes solves this with rolling updates. Instead of stopping all pods and replacing them at once, Kubernetes gradually spins up new pods while keeping old ones running. Your users never experience downtime because traffic keeps flowing to healthy pods throughout the process.

In this step, get ready to:
  • Update the container image to trigger a rolling update.
  • Watch Kubernetes replace pods with zero downtime.
  • Roll back to the previous version with a single command.
Update the image

Right now your deployment runs paulbouwer/hello-kubernetes:1.10. You will update it to tag 1.10.1 to trigger a rolling update.

  • Trigger the rolling update by running this command:
kubectl set image deployment/hello-k8s hello-k8s=paulbouwer/hello-kubernetes:1.10.1

What does this command do?

kubectl set image tells Kubernetes to update the container image for a specific deployment. The format is deployment/hello-k8s (the deployment name), followed by hello-k8s=paulbouwer/hello-kubernetes:1.10.1 (the container name and its new image tag).

Kubernetes immediately starts replacing old Pods with new ones running the updated image. It does this gradually so your app stays available throughout.

  • You should see output confirming the image was updated:
deployment.apps/hello-k8s image updated

Seeing an error about the deployment not found?

Make sure you type the deployment name exactly as hello-k8s. If your deployment was deleted during an earlier experiment, re-apply it with kubectl apply -f app-deployment.yaml first.

Help me fix a kubectl set image error

Watch the rollout

Kubernetes is now replacing pods in the background. You can watch the rollout progress in real time to confirm it completes without errors.

  • Check the rollout status by running:
kubectl rollout status deployment/hello-k8s
  • Wait for the command to complete. You should see a message confirming the rollout finished:
deployment "hello-k8s" successfully rolled out

What happened during the rollout?

Kubernetes created new pods running the 1.10.1 image one at a time. As each new pod became ready, Kubernetes terminated one old pod running 1.10. At no point were all pods unavailable. This is what makes rolling updates a zero-downtime deployment strategy.

Rollout seems stuck?

If the rollout status hangs without completing, the new image might be failing to start. Press Ctrl+C to cancel, then run kubectl get pods to check for pods in ImagePullBackOff or CrashLoopBackOff state.

Help me debug a stuck rollout

Verify the update and roll back

The rollout is complete. Time to confirm the new version is actually serving traffic, then practice rolling back to the previous version.

  • Open the app in your browser by running:
minikube service hello-k8s-svc
  • Your browser opens the app. Look at the page content to confirm it is now running the updated version.

What should I see?

The hello-kubernetes page displays details about the pod serving your request. The key thing to confirm is that the page loads successfully, which proves the updated pods are healthy and serving traffic through your Service.

Now that you have confirmed the update works, practice reverting to the previous version. In production, this is how you would undo a bad release in seconds.

  • Roll back to the previous image by running:
kubectl rollout undo deployment/hello-k8s
  • You should see confirmation that the rollback was initiated:
deployment.apps/hello-k8s rolled back

What does rollback do?

kubectl rollout undo tells Kubernetes to revert the deployment to its previous revision. Kubernetes performs another rolling update, this time replacing the 1.10.1 pods with 1.10 pods. The same zero-downtime guarantee applies in both directions.

  • Confirm the rollback completed by running:
kubectl rollout status deployment/hello-k8s
  • You should see the same success message as before:
deployment "hello-k8s" successfully rolled out
  • Open the app one more time to verify it is back to the original version:
minikube service hello-k8s-svc

Your browser opens the app again. The page confirms traffic is flowing to pods running the original image.

App not loading after rollback?

Give it a few seconds for the new pods to become ready. Run kubectl get pods to check all pods show Running status before trying minikube service again.

Help me access my app after a rollback

Secret mission

Production-Ready Deployment

Your Deployment works, but it is missing two critical safeguards that every production Kubernetes workload needs. In this secret mission, you will add resource limits and a liveness probe to protect your cluster from runaway containers and silently stuck applications.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on your local machine, so there are no ongoing cloud costs. Your Minikube cluster does consume approximately 2 CPUs and 2GB of RAM while it is running.

Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • Minikube cluster (running as a Docker container on your machine).
  • Local manifest files (app-deployment.yaml and app-service.yaml).
  • Installed tools: Minikube binary, kubectl binary, Docker Engine.

Keep everything running

No action needed. Choose this if you are still actively experimenting with Kubernetes.

  • Your cluster persists across reboots. If it stops for any reason, run minikube start to bring it back.
  • Your YAML manifest files remain on disk for you to edit and reapply.
  • Docker, Minikube, and kubectl stay installed and ready for your next project.

Pause - I'll come back to this later

Pause the cluster to free up CPU and memory while keeping all your cluster state intact.

  • Pause the cluster by running:
  • When you are ready to resume, run minikube unpause to pick up where you left off.
minikube pause

Your deployed applications and manifest files stay untouched.

Delete - I don't want to use this again

Remove all project resources and free up disk space completely.

  • Delete the Minikube cluster and all its data by running:
minikube delete --all
  • Delete your local manifest files by running:
rm app-deployment.yaml app-service.yaml
  • Remove the Minikube binary by running:
sudo rm /usr/local/bin/minikube
  • Remove the kubectl binary by running:
sudo rm /usr/local/bin/kubectl

What about Docker?

Only uninstall Docker if you do not plan to use it for other projects. Docker is a general-purpose tool used across many workflows.

If you do want to remove it, follow the official Docker Engine uninstall guide for your operating system.

Nice Work!

Nice Work!

Nice work! You just deployed, scaled, updated, and rolled back a real application on Kubernetes. You now have hands-on experience with the same orchestration platform that powers production workloads at companies of every size.

You learned how to:

  • Set up a local Kubernetes cluster with Minikube and Docker, and wrote declarative YAML manifests to define Deployments and Services.
  • Deployed a multi-replica web application, exposed it with a NodePort Service, and witnessed self-healing as Kubernetes automatically recreated deleted pods.
  • Performed a zero-downtime rolling update and rollback to safely change application versions without dropping traffic.
  • Added resource limits and a liveness probe to make your Deployment production-ready.

Ready to quiz yourself?