← Back to Blog

Modern Integration Environments: CI/CD with Jenkins, Kubernetes, and the Glue Between

· 10 min read Modern Integration Environments: CI/CD with Jenkins, Kubernetes, and the Glue Between

Somebody will draw you a pipeline: commit, build, test, deploy, four boxes and three arrows, and call it CI/CD. The boxes are right. The interesting parts are the words people blur together, the machine that runs the boxes, and the four numbers that tell you whether any of it is working. This is a walk through a modern integration environment: the vocabulary, Jenkins as the veteran engine, Kubernetes as the substrate underneath it, the DORA metrics as the scoreboard, and the hosted alternatives that have changed the default. Every capability below is quoted from the projects' own documentation.

Get the vocabulary straight first

The three terms people use interchangeably are not the same thing, and Martin Fowler, who coined the phrases, keeps them distinct. Continuous integration is the practice where team members integrate their work frequently, at least daily, and every integration is verified by an automated build and test so that integration errors are caught fast (Martin Fowler). Continuous delivery is the next discipline: "you build software in such a way that the software can be released to production at any time" (Martin Fowler). Note the word "can." Delivery is a capability; a human may still choose when to press the button. Continuous deployment is the fully automatic version, where "every change goes through the pipeline and automatically gets put into production." Fowler states the relationship exactly: "In order to do Continuous Deployment you must be doing Continuous Delivery." Delivery is the superset capability; deployment is the subset that removes the human from the last step. Most teams that say "we do CI/CD" mean continuous delivery, and that distinction is not pedantry, it is the difference between a pipeline that can ship and one that ships on its own.

Jenkins: the veteran engine, and pipeline-as-code

Jenkins calls itself "the leading open source automation server," providing plugins to build, deploy, and automate almost anything and integrating "with practically every tool in the continuous integration and continuous delivery toolchain" (Jenkins). Its plugin ecosystem is its blessing and its curse: the plugin index advertises well over 1,800 community-contributed plugins, which is why Jenkins can talk to nearly everything and also why a Jenkins install accretes maintenance debt.

The modern way to use Jenkins is pipeline-as-code. Rather than clicking a job together in a web UI, you write the pipeline into a text file called a Jenkinsfile and commit it to source control, so the delivery pipeline is versioned and reviewed like any other code (Jenkins). There are two syntaxes: declarative, which imposes a strict, readable, predefined structure, and scripted, an imperative Groovy model with few guardrails for power users (Jenkins). A minimal declarative Jenkinsfile reads almost like the four boxes:

pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        sh 'make build'
      }
    }
    stage('Test') {
      steps {
        sh 'make test'
      }
      post {
        always {
          junit 'reports/**/*.xml'
        }
      }
    }
    stage('Deploy') {
      when { branch 'main' }
      steps {
        sh 'kubectl apply -f k8s/deployment.yaml'
      }
    }
  }
}

The line that matters most for a modern setup is agent any, because where that agent runs is where Kubernetes enters. The Jenkins Kubernetes plugin runs dynamic agents inside a cluster: it creates a fresh Pod for each build and deletes it when the build finishes (Jenkins). That is a real change in how the engine behaves. Every build starts from a clean, known image, you pay for compute only while builds run, and concurrency scales with the cluster instead of with a fixed pool of always-on servers. You define the throwaway build environment right in the Jenkinsfile:

