skills/infrastructure/k8s/yaml-generator/SKILL.md
Comprehensive toolkit for generating, validating, and managing Kubernetes YAML resources. Use this skill when creating Kubernetes manifests (Deployments, Services, ConfigMaps, StatefulSets, etc.), working with Custom Resource Definitions (CRDs), or generating production-ready K8s configurations.
npx skillsauth add pantheon-org/tekhne k8s-yaml-generatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Mental Model: Kubernetes YAML generation is about translating application requirements into declarative infrastructure. Think in terms of desired state, not imperative commands.
Decision Framework:
When to use this skill:
Generation philosophy: Generate correct, complete, validated YAML on first pass. Never output YAML that hasn't been validated.
Gather: resource type, target K8s version, app requirements (replicas, ports, volumes), namespace/labels/annotations, and CRD specifics (kind, apiVersion, version).
Query library documentation for CRD specifications:
tessl_query_library_docs: query: "<project-name> <CRD-kind> <version> specification"
# e.g. "argo-cd Application v1alpha1 specification"
# e.g. "istio VirtualService v1beta1 specification"
# e.g. "cert-manager Certificate v1 specification"
The query should include:
If documentation is insufficient, fall back to web search:
WebSearch: "<CRD-name> <version> spec documentation"
# e.g. "ArgoCD Application v1alpha1 spec documentation"
Always include the version in the query for compatibility.
Recommended labels (use consistently across all resources):
labels:
app.kubernetes.io/name: myapp
app.kubernetes.io/instance: myapp-prod
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: backend
app.kubernetes.io/part-of: myplatform
app.kubernetes.io/managed-by: claude-code
Best practices checklist:
securityContext; Pod Security StandardsDeployment template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: default
labels:
app.kubernetes.io/name: myapp
app.kubernetes.io/instance: myapp-prod
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: myapp
app.kubernetes.io/instance: myapp-prod
template:
metadata:
labels:
app.kubernetes.io/name: myapp
app.kubernetes.io/instance: myapp-prod
spec:
containers:
- name: myapp
image: myapp:1.0.0
ports:
- containerPort: 8080
resources:
requests: { memory: "64Mi", cpu: "250m" }
limits: { memory: "128Mi", cpu: "500m" }
livenessProbe:
httpGet: { path: /health, port: 8080 }
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet: { path: /ready, port: 8080 }
initialDelaySeconds: 5
periodSeconds: 5
Service template:
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: default
spec:
type: ClusterIP # or LoadBalancer, NodePort
selector:
app.kubernetes.io/name: myapp
app.kubernetes.io/instance: myapp-prod
ports:
- protocol: TCP
port: 80
targetPort: 8080
name: http
ConfigMap template:
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: default
data:
app.properties: |
key1=value1
config.json: |
{ "setting": "value" }
CRITICAL: Always validate using the k8s-yaml-validator workflow immediately after generation.
See: yaml-validator/SKILL.md (in this tile)
The validator runs yamllint (syntax), kubeconform (schema/API compliance), best-practice checks, and optional cluster dry-run. Address all reported errors—fix, re-validate, repeat until clean.
Present the validated YAML with a brief summary, key configuration choices, and next steps:
kubectl apply -f <filename>.yaml
kubectl get <resource-type> <name> -n <namespace>
kubectl describe <resource-type> <name> -n <namespace>
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
labels:
app.kubernetes.io/managed-by: argocd
spec:
project: default
source:
repoURL: https://github.com/org/repo
targetRevision: HEAD
path: manifests
destination:
server: https://kubernetes.default.svc
namespace: myapp
syncPolicy:
automated:
prune: true
selfHeal: true
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp.example.com
gateways:
- myapp-gateway
http:
- route:
- destination:
host: myapp-service
port:
number: 8080
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: myapp-tls
namespace: default
spec:
secretName: myapp-tls-secret
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- myapp.example.com
BAD:
containers:
- name: app
image: myapp:1.0
# No resources defined - pods can consume unlimited CPU/memory
GOOD:
containers:
- name: app
image: myapp:1.0
resources:
requests: { memory: "64Mi", cpu: "250m" }
limits: { memory: "128Mi", cpu: "500m" }
Why: Unlimited resources lead to noisy neighbor issues and OOMKilled pods.
BAD:
kind: ConfigMap
data:
DATABASE_PASSWORD: "my-secret-password" # Visible in etcd
GOOD:
kind: Secret
type: Opaque
stringData:
DATABASE_PASSWORD: "my-secret-password" # Base64 encoded, separate RBAC
latest Tag in ProductionBAD:
containers:
- name: app
image: myapp:latest # Non-deterministic, breaks rollbacks
GOOD:
containers:
- name: app
image: myapp:1.2.3 # Immutable, traceable
imagePullPolicy: IfNotPresent
BAD:
containers:
- name: app
image: myapp:1.0
# No probes - K8s can't detect failures
GOOD:
containers:
- name: app
image: myapp:1.0
livenessProbe:
httpGet: { path: /health, port: 8080 }
initialDelaySeconds: 30
readinessProbe:
httpGet: { path: /ready, port: 8080 }
initialDelaySeconds: 5
BAD:
# Deployment
selector:
matchLabels: { app: myapp }
# Service
selector: { app: my-app } # Typo breaks routing
GOOD:
# Deployment
selector:
matchLabels: { app: myapp, version: v1 }
# Service
selector: { app: myapp } # Matches all versions
Never output YAML without running it through the validation workflow:
# Use yaml-validator from this tile
tessl_query_library_docs: query: "kubernetes yaml validation kubeconform yamllint"
metadata:
name: myapp
namespace: production # Never rely on default namespace
--- separators if desiredextensions/v1beta1 to networking.k8s.io/v1 in K8s 1.19+Before delivering generated YAML, confirm:
latest| Issue | Solution |
|---|---|
| CRD docs not found | Try name variations; fall back to WebSearch with version-specific query |
| Validation failures | Read errors carefully; verify field names/types/required fields; re-validate |
| Wrong API version | Confirm target K8s version; check deprecation status; update apiVersion; re-validate |
Workflow summary: Understand → Fetch CRD Docs (if needed) → Generate → Validate → Deliver
resources: limits and requests from container specsresources: block.requests for scheduling and limits for protection: resources: {requests: {cpu: 100m, memory: 128Mi}, limits: {cpu: 500m, memory: 512Mi}}latest as the image tag in Kubernetes manifestsimagePullPolicy: Always with :latest makes every pod start non-deterministic; imagePullPolicy: IfNotPresent with :latest uses a stale local image silently.image: myapp:latestimage: myapp:v1.2.3 with a specific, immutable tag and imagePullPolicy: IfNotPresentenv value appears in pod descriptions, process listings, and logs; it bypasses Kubernetes RBAC for Secret objects.env: [{name: DB_PASSWORD, value: "mysecret"}]env: [{name: DB_PASSWORD, valueFrom: {secretKeyRef: {name: db-secret, key: password}}}]livenessProbe or readinessProbe.readinessProbe to control traffic routing and livenessProbe to trigger pod restarts on deadlocks.kubectl apply -f - <<EOF\nenv:\n value: $SECRET\nEOFFor detailed examples and templates:
yaml-validator/SKILL.md in this tiledebug/SKILL.md in this tile for troubleshooting deployed resourcestools
A skill that produces warnings but no errors.
testing
A well-formed example skill for testing the validator.
development
A skill with code blocks and imperative instructions for testing content and contamination analysis.
tools