claude-vault/skills/skill-creator/examples/k3s-deployment-skill.md
2026-02-04 15:29:11 +01:00

368 lines
8.3 KiB
Markdown

# Example: K3s Deployment Skill
This is a complete example of a DevOps skill for K3s/Kubernetes deployments.
---
```yaml
---
name: k3s-deploy
description: Generates K3s deployment manifests with proper resource limits, probes, and HPA. Use when deploying applications to Kubernetes.
argument-hint: [app-name] [replicas] [image]
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
disable-model-invocation: true
---
# K3s Deployment Generator
Generate production-ready Kubernetes manifests for K3s clusters with proper resource limits, health probes, and autoscaling.
## When to Use
- Deploying new applications to K3s
- Creating or updating Deployment manifests
- Setting up Services and Ingress
- Configuring Horizontal Pod Autoscaling
## Prerequisites
- K3s cluster running and accessible
- kubectl configured with cluster access
- Container image available in registry
## Instructions
### Step 1: Parse Arguments
Extract from `$ARGUMENTS`:
- **app-name**: Name for the deployment (kebab-case)
- **replicas**: Initial replica count (default: 2)
- **image**: Container image with tag
### Step 2: Generate Deployment
Create `deployment.yaml`:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${APP_NAME}
namespace: default
labels:
app: ${APP_NAME}
version: v1
spec:
replicas: ${REPLICAS}
revisionHistoryLimit: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: ${APP_NAME}
template:
metadata:
labels:
app: ${APP_NAME}
version: v1
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8000"
prometheus.io/path: "/metrics"
spec:
serviceAccountName: ${APP_NAME}
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: ${APP_NAME}
image: ${IMAGE}
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8000
protocol: TCP
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
envFrom:
- configMapRef:
name: ${APP_NAME}-config
- secretRef:
name: ${APP_NAME}-secrets
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live/
port: http
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready/
port: http
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live/
port: http
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: ${APP_NAME}
topologyKey: kubernetes.io/hostname
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: ${APP_NAME}
```
### Step 3: Generate Service
Create `service.yaml`:
```yaml
apiVersion: v1
kind: Service
metadata:
name: ${APP_NAME}
namespace: default
labels:
app: ${APP_NAME}
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: http
protocol: TCP
selector:
app: ${APP_NAME}
```
### Step 4: Generate ConfigMap
Create `configmap.yaml`:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ${APP_NAME}-config
namespace: default
data:
LOG_LEVEL: "INFO"
ENVIRONMENT: "production"
```
### Step 5: Generate HPA
Create `hpa.yaml`:
```yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ${APP_NAME}
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ${APP_NAME}
minReplicas: 2
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
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
```
### Step 6: Generate ServiceAccount
Create `serviceaccount.yaml`:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: ${APP_NAME}
namespace: default
```
### Step 7: Generate Ingress (Traefik)
Create `ingress.yaml`:
```yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ${APP_NAME}
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(\`${APP_NAME}.example.com\`)
kind: Rule
services:
- name: ${APP_NAME}
port: 80
middlewares:
- name: ${APP_NAME}-ratelimit
tls:
certResolver: letsencrypt
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ${APP_NAME}-ratelimit
namespace: default
spec:
rateLimit:
average: 100
burst: 50
```
## Patterns & Best Practices
### Resource Sizing
Start conservative and adjust based on metrics:
| Workload Type | CPU Request | CPU Limit | Memory Request | Memory Limit |
|---------------|-------------|-----------|----------------|--------------|
| Web App | 100m | 500m | 128Mi | 256Mi |
| API Server | 200m | 1000m | 256Mi | 512Mi |
| Worker | 500m | 2000m | 512Mi | 1Gi |
| Database | 1000m | 4000m | 1Gi | 4Gi |
### Probe Configuration
- **startupProbe**: Use for slow-starting apps (Django, Java)
- **livenessProbe**: Detect deadlocks, restart if failed
- **readinessProbe**: Detect temporary unavailability, remove from LB
### Labels Convention
```yaml
labels:
app: my-app # Required: app name
version: v1.2.3 # Recommended: version
component: api # Optional: component type
part-of: platform # Optional: parent application
managed-by: kubectl # Optional: management tool
```
## Validation
```bash
# Dry run to validate manifests
kubectl apply --dry-run=client -f .
# Show diff before applying
kubectl diff -f .
# Apply with record
kubectl apply -f . --record
# Watch rollout
kubectl rollout status deployment/${APP_NAME}
# Check events
kubectl get events --field-selector involvedObject.name=${APP_NAME}
```
## Common Pitfalls
- **No Resource Limits**: Can cause node resource exhaustion
- **Missing Probes**: Leads to traffic to unhealthy pods
- **Wrong Probe Paths**: Causes constant restarts
- **No Anti-Affinity**: All pods on same node = single point of failure
- **Aggressive HPA**: Causes thrashing; use stabilization windows
## Rollback Procedure
```bash
# View rollout history
kubectl rollout history deployment/${APP_NAME}
# Rollback to previous version
kubectl rollout undo deployment/${APP_NAME}
# Rollback to specific revision
kubectl rollout undo deployment/${APP_NAME} --to-revision=2
```
```