Files

5.3 KiB
Raw Permalink Blame History

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)

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

# 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.