diff --git a/k8s/LAB09.md b/k8s/LAB09.md new file mode 100644 index 0000000000..39f76ade4f --- /dev/null +++ b/k8s/LAB09.md @@ -0,0 +1,189 @@ +# Task 1 + +Terminal output: +```sh +kubectl cluster-info +``` +```text +Kubernetes control plane is running at https://192.168.49.2:8443 +CoreDNS is running at https://192.168.49.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy + +To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. +``` + +```sh +kubectl get nodes +``` +```text +NAME STATUS ROLES AGE VERSION +minikube Ready control-plane 41m v1.35.1 +``` +Explanation: I chose minikube as the de-facto default choice for local cluster setup. + +# Task 2 + +```sh +kubectl describe deployment devops-infoservice +``` +```text +Name: devops-infoservice +Namespace: default +CreationTimestamp: Tue, 24 Mar 2026 14:21:22 +0300 +Labels: app=devops-infoservice +Annotations: deployment.kubernetes.io/revision: 1 +Selector: app=devops-infoservice +Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable +StrategyType: RollingUpdate +MinReadySeconds: 0 +RollingUpdateStrategy: 25% max unavailable, 25% max surge +Pod Template: + Labels: app=devops-infoservice + Containers: + devops-infoservice: + Image: 127.0.0.1:5000/timurusmanov/devops-infoservice:latest + Port: 5000/TCP + Host Port: 0/TCP + Limits: + cpu: 200m + memory: 256Mi + Requests: + cpu: 100m + memory: 128Mi + Liveness: http-get http://:5000/health delay=10s timeout=1s period=10s #success=1 #failure=3 + Readiness: http-get http://:5000/health delay=5s timeout=1s period=10s #success=1 #failure=3 + Environment: + Mounts: + Volumes: + Node-Selectors: + Tolerations: +Conditions: + Type Status Reason + ---- ------ ------ + Available True MinimumReplicasAvailable + Progressing True NewReplicaSetAvailable +OldReplicaSets: +NewReplicaSet: devops-infoservice-684dd6c4d7 (3/3 replicas created) +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal ScalingReplicaSet 6m38s deployment-controller Scaled up replica set devops-infoservice-684dd6c4d7 from 0 to 3 +``` + +# Task 3 + +Verification: +```sh +kubectl get services +``` +```text +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +devops-infoservice-service NodePort 10.106.40.29 80:30080/TCP 6m38s +kubernetes ClusterIP 10.96.0.1 443/TCP 146m +``` +```sh +kubectl describe service devops-infoservice-service +``` +```text +Name: devops-infoservice-service +Namespace: default +Labels: +Annotations: +Selector: app=devops-infoservice +Type: NodePort +IP Family Policy: SingleStack +IP Families: IPv4 +IP: 10.106.40.29 +IPs: 10.106.40.29 +Port: 80/TCP +TargetPort: 5000/TCP +NodePort: 30080/TCP +Endpoints: 10.244.0.46:5000,10.244.0.45:5000,10.244.0.44:5000 +Session Affinity: None +External Traffic Policy: Cluster +Internal Traffic Policy: Cluster +Events: +``` +```sh +kubectl get endpoints +``` +```text +Warning: v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice +NAME ENDPOINTS AGE +devops-infoservice-service 10.244.0.44:5000,10.244.0.45:5000,10.244.0.46:5000 6m50s +kubernetes 192.168.49.2:8443 147m +``` + +# Task 4 + +## Scaling + +```sh +kubectl apply -f k8s/deployment.yml +``` +```text +deployment.apps/devops-infoservice configured +``` +```sh +kubectl get pods +``` +```text +NAME READY STATUS RESTARTS AGE +devops-infoservice-684dd6c4d7-2hnv5 1/1 Running 0 53s +devops-infoservice-684dd6c4d7-dbn8f 1/1 Running 0 53s +devops-infoservice-684dd6c4d7-h7sbd 1/1 Running 0 19m +devops-infoservice-684dd6c4d7-s645x 1/1 Running 0 19m +devops-infoservice-684dd6c4d7-w87mf 1/1 Running 0 19m +``` + +## Rolling updates + +(Changed the tag to 1.0.0) + +```sh +kubectl apply -f k8s/deployment.yml +``` +```text +deployment.apps/devops-infoservice configured +``` +```sh +kubectl rollout status deployment/devops-infoservice +``` +```text +Waiting for deployment "devops-infoservice" rollout to finish: 1 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 1 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 1 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 2 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 2 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 2 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 2 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 3 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 3 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 3 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 3 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 4 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 4 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 4 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 4 out of 5 new replicas have been updated... +Waiting for deployment "devops-infoservice" rollout to finish: 1 old replicas are pending termination... +Waiting for deployment "devops-infoservice" rollout to finish: 1 old replicas are pending termination... +Waiting for deployment "devops-infoservice" rollout to finish: 1 old replicas are pending termination... +deployment "devops-infoservice" successfully rolled out +``` +```sh +kubectl rollout history deployment/devops-infoservice +``` +```text +deployment.apps/devops-infoservice +REVISION CHANGE-CAUSE +1 +2 +``` +```sh +kubectl rollout undo deployment/devops-infoservice +``` +```text +deployment.apps/devops-infoservice rolled back +``` + +# Task 5 +See `k8s/README.md` diff --git a/k8s/README.md b/k8s/README.md new file mode 100644 index 0000000000..195ea041d6 --- /dev/null +++ b/k8s/README.md @@ -0,0 +1,141 @@ +# Architecture Overview +## Diagram or description of your deployment architecture +I deploy 5 replicas of `devops-infoservice` to the `minikube` container. I use a kubernetes service as a load balancer. + +## How many Pods, which Services, networking flow +There are 5 pods and 1 service that connects them with the "outside". + +## Resource allocation strategy +We allocate 128MiB of space and 0.1CPU per Pod and allow at most 256MiB of space and 0.2CPU per Pod. + +# Manifest Files +## Brief description of each manifest +`deployment.yml` provides information about the desired running containers. + +`service.yml` provides information about the desired port forwarding configuration. + +## Key configuration choices +Described in the lab requirements. + +## Why you chose specific values (replicas, resources, etc.) +As required by the lab. + +# Deployment Evidence +## `kubectl get all` output + +```text +NAME READY STATUS RESTARTS AGE +pod/devops-infoservice-684dd6c4d7-69gqw 1/1 Running 0 11m +pod/devops-infoservice-684dd6c4d7-8zv2m 1/1 Running 0 10m +pod/devops-infoservice-684dd6c4d7-jr9mt 1/1 Running 0 10m +pod/devops-infoservice-684dd6c4d7-k4s5b 1/1 Running 0 11m +pod/devops-infoservice-684dd6c4d7-zg8cd 1/1 Running 0 10m + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/devops-infoservice-service NodePort 10.106.40.29 80:30080/TCP 29m +service/kubernetes ClusterIP 10.96.0.1 443/TCP 169m + +NAME READY UP-TO-DATE AVAILABLE AGE +deployment.apps/devops-infoservice 5/5 5 5 39m + +NAME DESIRED CURRENT READY AGE +replicaset.apps/devops-infoservice-5f7f6cb59c 0 0 0 14m +replicaset.apps/devops-infoservice-684dd6c4d7 5 5 5 39m +``` + +## `kubectl get pods,svc` with detailed view +```text +NAME READY STATUS RESTARTS AGE +pod/devops-infoservice-684dd6c4d7-69gqw 1/1 Running 0 11m +pod/devops-infoservice-684dd6c4d7-8zv2m 1/1 Running 0 11m +pod/devops-infoservice-684dd6c4d7-jr9mt 1/1 Running 0 11m +pod/devops-infoservice-684dd6c4d7-k4s5b 1/1 Running 0 11m +pod/devops-infoservice-684dd6c4d7-zg8cd 1/1 Running 0 10m + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/devops-infoservice-service NodePort 10.106.40.29 80:30080/TCP 29m +service/kubernetes ClusterIP 10.96.0.1 443/TCP 170m +``` + +## `kubectl describe deployment ` showing replicas and strategy +```text +Name: devops-infoservice +Namespace: default +CreationTimestamp: Tue, 24 Mar 2026 14:21:22 +0300 +Labels: app=devops-infoservice +Annotations: deployment.kubernetes.io/revision: 3 +Selector: app=devops-infoservice +Replicas: 5 desired | 5 updated | 5 total | 5 available | 0 unavailable +StrategyType: RollingUpdate +MinReadySeconds: 0 +RollingUpdateStrategy: 0 max unavailable, 1 max surge +Pod Template: + Labels: app=devops-infoservice + Containers: + devops-infoservice: + Image: 127.0.0.1:5000/timurusmanov/devops-infoservice:latest + Port: 5000/TCP + Host Port: 0/TCP + Limits: + cpu: 200m + memory: 256Mi + Requests: + cpu: 100m + memory: 128Mi + Liveness: http-get http://:5000/health delay=10s timeout=1s period=10s #success=1 #failure=3 + Readiness: http-get http://:5000/health delay=5s timeout=1s period=10s #success=1 #failure=3 + Environment: + Mounts: + Volumes: + Node-Selectors: + Tolerations: +Conditions: + Type Status Reason + ---- ------ ------ + Available True MinimumReplicasAvailable + Progressing True NewReplicaSetAvailable +OldReplicaSets: devops-infoservice-5f7f6cb59c (0/0 replicas created) +NewReplicaSet: devops-infoservice-684dd6c4d7 (5/5 replicas created) +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal ScalingReplicaSet 40m deployment-controller Scaled up replica set devops-infoservice-684dd6c4d7 from 0 to 3 + Normal ScalingReplicaSet 21m deployment-controller Scaled up replica set devops-infoservice-684dd6c4d7 from 3 to 5 + Normal ScalingReplicaSet 14m deployment-controller Scaled up replica set devops-infoservice-5f7f6cb59c from 0 to 1 + Normal ScalingReplicaSet 13m deployment-controller Scaled down replica set devops-infoservice-684dd6c4d7 from 5 to 4 + Normal ScalingReplicaSet 13m deployment-controller Scaled up replica set devops-infoservice-5f7f6cb59c from 1 to 2 + Normal ScalingReplicaSet 13m deployment-controller Scaled down replica set devops-infoservice-684dd6c4d7 from 4 to 3 + Normal ScalingReplicaSet 13m deployment-controller Scaled up replica set devops-infoservice-5f7f6cb59c from 2 to 3 + Normal ScalingReplicaSet 13m deployment-controller Scaled down replica set devops-infoservice-684dd6c4d7 from 3 to 2 + Normal ScalingReplicaSet 13m deployment-controller Scaled up replica set devops-infoservice-5f7f6cb59c from 3 to 4 + Normal ScalingReplicaSet 13m deployment-controller Scaled down replica set devops-infoservice-684dd6c4d7 from 2 to 1 + Normal ScalingReplicaSet 10m (x12 over 13m) deployment-controller (combined from similar events): Scaled down replica set devops-infoservice-5f7f6cb59c from 1 to 0 +``` + +## Screenshot or curl output showing app working + +![curl](/k8s/lab9-curl.png) + +# Operations Performed +See `/labs/lab09.md`. + +# Production Considerations +## What health checks did you implement and why? +I implemented the `/health` endpoint check to see if the container is healthy or some intervention is required. + +## Resource limits rationale +As required by the lab. + +## How would you improve this for production? +I would raise the resource limits and probably ditch `minikube`. + +## Monitoring and observability strategy +Add `loki` + `grafana` + `prometheus` getting metrics from `/metrics`, but individually from every Pod. + +# Challenges & Solutions +## Issues encountered +Docker's repositories are being blocked in Russia at the moment. I set up a local repo, put the images there, `exec`ed +into the `minikube` container and forwarded `localhost` to the host machine (which has the registry): +```sh +socat TCP4-LISTEN:5000,bind=127.0.0.1,fork TCP4:192.168.49.1:5000 +``` diff --git a/k8s/deployment.yml b/k8s/deployment.yml new file mode 100644 index 0000000000..5b57351844 --- /dev/null +++ b/k8s/deployment.yml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: devops-infoservice + labels: + app: devops-infoservice +spec: + replicas: 5 + selector: + matchLabels: + app: devops-infoservice + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 # Extra pods during update + maxUnavailable: 0 # Ensure availability + template: + metadata: + labels: + app: devops-infoservice + spec: + containers: + - name: devops-infoservice + image: 127.0.0.1:5000/timurusmanov/devops-infoservice:latest + ports: + - containerPort: 5000 + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "200m" + livenessProbe: + httpGet: + path: /health + port: 5000 + initialDelaySeconds: 10 + readinessProbe: + httpGet: + path: /health + port: 5000 + initialDelaySeconds: 5 diff --git a/k8s/lab9-curl.png b/k8s/lab9-curl.png new file mode 100644 index 0000000000..aca867e12f Binary files /dev/null and b/k8s/lab9-curl.png differ diff --git a/k8s/service.yml b/k8s/service.yml new file mode 100644 index 0000000000..853cd0860f --- /dev/null +++ b/k8s/service.yml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: devops-infoservice-service +spec: + type: NodePort + selector: + app: devops-infoservice # Must match Deployment labels + ports: + - protocol: TCP + port: 80 # Service port + targetPort: 5000 # Container port + nodePort: 30080 # Optional: specific node port (30000-32767)