KUBERNETES TUTORIAL Kubernetes: Deploy your first app (Deployment + pods)
You'll write a minimal Deployment, `kubectl apply` it, watch three pods schedule and become Ready, then open your app in the browser.*
What we're doing
When you hit Start, you're on a clean 3-node Kubernetes cluster (nothing deployed yet). You'll write a short Deployment manifest, apply it, watch the pods come up live, and reach the running app in your browser. The app image is already loaded on the cluster, so your apply comes up in seconds.
Watch the video first, then run these as you read. kubectl is already set up; nothing needs sudo. This is the happy path: write it, apply it, watch it work.
The idea: you describe, Kubernetes builds
You don't start things by hand in Kubernetes. You write down what you want in a YAML file (a Deployment), hand it over with kubectl apply, and Kubernetes makes it real and keeps it that way. That's the whole move.
Step 1: Read the manifest
The provided manifest is already on the box. Open it:
cat ~/web-deployment.yaml
apiVersion: apps/v1 # which API group this object belongs to
kind: Deployment # what KIND of object to create
metadata:
name: web # the Deployment's name
spec:
replicas: 3 # how many copies (Pods) to keep running
selector:
matchLabels:
app: web # "my Pods are the ones labeled app=web"
template: # the BLUEPRINT for each Pod:
metadata:
labels:
app: web # the label stamped on every Pod
spec:
containers:
- name: hello
image: nginxdemos/hello:0.4 # the app to run
ports:
- containerPort: 80 # the port it listens on
Read it top to bottom:
apiVersion+kind, what this is: a Deployment.metadata.name, its name:web.spec.replicas, how many copies you want: 3.spec.template, the blueprint for each Pod, its image (nginxdemos/hello) and port (80).spec.selector, how the Deployment recognises its Pods.
Notice
selector.matchLabels.app: webandtemplate.metadata.labels.app: webare the same. That's the link between the Deployment and its Pods. More on that in Step 5.
Step 2: Apply it
kubectl apply -f ~/web-deployment.yaml
deployment.apps/web created
apply means "make the cluster match this file." One line of output, but behind it Kubernetes created three things: the Deployment, a ReplicaSet (which does the counting), and the three Pods. You manage the Deployment; it manages the rest.
Step 3: Watch the pods come up
kubectl get pods -w
NAME READY STATUS AGE
web-xxxxxxxxxx-aaaaa 0/1 Pending 1s
web-xxxxxxxxxx-aaaaa 0/1 ContainerCreating 2s
web-xxxxxxxxxx-aaaaa 1/1 Running 4s
...
-w means watch, the list stays live. Each Pod climbs the same ladder:
- Pending, the scheduler is picking a node.
- ContainerCreating, the kubelet is starting the container (fast here, the image is pre-loaded).
- Running, the process is up.
- Ready 1/1, it passed its check and can serve.
Give it a few seconds, then Ctrl+C to stop watching. (Those are the scheduler and kubelet from FUND-002, doing their jobs on your app.)
Step 4: Confirm it
kubectl get deployment web
NAME READY UP-TO-DATE AVAILABLE AGE
web 3/3 3 3 30s
READY 3/3, three asked for, three ready. You declared a wish and the cluster made it true. And the pods:
kubectl get pods -o wide
Three web-... pods, Running, spread across the worker nodes (check the NODE column).
Step 5: How the Deployment finds its pods (labels)
A Deployment doesn't track its pods by name (names are random and pods come and go). It tracks them by label. See them:
kubectl get pods --show-labels # every web pod carries app=web
kubectl get pods -l app=web # select pods by that label (what the Deployment does)
-l app=web means "pods with this label," and you get your three. That shared app=web is the string tying the Deployment to its pods, which is exactly why the selector and the template label in the manifest must match. If they didn't, the Deployment couldn't find its own pods, and Kubernetes would reject the file.
Step 6: See it live in the browser
The pods run on an internal cluster network your browser can't reach. Open a quick tunnel with port-forward:
kubectl port-forward deployment/web 8080:80
This forwards port 8080 on this box straight into a web pod's port 80. Leave it running. Now add port 8080 in the environment and open it in your browser.
You'll see a "Hello World" page that prints the Server name, which is the pod's name. That's the proof: your app is real and serving, and there really are separate copies of it. Stop the forward with Ctrl+C when done.
port-forwardis a developer's quick way to reach a pod. The proper way to expose an app (a Service) comes in a later tutorial; you don't need it to see your work here.
What you just did
| Object | What it is |
|---|---|
Deployment (web) |
your declaration: "keep 3 of this image running" |
| ReplicaSet | created by the Deployment; keeps the count at 3 |
| Pods (x3) | created by the ReplicaSet; run your container |
One file, one apply, three running copies of your app.
Cheat sheet
cat ~/web-deployment.yaml # the manifest
kubectl apply -f ~/web-deployment.yaml # create it
kubectl get pods -w # watch Pending -> Running -> Ready
kubectl get deployment web # READY 3/3
kubectl get pods -o wide # the pods + their nodes
kubectl get pods -l app=web # select pods by label
kubectl port-forward deployment/web 8080:80 # then open http://VM:8080
The one thing to remember: you describe what you want in a Deployment file, kubectl apply it, and Kubernetes builds and keeps three running pods. Write it, apply it, watch it run.
Next tutorial: organising your resources with namespaces.
What's next
Start KUBERNETES