Meet
Unlike tools that embed logic into YAML or require custom template languages, kubepatch keeps your base manifests clean and idiomatic.
- Simple: No templates, DSLs, or logic in YAML, zero magic
- Predictable: No string substitutions or regex hacks
- Safe: Only native Kubernetes YAML manifests - readable, valid, untouched
- Layered: Patch logic is externalized and explicit via JSON Patch (RFC 6902)
- Declarative: Cross-environment deployment with predictable, understandable changes
🛠 Example
Given a base set of manifests for deploy a basic microservice
---
apiVersion: v1
kind: Service
metadata:
name: myapp
labels:
app: myapp
spec:
type: NodePort
selector:
app: myapp
ports:
- protocol: TCP
port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: "localhost:5000/restapiapp:latest"
A patches/prod.yamlmight look like:
name: myapp-prod
labels:
app: myapp-prod
patches:
# deployment
- target:
kind: Deployment
name: myapp
patches:
- op: replace
path: /spec/replicas
value: 1
- op: replace
path: /spec/template/spec/containers/0/image
value: "localhost:5000/restapiapp:1.21"
- op: add
path: /spec/template/spec/containers/0/env
value:
- name: RESTAPIAPP_VERSION
value: prod
- name: LOG_LEVEL
value: info
- op: add
path: /spec/template/spec/containers/0/resources
value:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "64m"
memory: "128Mi"
# service
- target:
kind: Service
name: myapp
patches:
- op: add
path: /spec/ports/0/nodePort
value: 30266
A patches/dev.yamlmight look like:
name: myapp-dev
labels:
app: myapp-dev
patches:
# deployment
- target:
kind: Deployment
name: myapp
patches:
- op: add
path: /spec/template/spec/containers/0/env
value:
- name: RESTAPIAPP_VERSION
value: dev
- name: LOG_LEVEL
value: debug
# service
- target:
kind: Service
name: myapp
patches:
- op: add
path: /spec/ports/0/nodePort
value: 30265
Apply the appropriate patch set based on the target environment.
kubepatch patch -f base/ -p patches/dev.yaml | kubectl apply -f -
Rendered manifest may look like this (note that all labels are set, as well as all patches are applied)
---
apiVersion: v1
kind: Service
metadata:
labels:
app: myapp-dev
name: myapp-dev
spec:
ports:
- nodePort: 30265
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: myapp-dev
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myapp-dev
name: myapp-dev
spec:
replicas: 1
selector:
matchLabels:
app: myapp-dev
template:
metadata:
labels:
app: myapp-dev
spec:
containers:
- env:
- name: RESTAPIAPP_VERSION
value: dev
- name: LOG_LEVEL
value: debug
image: localhost:5000/restapiapp:1.22
name: myapp
Installation
Manual Installation
- Download the latest binary for your platform from the
Releases page . - Place the binary in your system's
PATH(e.g.,/usr/local/bin).
Installation script
(
set -euo pipefail
OS="$(uname | tr '[:upper:]' '[:lower:]')"
ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')"
TAG="$(curl -s https://api.github.com/repos/kubepatch/kubepatch/releases/latest | jq -r .tag_name)"
curl -L "https://github.com/kubepatch/kubepatch/releases/download/${TAG}/kubepatch_${TAG}_${OS}_${ARCH}.tar.gz" |
tar -xzf - -C /usr/local/bin && \
chmod +x /usr/local/bin/kubepatch
)
Package-Based installation (suitable in CI/CD)
Debian
sudo apt update -y && sudo apt install -y curl
curl -LO https://github.com/kubepatch/kubepatch/releases/latest/download/kubepatch_linux_amd64.deb
sudo dpkg -i kubepatch_linux_amd64.deb
Alpine Linux
apk update && apk add --no-cache bash curl
curl -LO https://github.com/kubepatch/kubepatch/releases/latest/download/kubepatch_linux_amd64.apk
apk add kubepatch_linux_amd64.apk --allow-untrusted
✨ Key Features
JSON Patch Only
Patches are applied using
- op: replace
path: /spec/replicas
value: 1
Every patch is minimal, explicit, and easy to understand. No string manipulation or text templating involved.
Plain Kubernetes YAML Manifests
Your base manifests are 100% pure Kubernetes objects - no logic, no annotations, no overrides, no preprocessing. This
ensures:
- Easy editing
- Compatibility with other tools
- Clean Git diffs
Cross-Environment Deploys
Deploy to dev, staging, or prodjust by selecting the right set of patches. All logic lives in patch files, not
your base manifests.
Common Labels Support
Inject common labels (like env, team, app), including deep paths like pod templates and selectors.
Env Var Substitution (in Patch Values Only)
You can inject secrets and configuration values directly into patch files:
- op: add
path: /spec/template/spec/containers/0/env
value:
- name: PGPASSWORD
value: ${IAM_SERVICE_PGPASS}
Strict env-var substitution (prefix-based) is only allowed inside patches - never in base manifests.
Feedback
Have a feature request or issue? Feel free to