pipeline {
  agent {
    kubernetes {
      yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: build
    image: maven:3.9-eclipse-temurin-21
    command: ['sleep']
    args: ['99d']
'''
    }
  }
  stages {
    stage('Build') {
      steps { container('build') { sh 'mvn -B package' } }
    }
  }
}

Kubernetes: the substrate, not the CI tool

It is worth being precise about what Kubernetes is, because it is easy to overreach. Kubernetes is "a portable, extensible, open source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation" (Kubernetes). It is a container orchestrator. It is not itself a CI/CD tool; Jenkins, GitHub Actions, and GitLab CI are the engines, and Kubernetes plays three supporting roles: it runs the ephemeral build agents, it hosts short-lived test and preview environments, and it is very often the deployment target.

Three objects carry most of the weight. A Pod is "the smallest deployable unit of computing that you can create and manage in Kubernetes," a group of one or more containers sharing a network and storage, reachable from each other over localhost (Kubernetes). A Deployment "provides declarative updates for Pods and ReplicaSets": you describe the desired state and the controller moves the actual state toward it at a controlled rate, which is what gives you rolling updates and rollbacks (Kubernetes). A Namespace isolates groups of resources within one cluster, which is exactly what you want for a per-branch or per-team environment (Kubernetes). A minimal Deployment and the commands to ship and roll it back look like this:

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: demo
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: registry.example.com/web:1.4.2
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
kubectl create namespace demo
kubectl apply -f deployment.yaml
kubectl rollout status deployment/web -n demo
# ship a new image (triggers a rolling update):
kubectl set image deployment/web web=registry.example.com/web:1.4.3 -n demo
kubectl rollout status deployment/web -n demo
# roll back if the new version is bad:
kubectl rollout undo deployment/web -n demo

This substrate has effectively won. In the 2025 CNCF Annual Cloud Native Survey, 82 percent of container users were running Kubernetes in production, up from 66 percent in 2023, and the foundation now calls it the de facto operating system for modern infrastructure (CNCF). Read that number carefully: it is 82 percent of container users, not 82 percent of all organizations, a denominator people routinely inflate.

DORA: the four numbers that say whether it works

A pipeline is not good because it exists; it is good if it makes delivery fast and stable. The DORA program gives the industry-standard measuring stick, the "four keys": deployment frequency and lead time for changes, which measure throughput and speed, and change failure rate and failed-deployment recovery time, which measure stability (DORA). The critical caveat, and it is the most common misuse of these metrics, is what they do not measure: DORA is explicit that the four keys track software delivery and operational performance, not code quality, developer productivity, or individual output. A team can score elite and still ship mediocre software; the metrics grade the delivery process, not the product.

The benchmarks give a target. In the 2024 State of DevOps report, elite performers deploy on demand, carry a lead time for changes under a day, hold a change failure rate around 5 percent, and recover from a failed deployment in under an hour, with elite teams making up roughly 19 percent of respondents (DORA). Treat those qualitative thresholds as the stable part and any exact percentage bands as specific to a report year, because the clusters move: the 2022 report found only three tiers and no elite group at all. DORA has since added a fifth metric on rework and reliability, but the four keys are the durable core.

The hosted alternatives, and the shift they represent

Jenkins is self-hosted by design: you run the controller and the agents, and you own the maintenance. The industry's center of gravity has moved toward hosted, YAML-configured engines that hand that operational burden to a provider. GitHub Actions stores its workflows as YAML in a repository's .github/workflows directory and runs them on GitHub-hosted runners, managed virtual machines selected with a line like runs-on: ubuntu-latest (GitHub). GitLab CI does the same with a .gitlab-ci.yml at the repository root and hosted instance runners (GitLab). The honest framing is about the default operating model, not an absolute: all three engines can use self-hosted runners, but Jenkins defaults to self-hosted and the others default to provider-hosted. A minimal GitHub Actions pipeline that tests on every push and deploys main to a cluster shows the shape:

# .github/workflows/ci.yml
name: CI
on:
  push:
    branches: [ main ]
  pull_request:
jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npm test
  deploy:
    needs: build-test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: echo "$KUBECONFIG_DATA" | base64 -d > kubeconfig
        env:
          KUBECONFIG_DATA: ${{ secrets.KUBECONFIG_DATA }}
      - run: kubectl --kubeconfig=kubeconfig apply -f k8s/deployment.yaml

The connective tissue: ephemeral environments

The piece that ties CI, Kubernetes, and code review together is the ephemeral environment: a temporary, full running copy of the application spun up for a single branch or pull request and torn down when it merges or goes stale. GitLab's Review Apps are one well-documented implementation, creating a dynamic environment per merge request, keyed off a per-branch variable and reaped automatically with an auto-stop timer, so a reviewer can click a URL and see the change running before approving it (GitLab). The pattern is vendor-neutral, and on Kubernetes it usually means one namespace per pull request, which is exactly what namespaces are for. This is where the whole environment earns its name: the pipeline does not just build and test in the abstract, it stands up a real, isolated instance of the system on the same substrate that will eventually run production, checks it, and throws it away.

Put together, a modern integration environment is a small number of moving parts doing clearly separated jobs. An engine, Jenkins or a hosted equivalent, runs the pipeline as versioned code. Kubernetes provides clean throwaway build agents, per-branch preview environments, and the deploy target, all from the same declarative substrate. And DORA's four keys tell you, honestly and without vendor spin, whether the machine you built actually delivers. If you are assembling the rest of that engineering skill set, the pipeline is the part that turns everything else into something that ships.

Related reading

Fact-check notes and sources

Every technical claim was checked against the projects' own documentation or a primary reference; links are inline.

  • The vocabulary (continuous integration, continuous delivery as a capability, and continuous deployment as the automatic subset, with the exact relationship that continuous deployment requires continuous delivery): Martin Fowler on continuous integration and continuous delivery.
  • Jenkins (the automation-server self-description, the plugin ecosystem of well over 1,800, the Jenkinsfile and pipeline-as-code, declarative versus scripted syntax, and the Kubernetes plugin's per-build ephemeral pods): jenkins.io, the Pipeline handbook, the syntax docs, and the Kubernetes plugin. Jenkins's own homepage says "hundreds of plugins"; the plugin index says over 1,800, so the count is cited as a range.
  • Kubernetes (the container-orchestration definition, and the Pod, Deployment, and Namespace concepts): the Kubernetes overview, Pods, Deployments, and Namespaces. Adoption (82 percent of container users running Kubernetes in production in 2025, up from 66 percent in 2023): the CNCF Annual Survey announcement; the denominator is container users, not all organizations.
  • DORA (the four keys, the explicit framing that they measure delivery performance and not code quality, and the 2024 elite thresholds of on-demand deploys, sub-day lead time, roughly 5 percent change failure rate, sub-hour recovery, with elite at about 19 percent of respondents): DORA's four keys guide and the 2024 report. Exact cluster bands are report-year specific; a fifth metric on rework has since been added.
  • Hosted alternatives and ephemeral environments (GitHub Actions YAML and hosted runners, GitLab CI configuration, and Review Apps as dynamic per-branch environments): GitHub Actions docs, GitLab CI YAML, and GitLab Review Apps. All three engines support self-hosted runners; the hosted-versus-self-hosted contrast describes the default model.

This post is informational and technical, describing documented tool behavior and public references. Tool versions, metrics, and survey figures change; verify current documentation before relying on a specific detail. Mentions of specific tools and projects are nominative fair use, with no affiliation implied.

← Back to Blog

Accessibility Options

Text Size
High Contrast
Reduce Motion
Reading Guide
Link Highlighting
Accessibility Statement

J.A. Watte is committed to ensuring digital accessibility for people with disabilities. This site conforms to WCAG 2.1 and 2.2 Level AA guidelines.

Measures Taken

  • Semantic HTML with proper heading hierarchy
  • ARIA labels and roles for interactive components
  • Color contrast ratios meeting WCAG AA (4.5:1)
  • Full keyboard navigation support
  • Skip navigation link
  • Visible focus indicators (3:1 contrast)
  • 44px minimum touch/click targets
  • Dark/light theme with system preference detection
  • Responsive design for all devices
  • Reduced motion support (CSS + toggle)
  • Text size customization (14px–20px)
  • Print stylesheet

Feedback

Contact: jwatte.com/contact

Full Accessibility StatementPrivacy Policy

Last updated: April 2026