# Assignment The Nautilus DevOps team has noticed performance issues in some Kubernetes-hosted applications due to resource constraints. To address this, they plan to set limits on resource utilization. Here are the details: Create a pod named httpd-pod with a container named httpd-container. Use the httpd image with the latest tag (specify as httpd:latest). Configure the following container-level resource requests and limits for the container: Requests: Memory: 15Mi, CPU: 100m Limits: Memory: 20Mi, CPU: 100m Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster. # Solution # Kubernetes Pod with Resource Limits — `httpd-pod` A pod running `httpd:latest` with container-level CPU/memory requests and limits. Applied inline via a heredoc — no manifest file on disk. ## Apply (heredoc → kubectl) ```bash kubectl apply -f - <<'EOF' apiVersion: v1 kind: Pod metadata: name: httpd-pod labels: app: httpd spec: containers: - name: httpd-container image: httpd:latest resources: requests: memory: "15Mi" cpu: "100m" limits: memory: "20Mi" cpu: "100m" EOF ``` ## How it works ### The heredoc apply pattern - **`kubectl apply -f -`** reads from **stdin**; the heredoc feeds the YAML in, nothing on disk. - **`<<'EOF'` (delimiter quoted)** disables shell expansion, keeping `$VAR`/backticks literal — the right default for Kubernetes YAML. ### The pod - **`metadata.name: httpd-pod`** and container **`name: httpd-container`** — exactly as required. - **`image: httpd:latest`** — Apache HTTP Server at the `latest` tag, stated explicitly. ### The `resources` block — the heart of this task Resource controls are set **per container**, under `spec.containers[].resources`: - **`requests`** — the amount the scheduler **reserves** for the container. Kubernetes places the pod on a node that has at least this much free, and the request is what counts against node allocatable capacity. Here: `memory: 15Mi`, `cpu: 100m`. - **`limits`** — the hard **ceiling** the container may use at runtime. Here: `memory: 20Mi`, `cpu: 100m`. The two behave very differently when exceeded: | Resource | Over the limit → | |----------|------------------| | **CPU** | **Throttled** — the container is capped at its CPU limit; it's slowed, never killed. | | **Memory** | **OOM-killed** — memory is incompressible, so exceeding the limit terminates the container (it restarts per its policy). | ### Units explained - **`100m` CPU** = 100 millicores = 0.1 of a vCPU. CPU is measured in millicores; `1000m` = 1 full core. Request and limit are both `100m` here, so the container is guaranteed 0.1 core and capped at 0.1 core. - **`15Mi` / `20Mi` memory** — `Mi` is **mebibytes** (base-2, 1 Mi = 1,048,576 bytes), distinct from `M` (megabytes, base-10, 1,000,000 bytes). The task specifies `Mi`, so use `Mi` exactly — mixing units is a common mistake. ### Requests ≤ limits Note memory request (`15Mi`) is below its limit (`20Mi`), while CPU request equals its limit (`100m`). That's valid: a request must never exceed its limit, but being lower is fine and normal — it lets the container burst up to the limit when the node has spare capacity while only reserving the smaller request amount. ## Verify ```bash # Pod running kubectl get pod httpd-pod # Requests and limits are set correctly kubectl get pod httpd-pod \ -o jsonpath='{.spec.containers[0].resources}{"\n"}' ``` Expected — `httpd-pod` in `Running` status, and the resources printing requests `{cpu:100m, memory:15Mi}` with limits `{cpu:100m, memory:20Mi}`. > If the pod is `OOMKilled` on start, `httpd:latest` needed more than the `20Mi` memory > limit — but Apache's base footprint fits comfortably, so the given values are fine.