Deploy, Scale, and Update on Kubernetes
Deploy, scale, and roll back a web app on a local Kubernetes cluster.
Introduction
30 Second Summary
Every popular app you use has software running across dozens of machines to stay fast and available. Kubernetes is the technology that manages all of that, deciding where to run each piece and replacing anything that crashes.
In this project, you will deploy a web application to a local Kubernetes cluster on your Mac. You will scale it across multiple replicas, perform a zero-downtime rolling update, and roll it back when something goes wrong.
What You'll Build
A fully functional local Kubernetes environment where you deploy, expose, scale, update, and roll back a containerized web application using the same workflows tested on the CKAD certification exam.
By the end of this project, you'll have:
- A running Minikube cluster with a Deployment managing multiple replicas of a web application.
- A Service exposing your app externally with load balancing across pods.
- Hands-on experience with both imperative kubectl commands and declarative YAML manifests for managing Kubernetes resources.
- Secret Mission: Add resource limits, health probes, and a ConfigMap to make your deployment production-ready.
Do I need anything before starting?
You need Docker Desktop installed on your Mac and basic comfort with the terminal. No prior Kubernetes experience is required.
Install Minikube and kubectl
To deploy and manage applications on Kubernetes, you need two things: a cluster to run your workloads, and a tool to talk to that cluster.
In this step, you will install Minikube (which creates a local single-node Kubernetes cluster on your Mac) and kubectl (the command-line tool that sends instructions to any Kubernetes cluster). Once both are installed, you will start your cluster and confirm everything is healthy.
In this step, get ready to:
- Install Minikube and kubectl via Homebrew.
- Start a local Kubernetes cluster using Docker Desktop as the driver.
- Verify the cluster is healthy and kubectl can communicate with it.
Install Minikube and kubectl via Homebrew
Homebrew is the fastest way to install both tools on macOS. You will install them separately so you can verify each one independently.
- Install Minikube by running this command:
brew install minikube
- Install kubectl by running this command:
brew install kubectl
- Verify Minikube installed correctly by running:
minikube version
- Verify kubectl installed correctly by running:
kubectl version --client
Both commands should print version information confirming the tools are installed.
✔️ I see version numbers for both tools
Both tools are installed and ready. Move on to the next substep.
ⓧ I see command not found
Homebrew may not be installed, or the install did not complete. Try these steps:
- Confirm Homebrew itself is installed by running:
- If brew is not found, install Homebrew first from https://brew.sh.
- Once Homebrew is working, re-run brew install minikube and brew install kubectl.
brew --version
Start your Minikube cluster
Minikube needs a container runtime to create your cluster. Since you already have Docker Desktop running, Minikube will automatically detect and use it as the driver.
- Start your local Kubernetes cluster by running:
minikube start
What does this command do?
Minikube creates a single-node Kubernetes cluster inside a Docker container on your Mac. It downloads the Kubernetes components, configures networking, and sets up kubectl to point at the new cluster automatically.
This takes 1-2 minutes on the first run because it needs to download container images. Subsequent starts are much faster.
- Once the command finishes, verify the cluster is healthy by running:
minikube status
- Confirm the node is ready by running:
kubectl get nodes
You should see minikube status reporting "Running" for host, kubelet, and apiserver. The kubectl get nodes output should show one node with STATUS "Ready".
✔️ I see Running and Ready
Your cluster is up and healthy. Move on to the next substep.
ⓧ I see an error or the cluster won't start
- Make sure Docker Desktop is running. Open Docker Desktop and check that the whale icon in your menu bar shows a green "running" status.
- If you see a message about insufficient resources, check that your machine meets the minimum requirements: 2 CPUs, 2GB of free memory, and 20GB of free disk space.
- If the cluster started but kubectl get nodes shows "NotReady", wait 30 seconds and try again. The node needs time to initialize.
Explore the cluster
Now that your cluster is running, confirm that kubectl can communicate with the Kubernetes API server and that the control plane components are healthy.
- Check the cluster connection details by running:
kubectl cluster-info
- List all pods running across every namespace by running:
kubectl get po -A
What does this output show?
The kubectl cluster-info command confirms where the Kubernetes control plane and CoreDNS are running. This proves kubectl can reach your cluster.
The kubectl get po -A command shows the system pods that make Kubernetes work: CoreDNS (for DNS resolution inside the cluster), etcd (the database storing cluster state), the API server, and the scheduler.
You should see several pods in the kube-system namespace, all with STATUS "Running".
Seeing pods in Pending or CrashLoopBackOff?
- Wait 60 seconds and run kubectl get po -A again. Some system pods need time to fully initialize on first start.
- If pods remain unhealthy, try stopping and restarting the cluster with minikube stop followed by minikube start.
Still stuck? Help me troubleshoot my Minikube cluster pods
Your local Kubernetes cluster is running and kubectl can talk to it. Next up, you will deploy your first application to this cluster.
Deploy Your First Application
Your local Kubernetes cluster is up and running with one healthy node. Now it's time to deploy a real application to it.
In Kubernetes, you don't launch containers directly. You create a Deployment that tells the cluster what container image to run and how to manage it. If a container crashes, the Deployment automatically restarts it.
In this step, get ready to:
- Create a Deployment using imperative kubectl commands.
- Inspect the Deployment's state, events, and logs.
- Access the running app from your local machine via kubectl proxy.
Create a Deployment imperatively
The imperative approach uses a single command to create resources directly. This is the fastest way to get something running and is useful for quick experiments.
- Create a Deployment called kubernetes-bootcamp by running this command:
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
What does this command do?
- kubectl create deployment tells Kubernetes to create a new Deployment resource.
- kubernetes-bootcamp is the name you're giving this Deployment.
- --image=gcr.io/google-samples/kubernetes-bootcamp:v1 specifies the container image to run. Kubernetes pulls this image and starts a container from it.
- Behind the scenes, Kubernetes creates a Pod (the smallest deployable unit) to run your container. The Deployment watches over it and restarts it if anything goes wrong.
- Confirm your Deployment is running by running these commands:
kubectl get deployments
kubectl get pods
You should see kubernetes-bootcamp with 1/1 READY in the deployments output. The pod's STATUS should show Running (this may take a few seconds while the image is pulled).
Pod stuck in ContainerCreating?
- This usually means Kubernetes is still pulling the container image. Wait 30 seconds and run kubectl get pods again.
- If the pod shows ErrImagePull or ImagePullBackOff, check your internet connection. Minikube needs internet access to pull the image.
- Make sure Docker Desktop is still running. Minikube uses Docker to run containers.
Help me debug why my pod isn't starting
Inspect the Deployment
Now that your app is running, you can inspect what Kubernetes created under the hood. The describe command shows a Deployment's desired state, current state, and events.
- View detailed information about your Deployment by running:
kubectl describe deployment kubernetes-bootcamp
What does describe show?
The output includes the Deployment's labels, selectors, replicas, strategy, and events. The "Events" section at the bottom is especially useful for debugging. It shows every action Kubernetes took to reach the desired state.
This is how you debug deployments in both the real world and on the CKAD exam.
- View cluster-wide events by running:
kubectl get events
This shows a timeline of everything that happened in your cluster, including image pulls, pod scheduling, and container starts.
- View your application's logs. First, grab your pod name from kubectl get pods, then run:
kubectl logs [[PODNAME="your pod name from kubectl get pods"]]
The logs show output from the application running inside the container. This is your first tool for understanding what your app is doing.
Access the app via kubectl proxy
By default, Pods are only reachable inside the cluster's private network. The kubectl proxy command opens a gateway between your terminal and the cluster's API, letting you reach your app without creating a full Service yet.
- Open a new terminal tab by pressing **Cmd+T** (macOS) or **Ctrl+Shift+T** (Windows).
- In the new terminal, start the proxy by running:
kubectl proxy
What does kubectl proxy do?
It creates a local proxy on localhost:8001 that forwards requests to the Kubernetes API server. This terminal must stay open for the proxy to keep running.
- Switch back to your first terminal tab.
- Verify you can reach the app by running this curl command:
curl http://localhost:8001/api/v1/namespaces/default/pods/$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{end}}'):8080/proxy/
What's happening in this curl command?
- The $(kubectl get pods -o go-template ...) part automatically retrieves your pod's name so you don't have to type it manually.
- The URL hits the Kubernetes API proxy at localhost:8001, which routes the request to your pod's port 8080.
- The app responds with its pod name and version number, confirming it's alive and reachable.
You should see a response like "Hello Kubernetes bootcamp!" with the pod name and v=1.
Not getting a response?
- Make sure kubectl proxy is still running in your second terminal tab. If it stopped, run it again.
- Check that you're running the curl command in your first terminal, not the one running the proxy.
- If you see a connection refused error, wait a moment for the proxy to fully start, then try the curl again.
Why can't I reach my app through kubectl proxy?
Your application is deployed and reachable through the API proxy. Next up, you'll expose it with a proper Service so it gets a stable URL and can handle traffic from outside the cluster.
Expose the App with a Service
Your app is running inside the cluster, but right now it is completely isolated from the outside world. Pods get their own internal IP addresses, but those IPs are only reachable from within the cluster.
To make your app accessible from your browser or terminal, you need a Service. A Service creates a stable network endpoint that routes traffic to your Pods, even as Pods are created or destroyed.
In this step, get ready to:
- Expose your Deployment with a NodePort Service.
- Access the app from outside the cluster using a routable URL.
- Understand how labels and selectors connect Services to Pods.
Create a Service
A NodePort Service exposes your app on a port across all nodes in the cluster. This makes the app reachable from outside the cluster network.
- Expose your Deployment as a NodePort Service on port 8080 by running this command:
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
What does this command do?
This tells Kubernetes to create a Service that forwards external traffic to port 8080 on your Pods. The NodePort type assigns a random port in the 30000-32767 range that maps to the pod's port.
- Verify the Service was created by running:
kubectl get services
- Get more detail about your new Service by running:
kubectl describe services/kubernetes-bootcamp
You should see the Service listed with TYPE NodePort and a port mapping like 8080:3XXXX/TCP in the output. The describe output shows the assigned NodePort, the Endpoints (your pod's IP), and the Selector that connects the Service to Pods.
Seeing 'already exists'?
If you get an error saying the service already exists, it means you may have run the expose command twice. Delete the existing service with kubectl delete service kubernetes-bootcamp and try again.
If the command hangs, make sure your Minikube cluster is still running with minikube status.
help me troubleshoot my kubectl expose command
Access the app in your browser
On macOS with the Docker driver, containers run inside a Linux VM that is not directly reachable from your host. Minikube provides a built-in command to tunnel traffic and give you a routable URL.
- Get a routable URL for your Service by running:
minikube service kubernetes-bootcamp --url
Why not use the node IP directly?
Because you are using a Docker driver on darwin, the terminal needs to be open to run it. The minikube service command creates a tunnel from your Mac to the container network and outputs a URL like http://127.0.0.1:XXXXX.
- Test that the app responds by curling the URL:
curl $(minikube service kubernetes-bootcamp --url)
You should see a response like "Hello Kubernetes bootcamp!" along with the pod name and version. Your application is now accessible from outside the cluster.
Not getting a response?
Make sure the minikube service command completed without errors. If you see a connection refused error, wait a few seconds and try again. The tunnel takes a moment to establish.
Confirm your pod is still running with kubectl get pods. If the pod shows a status other than Running, the app cannot respond to requests.
help me access my Kubernetes app via minikube service
Understand labels and selectors
How does the Service know which Pods to send traffic to? The answer is labels. Labels are key/value pairs attached to Kubernetes objects. A Service uses a selector to find all Pods that match a specific label.
- See the labels on your Deployment by running:
kubectl describe deployment kubernetes-bootcamp
- Query Pods using the label selector by running:
kubectl get pods -l app=kubernetes-bootcamp
- Query Services using the same label by running:
kubectl get services -l app=kubernetes-bootcamp
How do labels connect Services to Pods?
When you created the Deployment, Kubernetes automatically added the label app=kubernetes-bootcamp to every Pod it manages. When you created the Service with kubectl expose, it inherited that same label as its selector.
The Service continuously watches for Pods matching its selector. If a Pod is added or removed, the Service automatically updates its list of endpoints. This is how Kubernetes keeps traffic flowing to healthy Pods without manual configuration.
You should see your pod listed when filtering by label, and your Service listed with the same label. This confirms the connection between the Service and the Pods it routes to.
Your app is now exposed and reachable from outside the cluster. Next up, you will scale the Deployment to multiple replicas and watch Kubernetes load-balance traffic across them.
Scale and Observe Self-Healing
Your app is live and accessible outside the cluster through a Service. In production, running a single instance of your application means a single point of failure.
In this step, you'll scale your Deployment to 4 replicas and watch Kubernetes distribute traffic across them. Then you'll delete a pod and watch the cluster heal itself automatically.
In this step, get ready to:
- Scale the Deployment to 4 replicas.
- Verify load balancing across pods.
- Test self-healing by deleting a pod.
Scale to 4 replicas
Right now your Deployment runs a single Pod. If that pod crashes, there's a brief outage before Kubernetes replaces it. Scaling to multiple replicas means your app stays available even when individual pods fail.
- Scale your Deployment to run 4 instances of the app by running these commands:
kubectl scale deployments/kubernetes-bootcamp --replicas=4
kubectl get deployments
kubectl get pods -o wide
What do these commands do?
- kubectl scale tells Kubernetes to adjust the desired replica count for your Deployment from 1 to 4.
- kubectl get deployments confirms the Deployment now shows 4/4 READY.
- kubectl get pods -o wide lists all pods with their individual IP addresses, proving Kubernetes created 4 separate instances.
You should see 4 pods listed, each with STATUS "Running" and a different IP address in the IP column.
Not seeing 4 pods running?
- If some pods show Pending or ContainerCreating, wait 10-15 seconds and run kubectl get pods again. Kubernetes needs a moment to pull the image for new pods.
- If pods show ErrImagePull, check that your Minikube cluster has internet access by running minikube ssh -- curl -I https://gcr.io.
Still stuck? Help me figure out why my pods aren't starting after scaling.
Verify load balancing
The Service you created in the previous step automatically discovers all pods with the matching label. It distributes incoming requests across all 4 replicas without any extra configuration.
- Hit the Service URL multiple times and observe traffic going to different pods by running:
curl $(minikube service kubernetes-bootcamp --url)
curl $(minikube service kubernetes-bootcamp --url)
curl $(minikube service kubernetes-bootcamp --url)
What should I see?
Each response includes the pod name that handled the request. You should see different pod names across the three responses, proving the Service distributes requests across all replicas.
If you see the same pod name every time, try running the commands a few more times. The Load Balancer distribution is not perfectly round-robin, so occasional repeats are normal.
Curl command returning an error?
- Make sure the minikube service tunnel is still open. If you closed that terminal, run minikube service kubernetes-bootcamp --url again in a new terminal window and keep it open.
- If you see "connection refused", wait a few seconds for all pods to finish starting and try again.
Need more help? Help me troubleshoot my curl command against the Kubernetes Service.
Test self-healing
Kubernetes continuously monitors the actual state of your cluster against the desired state. Your Deployment says "I want 4 replicas." If a pod disappears for any reason, Kubernetes immediately spins up a replacement.
- First, get the list of running pods by running:
kubectl get pods
- Pick any one of the pod names from the output. Delete it and immediately check the pod list again by running:
kubectl delete pod [[PODNAME="one of the pod names from kubectl get pods"]]
kubectl get pods
What is happening here?
The moment you delete a pod, the Deployment's controller detects that only 3 replicas exist instead of the desired 4. It immediately creates a new pod to bring the count back to 4.
This is self-healing in action. You'll see the deleted pod gone and a brand new pod (with a different name) in ContainerCreating or Running status.
Within seconds, you should see 4 pods listed again. The replacement pod has a different name than the one you deleted.
Still seeing only 3 pods?
- Run kubectl get pods again after waiting 5-10 seconds. The new pod may still be pulling its container image.
- If no new pod appears at all, check that your Deployment still exists by running kubectl get deployments. The READY column should show 4/4 (or 3/4 while recovering).
Still stuck? Help me understand why Kubernetes isn't replacing my deleted pod.
Your app is running at scale and can recover from failures automatically. Next up, you'll perform a rolling update to deploy a new version of the app with zero downtime.
Rolling Updates and Rollbacks
Your app is scaled to 4 replicas with automatic self-healing. But what happens when you need to ship a new version of your app?
In production, you cannot take all pods offline to deploy a new version. Kubernetes solves this with rolling updates, which gradually replace old pods with new ones. In this step, you will perform a zero-downtime update, simulate a failed deployment, roll it back safely, and then write a declarative YAML manifest that captures your desired state in a file.
In this step, get ready to:
- Perform a rolling update from v1 to v2 with zero downtime.
- Trigger a failed deployment and roll back to the last working version.
- Write a declarative YAML manifest and apply it with kubectl apply.
Perform a rolling update
A rolling update incrementally replaces old pods with new ones. At no point are all pods offline, so your users experience zero downtime.
- Update the application image from v1 to v2 by running this command:
kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=docker.io/jocatalin/kubernetes-bootcamp:v2
- Watch the rollout progress by running these commands:
kubectl rollout status deployments/kubernetes-bootcamp
kubectl get pods
You should see output ending with deployment "kubernetes-bootcamp" successfully rolled out. All 4 pods should show STATUS "Running" with new names (the old pods were replaced).
- Verify the app is now serving v2 by running:
curl $(minikube service kubernetes-bootcamp --url)
The response now shows v=2 along with the pod name.
What just happened?
Kubernetes gradually terminated old v1 pods and created new v2 pods. At every moment during the rollout, some pods remained available to serve traffic.
This is the default rolling update strategy. It ensures maximum 1 pod unavailable and 1 new pod created at a time, so your service never goes fully offline.
Still seeing v=1 in the response?
The rollout may still be in progress. Run kubectl rollout status deployments/kubernetes-bootcamp and wait for it to complete before curling again.
If the minikube service URL is no longer responding, check that the terminal running minikube service from the previous step is still open. Re-run minikube service kubernetes-bootcamp --url if needed.
Help me troubleshoot my rolling update
Trigger a failed update and rollback
Not every deployment succeeds. Let's simulate what happens when you push a broken image, and then recover safely.
- Simulate a bad deployment by setting an image tag that does not exist:
kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
- Check the pod status by running:
kubectl get pods
You should see some pods with status ImagePullBackOff or ErrImagePull. The old pods remain running because Kubernetes will not terminate them until new pods are ready. This is the safety of rolling updates.
Why are old pods still running?
Kubernetes only removes old pods after new ones pass their readiness checks. Since the v10 image does not exist, the new pods can never become ready. Your users continue hitting the healthy v2 pods throughout the failed rollout.
- Roll back to the last working version by running these commands:
kubectl rollout undo deployments/kubernetes-bootcamp
kubectl get pods
kubectl rollout status deployments/kubernetes-bootcamp
You should see deployment.apps/kubernetes-bootcamp rolled back followed by all 4 pods returning to Running status with v2.
- Confirm the app is serving v2 again by running:
curl $(minikube service kubernetes-bootcamp --url)
The response should show v=2 again, confirming the rollback was successful.
Rollback not working?
If kubectl get pods still shows pods in ImagePullBackOff after the undo, wait a few seconds and run kubectl get pods again. The rollback is asynchronous and may take a moment to complete.
Help me debug my Kubernetes rollback
Write a declarative YAML manifest
So far you have been using imperative commands to manage your Deployment. The declarative approach captures your desired state in a YAML file that you can version-control, review, and reapply.
This is how real-world Kubernetes is managed. It is also the approach tested on the CKAD exam.
- Create a new file called deployment.yaml in your current directory. You can use any text editor (nano, vim, VS Code, or your editor of choice).
- Paste the following content into deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubernetes-bootcamp
spec:
replicas: 4
selector:
matchLabels:
app: kubernetes-bootcamp
template:
metadata:
labels:
app: kubernetes-bootcamp
spec:
containers:
- name: kubernetes-bootcamp
image: docker.io/jocatalin/kubernetes-bootcamp:v2
ports:
- containerPort: 8080
What does this YAML do?
- apiVersion and kind tell Kubernetes this is a Deployment resource using the apps/v1 API.
- replicas: 4 declares that 4 pods should always be running.
- selector.matchLabels tells the Deployment which pods belong to it (those with the label app: kubernetes-bootcamp).
- template is the blueprint for each pod, specifying the container image and port.
- Save deployment.yaml.
- Apply the manifest by running:
kubectl apply -f deployment.yaml
You should see output confirming the deployment was configured. Since your cluster already has this Deployment running with the same settings, Kubernetes reconciles to the desired state without restarting pods.
Why use kubectl apply instead of kubectl create?
The kubectl apply -f command is idempotent. You can run it repeatedly with changes and Kubernetes reconciles to the desired state each time. This makes it safe to re-run after editing your file.
This file can live in version control, making your infrastructure repeatable and reviewable. This is the foundation of GitOps workflows.
- Verify your Deployment is still healthy by running:
kubectl get deployments
kubectl get pods
You should see 4/4 pods READY and all pods in Running status.
Seeing an error when applying?
Make sure the indentation in your YAML is correct. YAML uses spaces (not tabs) for indentation. Each level is 2 spaces.
Check that the file is saved as deployment.yaml in the directory where you are running kubectl. Run ls to confirm the file exists.
Help me fix my deployment YAML
✔️ Awesome, I've got everything!
Great. Make sure you have saved deployment.yaml and that kubectl get deployments shows 4/4 READY.
ⓧ I'd like to double check the full code
Here is the complete deployment.yaml for comparison:
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubernetes-bootcamp
spec:
replicas: 4
selector:
matchLabels:
app: kubernetes-bootcamp
template:
metadata:
labels:
app: kubernetes-bootcamp
spec:
containers:
- name: kubernetes-bootcamp
image: docker.io/jocatalin/kubernetes-bootcamp:v2
ports:
- containerPort: 8080
Secret mission
Production-Ready Configuration
Your deployment works, but it is not production-ready. Real Kubernetes clusters enforce resource limits, check container health with probes, and externalize configuration with ConfigMaps. Add all three to your deployment and prove they work.
Clean Up Your Resources
Clean Up Your Resources
Everything in this project runs locally on your machine, so there are no ongoing cloud costs. However, the Minikube cluster uses Docker Desktop resources (CPU and RAM) while running. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- Minikube cluster running locally (uses Docker Desktop CPU and RAM while active).
- Kubernetes Deployments, Services, and ConfigMaps inside the cluster.
- The deployment.yaml file on disk.
- Minikube and kubectl CLI tools installed via Homebrew.
Keep everything running
No action needed. Choose this if you are still actively practising Kubernetes commands or plan to continue experimenting soon.
- Your Minikube cluster stays running and uses Docker Desktop resources (CPU and RAM) in the background.
- All Deployments, Services, and ConfigMaps remain intact inside the cluster.
- You can pick up where you left off at any time by opening a terminal and running kubectl commands.
Pause - I'll come back to this later
Freeze or stop the cluster to free up CPU and RAM without losing your work. Your Deployments, Services, and ConfigMaps remain saved on disk.
- To pause the cluster (frees CPU but keeps disk state), run:
minikube pause
- To fully stop the cluster (frees both CPU and RAM), run:
minikube stop
- When you are ready to resume, run minikube start to bring the cluster back with all your resources intact.
Delete - I don't want to use this again
Remove all project resources and start fresh. This deletes the cluster, all Kubernetes resources inside it, and the local files you created.
- Delete the Minikube cluster and all Kubernetes resources (Deployments, Services, ConfigMaps) inside it by running:
minikube delete
- Delete the deployment.yaml file by running:
rm deployment.yaml
- Optionally, uninstall Minikube and kubectl from your machine by running:
brew uninstall minikube
brew uninstall kubectl
Nice Work!
Nice Work!
Nice work! You just deployed, scaled, updated, and rolled back a real application on a local Kubernetes cluster. These are the exact workflows tested on the CKAD exam and expected in DevOps interviews.
You've learned how to:
- Deploy and expose a web application on Kubernetes using both imperative kubectl commands and declarative YAML manifests.
- Scale to multiple replicas with automatic load balancing and verify Kubernetes self-healing by deleting pods and watching them recover.
- Perform a zero-downtime rolling update and safely roll back a failed deployment to a known-good version.
- Secret Mission: Added resource limits, liveness/readiness probes, and a ConfigMap to make your deployment production-ready.
Ready to quiz yourself?