Certified Jenkins Engineer

Pipeline Structure and Scripted vs Declarative

Demo Scripted Pipeline K8S Agent

In this tutorial, we’ll show you how to run Jenkins scripted pipelines inside Kubernetes pods using podTemplate and node(POD_LABEL). This approach dynamically spins up isolated build environments, improving resource usage and build consistency.

Table of Contents

  1. Scripted podTemplate Basics
  2. Advanced Pod Template with Multiple Containers
  3. Generating a podTemplate with Snippet Generator
  4. Complete Scripted Pipeline Example
  5. Observing Pod Creation and Logs
  6. Common Pitfalls
  7. Links and References

Scripted podTemplate Basics {#scripted-podtemplate-basics}

A minimal scripted pipeline using a Kubernetes agent:

podTemplate {
  node(POD_LABEL) {
    // pipeline steps...
  }
}
  • podTemplate: Defines the pod configuration.
  • node(POD_LABEL): Executes steps inside the dynamically created pod.

Advanced Pod Template with Multiple Containers {#advanced-pod-template}

You can run different build tools side by side. For example, a Maven container and a Golang container:

podTemplate(
  agentContainer: 'maven',
  agentInjection: true,
  containers: [
    containerTemplate(
      name: 'maven',
      image: 'maven:3.9.9-eclipse-temurin-17'
    ),
    containerTemplate(
      name: 'golang',
      image: 'golang:1.16.5',
      command: 'sleep',
      args: '99d'
    )
  ]
) {
  node(POD_LABEL) {
    stage('Build Maven Project') {
      git 'https://github.com/jenkinsci/kubernetes-plugin.git'
      container('maven') {
        sh 'mvn -B -ntp clean install'
      }
    }
    stage('Build Go Project') {
      git url: 'https://github.com/hashicorp/terraform.git', branch: 'main'
      container('golang') {
        sh '''
          mkdir -p /go/src/github.com/hashicorp
          ln -s `pwd` /go/src/github.com/hashicorp/terraform
          cd /go/src/github.com/hashicorp/terraform
          make
        '''
      }
    }
  }
}

This defines two containerTemplate entries and injects Maven as the default container.

Generating a podTemplate with Snippet Generator {#snippet-generator}

Use Jenkins’ Snippet Generator to bootstrap your podTemplate:

  1. Go to Manage Jenkins ▶️ Snippet Generator
  2. Select podTemplate under Sample Steps
  3. Choose your Kubernetes cloud, then set:
    • Name (optional)
    • Namespace
    • Label (e.g., nodejs-pod)
  4. Click Add Container Template, and fill in:
FieldValue
Namenode-18
Docker imagenode:18-alpine
Commandsleep
Arguments9999999
Allocate pseudo-TTY
Privileged

The image shows a Jenkins interface for creating a new pod template, with fields for name, namespace, labels, usage, and other settings.

Trim the generated block to include only necessary fields:

podTemplate(
  cloud: 'dasher-prod-k8s-us-east',
  label: 'nodejs-pod',
  containers: [
    containerTemplate(
      name: 'node-18',
      image: 'node:18-alpine',
      command: 'sleep',
      args: '9999999',
      privileged: true,
      ttyEnabled: true
    )
  ]
) {
  // your scripted pipeline here
}

The image shows a Jenkins interface with the "Snippet Generator" section open, displaying options for generating pipeline scripts. A dropdown menu lists various sample steps for configuration.

The image shows a Jenkins Pipeline Syntax configuration page for defining a pod template in the Kubernetes plugin, with fields for cloud selection, name, namespace, and label.

The image shows a web interface for configuring a Kubernetes pod in Jenkins, with options to add containers, environment variables, volumes, annotations, and raw YAML.

Full Scripted Pipeline Example {#full-scripted-pipeline}

Here’s a complete Jenkinsfile mixing a static Ubuntu agent for checkout and dependency install, then a Kubernetes pod for unit tests:

node('ubuntu-docker-jdk17-node20') {
  // Setup environment
  env.NODEJS_HOME = tool('nodejs-22-6-0')
  env.PATH = "${env.NODEJS_HOME}/bin:${env.PATH}"
  env.MONGO_URI = "mongodb+srv://supercluster.d83jj.mongodb.net/superData"

  properties([])

  stage('Checkout') {
    checkout scm
  }

  wrap([$class: 'TimestampedBuildWrapper']) {
    stage('Install Dependencies') {
      cache(maxCacheSize: 550, caches: [
        arbitraryFileCache(
          cacheName: 'npm-dependency-cache',
          cacheValidityDecidingFile: 'package-lock.json',
          includes: ['**/*'],
          path: 'node_modules'
        )
      ])
      sh 'node -v'
      sh 'npm install --no-audit'
      stash includes: 'node_modules/', name: 'npm-cache'
    }
  }

  stage('Unit Testing') {
    podTemplate(
      cloud: 'dasher-prod-k8s-us-east',
      label: 'nodejs-pod',
      containers: [
        containerTemplate(
          name: 'node-18',
          image: 'node:18-alpine',
          command: 'sleep',
          args: '9999999',
          privileged: true,
          ttyEnabled: true
        )
      ]
    ) {
      node('nodejs-pod') {
        container('node-18') {
          checkout scm
          unstash 'npm-cache'
          withCredentials([usernamePassword(
            credentialsId: 'mongo-db-credentials',
            usernameVariable: 'MONGO_USERNAME',
            passwordVariable: 'MONGO_PASSWORD'
          )]) {
            sh 'node -v'
            sh 'npm test'
          }
        }
      }
    }
  }
}

Commit and push:

git checkout -b pipeline/scripted
git add Jenkinsfile
git commit -m "Add scripted pipeline with Kubernetes pod for unit tests"
git push -u origin pipeline/scripted

Observing Pod Creation and Logs {#observing-pods}

Once the pipeline runs, the nodejs-pod appears in Blue Ocean or the classic UI:

The image shows a Jenkins pipeline interface with multiple build stages, including "Start," "Checkout," "Installing Dependencies," "Unit Testing," and "End." The build history is displayed on the left, showing the status and timestamps of recent builds.

Inspect the generated pod YAML in the console log:

[Pipeline] { (Unit Testing)
[Pipeline] node
Created pod: dasher-prod-k8s-us-east jenkins/nodejs-pod-xxxxx-yyyyy
...
spec:
  containers:
    - name: node-18
      image: node:18-alpine
      command: ["sleep"]
      args: ["9999999"]
      securityContext:
        privileged: true
      tty: true
      volumeMounts:
        - mountPath: "/home/jenkins/agent"
          name: "workspace-volume"

Common Pitfalls {#common-pitfalls}

  1. Missing checkout scm inside the node('nodejs-pod') block results in an empty workspace.
  2. Always stash and unstash dependencies when switching agents (e.g., node_modules).
  3. Verify container images include all required tools (Node.js, Mongo CLI, etc.).

Warning

Forgetting to checkout scm or unstash dependencies will cause failures inside the Kubernetes pod due to missing files.

Watch Video

Watch video content

Previous
Demo Scripted Pipeline Static Agent