Files
kodekloud-engineer/kubernetes/level 2/task-6.md

140 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Assignment
The Nautilus DevOps team is planning to set up a Jenkins CI server to create/manage some deployment pipelines for some of the projects. They want to set up the Jenkins server on Kubernetes cluster. Below you can find more details about the task:
1) Create a namespace jenkins
2) Create a Service for jenkins deployment. Service name should be jenkins-service under jenkins namespace, type should be NodePort, nodePort should be 30008
3) Create a Jenkins Deployment under jenkins namespace, It should be name as jenkins-deployment , labels app should be jenkins , container name should be jenkins-container , use jenkins/jenkins image , containerPort should be 8080 and replicas count should be 1. It should also have the environment variable JAVA_OPTS with the value -Djenkins.install.runSetupWizard=false to skip the initial setup wizard.
Make sure to wait for the pods to be in running state and make sure you are able to access the Jenkins UI screen in the browser before hitting the Check button.
Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.
# Solution
# Jenkins on Kubernetes — `jenkins-deployment` + `jenkins-service` in `jenkins`
A Jenkins Deployment exposed via a NodePort Service, with the setup wizard disabled. All objects
in one multi-document heredoc — no manifest file on disk.
## Apply (heredoc → kubectl)
```bash
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Namespace
metadata:
name: jenkins
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins-deployment
namespace: jenkins
labels:
app: jenkins
spec:
replicas: 1
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
containers:
- name: jenkins-container
image: jenkins/jenkins
ports:
- containerPort: 8080
env:
- name: JAVA_OPTS
value: "-Djenkins.install.runSetupWizard=false"
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-service
namespace: jenkins
spec:
type: NodePort
selector:
app: jenkins
ports:
- port: 8080
targetPort: 8080
nodePort: 30008
EOF
# Wait for Jenkins to come up (it takes a bit to initialize)
kubectl rollout status deployment/jenkins-deployment -n jenkins
```
## How it works
### The heredoc apply pattern
- **`kubectl apply -f -`** reads from **stdin**; `---` separates the three documents, applied in
order so the **Namespace** exists before the Deployment and Service land in it.
- **`<<'EOF'` (delimiter quoted)** keeps the manifest literal — important here so `JAVA_OPTS`'s
value (with its `-D...` flag) isn't mangled by the jump-host shell.
### The Deployment
- **`namespace: jenkins`, `name: jenkins-deployment`, `labels.app: jenkins`** — exactly as
required.
- **container `name: jenkins-container`, `image: jenkins/jenkins`** — the official Jenkins image.
- **`containerPort: 8080`** — Jenkins' web UI listens on 8080 inside the container.
- **`replicas: 1`** — a single Jenkins instance.
- **`env: JAVA_OPTS = -Djenkins.install.runSetupWizard=false`** — passed to Jenkins' JVM. This
system property **skips the initial setup wizard** (the "unlock Jenkins / install plugins"
screens), so the UI is immediately usable — which is what lets the Check succeed without manual
unlock steps.
- **`selector.matchLabels: app: jenkins`** equals the template labels — the Deployment↔pod link.
### The Service — port 8080 is the key detail
- **`type: NodePort`** exposes Jenkins outside the cluster.
- **`selector: app: jenkins`** targets the deployment's pod by its label.
- **Port mapping:**
- `port: 8080` — the Service's ClusterIP port.
- **`targetPort: 8080`** — the container port. This **must** be 8080 because that's where
Jenkins actually listens; pointing it elsewhere would give you a Service with endpoints but no
response.
- `nodePort: 30008` — the external port on each node (in the valid `3000032767` range).
Path: `<node-ip>:30008` → Service `:8080` → Jenkins pod `:8080`.
### Why waiting matters
Jenkins takes noticeably longer than a typical app to become ready — the JVM boots, unpacks
plugins, and initializes before the UI responds. `kubectl rollout status` blocks until the pod is
Ready, but the **UI** may need a few extra seconds after that. Confirm the login/dashboard
actually loads in the browser before hitting Check, as the task instructs.
## Verify
```bash
# Pod running
kubectl get pods -n jenkins
# Service exposed on 30008 with an endpoint
kubectl get service jenkins-service -n jenkins
kubectl get endpoints jenkins-service -n jenkins
# Jenkins responding inside the cluster (should return HTTP 200/403, not connection refused)
kubectl exec -n jenkins deploy/jenkins-deployment -- \
sh -c 'curl -sI http://localhost:8080 | head -n1' 2>/dev/null || true
```
Expected — the Jenkins pod `Running` (`READY 1/1`), `jenkins-service` NodePort `8080:30008/TCP`
with one endpoint, and the Jenkins dashboard loading at `<node-ip>:30008` in the browser (no setup
wizard, thanks to `JAVA_OPTS`).
> If the browser shows "unlock Jenkins," the `JAVA_OPTS` env var didn't take — confirm with
> `kubectl get deploy jenkins-deployment -n jenkins -o jsonpath='{.spec.template.spec.containers[0].env}'`.
> Give the pod a minute; Jenkins' first boot is slow.