KubeCon India — Shipwright Pavilion Prep
A 1-day interactive study guide to prepare for hosting the Shipwright project table. Built from upstream docs, Adam Kaplan's demos, and competitive research.
Study Plan — 7 Hours
| Time | Layer | Activity |
|---|---|---|
| 1 hr | Layer 1 | Problem, What is Shipwright, Elevator Pitch, Key Concepts |
| 2 hrs | Layer 2 | CRDs, Build YAML, BuildRun, Strategies, Features |
| 30 min | Lunch — practice elevator pitch out loud | |
| 1.5 hrs | Layer 3 | vs BuildConfig, vs Tekton, vs Tools, Landscape, CNCF |
| 1.5 hrs | Layer 4 | Demo setup + dry-run, FAQ practice, tough questions |
| 30 min | Self-test quiz + review weak areas | |
How to Use This Guide
- Navigate using the sidebar — topics are in study order
- Click "Mark as Studied" checkboxes as you complete each topic
- Progress bar tracks your completion across all 19 topics
- Expand accordion sections for detailed content
- Code blocks contain real YAML from the Shipwright repo
- End with the Self-Test Quiz to validate your knowledge
Your KubeCon Table Strategy
Pavilion conversations are 5-10 minutes. Read the person in 30 seconds:
| Who walks up | Start at | Go to |
|---|---|---|
| CNCF curious — "What is this?" | Elevator pitch | Quick demo |
| Developer — "How do I use it?" | Build YAML | Strategy options, CNB demo |
| Platform engineer — "Why should I adopt?" | vs BuildConfig | Multi-tenancy, security, caching |
| OpenShift user — "We use BuildConfig" | vs BuildConfig | Migration path, future direction |
| Tekton user — "We already have pipelines" | vs Raw Tekton | "Tekton is the engine" analogy |
The Problem
Why building container images on Kubernetes is harder than it should be.
Before Shipwright, your options were...
docker build, push to a registry. Problems: doesn't scale, no CI/CD integration, no audit trail, works on "my machine" syndrome. Every developer has a different Docker version and build environment.
privileged: true security context — massive security risk on shared clusters. One compromised build pod can access the host kernel. No multi-tenant isolation.
How We Got Here — The Evolution
Understanding why each tool exists helps you explain the landscape at the table:
docker build reads a Dockerfile, executes each instruction in a container, and produces an image. It worked great on laptops but had a fatal flaw for Kubernetes: it requires a Docker daemon running as root. On shared clusters, this means privileged containers — any build pod can escape to the host kernel. The Docker daemon is also monolithic — it does building, running, pushing, networking all in one process.
- Kaniko (Google, 2018) — Solved "how do I build a Dockerfile without a Docker daemon?" Runs entirely in userspace with filesystem snapshotting. No root, no daemon. Trade-off: slower than Docker for large images, can't use BuildKit syntax.
- Buildah (Red Hat, 2017) — Solved "how do I build OCI images without Docker at all?" Uses Linux user namespaces for rootless builds. Part of the Podman/Buildah/Skopeo trio that replaced Docker on RHEL. Trade-off: Linux-only, needs some kernel features.
- BuildKit (Docker/Moby, 2017) — Docker's own answer to its own problems. Rebuilt the builder from scratch with a DAG-based execution model. Concurrent stage execution, advanced caching (inline, registry, S3),
RUN --mountsyntax. Trade-off: rootless mode still needs some privileges on K8s.
- Cloud Native Buildpacks (Pivotal/Heroku, 2018) — Auto-detect your language, apply the right buildpack, produce an OCI image. No Dockerfile needed. Platform teams maintain buildpack images with security patches. Trade-off: builder images are 1GB+, opaque lifecycle, limited to supported languages.
- ko (Google, 2019) — For Go apps: run
go build, layer the binary onto a distroless base, push. Images under 10MB. Absurdly fast. Trade-off: Go only, no OS packages, no cgo. - Source-to-Image / S2I (Red Hat, 2015) — OpenShift's original "no Dockerfile" approach. Builder images contain build logic for a language. Trade-off: OpenShift-specific, limited ecosystem.
Now we have 7+ excellent build tools — each solving a real problem. But this created a new problem: fragmentation.
- Team A uses Kaniko, Team B uses Buildpacks, Team C uses BuildKit
- Each team has different Tekton pipelines, different credential management, different YAML
- Platform teams can't enforce governance — they don't even know what tools teams are using
- Switching tools means rewriting pipelines
- No unified audit trail across tools
This is exactly what Shipwright solves. It doesn't replace these tools — it wraps them in a unified API. One Build spec, any strategy. The tools compete on build quality; Shipwright provides the management plane.
What is Shipwright
The core concept and architecture in one mental model.
One-sentence definition
Shipwright is a Kubernetes-native framework that provides a unified API for building container images, powered by Tekton, with pluggable build strategies.
The Key Insight
This separation is what makes everything else possible — tool flexibility, governance, simplicity, and security.
Four Pillars
Vendor neutral, community governed, open source.
Uses Tekton TaskRuns/PipelineRuns under the hood. Developers never see Tekton.
Buildah, Kaniko, BuildKit, Buildpacks, ko, S2I — all through one API.
Used in production by multiple organizations. Enterprise vendors build supported products on top of it.
Elevator Pitch
Practice this until you can say it naturally in 30 seconds.
The 30-Second Pitch
Key Analogies (pick one that fits)
Key Concepts
Foundation knowledge you need before diving into the API.
Container Image Basics
- OCI Image Spec — container images are standardized. Any OCI-compliant tool produces the same format. This is why tool choice matters less than people think — the output is the same regardless of whether Buildah, Kaniko, or BuildKit built it.
- Layers — images are stacks of filesystem layers. Each Dockerfile instruction creates a layer. Understanding this helps explain caching: unchanged layers are reused.
- Image Digest — a SHA256 hash of the image manifest. Shipwright records this in BuildRun status for audit.
- Multi-arch / Manifest Lists — a single image tag can point to multiple architecture-specific images via an OCI Index (manifest list). Critical for ARM64 + AMD64 support.
CNCF Landscape Position
Shipwright sits between the developer and Tekton. It's not a CI/CD system — it's a build-specific abstraction layer.
Shipwright Project Structure
| Repository | What it is |
|---|---|
| shipwright-io/build | Core Build controller — CRDs, reconcilers, webhook |
| shipwright-io/operator | OLM operator for installing Shipwright |
| shipwright-io/cli | shp CLI tool for managing builds |
| shipwright-io/triggers | Event-driven build triggers (webhooks, image changes) |
| shipwright-io/website | Documentation and blog at shipwright.io |
| shipwright-io/community | SHIPs (enhancement proposals), tracking issues |
CRD Model
The 4 custom resources that make up Shipwright.
Architecture Overview
Override Precedence (the key design insight)
This is consistent across every overridable field: timeout, paramValues, output, env, stepResources, nodeSelector, tolerations, schedulerName, runtimeClassName, volumes. Platform teams set sensible defaults; developers override per-run.
Build YAML Deep Dive
Real examples from the Shipwright repo with field-by-field explanation.
Minimal Build (12 lines)
apiVersion: shipwright.io/v1beta1
kind: Build
metadata:
name: my-app
spec:
source:
type: Git
git:
url: https://github.com/shipwright-io/sample-go
contextDir: docker-build
strategy:
name: buildah
kind: ClusterBuildStrategy
output:
image: quay.io/my-org/my-app:latest
pushSecret: my-registry-creds
That's it. Source, strategy, output. The developer doesn't need to know Tekton, pipelines, or Buildah flags.
Full Spec Fields
| Field | Description |
|---|---|
source.type | Git, OCI, or Local |
source.git.url | Repository URL (HTTPS or SSH) |
source.git.revision | Branch, tag, or commit SHA |
source.git.cloneSecret | Secret for private repos |
source.git.depth | Clone depth (default 1 = shallow) |
source.contextDir | Subdirectory within repo |
| Field | Description |
|---|---|
output.image | Destination registry URL |
output.pushSecret | Secret for registry auth |
output.annotations | OCI annotations on image |
output.labels | Labels on image |
output.timestamp | Zero, SourceTimestamp, BuildTimestamp, or epoch |
output.vulnerabilityScan | Enable scan, failOnFinding, ignore list |
output:
image: registry.example.com/app:latest
pushSecret: creds
vulnerabilityScan:
enabled: true
failOnFinding: true
ignore:
issues: [CVE-2022-12345]
severity: Low
unfixed: true
Parameters pass values into BuildStrategy steps. Support strings, arrays, ConfigMap references, and Secret references.
paramValues:
- name: build-args
values:
- configMapValue:
name: project-config
key: node-version
format: NODE_VERSION=${CONFIGMAP_VALUE}
- value: DEBUG_MODE=true
- secretValue:
name: npm-registry
key: auth-token
format: NPM_AUTH_TOKEN=${SECRET_VALUE}
The format syntax lets you compose values from external sources without scripting.
| Field | Description |
|---|---|
timeout | Go duration (default 10m) |
env | Extra env vars (supports Downward API) |
retention | TTL + limits for BuildRun cleanup |
volumes | Override strategy volumes (if marked overridable) |
stepResources | CPU/memory per strategy step v0.19 |
nodeSelector | Schedule on specific nodes |
tolerations | Tolerate taints (NoSchedule only) |
schedulerName | Custom scheduler |
runtimeClassName | Alternative runtime (kata, etc.) v0.19 |
trigger | GitHub webhooks, image change, pipeline triggers |
BuildRun & Execution
How builds actually execute, plus the standalone BuildRun pattern.
Controller Flow
Two Patterns
apiVersion: shipwright.io/v1beta1
kind: BuildRun
metadata:
name: my-app-run-1
spec:
build:
name: my-app # references existing Build
serviceAccount: pipeline
timeout: 15m # override Build's timeout
apiVersion: shipwright.io/v1beta1
kind: BuildRun
metadata:
name: standalone-run
spec:
build:
spec: # embed Build spec inline
source:
type: Git
git:
url: https://github.com/shipwright-io/sample-go
contextDir: source-build
strategy:
kind: ClusterBuildStrategy
name: buildpacks-v3
output:
image: quay.io/my-org/app:latest
No Build CR needed — perfect for CI/CD pipelines where the build definition is ephemeral.
What's in BuildRun Status (Audit Gold)
- Image digest — SHA256 of the built image
- Image size — compressed size
- Git commit SHA — exact commit that was built
- Git commit author — who committed
- Vulnerability scan results — CVE IDs with severities
- Build spec snapshot — copy of the Build spec at execution time (if the Build changes later, you still know what config produced each image)
- 30+ failure reason codes — rich error reporting:
BuildRunTimeout,StepOutOfMemory,GitAuthInvalidKey,GitRevisionNotFound, etc.
BuildStrategies
The pluggable build engine abstraction — where the real power is.
Why Multiple Strategies?
There is no single "best" way to build a container image. Different teams have different needs:
Some teams write Dockerfiles, others don't want to. Buildpacks auto-detect your language. ko compiles Go directly. S2I uses builder images. Shipwright lets each team use what fits.
Some clusters ban privileged containers entirely (rootless-only). Others need daemon-based tools for cache performance. The strategy abstraction lets platform teams enforce policy without blocking developers.
BuildKit has advanced layer caching and parallel stage execution. Kaniko trades speed for zero-privilege simplicity. ko skips the Dockerfile entirely for fastest Go builds. Teams pick the right tradeoff.
Developers use the same
Build/BuildRun CRDs regardless of strategy. Platform teams swap engines without changing developer workflows. That's the whole point of the abstraction.
Supported Strategies
| Strategy | Tool | What it does | Rootless? | Platforms |
|---|---|---|---|---|
| Buildah | buildah | Dockerfile-based builds | Yes | All |
| Multi-arch Buildah | buildah | Orchestrator + per-arch jobs → manifest list | Yes | All |
| Kaniko | kaniko | Dockerfile in userspace, no daemon | Yes | All |
| BuildKit | buildkit | Daemonless, cache exporters, multi-platform | Setup | All |
| Buildpacks v3 | CNB lifecycle | Auto-detect language, no Dockerfile | Yes | amd64 |
| ko | ko | Go binaries → images directly | Yes | All |
| Source-to-Image | s2i + kaniko | S2I generates Dockerfile, kaniko builds it | Yes | amd64 |
How Do They Differ?
Quick decision guide — pick based on your constraints:
| Dimension | Buildah | Kaniko | BuildKit | Buildpacks | ko | S2I |
|---|---|---|---|---|---|---|
| Needs Dockerfile? | Yes | Yes | Yes | No | No | No |
| Best for | General purpose, OCI-native | Locked-down clusters | Speed, caching, multi-stage | Source-only devs | Go projects | Legacy OpenShift |
| Cache support | Layer cache | Layer cache | Advanced (inline, registry, local) | Layer reuse | Go module cache | Incremental builds |
| Multi-arch | Yes (dedicated strategy) | Single arch | Yes (cross-compile) | Single arch | Yes | Single arch |
| Privileged? | No (rootless) | No (userspace) | Needs setup | No (rootless) | No | No |
| Tradeoff | Jack of all trades | Slower but zero-privilege | Fastest but needs config | No control over image layers | Go-only | Fewer maintainers, limited to amd64 |
System Parameters (injected by controller)
| Parameter | Description |
|---|---|
$(params.shp-source-root) | Absolute path to cloned source |
$(params.shp-source-context) | Path to context dir |
$(params.shp-output-directory) | Where to store image locally (Shipwright-managed push) |
$(params.shp-output-image) | Output image URL |
The Push Model Decision
Strategy authors choose who pushes the image:
Strategy writes image to
$(params.shp-output-directory). Shipwright handles the push. Gets annotations/labels/SBOM for free.
Strategy pushes directly to
$(params.shp-output-image). Can optimize (skip base layer downloads). Annotations cause a second push.
Key Features
The features that make people say "oh, that's nice."
shipwright-io/triggers controller.
trigger:
when:
- name: push-to-main
type: GitHub
github:
events: [Push]
branches: [main]
failOnFinding: true gates the build on security. Can ignore specific CVEs, unfixed vulnerabilities, or below a severity threshold.
ttlAfterFailed: 30m, ttlAfterSucceeded: 1h) or keep only N most recent (failedLimit: 10, succeededLimit: 20). Cascade-delete BuildRuns when a Build is deleted with atBuildDeletion: true.
overridable: true. Developers override with PVCs for persistent caches. First build: 2+ minutes. Second build with cache: 30 seconds. Platform team sets up the caching strategy, every developer gets fast builds automatically.
strategy:
name: buildah
kind: ClusterBuildStrategy
stepResources:
- name: build
resources:
requests: { cpu: 500m, memory: 512Mi }
limits: { cpu: "1", memory: 1Gi }
vs OpenShift BuildConfig
Your #1 question from OpenShift users. Know this cold.
Comparison
| Dimension | BuildConfig (legacy) | Shipwright |
|---|---|---|
| API | v1, frozen — no new features | v1beta1, actively developed |
| Build tools | Docker build + S2I only | Buildah, Kaniko, BuildKit, Buildpacks, ko, S2I, custom |
| Portability | OpenShift-only | Any Kubernetes |
| Extensibility | None | BuildStrategy API — bring your own tool |
| Multi-arch | Not supported | Native multi-arch Buildah + PipelineRun mode |
| Security | Docker build needs privileged | Rootless by default |
| Migration | — | Crane-based migration tool (dev preview, Jan 2026) |
| Future | Deprecated path | Strategic direction for OpenShift |
Your Lines
Migration Path
- S2I builds: Shipwright has an S2I strategy — existing builder images still work
- Docker builds: Switch to the Buildah strategy (rootless, more secure)
- Jenkins Pipeline: Already deprecated — move to Tekton pipelines or Shipwright
- YAML conversion: Build YAML is simpler than BuildConfig — concepts map 1:1
- Tooling: Crane-based migration tool auto-converts BuildConfig → Build (dev preview)
vs Raw Tekton
"Why not just write a Tekton pipeline for builds?"
| Dimension | Raw Tekton | Shipwright |
|---|---|---|
| YAML lines | 60-100+ (Task + Pipeline + PipelineRun + Workspaces) | ~15-25 (Build + BuildRun) |
| Abstraction | General-purpose CI/CD | Purpose-built for builds |
| Strategy reuse | Copy-paste Tasks across teams | ClusterBuildStrategy — install once |
| Credential mgmt | Manual workspace/secret wiring | Declarative pushSecret |
| Build features | Build yourself: clone, push, digest, scanning | All built-in |
| Maintenance | Every team maintains pipelines | Platform team maintains strategies |
vs Standalone Tools
For people who say "I just use Kaniko / ko / Buildpacks directly."
| Concern | Standalone tool | Shipwright |
|---|---|---|
| Switching tools | Rewrite CI/CD pipeline | Change one line (strategy.name) |
| Multi-tenancy | Roll your own RBAC | K8s-native namespaces, RBAC, resource limits |
| Audit trail | Check CI logs | BuildRun status: digest, commit, author — in K8s API |
| Governance | No control over dev choices | ClusterBuildStrategy — platform curates approved tools |
| Consistency | Every team does it differently | One API, one workflow, any tool |
Tool-Specific Details
RUN --mount=type=cache), slower than BuildKit for large images, single-platform per run. Available as a Shipwright strategy.RUN --mount syntax, parallel stage execution, zstd compression. Limitations: Rootless mode still needs privileged: true with hostUsers: false; requires AppArmor/SecComp unconfined profiles. Available as a Shipwright strategy.go build, layers binary onto distroless base. Images under 10MB. Native multi-platform. Used by Tekton, Knative, Sigstore. Limitations: Go only, no cgo, no OS packages. CNCF Sandbox. Available as a Shipwright strategy.Competitive Landscape
The full picture — where everything sits.
Landscape Map
| Project | Category | Shipwright Relationship |
|---|---|---|
| Tekton | CI/CD engine | Shipwright's runtime — layer above, not competitor |
| Kaniko | Build tool | One of 7 Shipwright strategies |
| BuildKit | Build tool | One of 7 Shipwright strategies |
| Buildpacks (CNB) | Build tool | One of 7 Shipwright strategies |
| ko | Build tool | One of 7 Shipwright strategies |
| BuildConfig | Legacy OCP builds | Shipwright is its successor |
| Google Cloud Build | Managed service | Vendor lock-in, not portable, not self-hosted |
| GitHub Actions | Managed CI/CD | Off-cluster, no K8s-native governance |
| GitLab CI/CD | Managed CI/CD | Pipeline-first, not build-specific abstraction |
Why In-Cluster Builds Matter
For skeptics who say "just use GitHub Actions":
- Data sovereignty — source code and images never leave your cluster
- Air-gapped environments — works without internet access
- Unified RBAC — one access control system for everything
- Supply chain security — Tekton Chains provides SLSA attestations
- Cost predictability — no per-minute billing at scale
- Cloud portability — same build definitions work anywhere
CNCF Story
Project governance, community health, and enterprise adoption.
Project Facts
- Status: CNCF Sandbox (accepted Aug 2024)
- Previously: CDF Incubating
- Stars: 808+ on GitHub
- Contributors: 197 (+18% YoY)
- Contributing orgs: 78 (+37% YoY)
- Latest release: v0.19.7 (June 2026)
- Community calls: Weekly, Monday 9AM ET
- Enhancement process: SHIPs
- Slack: #shipwright on Kubernetes Slack
- YouTube: @shipwright-io
Lines for the Table
Live Demos
From Adam Kaplan's builds-openshift-demos repo. Pick 2 for the table.
Demo 1: Build Strategies (2-3 min)
Point: Same app, two different strategies, one-line change.
apiVersion: shipwright.io/v1beta1
kind: Build
metadata:
name: s2i-nodejs
spec:
source:
type: Git
git:
url: https://github.com/sclorg/nodejs-ex
strategy:
name: source-to-image
kind: ClusterBuildStrategy
paramValues:
- name: builder-image
value: image-registry.openshift-image-registry.svc:5000/openshift/nodejs:16-ubi9
output:
image: image-registry.openshift-image-registry.svc:5000/demo-builds/nodejs-ex:s2i
apiVersion: shipwright.io/v1beta1
kind: Build
metadata:
name: buildah-nodejs
spec:
source:
type: Git
git:
url: https://github.com/shipwright-io/sample-nodejs.git
contextDir: docker-build
strategy:
name: buildah # <-- only this changes
kind: ClusterBuildStrategy
output:
image: image-registry.openshift-image-registry.svc:5000/demo-builds/nodejs-ex:buildah
oc new-project demo-builds
oc create imagestream nodejs-ex
oc apply -f 01-s2i-nodejs-build.yaml
shp build run s2i-nodejs --follow
# Then switch strategy:
oc apply -f 02-buildah-nodejs-build.yaml
shp build run buildah-nodejs --follow
Demo 2: Build Volumes / Caching (3-5 min)
Point: Platform team sets up caching, developers get fast builds.
apiVersion: shipwright.io/v1beta1
kind: Build
metadata:
name: buildah-nodejs-cache
spec:
source:
type: Git
git:
url: https://github.com/shipwright-io/sample-nodejs.git
contextDir: docker-build
strategy:
name: buildah-cache
kind: BuildStrategy
output:
image: image-registry.openshift-image-registry.svc:5000/demo-builds/nodejs-ex:buildah
volumes:
- name: build-cache
persistentVolumeClaim:
claimName: build-cache # PVC for layer caching
oc apply -f 00-cache-pvc.yaml # Create the PVC
oc apply -f 01-buildah-cache-strategy.yaml # Namespace strategy with cache volume
oc apply -f 02-buildah-nodejs-cache-build.yaml
time shp build run buildah-nodejs-cache --follow # First: ~2 min
time shp build run buildah-nodejs-cache --follow # Second: ~30 sec!
Demo Prep Checklist
adambkaplan/builds-openshift-demosTop 15 FAQ
What people actually ask at a KubeCon pavilion table. Click to reveal answers.
The Basics
The OpenShift Crowd
The Platform Engineer
pushSecret for registry, cloneSecret for git. Shipwright injects them into the right steps. You can also pass Secret/ConfigMap values as strategy parameters with format strings."overridable: true. Developers replace them with PVCs. Buildah gets layer caching, BuildKit gets its cache exporters, Buildpacks has built-in layer caching. First build: 2+ min. With cache: ~30 seconds. Platform team configures it once, every developer benefits."The Technical Deep-Dive
vulnerabilityScan to your Build spec. Set failOnFinding: true to gate builds on security. Results appear in BuildRun status with CVE IDs and severities. Ignore specific CVEs, unfixed vulns, or below a severity threshold."shipwright-io/triggers controller handles event routing."The Skeptic
Tough Questions
The ones that could catch you off guard. Practice these.
Know the SHIPs in progress:
- SHIP-0040 — RuntimeClass support (landed in v0.19)
- SHIP-0043 — Multi-Arch Image Builds (in progress)
- SHIP-0044 — BuildRun Executor Field
- SHIP-0046 — Build Step Resources Override (landed in v0.19)
- SHIP-0041 — Documentation Restructure
Check the community meeting notes before KubeCon for latest v0.20 plans. Version mapping: v0.20 upstream = builds-1.9 downstream.
stepResources (v0.19) to tune. Third: consider your strategy choice — BuildKit with inline cache is often fastest for Dockerfile builds."
Self-Test Quiz
10 questions to validate your readiness. Click options to check.