Kubernetes
Production-ready Kubernetes manifest generation covering Deployments, StatefulSets, CronJobs, Services, Ingresses, ConfigMaps, Secrets, and PVCs with security contexts, health checks, and resource management.
Installation
OpenClaw / Moltbot / Clawbot
npx clawhub@latest install kubernetes
When to Use
| Scenario | Example | |----------|---------| | Create deployment manifests | New microservice needing Deployment + Service | | Define networking resources | ClusterIP, LoadBalancer, Ingress with TLS | | Manage configuration | ConfigMaps for app config, Secrets for credentials | | Stateful workloads | Databases with StatefulSets + PVCs | | Scheduled jobs | CronJobs for batch processing | | Multi-environment setup | Kustomize overlays for dev/staging/prod |
Workload Selection
| Workload Type | Resource | When to Use | |---------------|----------|-------------| | Stateless app | Deployment | Web servers, APIs, microservices | | Stateful app | StatefulSet | Databases, message queues, caches | | One-off task | Job | Migrations, data imports | | Scheduled task | CronJob | Backups, reports, cleanup | | Per-node agent | DaemonSet | Log collectors, monitoring agents |
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
labels:
app.kubernetes.io/name: my-app
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: backend
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: my-app
template:
metadata:
labels:
app.kubernetes.io/name: my-app
app.kubernetes.io/version: "1.0.0"
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: my-app
image: registry.example.com/my-app:1.0.0
ports:
- containerPort: 8080
name: http
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
periodSeconds: 5
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: my-app-config
key: LOG_LEVEL
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-app-secret
key: DATABASE_PASSWORD
Services
ClusterIP (Internal)
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: production
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: my-app
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
LoadBalancer (External)
apiVersion: v1
kind: Service
metadata:
name: my-app-lb
namespace: production
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
spec:
type: LoadBalancer
selector:
app.kubernetes.io/name: my-app
ports:
- name: http
port: 80
targetPort: 8080
Service Type Quick Reference
| Type | Scope | Use Case | |------|-------|----------| | ClusterIP | Cluster-internal | Inter-service communication | | NodePort | External via node IP | Dev/testing, on-prem | | LoadBalancer | External via cloud LB | Production external access | | ExternalName | DNS alias | Mapping to external services |
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
namespace: production
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
ingressClassName: nginx
tls:
- hosts: [app.example.com]
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
ConfigMap & Secret
ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app-config
namespace: production
data:
LOG_LEVEL: info
APP_MODE: production
DATABASE_HOST: db.internal.svc.cluster.local
app.properties: |
server.port=8080
server.host=0.0.0.0
Secret
apiVersion: v1
kind: Secret
metadata:
name: my-app-secret
namespace: production
type: Opaque
stringData:
DATABASE_PASSWORD: "changeme"
API_KEY: "secret-api-key"
Important: Never commit plaintext Secrets to Git. Use Sealed Secrets, External Secrets Operator, or Vault for production.
Persistent Storage
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-app-data
namespace: production
spec:
accessModes: [ReadWriteOnce]
storageClassName: gp3
resources:
requests:
storage: 10Gi
Mount in a container:
containers:
- name: app
volumeMounts:
- name: data
mountPath: /var/lib/app
volumes:
- name: data
persistentVolumeClaim:
claimName: my-app-data
| Access Mode | Abbreviation | Use Case | |-------------|-------------|----------| | ReadWriteOnce | RWO | Single-pod databases | | ReadOnlyMany | ROX | Shared config/static assets | | ReadWriteMany | RWX | Multi-pod shared storage |
Security Context
Pod-Level
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
Container-Level
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
Security Checklist
| Check | Status |
|-------|--------|
| runAsNonRoot: true | Required |
| allowPrivilegeEscalation: false | Required |
| readOnlyRootFilesystem: true | Recommended |
| capabilities.drop: [ALL] | Required |
| seccompProfile: RuntimeDefault | Recommended |
| Specific image tags (never :latest) | Required |
| Resource requests and limits set | Required |
Standard Labels
metadata:
labels:
app.kubernetes.io/name: my-app
app.kubernetes.io/instance: my-app-prod
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: backend
app.kubernetes.io/part-of: my-system
app.kubernetes.io/managed-by: kubectl
Manifest Organization
Option 1 — Separate Files
manifests/
├── configmap.yaml
├── secret.yaml
├── deployment.yaml
├── service.yaml
└── pvc.yaml
Option 2 — Kustomize
base/
├── kustomization.yaml
├── deployment.yaml
├── service.yaml
└── configmap.yaml
overlays/
├── dev/
│ └── kustomization.yaml
└── prod/
├── kustomization.yaml
└── resource-patch.yaml
Validation
# Client-side dry run
kubectl apply -f manifest.yaml --dry-run=client
# Server-side validation
kubectl apply -f manifest.yaml --dry-run=server
# Lint with kube-score
kube-score score manifest.yaml
# Lint with kube-linter
kube-linter lint manifest.yaml
Troubleshooting Quick Reference
| Problem | Diagnosis | Fix |
|---------|-----------|-----|
| Pod stuck Pending | kubectl describe pod — check events | Fix resource requests, node capacity, PVC binding |
| ImagePullBackOff | Wrong image name/tag or missing pull secret | Verify image exists, add imagePullSecrets |
| CrashLoopBackOff | App crashes on start | Check logs: kubectl logs <pod> --previous |
| Service not reachable | Selector mismatch | Verify kubectl get endpoints <svc> is non-empty |
| ConfigMap not loading | Name mismatch or wrong namespace | Check names match and namespace is correct |
| Readiness probe failing | Wrong path or port | Verify health endpoint works inside container |
| OOMKilled | Memory limit too low | Increase resources.limits.memory |
NEVER Do
| Anti-Pattern | Why | Do Instead |
|-------------|-----|------------|
| Use :latest image tag | Non-reproducible deployments | Pin exact version: image:1.2.3 |
| Skip resource limits | Pods can starve the node | Always set requests and limits |
| Run as root | Container escape = full host access | Set runAsNonRoot: true + USER |
| Commit plaintext Secrets | Credentials in Git history forever | Use Sealed Secrets / External Secrets / Vault |
| Skip health checks | K8s can't detect unhealthy pods | Always configure liveness + readiness probes |
| Omit labels | Cannot filter, select, or organize | Use standard app.kubernetes.io/* labels |
| Single replica for production | Zero availability during updates | Use replicas: 3 minimum for HA |
| Hardcode config in containers | Requires rebuild for config changes | Use ConfigMaps and Secrets |
Assets & References
Assets (Templates)
| Template | Description | |----------|-------------| | assets/deployment-template.yaml | Production Deployment with security + probes | | assets/service-template.yaml | ClusterIP, LoadBalancer, NodePort examples | | assets/configmap-template.yaml | ConfigMap with data types | | assets/statefulset-template.yaml | StatefulSet with headless Service + PVC | | assets/cronjob-template.yaml | CronJob with concurrency + history | | assets/ingress-template.yaml | Ingress with TLS, rate limiting, CORS |
References
| Reference | Description | |-----------|-------------| | references/deployment-spec.md | Detailed Deployment specification | | references/service-spec.md | Service types and networking details |
扫码联系在线客服