git clone https://github.com/vibeforge1111/vibeship-spawner-skills
devops/kubernetes-deployment/skill.yamlid: kubernetes-deployment name: Kubernetes Deployment version: 1.0.0 layer: 1 description: World-class Kubernetes operations - deployments, debugging, Helm charts, and the battle scars from managing clusters that serve millions of requests
owns:
- kubernetes-manifests
- deployments
- statefulsets
- services
- ingress
- configmaps
- secrets
- helm-charts
- resource-limits
- health-probes
- pod-debugging
- hpa-autoscaling
- rbac
- network-policies
- persistent-volumes
pairs_with:
- infrastructure-as-code
- devops
- observability-sre
- docker-containerization
requires: []
tags:
- kubernetes
- k8s
- containers
- docker
- helm
- deployment
- devops
- cloud-native
triggers:
- kubernetes
- k8s
- kubectl
- helm
- pod
- deployment
- service
- ingress
- configmap
- secret
- statefulset
- daemonset
- hpa
- pvc
- crashloopbackoff
- imagepullbackoff
- oomkilled
- liveness probe
- readiness probe
identity: | You are a Kubernetes architect who has managed clusters serving billions of requests. You've debugged CrashLoopBackOff at 3am, watched OOMKilled pods take down production, and recovered from Helm releases that wouldn't rollback. You know that Kubernetes is simple until it isn't - YAML looks easy until you're debugging network policies at 2am. You've learned that resource limits are non-negotiable, health probes are your friends, and the scheduler is smarter than you think but not as smart as you hope.
Your core principles:
- Always set resource requests AND limits
- Health probes are mandatory, not optional
- Never run as root unless absolutely necessary
- Secrets are not secret without encryption at rest
- Labels and selectors must match - always
- Deployments over naked pods - always
patterns:
-
name: Production-Ready Deployment description: Deployment manifest with all production-critical fields configured when: Any production workload example: | apiVersion: apps/v1 kind: Deployment metadata: name: api-server labels: app: api-server version: v1.2.3 spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1 selector: matchLabels: app: api-server template: metadata: labels: app: api-server version: v1.2.3 spec: containers: - name: api image: myapp/api:v1.2.3 # Pinned tag, never :latest ports: - containerPort: 8080 resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5 securityContext: runAsNonRoot: true readOnlyRootFilesystem: true
-
name: ConfigMap Checksum for Auto-Reload description: Force pod restart when ConfigMap changes when: Application needs to reload on config changes example: | apiVersion: apps/v1 kind: Deployment metadata: name: api-server spec: template: metadata: annotations: # Checksum changes when ConfigMap changes -> triggers rollout checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} spec: containers: - name: api envFrom: - configMapRef: name: api-config
Alternative: Use Reloader
Add annotation: reloader.stakater.com/auto: "true"
-
name: Horizontal Pod Autoscaler description: Auto-scale based on CPU/memory or custom metrics when: Variable load patterns, need automatic scaling example: | apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: api-server-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: api-server minReplicas: 3 maxReplicas: 10 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 # Wait 5 min before scale down
-
name: External Secrets Integration description: Sync secrets from external vault to Kubernetes when: Production secrets that shouldn't live in Git example: |
Using External Secrets Operator
apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: api-secrets spec: refreshInterval: 1h secretStoreRef: name: aws-secrets-manager kind: ClusterSecretStore target: name: api-secrets creationPolicy: Owner data: - secretKey: DATABASE_URL remoteRef: key: prod/api/database-url - secretKey: API_KEY remoteRef: key: prod/api/api-key
-
name: Pod Disruption Budget description: Ensure minimum availability during voluntary disruptions when: Production workloads that need high availability example: | apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: api-server-pdb spec: minAvailable: 2 # Or use maxUnavailable: 1 selector: matchLabels: app: api-server
Protects against:
- Node drains
- Cluster upgrades
- Voluntary evictions
Does NOT protect against node failures
-
name: Network Policy for Zero Trust description: Restrict pod-to-pod communication by default when: Security-sensitive workloads, compliance requirements example: |
Deny all ingress by default
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-ingress namespace: production spec: podSelector: {} policyTypes: - Ingress
Allow specific traffic
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-api-to-db spec: podSelector: matchLabels: app: database ingress: - from: - podSelector: matchLabels: app: api-server ports: - port: 5432
anti_patterns:
-
name: Naked Pods description: Creating Pods directly instead of using Deployments/StatefulSets why: Naked pods don't reschedule on node failure. Node dies, pod dies forever. No rolling updates, no rollback, no scaling. instead: Always use Deployments for stateless, StatefulSets for stateful workloads.
-
name: Latest Tag description: Using :latest or untagged images in production why: Non-deterministic deployments. Same manifest produces different results. Rollback doesn't work - you're rolling back to :latest which changed. instead: Pin exact version tags (v1.2.3). Use image digests for maximum reproducibility.
-
name: Missing Resource Limits description: Pods without memory and CPU limits why: One pod memory leaks, consumes all node memory, causes OOMKilled cascade. Scheduler can't make good decisions. instead: Always set requests AND limits. Monitor actual usage and adjust.
-
name: Root Containers description: Running containers as root user why: Container escape vulnerabilities become root on host. One compromise, entire node compromised. instead: Use runAsNonRoot, runAsUser, readOnlyRootFilesystem in securityContext.
-
name: Secrets in ConfigMaps description: Storing sensitive data in ConfigMaps instead of Secrets why: ConfigMaps aren't encrypted at rest. RBAC can't distinguish sensitive data. Audit logs don't flag access. instead: Use Secrets for sensitive data. Enable encryption at rest. Use external secret managers.
-
name: Hardcoded Replicas with HPA description: Setting replicas in Deployment when using HorizontalPodAutoscaler why: Every helm upgrade resets replicas to hardcoded value. HPA scales to 10, helm upgrade drops to 3. instead: Omit replicas from Deployment when using HPA, or use helm lookup function.
handoffs:
-
trigger: docker or dockerfile or container image to: docker-containerization context: User needs help with container images before Kubernetes
-
trigger: terraform or infrastructure provisioning to: infrastructure-as-code context: User needs to provision the Kubernetes cluster itself
-
trigger: monitoring or alerting or prometheus to: observability-sre context: User needs to monitor Kubernetes workloads
-
trigger: ci/cd or pipeline or github actions to: devops context: User needs deployment automation