Jenkins on K8s is Still a Mistake
It’s 2026, and teams are still running Jenkins agents on Kubernetes like it’s a hotel lobby: take up twice as much space as you need, nobody’s happy, and everything’s held together with duct tape.
The Kubernetes-native CI/CD revolution happened. You probably just haven’t switched yet.
Two CNCF projects have matured into genuinely solid pipeline engines that actually understand Kubernetes: Argo Workflows and Tekton. Both are battle-tested, both run your pipelines as Kubernetes workloads (no agents, no VMs, just pods), both treat K8s secrets as first-class citizens, and both let the Kubernetes scheduler decide where to run your jobs. No more Jenkins controller eating 4 GB of RAM just to exist.
But here’s the thing: they’re built on different philosophies. One thinks in directed acyclic graphs (DAGs) and excels at batch processing and ML pipelines. The other thinks in tasks and is laser-focused on CI builds. Both are excellent. They’re just different.
Let’s be honest about what you’re actually getting with each.
Why Kubernetes-Native Matters
Before we get into the weeds, understand why you should care about K8s-native pipelines at all.
Jenkins on Kubernetes means:
- Pod agents that spin up for every job, spin down when done. No persistence, no overhead.
- Secrets live in Kubernetes Secrets, not Jenkins credential stores (one source of truth).
- The Kubernetes scheduler decides where your workload runs — your resources, your constraints, your labels.
- No Jenkins controller acting as a single point of failure. The control plane is just a CRD and some controllers.
- You audit with
kubectlandetcd, not Jenkins logs buried in some container. - Your entire CI/CD stack is declarative YAML, version-controlled, reviewable.
This is a paradigm shift from “Jenkins manages everything” to “Kubernetes manages everything, and CI/CD is just one more workload.”
Argo Workflows: The DAG Pipeline Engine
Argo Workflows thinks in directed acyclic graphs. Your pipeline is a DAG: steps have dependencies, steps can run in parallel, and the execution flow is fully visualized.
Philosophy
Argo Workflows was built for tasks that care about orchestration complexity. Machine learning pipelines. Data engineering. Batch processing. Anything where steps depend on each other’s outputs and you need fine-grained control over parallelism.
A Workflow is a Kubernetes CRD that describes:
- Steps templates — each one is a container that runs and produces output
- DAG templates — describe dependencies between steps
- Arguments and parameters — JSON-based, passed between steps
- Artifact repository — S3-compatible storage for passing files between steps
The Workflow Model
apiVersion: argoproj.io/v1alpha1kind: Workflowmetadata: generateName: data-pipeline- namespace: workflowsspec: entrypoint: main serviceAccountName: argo-workflow arguments: parameters: - name: dataset-url value: "s3://bucket/data.csv" volumeClaimTemplates: - metadata: name: work spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi
templates: - name: main dag: tasks: - name: fetch template: fetch-data arguments: parameters: - name: url value: "{{workflow.parameters.dataset-url}}" - name: process dependencies: fetch template: process-data arguments: artifacts: - name: dataset from: "{{tasks.fetch.outputs.artifacts.dataset}}" - name: analyze dependencies: process template: analyze-results arguments: artifacts: - name: processed from: "{{tasks.process.outputs.artifacts.processed}}"
- name: fetch-data inputs: parameters: - name: url container: image: curlimages/curl:latest command: [sh, -c] args: - | curl -o /tmp/data.csv {{inputs.parameters.url}} outputs: artifacts: - name: dataset path: /tmp/data.csv s3: bucket: argo-artifacts key: "{{workflow.uid}}/data.csv" endpoint: minio:9000 insecure: true accessKeySecret: name: argo-artifact-repo key: accesskey secretKeySecret: name: argo-artifact-repo key: secretkey
- name: process-data inputs: artifacts: - name: dataset path: /data/input.csv container: image: python:3.11 command: [python] args: - | import pandas as pd df = pd.read_csv('/data/input.csv') df_processed = df.dropna() df_processed.to_csv('/data/processed.csv', index=False) outputs: artifacts: - name: processed path: /data/processed.csv s3: bucket: argo-artifacts key: "{{workflow.uid}}/processed.csv" endpoint: minio:9000 insecure: true accessKeySecret: name: argo-artifact-repo key: accesskey secretKeySecret: name: argo-artifact-repo key: secretkey
- name: analyze-results inputs: artifacts: - name: processed path: /data/processed.csv container: image: python:3.11 command: [python] args: - | import pandas as pd df = pd.read_csv('/data/processed.csv') print(f"Rows: {len(df)}") print(df.describe())See what just happened? One YAML file defined a three-step pipeline with dependencies, artifact passing, and parameter injection. The DAG is explicit. Running this:
kubectl apply -f workflow.yamlkubectl get workflows -n workflows -wkubectl logs <workflow-name> -c main -n workflowsArgo generates pods for each step, manages their lifecycle, passes outputs as artifacts, and gives you a web UI showing the DAG in real-time.
Strengths
- DAG clarity — your pipeline structure is right there, visual, unambiguous
- Parameter passing — JSON-based, strongly typed, no string interpolation nonsense
- Artifact repository — S3 integration is built-in; swap minio for real S3, GCS, or Azure Blob
- Batch + ML ready — designed for data pipelines, model training, hyperparameter sweeps
- Argo Events — native triggering from external systems (webhooks, Kafka, S3 events, Cron)
- Argo CD integration — Argo Workflows + Argo CD = full GitOps stack; Argo CD deploys apps, Workflows run the data processing that feeds them
- Visualization — web UI is sharp; DAG view, artifact inspection, parameter tracing
Weaknesses
- Steep YAML curve — that first Workflow is dense. Lots of moving parts (artifact repositories, S3 credentials, templates)
- Artifact repository requirement — you need S3-compatible storage if you’re passing files. Some teams hate that extra dependency
- CRD complexity — the Workflow spec is rich (good for flexibility, bad for simplicity). Debugging template resolution can be painful
- Parameter serialization — everything through JSON. Not ideal if you’re passing huge objects
Tekton: The Task-Based Build Engine
Tekton thinks in tasks and pipelines. A Task is a reusable unit of work (like “build a container image”). A Pipeline stitches tasks together. A PipelineRun executes a pipeline for a specific Git commit.
Philosophy
Tekton was built for CI builds. The mental model is: “I have steps that run in a container, they share a workspace, and they produce artifacts. Let me compose these into a pipeline.”
Unlike Argo’s DAG template language, Tekton’s tasks are concrete and opinionated: each task gets a pod, each step in the task is a container in that pod (via init containers and sidecars), and shared data lives in a PersistentVolume (the workspace).
The Task and Pipeline Model
apiVersion: tekton.dev/v1kind: Taskmetadata: name: git-clone namespace: tekton-pipelinesspec: params: - name: url type: string - name: revision type: string default: main workspaces: - name: output steps: - name: clone image: cgr.dev/chainguard/git:latest script: | git clone --depth 1 --branch $(params.revision) $(params.url) $(workspaces.output.path)
---apiVersion: tekton.dev/v1kind: Taskmetadata: name: build-image namespace: tekton-pipelinesspec: params: - name: image-ref type: string workspaces: - name: source steps: - name: build image: gcr.io/kaniko-project/executor:latest args: - --dockerfile=Dockerfile - --context=$(workspaces.source.path) - --destination=$(params.image-ref) - --snapshot-mode=redo
---apiVersion: tekton.dev/v1kind: Taskmetadata: name: run-tests namespace: tekton-pipelinesspec: params: - name: test-command type: string default: "pytest" workspaces: - name: source steps: - name: test image: python:3.11 workingDir: $(workspaces.source.path) script: | pip install -r requirements.txt $(params.test-command)
---apiVersion: tekton.dev/v1kind: Pipelinemetadata: name: ci-pipeline namespace: tekton-pipelinesspec: params: - name: git-repo-url type: string - name: git-revision type: string default: main - name: image-ref type: string workspaces: - name: workspace tasks: - name: clone taskRef: name: git-clone params: - name: url value: $(params.git-repo-url) - name: revision value: $(params.git-revision) workspaces: - name: output workspace: workspace
- name: test taskRef: name: run-tests runAfter: - clone params: - name: test-command value: "pytest -v" workspaces: - name: source workspace: workspace
- name: build taskRef: name: build-image runAfter: - test params: - name: image-ref value: $(params.image-ref) workspaces: - name: source workspace: workspaceRunning this pipeline:
apiVersion: tekton.dev/v1kind: PipelineRunmetadata: generateName: ci-run- namespace: tekton-pipelinesspec: pipelineRef: name: ci-pipeline params: - name: git-repo-url value: "https://github.com/your-org/your-repo" - name: git-revision value: main - name: image-ref value: "us.gcr.io/your-project/your-image:latest" workspaces: - name: workspace volumeClaimTemplate: spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi serviceAccountName: tekton-runnerSubmit it:
kubectl apply -f pipelinerun.yamlkubectl get pipelinerun -n tekton-pipelines -wtkn pipelinerun logs -L -n tekton-pipelinesEach PipelineRun gets a pod. The pipeline’s tasks become steps in that pod. Tekton Triggers can watch a webhook and fire off PipelineRuns automatically.
Strengths
- Task reusability — tasks are CRDs, shared across pipelines. Tekton Hub has 300+ pre-built tasks (git-clone, build-image, deploy-helm, etc.)
- Workspace simplicity — shared storage is straightforward; all steps see the same filesystem
- Build-focused — designed for CI. Git clone, test, build, push. It just works
- Tekton Triggers — native webhook support; GitHub can fire off a PipelineRun on every push
- Lower YAML overhead — PipelineRun is cleaner than Argo Workflow. Less boilerplate
- Step isolation — each step is a container; failures are crisp, isolation is clear
- CLI tooling —
tknCLI is polished; log streaming, resource inspection, deletion
Weaknesses
- No DAG templates — dependencies are
runAfter. Complex graphs get unwieldy fast. If you have lots of parallel tasks with intricate dependencies, the YAML gets messy - Workspace-only sharing — no built-in artifact repository like Argo. You manage PVCs yourself. For distributed pipelines across clusters, that’s annoying
- Sidecar pattern overhead — steps in a task run in the same pod. Sidecars are sometimes needed for logging or monitoring; that’s an extra container per task
- Parameter passing — simpler than Argo, but still string-based. Type safety is loose
- UI — web dashboard exists (Tekton Dashboard) but it’s functional, not beautiful. Nowhere near Argo’s polish
Head-to-Head Comparison
| Aspect | Argo Workflows | Tekton |
|---|---|---|
| Model | DAG-based; template language | Task-based; pipeline composition |
| Best for | ML, batch, data pipelines | CI/CD builds |
| Artifact sharing | S3-compatible repo (built-in) | Workspace (manual PVC management) |
| Parameter passing | JSON, typed | String interpolation |
| CRD learning curve | Steep; lots of concepts | Gentler; tasks are intuitive |
| Reusable components | Templates; less discoverable | Tasks; Tekton Hub integration |
| Web UI | Sharp, DAG visualization | Functional, task-focused |
| External triggering | Argo Events (webhooks, Kafka, Cron) | Tekton Triggers (webhooks, EventListeners) |
| Debugging | Good; parameter tracing, artifact inspection | Good; step logs, clear failures |
| Ecosystem pairing | Argo CD (full GitOps) | Standalone; integrates with any deployer |
| Secrets handling | K8s Secrets (native) | K8s Secrets (native) |
| Maturity | Very stable (5+ years CNCF) | Very stable (5+ years CNCF) |
When to Choose Argo Workflows
Choose Argo if you have:
- Machine learning pipelines — hyperparameter sweeps, model training, batch inference
- Data engineering workflows — ETL, complex transformations, fan-out/fan-in patterns
- Interdependent steps — each step consumes outputs from others; a DAG is your natural language
- Distributed artifact storage needs — S3 integration out-of-the-box beats managing PVCs
- Desire for full Argo stack — Argo CD (GitOps deployments) + Argo Workflows (pipeline orchestration) + Argo Events (triggering) is a cohesive story
- Batch processing — hourly, daily, or event-driven batch jobs that care about parallelism and resource efficiency
When to Choose Tekton
Choose Tekton if you have:
- CI/CD pipelines — clone, test, build, push. Straightforward linear flow
- Kubernetes-native builds — you want Kaniko, buildpacks, or container-in-container. Tekton has excellent task support
- Reusable task library — you value Tekton Hub and want to compose from existing tasks
- Webhook-driven CI — GitHub, GitLab, or custom webhooks triggering builds on every commit
- Simpler YAML — you want fewer moving parts and lower initial complexity
- Multi-repo builds — git-clone is trivial; orchestrating across repos is straightforward
- DevOps simplicity — teams that want CI working with minimal fuss
The Real Difference: Philosophy
Here’s what separates them:
Argo Workflows asks: “What if we made a Kubernetes-native orchestration engine for complex, interdependent workloads?” The answer is a rich, flexible DAG engine that’s overkill for CI but perfect for ML/data pipelines.
Tekton asks: “What if we made CI/CD that’s just tasks and pipelines, no Jenkins cruft?” The answer is a focused, composable system that feels familiar to anyone who’s written a shell script.
Neither is “better.” They’re solving different problems.
Integration with Your Stack
With Argo CD
If you’re using Argo CD for GitOps deployments, Argo Workflows is the natural fit:
apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: my-projectspec: namespaceResourceBlacklist: - group: argoproj.io kind: WorkflowYour Argo CD applications can trigger Workflows via webhooks or Argo Events, creating a full CI/CD + orchestration platform.
With Other Deployers
If you’re using Helm, Flux, kustomize, or custom operators for deployments, Tekton integrates cleanly because it’s agnostic:
# Tekton runs the pipelinetkn pipeline start my-build --param image=myimage:latest
# Your deployer handles the deploymentkubectl apply -f deployment.yaml# or helm upgrade, or flux reconcile, etc.The Verdict
Jenkins is dead. Both of these tools prove it. You get K8s scheduling, declarative pipelines, secrets integration, and zero agent overhead.
If you’re building an ML data processing platform or complex batch workflows, Argo Workflows is your friend. The DAG model shines. Invest in learning the Workflow spec; it’s dense but worth it.
If you’re a DevOps team running CI/CD, Tekton is the path of least resistance. Tasks are composable, webhooks just work, and the learning curve is gentler. Your developers will thank you.
And here’s the thing: in 2026, both are production-ready, battle-tested, and backed by serious CNCF investment. You don’t have a “wrong” choice here. You have a philosophy choice. Pick the one that matches your workload, commit, and never look back at Jenkins again.
Your 2 AM self will appreciate it.