Deploy and Manage Apps on Kubernetes
Deploy, scale, update, and debug a web app on your local Kubernetes cluster.
Introduction
30 Second Summary
Reading about Kubernetes concepts is one thing. Actually deploying, breaking, and fixing applications on a real cluster is where confidence comes from.
In this project, you will deploy a multi-replica web application on your local Rancher Desktop cluster, perform rolling updates and rollbacks, intentionally break a deployment, and diagnose it using kubectl.
What You'll Build
A hands-on Kubernetes operations exercise that builds muscle memory for the exact commands and workflows practitioners use daily.
By the end of this project, you'll have:
- A Deployment running multiple replicas of a web server, exposed via a Service and accessible through port-forwarding.
- A rolling update from one image variant to another, followed by a successful rollback.
- A deliberately broken deployment that you'll diagnose and fix using kubectl debugging commands like describe, logs, and events.
- Secret Mission: Create a custom namespace with resource limits and deploy a second application into it.
Are there any prerequisites?
This project assumes you already have Rancher Desktop installed on your Mac with Kubernetes enabled and running. You should also have a basic understanding of Kubernetes terminology like Pods, Deployments, Services, and Nodes.
No additional tools are needed. Rancher Desktop bundles kubectl and everything else you need.
Verify Your Cluster
Before deploying any applications, you need to confirm your Kubernetes cluster is running and healthy.
In this step, you'll use kubectl to verify that Rancher Desktop's built-in cluster is ready to accept workloads.
In this step, get ready to:
- Confirm Rancher Desktop is running with Kubernetes enabled.
- Check your node is in a Ready state.
- Note your Kubernetes server version.
Confirm Rancher Desktop is running
Your cluster runs inside Rancher Desktop. You need to confirm it's active and that Kubernetes shows a green status before running any commands.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Rancher Desktop and press Enter to open it.
- Look for the Kubernetes indicator in the bottom-left of the Rancher Desktop window. It should show a green status, meaning the cluster is running.
- Verify the connection from your terminal by running this command:
kubectl --context rancher-desktop cluster-info
You should see output showing that the Kubernetes control plane is running, along with an address like https://127.0.0.1:6443. This confirms kubectl can talk to your cluster.
Seeing a connection refused error?
Make sure Rancher Desktop is fully started. The Kubernetes indicator needs to be green, not orange or red. It can take a minute or two after launching for the cluster to be ready.
If the indicator stays red, try restarting Rancher Desktop from its menu bar icon.
help me troubleshoot why kubectl can't connect to my Rancher Desktop cluster
Check your node and system Pods
A Node is the machine (real or virtual) that runs your workloads. Rancher Desktop gives you a single node. Let's confirm it's healthy.
- Check your node is in a Ready state by running:
kubectl get nodes
You should see one node with a STATUS of Ready. The ROLES column shows control-plane,master because your single node handles everything.
What is a single-node cluster?
In production, Kubernetes clusters have many nodes. Rancher Desktop runs a single-node k3s cluster inside a virtual machine on your Mac. All Kubernetes concepts (Deployments, Services, scaling) work identically on a single node.
- Inspect what's already running across all namespaces by running:
kubectl get pods -A
You should see system Pods in the kube-system namespace. These handle networking, DNS, and other internal cluster services. You don't need to touch them.
What does the -A flag do?
The -A flag stands for "all namespaces." Without it, kubectl only shows resources in the default namespace. Since system Pods live in kube-system, you need -A to see them.
Some Pods not showing Running?
If you just started Rancher Desktop, some system Pods may still be initializing. Wait 30 seconds and run the command again. All Pods should eventually show a STATUS of Running or Completed.
help me understand why my system Pods aren't all in Running status
Check your Kubernetes version
Knowing your exact Kubernetes version helps when reading documentation or troubleshooting. The server version tells you which version of k3s is powering your cluster.
- Check both your client and server versions by running:
kubectl version
The output shows two version numbers. The Client Version is your local kubectl binary. The Server Version is the Kubernetes version running inside Rancher Desktop (your k3s cluster).
Do the client and server versions need to match?
They don't need to be identical. Kubernetes supports kubectl within one minor version of the server. Since Rancher Desktop bundles a compatible kubectl, you're good to go.
Your cluster is verified and ready for action. Next up, you'll deploy a real web application and watch Kubernetes manage it.
Deploy a Web Application
Your cluster is verified and healthy. Now it's time to put it to work by deploying a real application.
In this step, you'll write a Deployment manifest in YAML and apply it to your cluster. A Deployment tells Kubernetes how many copies (replicas) of your app to run and which container image to use.
In this step, get ready to:
- Create a project directory and a Deployment YAML file.
- Apply the Deployment and watch Pods start in real-time.
- Inspect the running Deployment and check Pod placement.
Create your project directory and deployment file
Every Kubernetes project starts with a manifest file. This is a YAML file that describes the desired state of your application. You'll create a folder to keep your manifests organized.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir k8s-homelab
cd k8s-homelab
- Verify you're in the project folder by running:
pwd
- You should see a path ending in k8s-homelab.
- Create a new file called nginx-deployment.yaml in your k8s-homelab folder and add the following Deployment configuration:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
What does this YAML do?
- apiVersion: apps/v1 and kind: Deployment tell Kubernetes you want a Deployment resource.
- replicas: 3 tells Kubernetes to always keep three copies (Pods) of this app running.
- selector and the template labels (app: nginx) connect the Deployment to its Pods. The Deployment manages any Pod with a matching label.
- image: nginx:1.27-alpine pulls the lightweight Alpine variant of the official Nginx web server image.
- containerPort: 80 declares that the container listens on port 80.
- Save nginx-deployment.yaml.
- Confirm the file exists by running:
ls
- You should see nginx-deployment.yaml in the output.
Don't see the file?
- Make sure you saved the file inside the k8s-homelab folder, not somewhere else on your system.
- Run pwd to double-check you're in the right directory.
Still stuck? Help me find my nginx-deployment.yaml file
Apply the deployment and watch pods start
With your manifest ready, you'll hand it to Kubernetes. The cluster reads the YAML and creates the exact state you described.
- Apply your Deployment to the cluster by running:
kubectl apply -f nginx-deployment.yaml
What does this command do?
kubectl apply -f reads your YAML file and sends it to the Kubernetes API server. The server creates (or updates) the resources described in the file. You should see deployment.apps/nginx-deployment created confirming that Kubernetes accepted your manifest.
- Watch the Pods come up in real-time by running:
kubectl get pods -w
You'll see each Pod transition through states like Pending and ContainerCreating before reaching Running. Press Ctrl+C once all three Pods show Running status.
Pods stuck in Pending or ContainerCreating?
- The first time you deploy, Kubernetes needs to pull the nginx:1.27-alpine image from Docker Hub. This can take 30-60 seconds depending on your internet speed.
- If Pods stay in Pending for more than 2 minutes, check that Rancher Desktop's Kubernetes indicator still shows green.
- If you see ErrImagePull, confirm you have an active internet connection and the image name is spelled exactly as shown.
Need more help? My pods are stuck and not reaching Running status
Inspect the deployment details
Your Pods are running, but Kubernetes stores much more detail under the hood. Inspecting a Deployment teaches you where to look when things go wrong later.
- Inspect the full details of your Deployment by running:
kubectl describe deployment nginx-deployment
What should I look for?
The output is long. Focus on these sections:
- Replicas shows desired vs current vs available replica counts.
- Conditions tells you whether the Deployment is progressing normally or has issues.
- Events at the bottom shows the timeline of actions Kubernetes took (scaling up replicas, creating Pods).
- Check which node each Pod is running on by running:
kubectl get pods -o wide
Since Rancher Desktop runs a single-node k3s cluster, all three Pods land on the same node. In a multi-node production cluster, Kubernetes would spread them across nodes for resilience.
Command returns No resources found?
- Make sure your kubectl context is still set to rancher-desktop. Verify with kubectl config current-context.
- If you accidentally deleted the deployment, re-apply it with kubectl apply -f nginx-deployment.yaml.
Still seeing issues? Help me troubleshoot my kubectl describe output
✔️ Awesome, I've got everything!
Great. Double check you've saved nginx-deployment.yaml in your k8s-homelab folder.
ⓧ I'd like to double check the full code
Here's the complete nginx-deployment.yaml for comparison:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
Your application is deployed and running across three replicas. Next up, you'll create a Service to expose it and access it in your browser.
Expose and Access the App
Your Pods are running, but they're only accessible from inside the cluster. If a Pod dies and gets replaced, its IP address changes too.
A Service solves this by providing a single, stable address that routes traffic to your Pods no matter which ones are alive. In this step, you'll create a Service and use port-forwarding to access your app from your browser.
In this step, get ready to:
- Create a Service YAML file targeting your Nginx Pods.
- Apply the Service and verify it received a ClusterIP.
- Access the Nginx welcome page through port-forwarding.
Create a Service YAML file
A ClusterIP Service gives your Deployment a stable internal address. Traffic sent to that address gets load-balanced across all matching Pods.
- Create a new file called nginx-service.yaml in your project directory by running:
touch nginx-service.yaml
- Open nginx-service.yaml in your preferred text editor and paste the following content:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
What does this YAML do?
- selector: app: nginx tells the Service to route traffic to any Pod with the label app: nginx. This matches the Pods your Deployment created.
- port: 80 is the port the Service listens on. targetPort: 80 is the port the traffic gets forwarded to on the container.
- type: ClusterIP means the Service is only reachable from inside the cluster. You'll use port-forwarding to reach it from your machine.
- Save nginx-service.yaml.
- Confirm the file exists by running:
ls
You should see both nginx-deployment.yaml and nginx-service.yaml in the output.
Don't see nginx-service.yaml?
Make sure you ran touch from the same project directory where nginx-deployment.yaml lives. Run pwd to check your current directory.
Help me find my nginx-service.yaml 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
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Apply the Service and verify it
- Apply the Service to your cluster by running:
kubectl apply -f nginx-service.yaml
You should see output confirming the service was created.
- Verify the Service is running and note the ClusterIP assigned by running:
kubectl get svc
What should I see?
The output shows a table with your nginx-service listed. The CLUSTER-IP column shows the stable internal address assigned to it. The TYPE column shows ClusterIP.
You'll also see the default kubernetes service that every cluster has. That one is normal.
Service not appearing?
Make sure the YAML file was saved before you ran kubectl apply. Also check for indentation errors in your YAML by running:
kubectl apply -f nginx-service.yaml --dry-run=client
This validates the file without creating anything. If there's a syntax error, the output tells you exactly which line.
Help me debug my Service
Port-forward to access the app in your browser
The ClusterIP address is only reachable inside the cluster. Port-forwarding bridges your local machine to the cluster so you can open the app in your browser.
- Start port-forwarding by running:
kubectl port-forward svc/nginx-service 8080:80
What does this command do?
This maps port 8080 on your local machine to port 80 on the Service. Any request you send to localhost:8080 gets forwarded through the cluster to one of your Nginx Pods.
Your terminal stays occupied while port-forwarding is active. You'll stop it later with a keyboard shortcut.
- Open your browser and navigate to http://localhost:8080.
You should see the Nginx welcome page confirming your app is accessible through the Service.
- Return to your terminal and press Ctrl+C to stop port-forwarding.
Not seeing the welcome page?
If your browser shows a connection error, check that the kubectl port-forward command is still running in your terminal. It must stay active for the connection to work.
If port 8080 is already in use on your machine, you'll see an error in the terminal. Try a different local port like 9090:80 and open http://localhost:9090 instead.
Help me troubleshoot port-forwarding
Your app is deployed and reachable. Next up, you'll perform a rolling update to swap the container image to a different variant and then roll it back with zero downtime.
Perform a Rolling Update and Rollback
Your application is deployed and serving traffic. In production, you'll regularly push new versions of your container images to fix bugs or add features.
Kubernetes handles version changes through rolling updates. It gradually replaces old Pods with new ones so your application stays available during the transition. In this step, you'll perform an update and then practice the equally important skill of rolling it back.
In this step, get ready to:
- Update the deployment image and watch the rollout in real-time.
- Inspect the rollout history to see revision tracking.
- Roll back to the previous version and confirm it reverted.
Update the deployment image
A rolling update replaces Pods one at a time with a new image version. Kubernetes ensures some Pods are always available during the transition, so there's zero downtime.
- Update the deployment to use the nginx:1.27-bookworm image by running this command:
kubectl set image deployment/nginx-deployment nginx=nginx:1.27-bookworm
- Immediately watch the rollout progress by running:
kubectl rollout status deployment/nginx-deployment
You should see Kubernetes reporting Pods being created and old ones being terminated. The output ends with deployment "nginx-deployment" successfully rolled out once the update is complete.
What's happening here?
- kubectl set image tells Kubernetes to update the container named nginx inside the deployment to use the new image.
- kubectl rollout status streams the live progress of the update, showing new Pods coming up and old Pods terminating one by one.
Rollout seems stuck?
Make sure Rancher Desktop is running and your cluster is healthy. If the rollout appears to hang, wait a moment. The new image needs to be pulled from Docker Hub, which can take a few seconds on slower connections.
help me debug my stuck rollout
Check the rollout history
Kubernetes tracks every change to a Deployment as a numbered revision. This history is what makes rollbacks possible.
- View the rollout history by running:
kubectl rollout history deployment/nginx-deployment
- Confirm the new Pods are running with the updated image by running:
kubectl get pods
What does rollout history show?
Each revision represents a change to the Deployment's Pod template, such as an image update. You should see at least 2 revisions listed.
Revision 1 is your original nginx:1.27-alpine deployment. Revision 2 is the nginx:1.27-bookworm update you just performed.
You should see all 3 Pods in Running status with recent AGE values, confirming they were replaced during the rolling update.
Roll back to the previous version
Rolling back is just as important as updating. If a new version introduces a bug, you need to revert to a known-good state quickly.
- Roll back the deployment to the previous revision by running:
kubectl rollout undo deployment/nginx-deployment
- Watch the rollback complete by running:
kubectl rollout status deployment/nginx-deployment
- Confirm the image reverted back to nginx:1.27-alpine by running:
kubectl describe deployment nginx-deployment | grep Image
What does rollout undo do?
kubectl rollout undo reverts the Deployment to the previous revision in its history. Kubernetes performs another rolling update, this time replacing the newer Pods with the old image.
The grep Image filter shows only the image line from the describe output, making it easy to confirm which version is currently running.
The output should show Image: nginx:1.27-alpine, confirming you're back to the original version. All 3 Pods should be in Running status.
Still seeing the bookworm image?
Make sure the rollback completed by running kubectl rollout status deployment/nginx-deployment again.
If you accidentally ran kubectl rollout undo twice, you may have rolled forward again. Run the describe | grep Image command to check, and undo once more if needed.
help me fix my rollback
You've proven you can update and roll back with confidence. Next up, you'll intentionally break your deployment and practice the debugging commands that save you in production.
Break Things and Fix Them
You now know how to deploy, expose, update, and roll back an application. But the most important skill for any Kubernetes practitioner is knowing what to do when something goes wrong.
In this step, you will intentionally break your deployment by pointing it at a container image that does not exist. Then you will use the exact debugging commands that engineers use in production to figure out what happened and fix it.
In this step, get ready to:
- Break the deployment with a non-existent image tag.
- Debug the failure using kubectl describe and kubectl logs.
- Fix the deployment by rolling back to the last working version.
Intentionally deploy a broken image
In production, broken deployments happen. A typo in a tag, a deleted image, a registry outage. The difference between a calm response and a panic comes down to practice.
- Break the deployment by setting the container image to a tag that does not exist on Docker Hub:
kubectl set image deployment/nginx-deployment nginx=nginx:nonexistent-tag
What does this command do?
This tells Kubernetes to update the Pods in nginx-deployment to use the image nginx:nonexistent-tag. Since this tag does not exist, Kubernetes will try to pull it and fail.
Thanks to the rolling update strategy, Kubernetes will not terminate your old Pods until the new ones are healthy. So your app stays partially available even during this failure.
- Check the Pod status by running:
kubectl get pods
You should see one or more Pods with ImagePullBackOff or ErrImagePull in the STATUS column. This means Kubernetes tried to pull the image, failed, and is retrying with increasing delays.
What is ImagePullBackOff?
ErrImagePull appears on the first failed attempt to pull an image. ImagePullBackOff appears after Kubernetes starts exponential backoff between retries. Both indicate the same underlying failure.
The Pod is not crashing. It has never started because the container image could not be downloaded. Kubernetes will keep retrying with delays up to 5 minutes.
Still seeing Running on all Pods?
The rolling update only replaces Pods gradually. Give it 10-20 seconds and run kubectl get pods again. You should see at least one Pod with ErrImagePull or ImagePullBackOff status.
help me debug why my Pods are not showing ImagePullBackOff after setting a non-existent image tag
Debug the failing Pods
Now you will use the two most important debugging commands in Kubernetes. These are the exact steps you would take in production when a deployment goes wrong.
- First, identify a failing Pod name from the output above. Look for a Pod with ImagePullBackOff or ErrImagePull status.
- Inspect the failing Pod's events by running:
kubectl describe pod [[FAILING_POD="a pod name showing ImagePullBackOff from the output above"]]
What should I look for?
Scroll to the Events section at the bottom of the output. This is the most actionable part. You will see entries like Failed to pull image followed by the specific error. In this case, the tag does not exist on the registry.
The Events section is a chronological record of everything Kubernetes has done to the Pod. It shows scheduling decisions, image pulls, and failures. When debugging, always check Events first.
- Try checking the container logs for additional context:
kubectl logs [[FAILING_POD="a pod name showing ImagePullBackOff from the output above"]]
Why are the logs empty?
You will likely see an error saying the container has not started. This is expected. Since the image could not be pulled, no container has ever run, so there are no application logs.
This teaches an important lesson. Use kubectl describe pod for infrastructure-level issues (image pulls, scheduling, resource limits). Use kubectl logs for application-level issues (crashes, exceptions, misconfigurations inside the running container).
Pod name not found?
Pod names are generated dynamically. Make sure you copied the exact name from your kubectl get pods output, including the random suffix (it looks something like nginx-deployment-abc123-xyz45).
help me find and describe my failing Pod
Fix it by rolling back
You have identified the problem. The image tag does not exist. In production, you might fix the tag or push the missing image. Here, you will use the fastest fix available: rolling back to the last known-good version.
- Roll back to the previous working version by running:
kubectl rollout undo deployment/nginx-deployment
What does this command do?
This reverts the Deployment to its previous revision, which was running nginx:1.27-alpine successfully. Kubernetes terminates the broken Pods and brings back healthy ones with the correct image.
- Verify the rollback completed by running:
kubectl rollout status deployment/nginx-deployment
You should see a message confirming the deployment has successfully rolled out.
- Confirm all Pods are healthy again by running:
kubectl get pods
All 3 Pods should now show Running status with 1/1 in the READY column.
- Review the full timeline of what happened by checking recent events:
kubectl get events --sort-by=.lastTimestamp
What does this show?
This displays cluster events sorted by time, giving you a complete story: the failed image pull attempts, the backoff retries, and then the successful rollback. In production, this command helps you build a timeline of an incident.
- Confirm the image reverted by running:
kubectl describe deployment nginx-deployment | grep Image
You should see nginx:1.27-alpine listed as the current image. The broken nginx:nonexistent-tag is gone.
Still seeing failing Pods?
Run kubectl get pods again. If any Pods are still in ImagePullBackOff, the rollback may still be in progress. Wait 10-20 seconds and check again.
If the problem persists, try running kubectl rollout undo deployment/nginx-deployment one more time. Sometimes a previous rollout attempt leaves an intermediate state.
help me fix my deployment that is still broken after rollback
You just completed the most valuable exercise in this project. You broke something on purpose, stayed calm, diagnosed the problem with real tools, and fixed it. That is the core loop of Kubernetes operations.
Next up, you will scale the deployment and watch Kubernetes self-heal when you manually kill a Pod.
Scale and Self-Heal
You've proven you can diagnose and fix a broken deployment. That's a critical skill for any Kubernetes practitioner.
Now let's see two more production behaviors in action: horizontal scaling and self-healing. Kubernetes doesn't just run your Pods. It actively maintains the exact number of replicas you ask for, replacing any that disappear.
In this step, get ready to:
- Scale the deployment up to 5 replicas.
- Observe Kubernetes self-healing by deleting a Pod.
- Clean up all resources from your cluster.
Scale up to 5 replicas
Your deployment currently has 3 replicas. In production, you'd scale up to handle more traffic. Let's increase the replica count and watch Kubernetes spin up the new Pods.
- Scale the deployment to 5 replicas by running this command:
kubectl scale deployment/nginx-deployment --replicas=5
- Verify that all 5 Pods are running by running:
kubectl get pods
You should see 5 Pods listed, all with a Running status. Two new Pods appeared almost instantly.
What just happened?
The kubectl scale command told the Deployment's controller to change the desired replica count from 3 to 5. Kubernetes immediately created 2 new Pods to match that desired state.
This is horizontal scaling. Instead of making a single Pod bigger, you add more identical Pods to distribute the workload.
Not seeing 5 Running Pods?
If some Pods show Pending, your node may need a moment to pull the image for the new Pods. Wait a few seconds and run kubectl get pods again.
If you see an error about the deployment not being found, make sure the rollback from the previous step completed successfully.
Why aren't my Pods scaling up?
Delete a Pod and observe self-healing
Kubernetes constantly monitors your Pods. If any Pod disappears, the Deployment controller notices the actual replica count no longer matches the desired count and immediately creates a replacement.
- First, note the names of your running Pods by running:
kubectl get pods
- Pick any Pod name from the list and delete it by running this command:
kubectl delete pod [[POD_NAME="one of your nginx-deployment Pod names"]]
- Immediately check the Pods to see the self-healing in action by running:
kubectl get pods
You should still see 5 Pods. One will be brand new (with a different name and a very recent AGE value). Kubernetes detected the missing Pod and created a replacement within seconds.
Why is this called self-healing?
You told Kubernetes you want 5 replicas. When you killed one, the count dropped to 4. The Deployment controller noticed the mismatch and immediately scheduled a new Pod to bring the count back to 5.
This happens automatically in production too. If a node crashes or a container runs out of memory, Kubernetes replaces the affected Pods without any manual intervention.
Don't see a replacement Pod?
If you still see only 4 Pods, wait a moment and run kubectl get pods again. The replacement usually appears within a second or two.
Make sure you copied one of the actual Pod names from your output. Pod names look like nginx-deployment-xxxxxxxxx-xxxxx with random characters at the end.
My Pod didn't get replaced after deletion. What's wrong?
Clean up all resources
You've deployed, scaled, updated, broken, fixed, and healed your application. Time to clean up the cluster so it's fresh for whatever comes next.
- Delete the Service by running this command:
kubectl delete -f nginx-service.yaml
- Delete the Deployment by running:
kubectl delete -f nginx-deployment.yaml
- Verify that no user resources remain in the default namespace by running:
kubectl get all
You should see only the kubernetes ClusterIP service (the built-in API server endpoint). Your nginx Deployment, Pods, and Service are all gone.
Why delete with -f instead of by name?
Using kubectl delete -f <file> deletes everything defined in that YAML file. This is the cleanest approach because it mirrors how you applied the resources. It also handles cases where a single YAML file defines multiple resources.
Seeing a 'not found' error?
Make sure your terminal is in the project directory that contains nginx-service.yaml and nginx-deployment.yaml. Run ls to confirm both files are visible.
If the resource was already deleted (for example by running the command twice), the error is harmless. Proceed to the verification step.
I'm getting errors when trying to delete my Kubernetes resources. What should I check?
Secret mission
Namespaces and Resource Limits
In production, teams don't dump everything into the default namespace. They isolate workloads and enforce resource constraints so no single container can hog the cluster. Can you create a staging namespace, deploy a second app, and enforce CPU/memory limits automatically?
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely on your local machine using Rancher Desktop. There are no cloud resources or ongoing costs to worry about.
Decide whether to keep your project files for reference, pause Rancher Desktop to free up system resources, or delete the project directory entirely.
Resources you used:
- Project directory on your Desktop containing nginx-deployment.yaml, nginx-service.yaml, limitrange.yaml, and httpd-deployment.yaml.
- Rancher Desktop application (pre-installed, running the k3s Kubernetes cluster in a local VM).
Keep everything running
No action needed. Choose this if you plan to keep experimenting with Kubernetes on your local cluster.
- Your YAML files remain on your Desktop for reference or reuse.
- Rancher Desktop continues running its k3s cluster. The Kubernetes resources (Deployments, Services, namespace) were already cleaned up during the project steps.
- Rancher Desktop uses system memory for its VM while running. You can quit and relaunch it anytime without losing your files.
Pause - I'll come back to this later
Shut down Rancher Desktop to free up the memory and CPU its VM uses. Your YAML files stay on disk.
- Right-click the Rancher Desktop icon in your menu bar and select Quit Rancher Desktop.
- Your project YAML files remain on your Desktop. When you're ready to return, relaunch Rancher Desktop and your cluster starts back up automatically.
Delete - I don't want to use this again
Remove all project files from your machine. This does not uninstall Rancher Desktop itself.
- Delete your project directory by running these commands in your terminal:
cd ~/Desktop
rm -rf [[PROJECT_FOLDER="your project folder name (e.g. k8s-homelab)"]]
- Confirm the folder is gone by running:
ls ~/Desktop
- Your project folder should no longer appear in the output.
Nice Work!
Nice Work!
You did it. You're not just reading about Kubernetes anymore. You're operating it.
You've taken your Rancher Desktop cluster from idle to battle-tested. You deployed, scaled, updated, broke, and fixed a real application using the exact same commands practitioners use in production every day.
Here's what you accomplished:
- Deployed a multi-replica application from YAML and exposed it with a Service to access it locally via port-forwarding.
- Performed a rolling update between image variants and rolled it back to the previous version with a single command.
- Intentionally broke a deployment with a bad image tag, then diagnosed and fixed it using kubectl describe, kubectl logs, and kubectl rollout undo.
- Secret Mission: Created an isolated namespace with a LimitRange to enforce automatic resource constraints on every Pod.
Ready to quiz yourself?