Lab: Hello World
This lab will walk you through deploying a very simple "Hello World" web app.
Preparing your environment
Start by starting your local minikube cluster:
Then clone this repo and cd into this directory:
git clone https://github.com/99/meetup-workshop cd meetup-workshop
We are now ready to deploy our Hello world web app!
Run a bare Pod
kubectl create -f pod.yaml
Breaking this down, we're using the Kubernetes CLI (kubectl) and we're telling it to create the resource specified in the given file (
From here, you can watch your Pod come up:
kubectl get pods -w
If you run this fast enough, you may see your Pod in a
Pending state. Finally, you'll eventually see it transition to
Poke the Pod
Now that your Pod is running, let's look at a few things:
kubectl describe pod hello-world
This will show you how the Pod has been configured, which image it's running, which port(s) it exposes (if any), any recent events, crashes, or restarts, which node it's running on, and much more.
If we'd like to view the logs from the application running in the Pod:
kubectl logs hello-world
Or perhaps we'd like to attach to a shell within the Pod (sort of like SSH'ing):
kubectl exec -it hello-world /bin/sh
You can also find and do all of this the Kubernetes dashboard:
Exposing the Pod
If you'd like to reach a specific port on a particular pod, you can port forward it to your local machine by doing something like:
# The port format here is LOCAL_PORT:REMOTE_PORT kubectl port-forward hello-world 5000:5000
However, this is not useful for a production application. Your Pods will be constantly coming and going, and port-forwarding to our machine does nothing for our users.
kubectl create -f service.yaml
After the Service is created, you can have minikube point your browser at it:
minikube service hello-world
This works a bit differently in production, but your traffic was routed through what amounts to a front-facing load balancer for the Pod(s) that matches the Service's selector.
It is rare that we use a stand-alone Pod by itself, primarily due to two attributes:
- A single Pod can't be cloned to scale up.
- If the Node that a Pod is running on dies, it will be marked as Terminated and will not be re-scheduled.
To simulate Node failure, let's delete your single Pod and try to go through our Service again:
kubectl delete pod hello-world # See the Pod terminate and goes away. Append a -w to watch in realtime. kubectl get pods # Try to reach your Service. minikube service hello-world
You'll see that we're now failing to connect, as expected. There are no Pods backing the Service. The users are furiously refreshing.
To handle our availability and scaling concerns, we instead use a Deployment object. A Deployment uses a
template to create the number of desired Pods (in the
replicas field). If a Pod is Terminated, the Deployment will ensure that it gets replaced. It also becomes easy to scale the Pod count up or down.
Let's start by creating the included Deployment:
kubectl create -f deployment.yaml
You should now be able to see a single Pod via:
kubectl get pods
Unlike with our bare Pod, you'll notice that the name has a long hash appended to the name. For example
hello-world-596fc9fdcf-x9rlz. To break this name down:
hello-world= The value in
596fc9fdcf= The ReplicaSet name. We'll gloss over this for now, but it'll correspond to a distinct "version" managed by the Deployment.
x9rlz= A unique hash, to avoid Pod name collisions.
The Pod acts just like our previous bare pod, but has a slightly different name.
Moving on, you should once again be able to reach your app through its service:
minikube service hello-world
If you recall how we deleted our single bare Pod earlier, let's go on ahead and attempt to do the same with the Pod that our Deployment created:
# Find the name of the Pod to delete, since it's now long and semi-random kubectl get pods # Delete the Pod (your name will be different) kubectl delete pod hello-world-xxxxxxxxx-yyyyy # Make sure the Pod Terminates and goes away. kubectl get pods
Depending on how quickly you get the updated Pod list, you'll either see a Terminating Pod and a new Pod, or just the new Pod (identifiable by its recent
AGE column). The Deployment as a
replica count of
1, so Kubernetes knows to replace any Terminated Pods.
However, there was a second or two after you deleted the Pod to where your imaginary users were unable to reach your app.
Let's reduce the likelihood of service disruptions by scaling the Deployment up!
# This will an open an editor. You'll want to edit the 'replicas' field # from 1 to 3. Save+Quit and your changes will be applied. kubectl edit deployment hello-world # Or you can run this shorter command: kubectl scale --replicas=3 deployment/hello-world # After doing one or the other: kubectl get pods
You should now see three Pods, two being newer than the other. You'll notice that the names have some overlap until the last hash.
You can now delete any of the three Pods without taking your app down!
Deploying a new version your app
Now it's time to deploy a new version of your smash hit, "Hello world!". Let's pivot a bit and greet this Meetup group instead:
# We'll re-open our editor. Edit the 'image' field's tag from 1.0 to 1.1. # Save+Quit and your changes will be applied. kubectl edit deployment hello-world # Let's re-visit your service: minikube service hello-world
You should now see "Hello Meetup Group!" instead of "Hello world!". We'll go into this in more detail later, but what happened:
- The initial state was three pods running version 1.0.
- After you made your changes, the Deployment spun up a fourth Pod running 1.1.
- Once the new Pod passed health checks, one of the 1.0 Pods was terminated.
- New Pods are continuously stood up, replacing the old ones until all Pods are running 1.1.
This completes our Kubernetes Workshop! To review:
Podis the unit of work in Kubernetes.
- A Pod's ports can be reached via
kubectl port-forwardor through a Service.
- We use a Deployment and its
templateto stamp out a desired number of
replicaPods. Unhealthy or terminated Pods get replaced for us with a Deployment.