---
title: "Jenkins Kubernetes Integration: Dynamic Pod Agents, Pod Templates, and In-Cluster Builds"
description: "Running Jenkins on Kubernetes with dynamic pod agents via the kubernetes plugin, defining pod templates, using kaniko for Docker builds, and managing persistent storage."
url: https://agent-zone.ai/knowledge/cicd/jenkins-kubernetes-integration/
section: knowledge
date: 2026-02-22
categories: ["cicd"]
tags: ["jenkins","kubernetes","cicd","kaniko","pod-templates","helm"]
skills: ["jenkins-kubernetes-agents","kubernetes-workloads"]
tools: ["jenkins","kubectl","helm","kaniko"]
levels: ["intermediate"]
word_count: 791
formats:
  json: https://agent-zone.ai/knowledge/cicd/jenkins-kubernetes-integration/index.json
  html: https://agent-zone.ai/knowledge/cicd/jenkins-kubernetes-integration/?format=html
  api: https://api.agent-zone.ai/api/v1/knowledge/search?q=Jenkins+Kubernetes+Integration%3A+Dynamic+Pod+Agents%2C+Pod+Templates%2C+and+In-Cluster+Builds
---


# Jenkins Kubernetes Integration

The kubernetes plugin gives Jenkins elastic build capacity. Each build spins up a pod, runs its work, and the pod is deleted. No idle agents, no capacity planning, no snowflake build servers.

## The Kubernetes Plugin

The plugin creates agent pods on demand. When a pipeline requests an agent, a pod is created from a template, its JNLP container connects back to Jenkins, the build runs, and the pod is deleted.

Configure the cloud in JCasC:

```yaml
jenkins:
  clouds:
    - kubernetes:
        name: "k8s"
        serverUrl: ""  # empty string = in-cluster config
        namespace: "jenkins"
        jenkinsUrl: "http://jenkins.jenkins.svc.cluster.local:8080"
        jenkinsTunnel: "jenkins-agent.jenkins.svc.cluster.local:50000"
        podLabels:
          - key: "jenkins"
            value: "agent"
        templates:
          - name: "default"
            label: "k8s-agent"
            serviceAccount: "jenkins-agent"
            containers:
              - name: "jnlp"
                image: "jenkins/inbound-agent:latest-jdk17"
                resourceRequestCpu: "500m"
                resourceRequestMemory: "512Mi"
                resourceLimitCpu: "1"
                resourceLimitMemory: "1Gi"
```

The `jenkinsUrl` and `jenkinsTunnel` tell agent pods how to reach the Jenkins controller. If Jenkins runs in the same cluster, use the in-cluster service DNS names. The `jenkinsTunnel` points to the agent listener service on port 50000.

## Pod Templates in Jenkinsfile

For most pipelines, define the pod template inline in the Jenkinsfile. This keeps the build environment versioned with the code:

```groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: jenkins-agent
spec:
  serviceAccountName: jenkins-agent
  containers:
    - name: golang
      image: golang:1.22
      command: ["sleep"]
      args: ["infinity"]
      resources:
        requests:
          cpu: "1"
          memory: "2Gi"
    - name: kubectl
      image: bitnami/kubectl:1.29
      command: ["sleep"]
      args: ["infinity"]
'''
            defaultContainer 'golang'
        }
    }

    stages {
        stage('Build') {
            steps {
                sh 'go build ./...'
            }
        }
        stage('Test') {
            steps {
                sh 'go test ./... -v'
            }
        }
        stage('Deploy') {
            steps {
                container('kubectl') {
                    sh 'kubectl apply -f k8s/deployment.yaml'
                }
            }
        }
    }
}
```

Key details:

- The `jnlp` container is injected automatically by the kubernetes plugin. You do not need to declare it unless you want to customize its image or resources.
- Use `command: ["sleep"]` and `args: ["infinity"]` to keep sidecar containers alive. Without this, the container exits immediately and Jenkins cannot exec into it.
- `defaultContainer` sets which container runs `sh` steps by default. Switch containers with `container('name') { ... }`.
- Each stage can target a different container for different toolchains.

## Persistent Jenkins Home

Jenkins state (job configs, build history, credentials) lives in `$JENKINS_HOME`. On Kubernetes, back this with a PersistentVolumeClaim:

```yaml
# In Helm values
persistence:
  enabled: true
  storageClass: "standard"  # or your cluster's storage class
  size: 50Gi
  accessMode: ReadWriteOnce
```

Without persistence, restarting the Jenkins pod loses everything. Size the PVC based on build history retention and use `buildDiscarder(logRotator(...))` in pipelines to control growth.

## RBAC for Agent Pods

The Jenkins controller needs permission to create and delete pods in the agent namespace. Create a ServiceAccount and bind it:

```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: jenkins-agent-manager
  namespace: jenkins
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/exec", "pods/log"]
    verbs: ["get", "list", "watch", "create", "delete", "patch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "create", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: jenkins-agent-manager
  namespace: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: jenkins-agent-manager
subjects:
  - kind: ServiceAccount
    name: jenkins
    namespace: jenkins
```

The Helm chart creates these automatically when `rbac.create: true` (the default). Cross-namespace agent launching requires a ClusterRole or cross-namespace RoleBinding.

## Kaniko: Docker Builds Without Docker Socket

Building Docker images inside Kubernetes pods is a common challenge. Mounting the Docker socket (`/var/run/docker.sock`) is a security risk -- it gives the build container root access to the host. Kaniko builds container images from a Dockerfile without requiring Docker or root privileges.

```groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
    - name: kaniko
      image: gcr.io/kaniko-project/executor:debug
      command: ["sleep"]
      args: ["infinity"]
      volumeMounts:
        - name: docker-config
          mountPath: /kaniko/.docker
  volumes:
    - name: docker-config
      secret:
        secretName: docker-registry-creds
        items:
          - key: .dockerconfigjson
            path: config.json
'''
        }
    }
    stages {
        stage('Build and Push') {
            steps {
                container('kaniko') {
                    sh '''
                        /kaniko/executor \
                          --context=dir://$(pwd) \
                          --destination=registry.example.com/myapp:${BUILD_NUMBER} \
                          --cache=true \
                          --cache-repo=registry.example.com/myapp/cache
                    '''
                }
            }
        }
    }
}
```

The `debug` tag of the kaniko image includes a shell. The standard image does not, which makes it unusable as a Jenkins agent container. The Docker config secret provides registry authentication. Create it with:

```bash
kubectl create secret docker-registry docker-registry-creds \
  --docker-server=registry.example.com \
  --docker-username=user \
  --docker-password=pass \
  -n jenkins
```

## Scaling Considerations

- **Pod resource requests** determine scheduling. If your cluster lacks nodes with enough capacity, agent pods stay Pending. Use a cluster autoscaler or set reasonable resource requests.
- **Pod retention** defaults to deleting pods after the build. Set `podRetention: OnFailure` in the pod template to keep failed pods for debugging.
- **Workspace sharing** between stages works because all containers in the pod share the same workspace volume. Files created in one container are visible in another.
- **Init containers** can pre-populate caches or download tools before the build starts, reducing build time for subsequent stages.

