
kustomize-overlays
by TheBushidoCollective
A curated marketplace of Claude Code plugins that embody the principles of ethical and professional software development.
SKILL.md
name: kustomize-overlays description: Use when managing environment-specific Kubernetes configurations with Kustomize overlays and patches. allowed-tools: [Bash, Read]
Kustomize Overlays
Master environment-specific Kubernetes configuration management using Kustomize overlays, strategic merge patches, and JSON patches for development, staging, and production environments.
Overview
Overlays enable environment-specific customization of Kubernetes resources without duplicating configuration. Each overlay references a base configuration and applies environment-specific patches, transformations, and resource adjustments.
Basic Overlay Structure
myapp/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── configmap.yaml
│ └── ingress.yaml
└── overlays/
├── development/
│ ├── kustomization.yaml
│ ├── replica-patch.yaml
│ └── namespace.yaml
├── staging/
│ ├── kustomization.yaml
│ ├── replica-patch.yaml
│ ├── resource-patch.yaml
│ └── namespace.yaml
└── production/
├── kustomization.yaml
├── replica-patch.yaml
├── resource-patch.yaml
├── hpa.yaml
└── namespace.yaml
Base Configuration
Base Kustomization
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
name: myapp-base
# Resources to include
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
- ingress.yaml
# Common labels applied to all resources
commonLabels:
app: myapp
managed-by: kustomize
# Common annotations
commonAnnotations:
version: "1.0.0"
team: platform
# Name prefix for all resources
namePrefix: myapp-
# Default namespace (can be overridden in overlays)
namespace: default
# Image transformations
images:
- name: myapp
newName: registry.example.com/myapp
newTag: latest
Base Deployment
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 8080
name: http
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: config
key: log-level
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
periodSeconds: 5
Base Service
# base/service.yaml
apiVersion: v1
kind: Service
metadata:
name: service
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: myapp
Base ConfigMap
# base/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: config
data:
log-level: "info"
cache-enabled: "true"
timeout: "30"
Base Ingress
# base/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
Development Overlay
Development Kustomization
# overlays/development/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Reference the base
resources:
- ../../base
- namespace.yaml
# Override namespace
namespace: development
# Development-specific labels
commonLabels:
environment: development
cost-center: engineering
# Development-specific annotations
commonAnnotations:
deployed-by: ci-cd
environment: dev
# Name suffix for development resources
nameSuffix: -dev
# Image overrides for development
images:
- name: myapp
newName: registry.example.com/myapp
newTag: dev-latest
# ConfigMap overrides
configMapGenerator:
- name: config
behavior: merge
literals:
- log-level=debug
- cache-enabled=false
- debug-mode=true
# Replica overrides
replicas:
- name: myapp-deployment
count: 1
# Strategic merge patches
patches:
- path: replica-patch.yaml
target:
kind: Deployment
name: myapp-deployment
# Inline patches
patchesStrategicMerge:
- |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
template:
spec:
containers:
- name: myapp
env:
- name: ENVIRONMENT
value: development
- name: DEBUG
value: "true"
Development Namespace
# overlays/development/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: development
labels:
environment: development
team: platform
Development Replica Patch
# overlays/development/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 1
template:
spec:
containers:
- name: myapp
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
Staging Overlay
Staging Kustomization
# overlays/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
- namespace.yaml
namespace: staging
commonLabels:
environment: staging
cost-center: engineering
commonAnnotations:
deployed-by: ci-cd
environment: staging
nameSuffix: -staging
images:
- name: myapp
newName: registry.example.com/myapp
newTag: staging-v1.2.3
configMapGenerator:
- name: config
behavior: merge
literals:
- log-level=info
- cache-enabled=true
- cache-ttl=300
replicas:
- name: myapp-deployment
count: 2
patches:
- path: replica-patch.yaml
target:
kind: Deployment
name: myapp-deployment
- path: resource-patch.yaml
target:
kind: Deployment
name: myapp-deployment
patchesStrategicMerge:
- |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
spec:
containers:
- name: myapp
env:
- name: ENVIRONMENT
value: staging
- name: METRICS_ENABLED
value: "true"
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
topologyKey: kubernetes.io/hostname
Staging Replica Patch
# overlays/staging/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
Staging Resource Patch
# overlays/staging/resource-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
template:
spec:
containers:
- name: myapp
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
Production Overlay
Production Kustomization
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
- namespace.yaml
- hpa.yaml
- pdb.yaml
- network-policy.yaml
namespace: production
commonLabels:
environment: production
cost-center: product
compliance: pci
commonAnnotations:
deployed-by: ci-cd
environment: production
backup: "true"
nameSuffix: -prod
images:
- name: myapp
newName: registry.example.com/myapp
newTag: v1.2.3
digest: sha256:abc123...
configMapGenerator:
- name: config
behavior: merge
literals:
- log-level=warn
- cache-enabled=true
- cache-ttl=600
- rate-limit-enabled=true
replicas:
- name: myapp-deployment
count: 5
patches:
- path: replica-patch.yaml
target:
kind: Deployment
name: myapp-deployment
- path: resource-patch.yaml
target:
kind: Deployment
name: myapp-deployment
- path: security-patch.yaml
target:
kind: Deployment
name: myapp-deployment
patchesStrategicMerge:
- |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "myapp"
spec:
containers:
- name: myapp
env:
- name: ENVIRONMENT
value: production
- name: METRICS_ENABLED
value: "true"
- name: TRACING_ENABLED
value: "true"
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
topologyKey: kubernetes.io/hostname
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node.kubernetes.io/instance-type
operator: In
values:
- m5.xlarge
- m5.2xlarge
patchesJson6902:
- target:
group: networking.k8s.io
version: v1
kind: Ingress
name: myapp-ingress
patch: |-
- op: replace
path: /spec/rules/0/host
value: myapp.production.example.com
- op: add
path: /metadata/annotations/cert-manager.io~1cluster-issuer
value: letsencrypt-prod
- op: add
path: /spec/tls
value:
- hosts:
- myapp.production.example.com
secretName: myapp-tls
Production Replica Patch
# overlays/production/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 0
minReadySeconds: 30
Production Resource Patch
# overlays/production/resource-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
template:
spec:
containers:
- name: myapp
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
Production Security Patch
# overlays/production/security-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: myapp
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /app/cache
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
Production HPA
# overlays/production/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa-prod
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp-deployment-prod
minReplicas: 5
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 100
periodSeconds: 30
- type: Pods
value: 2
periodSeconds: 30
selectPolicy: Max
Production PDB
# overlays/production/pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb-prod
spec:
minAvailable: 3
selector:
matchLabels:
app: myapp
environment: production
Production Network Policy
# overlays/production/network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: myapp-network-policy-prod
spec:
podSelector:
matchLabels:
app: myapp
environment: production
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
- podSelector:
matchLabels:
app: prometheus
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector:
matchLabels:
name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
JSON Patch Examples
Replace Operations
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: myapp-deployment
patch: |-
- op: replace
path: /spec/replicas
value: 10
- op: replace
path: /spec/template/spec/containers/0/image
value: registry.example.com/myapp:v2.0.0
Add Operations
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: myapp-deployment
patch: |-
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: NEW_FEATURE_FLAG
value: "true"
- op: add
path: /spec/template/metadata/annotations/sidecar.istio.io~1inject
value: "true"
Remove Operations
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: myapp-deployment
patch: |-
- op: remove
path: /spec/template/spec/containers/0/env/2
- op: remove
path: /spec/template/metadata/annotations/deprecated-annotation
Advanced Patch Techniques
Conditional Patches
# overlays/production/kustomization.yaml
patches:
- target:
kind: Deployment
labelSelector: "tier=frontend"
patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: not-used
spec:
template:
spec:
containers:
- name: myapp
resources:
limits:
memory: "2Gi"
Multi-Resource Patches
patches:
- target:
kind: Deployment|StatefulSet
name: myapp-.*
patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: not-used
annotations:
monitoring: "enabled"
Patch with Options
patches:
- path: cpu-patch.yaml
target:
kind: Deployment
options:
allowNameChange: true
allowKindChange: false
Multi-Environment Configuration
Region-Specific Overlays
overlays/
├── us-east-1/
│ ├── development/
│ ├── staging/
│ └── production/
└── eu-west-1/
├── development/
├── staging/
└── production/
Regional Production Overlay
# overlays/us-east-1/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../overlays/production
commonLabels:
region: us-east-1
configMapGenerator:
- name: config
behavior: merge
literals:
- region=us-east-1
- s3-bucket=myapp-prod-us-east-1
- cdn-url=https://us-east-1.cdn.example.com
patchesStrategicMerge:
- |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- us-east-1
When to Use This Skill
Use the kustomize-overlays skill when you need to:
- Manage multiple environments (dev, staging, production) with different configurations
- Apply environment-specific patches to base Kubernetes resources
- Override resource limits, replicas, or environment variables per environment
- Maintain a single source of truth with environment-specific variations
- Apply strategic merge patches or JSON patches to resources
- Manage region-specific or tenant-specific configurations
- Implement progressive delivery with canary or blue-green deployments
- Apply security policies and network policies per environment
- Configure autoscaling differently across environments
- Manage image tags and versions across multiple environments
- Apply conditional patches based on labels or resource types
- Implement cost optimization by varying resources per environment
- Configure monitoring and observability settings per environment
- Manage ingress rules and certificates per environment
- Apply compliance and regulatory requirements to specific environments
Best Practices
- Keep base configurations minimal and environment-agnostic
- Use strategic merge patches for simple modifications
- Use JSON patches for precise, surgical changes
- Organize overlays by environment, then by region if needed
- Use commonLabels to track resources by environment
- Apply nameSuffix or namePrefix to avoid resource conflicts
- Pin image tags with digests in production overlays
- Use configMapGenerator with behavior: merge to override specific keys
- Test overlay output with kustomize build before applying
- Use kustomize edit commands for programmatic updates
- Leverage replicas field for quick replica count overrides
- Apply security contexts progressively from dev to production
- Use HPA in production, fixed replicas in development
- Document patch rationale in comments within kustomization.yaml
- Use version control to track overlay changes over time
- Validate patches don't inadvertently remove critical settings
- Use namespace field consistently across all overlays
- Apply resource quotas and limits progressively
- Use podDisruptionBudgets only in production environments
- Test disaster recovery by applying production overlays to staging
- Use labelSelector in patches for conditional application
- Avoid hardcoding environment-specific values in base
- Use generators for ConfigMaps and Secrets instead of static files
- Apply network policies in production for security
- Use affinity rules to distribute pods across nodes in production
Common Pitfalls
- Duplicating entire resources in overlays instead of patching
- Hardcoding environment-specific values in base configurations
- Not using namespace field consistently across overlays
- Forgetting to update image tags in production overlays
- Over-patching - making too many changes in overlays
- Not testing overlay output before applying to clusters
- Using incorrect patch paths in JSON patches
- Forgetting to escape tildes in JSON patch paths
- Not using behavior: merge with configMapGenerator
- Applying production-grade resources to development environments
- Not validating that patches actually apply successfully
- Using replicas in kustomization.yaml and deployment patches simultaneously
- Not organizing overlays in a clear directory structure
- Forgetting to add new resources to kustomization.yaml
- Using absolute paths instead of relative paths in resources
- Not documenting why specific patches are necessary
- Applying breaking patches without testing
- Not using version control for overlay changes
- Forgetting to apply security contexts in production
- Using mutable image tags in production overlays
- Not considering resource consumption differences across environments
- Applying patches that conflict with each other
- Not validating JSON patch syntax before committing
- Using strategic merge for complex changes better suited to JSON patch
- Not cleaning up obsolete patches and overlay resources
- Forgetting to update overlay references when restructuring
- Not using labelSelector for conditional patches
- Hardcoding secrets in overlays instead of using external secret management
- Not testing overlay changes in lower environments first
- Applying network policies without understanding connectivity requirements
Resources
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon