Template do pack (devops/03-kubernetes-helm.md). Orienta o agente em infra, deploy, CI/CD e operacao alinhado a esse contexto.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add artubss/SKILLS-CLAUDE-CODE --skill tpl-devops-kubernetes-helm --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Tpl Devops Kubernetes Helm?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/artubss-tpl-devops-kubernetes-helm)More formats (shields.io, HTML) on the badges page.
---
name: tpl-devops-kubernetes-helm
description: Template do pack (devops/03-kubernetes-helm.md). Orienta o agente em infra, deploy, CI/CD e operacao alinhado a esse contexto.
metadata:
version: 1.0.0
source_template: devops/03-kubernetes-helm.md
generated_by: install_pack_templates_as_claude_skills
---
# PROJECT: Kubernetes + Helm Production Deployment
Skill gerado a partir do pack `templates-claude-code`. Arquivo de origem: `devops/03-kubernetes-helm.md`. Use como baseline e adapte ao projeto antes de mudancas grandes.
## Conteudo do template
## STACK
- **Orchestration:** Kubernetes 1.29+
- **Package Manager:** Helm 3.14+
- **Ingress:** ingress-nginx (stable/ingress-nginx)
- **TLS:** cert-manager + Let's Encrypt (ClusterIssuer)
- **Autoscaling:** HorizontalPodAutoscaler (HPA) + KEDA (optional)
- **Secrets:** External Secrets Operator + AWS Secrets Manager / Vault
- **Storage:** PersistentVolumeClaims (EBS GP3 via StorageClass)
- **Monitoring:** Prometheus + Grafana (kube-prometheus-stack)
---
## HELM CHART STRUCTURE
```
charts/my-app/
├── Chart.yaml
├── values.yaml # Default values (non-sensitive)
├── values-staging.yaml # Override for staging
├── values-prod.yaml # Override for prod
└── templates/
├── deployment.yaml
├── service.yaml
├── ingress.yaml
├── hpa.yaml
├── pdb.yaml # PodDisruptionBudget
├── externalsecret.yaml
├── configmap.yaml
└── _helpers.tpl # Named templates
```
---
## ARCHITECTURE RULES
1. **Resource limits are mandatory** — every container has `requests` and `limits`; no exceptions.
2. **Readiness gates before traffic** — readiness probe must succeed before pod receives traffic; liveness resets late.
3. **Rolling update is default** — `maxUnavailable: 0`, `maxSurge: 1` ensuring zero-downtime deploys.
4. **PodDisruptionBudget on every prod deployment** — `minAvailable: 1` protects against node drain.
5. **Secrets never in values.yaml** — use External Secrets Operator; never `kubectl create secret` manually.
6. **Namespace per application** — not per environment; use separate clusters for prod vs non-prod.
7. **HPA targets 60% CPU** — scale out before saturation; not at 80%.
8. **Images use immutable tags** — `sha256:abc…` or `1.2.3`; never `latest` in production.
---
## DEPLOYMENT TEMPLATE
```yaml
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
labels: {{ include "my-app.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels: {{ include "my-app.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
template:
metadata:
labels: {{ include "my-app.selectorLabels" . | nindent 8 }}
annotations:
# Force pod restart when configmap changes
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
spec:
terminationGracePeriodSeconds: 60
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: app
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
ports:
- containerPort: {{ .Values.service.port }}
protocol: TCP
envFrom:
- configMapRef:
name: {{ include "my-app.fullname" . }}-config
- secretRef:
name: {{ include "my-app.fullname" . }}-secrets
resources:
requests:
cpu: {{ .Values.resources.requests.cpu }}
memory: {{ .Values.resources.requests.memory }}
limits:
cpu: {{ .Values.resources.limits.cpu }}
memory: {{ .Values.resources.limits.memory }}
readinessProbe:
httpGet:
path: /healthz/ready
port: {{ .Values.service.port }}
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz/live
port: {{ .Values.service.port }}
initialDelaySeconds: 30 # Give app time to fully start
periodSeconds: 15
failureThreshold: 3
startupProbe:
httpGet:
path: /healthz/ready
port: {{ .Values.service.port }}
failureThreshold: 30 # 30 * 10s = 5 min startup window
periodSeconds: 10
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 5"] # Drain in-flight requests
```
---
## VALUES.YAML STRUCTURE
```yaml
# values.yaml
replicaCount: 2
image:
repository: 123456789.dkr.ecr.us-east-1.amazonaws.com/my-app
tag: "1.0.0" # Never "latest"
service:
type: ClusterIP
port: 3000
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
nginx.ingress.kubernetes.io/rate-limit: "100"
hosts:
- host: api.myapp.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: myapp-tls
hosts: [api.myapp.com]
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 60
targetMemoryUtilizationPercentage: 70
# Override per environment:
# values-prod.yaml:
# replicaCount: 3
# resources:
# requests: { cpu: "250m", memory: "256Mi" }
# limits: { cpu: "1000m", memory: "1Gi" }
```
---
## HPA TEMPLATE
```yaml
# templates/hpa.yaml
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "my-app.fullname" . }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "my-app.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # Wait 5 min before scaling down
policies:
- type: Pods
value: 1
periodSeconds: 60
{{- end }}
```
---
## EXTERNAL SECRETS OPERATOR
```yaml
# templates/externalsecret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ include "my-app.fullname" . }}-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secretsmanager # ClusterSecretStore configured cluster-wide
kind: ClusterSecretStore
target:
name: {{ include "my-app.fullname" . }}-secrets
creationPolicy: Owner
data:
- secretKey: DATABASE_URL
remoteRef:
key: myapp/prod/database
property: url
- secretKey: JWT_SECRET
remoteRef:
key: myapp/prod/jwt
property: secret
```
---
## PERSISTENT VOLUME CLAIM
```yaml
# StorageClass — EBS GP3 (create once per cluster)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gp3
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
throughput: "125"
reclaimPolicy: Retain # Never Delete for prod data
volumeBindingMode: WaitForFirstConsumer
---
# PVC in deployment
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
spec:
accessModes: [ReadWriteOnce]
storageClassName: gp3
resources:
requests:
storage: 20Gi
```
---
## HELM DEPLOY COMMANDS
```bash
# Add chart repos
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo add cert-manager https://charts.jetstack.io
helm repo add external-secrets https://charts.external-secrets.io
helm repo update
# Install cert-manager
helm install cert-manager cert-manager/cert-manager \
--namespace cert-manager --create-namespace \
--set installCRDs=true
# Deploy app
helm upgrade --install my-app ./charts/my-app \
--namespace my-app --create-namespace \
--values charts/my-app/values.yaml \
--values charts/my-app/values-prod.yaml \
--set image.tag=$IMAGE_TAG \
--atomic \
--timeout 5m \
--history-max 5
# Rollback
helm rollback my-app 0 # 0 = previous revision
```
---
## READINESS vs LIVENESS RULES
```
readinessProbe → "Is the pod ready to receive traffic?"
- Fails if DB connection pool is exhausted
- Fails during app initialization
- Pod removed from Service endpoints when failing
- Use: /healthz/ready → check DB, Redis, downstream deps
livenessProbe → "Is the pod in a broken, unrecoverable state?"
- Only fails if app is truly hung (deadlock, OOM)
- Triggers pod restart
- Use: /healthz/live → simple ping, no external deps
startupProbe → "Has the app finished booting?"
- Disables liveness during slow startup (heavy apps, migrations)
- Once succeeds, hands off to liveness
```
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!