Skip to main content

Deployments

Deployments are the most common workload controller for running stateless applications. They make sure your application always runs the desired number of Pods - automatically handling creation, scaling, updates, and recovery.

Instead of managing Pods manually, Deployments let Kubernetes:

  • Run multiple identical Pods for reliability and load distribution
  • Scale automatically by adjusting replica counts
  • Recover failed Pods without manual intervention
  • Perform rolling updates without downtime
  • Rollback easily to previous versions when needed

Creating a Deployment

Let's deploy the retail store UI using a deployment:

~/environment/eks-workshop/base-application/ui/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ui
labels:
app.kubernetes.io/created-by: eks-workshop
app.kubernetes.io/type: app
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ui
app.kubernetes.io/instance: ui
app.kubernetes.io/component: service
template:
metadata:
annotations:
prometheus.io/path: /actuator/prometheus
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
labels:
app.kubernetes.io/name: ui
app.kubernetes.io/instance: ui
app.kubernetes.io/component: service
app.kubernetes.io/created-by: eks-workshop
spec:
serviceAccountName: ui
securityContext:
fsGroup: 1000
containers:
- name: ui
env:
- name: JAVA_OPTS
value: -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/urandom
- name: METADATA_KUBERNETES_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: METADATA_KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: METADATA_KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
envFrom:
- configMapRef:
name: ui
securityContext:
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
image: "public.ecr.aws/aws-containers/retail-store-sample-ui:1.2.1"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 45
periodSeconds: 20
resources:
limits:
memory: 1.5Gi
requests:
cpu: 250m
memory: 1.5Gi
volumeMounts:
- mountPath: /tmp
name: tmp-volume
volumes:
- name: tmp-volume
emptyDir:
medium: Memory
A

kind: Deployment: Defines a Deployment controller

B

metadata.name: Name of the Deployment (ui)

C

spec.replicas: Desired number of pods (1 in this example)

D

spec.selector: Labels used to find managed Pods

E

spec.template: Pod template defining what each pod should looks like

The deployment ensures that the actual Pods always match this template.

Apply the Deployments:

~$kubectl apply -k ~/environment/eks-workshop/base-application/ui

Inspecting Deployment

Check deployment status:

~$kubectl get deployment -n ui
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
ui     1/1     1            1           30s

List the Pods created by the Deployment:

~$kubectl get pods -n ui
NAME                  READY   STATUS    RESTARTS   AGE
ui-6d5bb7b9c8-xyz12   1/1     Running   0          30s

Get detailed information:

~$kubectl describe deployment -n ui ui

Scaling Deployment

Scale up to 5 replicas:

~$kubectl scale deployment -n ui ui --replicas=5
~$kubectl get pods -n ui
NAME                  READY   STATUS    RESTARTS   AGE
ui-6d5bb7b9c8-abc12   1/1     Running   0          2m
ui-6d5bb7b9c8-def34   1/1     Running   0          12s
ui-6d5bb7b9c8-ghi56   1/1     Running   0          12s
ui-6d5bb7b9c8-arx97   1/1     Running   0          10s
ui-6d5bb7b9c8-uiv85   1/1     Running   0          10s
info

Kubernetes automatically spreads these Pods across available worker nodes for high availability.

Scale back down to 3 replicas:

~$kubectl scale deployment -n ui ui --replicas=3
~$kubectl get pods -n ui
NAME                  READY   STATUS    RESTARTS   AGE
ui-6d5bb7b9c8-abc12   1/1     Running   0          2m
ui-6d5bb7b9c8-def34   1/1     Running   0          12s
ui-6d5bb7b9c8-ghi56   1/1     Running   0          12s

Rolling Updates and Rollbacks

You can update a Deployment by changing the image version:

~$kubectl set image deployment/ui ui=public.ecr.aws/aws-containers/retail-store-sample-ui:v2 -n ui
~$kubectl get pods -n ui
NAME                  READY   STATUS         RESTARTS   AGE
ui-5989474687-5gcbt   1/1     Running        0          13m
ui-5989474687-dhk6q   1/1     Running        0          14s
ui-5989474687-dw8x8   1/1     Running        0          14s
ui-7c65b44b7c-znm9c   0/1     ErrImagePull   0          7s

You'll see a new pod created but with status ErrImagePull.

Now let's rollback the change

~$kubectl rollout undo deployment/ui -n ui
~$kubectl get pods -n ui
NAME                  READY   STATUS         RESTARTS   AGE
ui-5989474687-5gcbt   1/1     Running        0          13m
ui-5989474687-dhk6q   1/1     Running        0          14s
ui-5989474687-dw8x8   1/1     Running        0          14s

Rolling updates let you update your application gradually without downtime, while Kubernetes ensures new Pods match the desired state. If something goes wrong — like an invalid image — you can rollback safely to the previous working version, keeping your application available and stable.

This demonstrates how Deployments simplify application updates, maintain availability, and reduce risk in production environments.

Key Points to Remember

  • Deployments manage multiple identical pods automatically
  • Use deployments instead of creating pods directly in production
  • Scaling is as simple as changing the replica count
  • Pod names include the deployment name plus random suffixes
  • Deployments are perfect for stateless applications like web apps and APIs