163 lines
5.6 KiB
Markdown
163 lines
5.6 KiB
Markdown
# Assignment
|
||
|
||
There is a production deployment planned for next week. The Nautilus DevOps team wants to test the deployment update and rollback on Dev environment first so that they can identify the risks in advance. Below you can find more details about the plan they want to execute.
|
||
|
||
|
||
|
||
Create a namespace xfusion. Create a deployment called httpd-deploy under this new namespace, It should have one container called httpd, use httpd:2.4.27 image and 3 replicas. The deployment should use RollingUpdate strategy with maxSurge=1, and maxUnavailable=2. Also create a NodePort type service named httpd-service and expose the deployment on nodePort: 30008.
|
||
|
||
|
||
Now upgrade the deployment to version httpd:2.4.43 using a rolling update.
|
||
|
||
|
||
Finally, once all pods are updated undo the recent update and roll back to the previous/original version.
|
||
|
||
|
||
Note:
|
||
|
||
a. The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.
|
||
|
||
|
||
b. Please make sure you only use the specified image(s) for this deployment and as per the sequence mentioned in the task description. If you mistakenly use a wrong image and fix it later, that will also distort the revision history which can eventually fail this task.
|
||
|
||
# Solution
|
||
|
||
# Deployment Update + Rollback — `httpd-deploy` in `devops`
|
||
|
||
Create the deployment at `httpd:2.4.27`, roll it forward to `httpd:2.4.43`, then roll it back —
|
||
keeping revision history clean throughout.
|
||
|
||
> **Sequencing matters:** apply each image one at a time and let each rollout finish before the
|
||
> next. Do **not** put `2.4.43` in the initial manifest, and don't "fix" a wrong image mid-stream
|
||
> — either distorts the revision history.
|
||
|
||
## Step 1 — Namespace + deployment (`2.4.27`) + service
|
||
|
||
```bash
|
||
kubectl apply -f - <<'EOF'
|
||
apiVersion: v1
|
||
kind: Namespace
|
||
metadata:
|
||
name: devops
|
||
---
|
||
apiVersion: apps/v1
|
||
kind: Deployment
|
||
metadata:
|
||
name: httpd-deploy
|
||
namespace: devops
|
||
labels:
|
||
app: httpd
|
||
spec:
|
||
replicas: 2
|
||
strategy:
|
||
type: RollingUpdate
|
||
rollingUpdate:
|
||
maxSurge: 1
|
||
maxUnavailable: 2
|
||
selector:
|
||
matchLabels:
|
||
app: httpd
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: httpd
|
||
spec:
|
||
containers:
|
||
- name: httpd
|
||
image: httpd:2.4.27
|
||
ports:
|
||
- containerPort: 80
|
||
---
|
||
apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: httpd-service
|
||
namespace: devops
|
||
spec:
|
||
type: NodePort
|
||
selector:
|
||
app: httpd
|
||
ports:
|
||
- port: 80
|
||
targetPort: 80
|
||
nodePort: 30008
|
||
EOF
|
||
|
||
# Let revision 1 fully settle BEFORE any update
|
||
kubectl rollout status deployment/httpd-deploy -n devops
|
||
```
|
||
|
||
## Step 2 — Rolling update to `httpd:2.4.43`
|
||
|
||
```bash
|
||
kubectl set image deployment/httpd-deploy httpd=httpd:2.4.43 -n devops
|
||
|
||
# Wait for the update to fully complete (revision 2)
|
||
kubectl rollout status deployment/httpd-deploy -n devops
|
||
```
|
||
|
||
## Step 3 — Roll back to the original version
|
||
|
||
```bash
|
||
kubectl rollout undo deployment/httpd-deploy -n devops
|
||
|
||
# Wait for the rollback to complete (revision 3, template of revision 1)
|
||
kubectl rollout status deployment/httpd-deploy -n devops
|
||
```
|
||
|
||
## How it works
|
||
|
||
### Sequencing keeps revision history clean
|
||
|
||
Each `kubectl` action that changes the pod template creates a new **revision**, each backed by a
|
||
ReplicaSet:
|
||
|
||
- **Revision 1** — the initial `2.4.27` deployment.
|
||
- **Revision 2** — the `set image` update to `2.4.43`.
|
||
- **Revision 3** — the `rollout undo`, which reuses revision 1's template (`2.4.27`).
|
||
|
||
`kubectl rollout status` between each step forces each rollout to **finish** before the next
|
||
begins, so the revisions are distinct and ordered. Firing the update before the create settles —
|
||
or applying a wrong image and correcting it — would inject extra revisions.
|
||
|
||
### The initial manifest
|
||
|
||
- **Namespace `devops`** created first so the deployment and service land in it.
|
||
- **Deployment** — `httpd-deploy`, container **`httpd`**, image **`httpd:2.4.27`**, `replicas: 2`.
|
||
- **`strategy.rollingUpdate`** — `maxSurge: 1` (at most 1 pod above the desired 2 during a
|
||
rollout) and `maxUnavailable: 2` (up to 2 pods down at once). With only 2 replicas and
|
||
`maxUnavailable: 2`, both pods can be replaced at once, so the rollout is fast.
|
||
- **`selector.matchLabels: app: httpd`** equals the template labels, and the **Service**'s
|
||
`selector: app: httpd` targets those same pods. `nodePort: 30008` is in the valid range
|
||
(`30000–32767`).
|
||
|
||
### `set image` for the update, `rollout undo` for the rollback
|
||
|
||
- **`set image`** patches just the container image on the live deployment — the idiomatic way to
|
||
trigger a rolling update. Container name `httpd` is the left side of `httpd=httpd:2.4.43`.
|
||
- **`rollout undo`** with no `--to-revision` reverts to the **immediately previous** revision
|
||
(revision 1's `2.4.27` template) — exactly "the previous/original version" — and records it as a
|
||
new forward revision (3), preserving the audit trail.
|
||
|
||
## Verify
|
||
|
||
```bash
|
||
# Current image after rollback should be the ORIGINAL 2.4.27
|
||
kubectl get deployment httpd-deploy -n devops \
|
||
-o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
|
||
|
||
# Revision history: expect revisions 1, 2, 3 in order
|
||
kubectl rollout history deployment/httpd-deploy -n devops
|
||
|
||
# All pods ready, service exposed on 30008
|
||
kubectl get deployment httpd-deploy -n devops
|
||
kubectl get service httpd-service -n devops
|
||
kubectl get endpoints httpd-service -n devops
|
||
```
|
||
|
||
Expected — after Step 3 the image is back to `httpd:2.4.27`, rollout history shows three
|
||
revisions, deployment `READY 2/2`, and `httpd-service` NodePort `80:30008/TCP` with two
|
||
endpoints.
|
||
|
||
> Everything is in `devops` — keep `-n devops` on every command. If endpoints is empty, the
|
||
> service selector doesn't match the pod labels. |