mirror of
https://github.com/BagelHole/DevOps-Security-Agent-Skills.git
synced 2026-08-22 12:49:53 +02:00
.
This commit is contained in:
@@ -0,0 +1,516 @@
|
||||
---
|
||||
name: kubernetes-ops
|
||||
description: Deploy, scale, and manage Kubernetes workloads. Create deployments, services, and configurations, manage cluster resources, troubleshoot pods, and implement production-ready Kubernetes patterns. Use when working with Kubernetes clusters, K8s deployments, or container orchestration.
|
||||
license: MIT
|
||||
metadata:
|
||||
author: devops-skills
|
||||
version: "1.0"
|
||||
---
|
||||
|
||||
# Kubernetes Operations
|
||||
|
||||
Deploy and manage containerized applications on Kubernetes clusters.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when:
|
||||
- Deploying applications to Kubernetes
|
||||
- Managing pods, deployments, and services
|
||||
- Configuring resource limits and scaling
|
||||
- Troubleshooting Kubernetes workloads
|
||||
- Setting up networking and ingress
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- kubectl installed and configured
|
||||
- Access to a Kubernetes cluster
|
||||
- Basic understanding of containers
|
||||
|
||||
## Core Resources
|
||||
|
||||
### Deployment
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: myapp
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: myapp:1.0.0
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "500m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ready
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: myapp-secrets
|
||||
key: database-url
|
||||
```
|
||||
|
||||
### Service
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myapp
|
||||
spec:
|
||||
selector:
|
||||
app: myapp
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
type: ClusterIP
|
||||
---
|
||||
# LoadBalancer for external access
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myapp-external
|
||||
spec:
|
||||
selector:
|
||||
app: myapp
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
type: LoadBalancer
|
||||
```
|
||||
|
||||
### Ingress
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: myapp
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
tls:
|
||||
- hosts:
|
||||
- myapp.example.com
|
||||
secretName: myapp-tls
|
||||
rules:
|
||||
- host: myapp.example.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: myapp
|
||||
port:
|
||||
number: 80
|
||||
```
|
||||
|
||||
## Configuration Management
|
||||
|
||||
### ConfigMap
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: myapp-config
|
||||
data:
|
||||
config.yaml: |
|
||||
server:
|
||||
port: 8080
|
||||
logging:
|
||||
level: info
|
||||
APP_ENV: production
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Using ConfigMap
|
||||
containers:
|
||||
- name: myapp
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: myapp-config
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/config
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: myapp-config
|
||||
```
|
||||
|
||||
### Secret
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: myapp-secrets
|
||||
type: Opaque
|
||||
stringData:
|
||||
database-url: postgres://user:pass@host:5432/db
|
||||
api-key: secret-key-value
|
||||
```
|
||||
|
||||
```bash
|
||||
# Create secret from command line
|
||||
kubectl create secret generic myapp-secrets \
|
||||
--from-literal=database-url='postgres://...' \
|
||||
--from-file=tls.crt=cert.pem
|
||||
```
|
||||
|
||||
## kubectl Commands
|
||||
|
||||
### Resource Management
|
||||
|
||||
```bash
|
||||
# Apply configuration
|
||||
kubectl apply -f deployment.yaml
|
||||
|
||||
# Get resources
|
||||
kubectl get pods
|
||||
kubectl get deployments
|
||||
kubectl get services
|
||||
kubectl get all -n myapp
|
||||
|
||||
# Describe resource
|
||||
kubectl describe pod myapp-xxx
|
||||
|
||||
# Delete resource
|
||||
kubectl delete -f deployment.yaml
|
||||
kubectl delete pod myapp-xxx
|
||||
|
||||
# Edit resource
|
||||
kubectl edit deployment myapp
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
||||
```bash
|
||||
# View logs
|
||||
kubectl logs myapp-xxx
|
||||
kubectl logs -f myapp-xxx --tail=100
|
||||
kubectl logs myapp-xxx -c sidecar # specific container
|
||||
|
||||
# Execute command
|
||||
kubectl exec -it myapp-xxx -- /bin/sh
|
||||
|
||||
# Port forward
|
||||
kubectl port-forward svc/myapp 8080:80
|
||||
kubectl port-forward pod/myapp-xxx 8080:8080
|
||||
|
||||
# View events
|
||||
kubectl get events --sort-by='.lastTimestamp'
|
||||
|
||||
# Debug pod
|
||||
kubectl debug myapp-xxx -it --image=busybox
|
||||
```
|
||||
|
||||
### Scaling
|
||||
|
||||
```bash
|
||||
# Manual scaling
|
||||
kubectl scale deployment myapp --replicas=5
|
||||
|
||||
# Autoscaling
|
||||
kubectl autoscale deployment myapp \
|
||||
--min=2 --max=10 \
|
||||
--cpu-percent=80
|
||||
```
|
||||
|
||||
## Horizontal Pod Autoscaler
|
||||
|
||||
```yaml
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: myapp
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: myapp
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 80
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 80
|
||||
```
|
||||
|
||||
## Persistent Storage
|
||||
|
||||
### PersistentVolumeClaim
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: myapp-data
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: standard
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
---
|
||||
# Using PVC
|
||||
containers:
|
||||
- name: myapp
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: myapp-data
|
||||
```
|
||||
|
||||
## StatefulSet
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: postgres
|
||||
spec:
|
||||
serviceName: postgres
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:15
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
```
|
||||
|
||||
## Jobs and CronJobs
|
||||
|
||||
### Job
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: migration
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: migrate
|
||||
image: myapp:1.0.0
|
||||
command: ["./migrate.sh"]
|
||||
restartPolicy: Never
|
||||
backoffLimit: 3
|
||||
```
|
||||
|
||||
### CronJob
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: backup
|
||||
spec:
|
||||
schedule: "0 2 * * *"
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: backup
|
||||
image: backup-tool:latest
|
||||
command: ["./backup.sh"]
|
||||
restartPolicy: OnFailure
|
||||
```
|
||||
|
||||
## Network Policies
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: myapp-network-policy
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: frontend
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: database
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
```
|
||||
|
||||
## Resource Quotas
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ResourceQuota
|
||||
metadata:
|
||||
name: myapp-quota
|
||||
namespace: myapp
|
||||
spec:
|
||||
hard:
|
||||
requests.cpu: "10"
|
||||
requests.memory: 20Gi
|
||||
limits.cpu: "20"
|
||||
limits.memory: 40Gi
|
||||
pods: "20"
|
||||
```
|
||||
|
||||
## Rolling Updates
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
```
|
||||
|
||||
```bash
|
||||
# Update image
|
||||
kubectl set image deployment/myapp myapp=myapp:2.0.0
|
||||
|
||||
# Check rollout status
|
||||
kubectl rollout status deployment/myapp
|
||||
|
||||
# View history
|
||||
kubectl rollout history deployment/myapp
|
||||
|
||||
# Rollback
|
||||
kubectl rollout undo deployment/myapp
|
||||
kubectl rollout undo deployment/myapp --to-revision=2
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Issue: Pod Stuck in Pending
|
||||
**Problem**: Pod won't start
|
||||
**Solution**: Check resource availability, node selector, PVC binding
|
||||
|
||||
```bash
|
||||
kubectl describe pod myapp-xxx
|
||||
kubectl get events
|
||||
```
|
||||
|
||||
### Issue: CrashLoopBackOff
|
||||
**Problem**: Container keeps restarting
|
||||
**Solution**: Check logs, verify entrypoint, check probes
|
||||
|
||||
```bash
|
||||
kubectl logs myapp-xxx --previous
|
||||
kubectl describe pod myapp-xxx
|
||||
```
|
||||
|
||||
### Issue: Service Not Accessible
|
||||
**Problem**: Cannot connect to service
|
||||
**Solution**: Check selector labels, verify endpoints exist
|
||||
|
||||
```bash
|
||||
kubectl get endpoints myapp
|
||||
kubectl describe svc myapp
|
||||
```
|
||||
|
||||
### Issue: Image Pull Error
|
||||
**Problem**: ImagePullBackOff
|
||||
**Solution**: Check image name, verify registry credentials
|
||||
|
||||
```bash
|
||||
kubectl create secret docker-registry regcred \
|
||||
--docker-server=registry.example.com \
|
||||
--docker-username=user \
|
||||
--docker-password=pass
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Always set resource requests and limits
|
||||
- Implement liveness and readiness probes
|
||||
- Use namespaces for isolation
|
||||
- Apply network policies for security
|
||||
- Use ConfigMaps and Secrets for configuration
|
||||
- Implement pod disruption budgets for availability
|
||||
- Use labels consistently for organization
|
||||
- Enable RBAC for access control
|
||||
|
||||
## Related Skills
|
||||
|
||||
- [helm-charts](../helm-charts/) - Package management
|
||||
- [argocd-gitops](../argocd-gitops/) - GitOps deployments
|
||||
- [kubernetes-hardening](../../../security/hardening/kubernetes-hardening/) - Security
|
||||
@@ -0,0 +1,166 @@
|
||||
# Production-Ready Deployment Template
|
||||
# Customize values marked with <REPLACE>
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: <APP_NAME>
|
||||
labels:
|
||||
app: <APP_NAME>
|
||||
version: v1
|
||||
spec:
|
||||
replicas: 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: "8080"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
serviceAccountName: <APP_NAME>
|
||||
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
fsGroup: 1000
|
||||
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: <APP_NAME>
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
containers:
|
||||
- name: <APP_NAME>
|
||||
image: <IMAGE>:<TAG>
|
||||
imagePullPolicy: Always
|
||||
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
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: "256Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ready
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: cache
|
||||
mountPath: /var/cache
|
||||
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: cache
|
||||
emptyDir: {}
|
||||
|
||||
terminationGracePeriodSeconds: 30
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: <APP_NAME>
|
||||
labels:
|
||||
app: <APP_NAME>
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: <APP_NAME>
|
||||
|
||||
---
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: <APP_NAME>
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: <APP_NAME>
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 70
|
||||
|
||||
---
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: <APP_NAME>
|
||||
spec:
|
||||
minAvailable: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: <APP_NAME>
|
||||
@@ -0,0 +1,187 @@
|
||||
# Kubernetes Best Practices
|
||||
|
||||
## Resource Management
|
||||
|
||||
### Always Set Resource Requests and Limits
|
||||
```yaml
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
**Guidelines:**
|
||||
- Requests = guaranteed resources
|
||||
- Limits = maximum resources
|
||||
- Set requests based on normal usage
|
||||
- Set limits based on peak usage
|
||||
- Memory limit = 2x request is common
|
||||
- Avoid CPU limits in most cases (causes throttling)
|
||||
|
||||
### Use Horizontal Pod Autoscaler
|
||||
```yaml
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: myapp-hpa
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: myapp
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 70
|
||||
```
|
||||
|
||||
## Pod Configuration
|
||||
|
||||
### Use Liveness and Readiness Probes
|
||||
```yaml
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ready
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
```
|
||||
|
||||
### Configure Pod Disruption Budgets
|
||||
```yaml
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: myapp-pdb
|
||||
spec:
|
||||
minAvailable: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
```
|
||||
|
||||
### Use Anti-Affinity for High Availability
|
||||
```yaml
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
topologyKey: kubernetes.io/hostname
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
### Run as Non-Root
|
||||
```yaml
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
```
|
||||
|
||||
### Read-Only Root Filesystem
|
||||
```yaml
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
```
|
||||
|
||||
### Drop All Capabilities
|
||||
```yaml
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
```
|
||||
|
||||
## Networking
|
||||
|
||||
### Use Network Policies
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: deny-all
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
```
|
||||
|
||||
### Service Mesh for mTLS
|
||||
- Istio, Linkerd, or Consul Connect
|
||||
- Automatic encryption between services
|
||||
- Traffic management capabilities
|
||||
|
||||
## Configuration Management
|
||||
|
||||
### Use ConfigMaps for Configuration
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config
|
||||
data:
|
||||
LOG_LEVEL: "info"
|
||||
DATABASE_HOST: "postgres.default.svc"
|
||||
```
|
||||
|
||||
### Use Secrets for Sensitive Data
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: app-secrets
|
||||
type: Opaque
|
||||
stringData:
|
||||
DATABASE_PASSWORD: "secret123"
|
||||
```
|
||||
|
||||
### External Secrets for Production
|
||||
- Use External Secrets Operator
|
||||
- Integrate with Vault, AWS Secrets Manager, etc.
|
||||
- Never commit secrets to git
|
||||
|
||||
## Observability
|
||||
|
||||
### Structured Logging
|
||||
- Output JSON logs
|
||||
- Include correlation IDs
|
||||
- Use consistent field names
|
||||
|
||||
### Metrics
|
||||
- Expose Prometheus metrics
|
||||
- Use standard naming conventions
|
||||
- Include SLI metrics
|
||||
|
||||
### Distributed Tracing
|
||||
- Implement OpenTelemetry
|
||||
- Propagate trace context
|
||||
- Sample appropriately
|
||||
@@ -0,0 +1,165 @@
|
||||
# Kubernetes Troubleshooting Guide
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
### Pod Issues
|
||||
|
||||
#### Pod Stuck in Pending
|
||||
```bash
|
||||
# Check events
|
||||
kubectl describe pod <pod-name> -n <namespace>
|
||||
|
||||
# Common causes:
|
||||
# - Insufficient resources
|
||||
kubectl describe nodes | grep -A 5 "Allocated resources"
|
||||
|
||||
# - No matching nodes (taints/tolerations)
|
||||
kubectl get nodes -o json | jq '.items[].spec.taints'
|
||||
|
||||
# - PVC not bound
|
||||
kubectl get pvc -n <namespace>
|
||||
```
|
||||
|
||||
#### Pod in CrashLoopBackOff
|
||||
```bash
|
||||
# Check logs
|
||||
kubectl logs <pod-name> -n <namespace> --previous
|
||||
|
||||
# Check container exit code
|
||||
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'
|
||||
|
||||
# Common exit codes:
|
||||
# 0 - Success (check livenessProbe)
|
||||
# 1 - Application error
|
||||
# 137 - OOMKilled (increase memory)
|
||||
# 139 - Segmentation fault
|
||||
# 143 - SIGTERM received
|
||||
```
|
||||
|
||||
#### Pod in ImagePullBackOff
|
||||
```bash
|
||||
# Check image name
|
||||
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.spec.containers[0].image}'
|
||||
|
||||
# Verify image exists
|
||||
docker pull <image>
|
||||
|
||||
# Check imagePullSecrets
|
||||
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.spec.imagePullSecrets}'
|
||||
kubectl get secret <secret-name> -n <namespace> -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d
|
||||
```
|
||||
|
||||
### Service Issues
|
||||
|
||||
#### Service Not Accessible
|
||||
```bash
|
||||
# Verify endpoints exist
|
||||
kubectl get endpoints <service-name> -n <namespace>
|
||||
|
||||
# Check selector matches pod labels
|
||||
kubectl get svc <service-name> -n <namespace> -o jsonpath='{.spec.selector}'
|
||||
kubectl get pods -n <namespace> --show-labels
|
||||
|
||||
# Test from within cluster
|
||||
kubectl run debug --rm -it --image=busybox -- wget -qO- http://<service>.<namespace>.svc.cluster.local
|
||||
```
|
||||
|
||||
#### DNS Resolution Issues
|
||||
```bash
|
||||
# Test DNS from pod
|
||||
kubectl run dns-test --rm -it --image=busybox -- nslookup kubernetes.default
|
||||
|
||||
# Check CoreDNS pods
|
||||
kubectl get pods -n kube-system -l k8s-app=kube-dns
|
||||
|
||||
# Check CoreDNS logs
|
||||
kubectl logs -n kube-system -l k8s-app=kube-dns
|
||||
```
|
||||
|
||||
### Node Issues
|
||||
|
||||
#### Node NotReady
|
||||
```bash
|
||||
# Check node conditions
|
||||
kubectl describe node <node-name> | grep -A 20 Conditions
|
||||
|
||||
# Check kubelet status
|
||||
systemctl status kubelet
|
||||
|
||||
# Check kubelet logs
|
||||
journalctl -u kubelet -f
|
||||
|
||||
# Common causes:
|
||||
# - Disk pressure
|
||||
# - Memory pressure
|
||||
# - Network issues
|
||||
# - Container runtime issues
|
||||
```
|
||||
|
||||
#### Node Disk Pressure
|
||||
```bash
|
||||
# Check disk usage
|
||||
kubectl describe node <node-name> | grep -A 3 "Allocated resources"
|
||||
|
||||
# Cleanup unused images
|
||||
docker system prune -af
|
||||
|
||||
# Check for large logs
|
||||
du -sh /var/log/containers/*
|
||||
```
|
||||
|
||||
### Networking Issues
|
||||
|
||||
#### Pod-to-Pod Communication Fails
|
||||
```bash
|
||||
# Test connectivity
|
||||
kubectl exec <pod-a> -- ping <pod-b-ip>
|
||||
|
||||
# Check network policies
|
||||
kubectl get networkpolicies -n <namespace>
|
||||
|
||||
# Verify CNI plugin
|
||||
kubectl get pods -n kube-system | grep -E "calico|weave|flannel|cilium"
|
||||
```
|
||||
|
||||
### Storage Issues
|
||||
|
||||
#### PVC Stuck in Pending
|
||||
```bash
|
||||
# Check PVC events
|
||||
kubectl describe pvc <pvc-name> -n <namespace>
|
||||
|
||||
# Verify StorageClass exists
|
||||
kubectl get storageclass
|
||||
|
||||
# Check provisioner pods
|
||||
kubectl get pods -n kube-system | grep provisioner
|
||||
```
|
||||
|
||||
## Diagnostic Commands Cheat Sheet
|
||||
|
||||
```bash
|
||||
# Cluster overview
|
||||
kubectl cluster-info
|
||||
kubectl get componentstatuses
|
||||
|
||||
# Resource usage
|
||||
kubectl top nodes
|
||||
kubectl top pods -n <namespace>
|
||||
|
||||
# Events
|
||||
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
|
||||
|
||||
# Logs
|
||||
kubectl logs -f <pod> -n <namespace>
|
||||
kubectl logs -f <pod> -n <namespace> --all-containers
|
||||
|
||||
# Exec into pod
|
||||
kubectl exec -it <pod> -n <namespace> -- /bin/sh
|
||||
|
||||
# Port forward
|
||||
kubectl port-forward <pod> 8080:80 -n <namespace>
|
||||
|
||||
# Copy files
|
||||
kubectl cp <namespace>/<pod>:/path/to/file ./local-file
|
||||
```
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
# Kubernetes Cluster Health Check Script
|
||||
# Usage: ./cluster-health-check.sh [namespace]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
NAMESPACE="${1:-default}"
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo "========================================="
|
||||
echo "Kubernetes Cluster Health Check"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Check cluster connectivity
|
||||
echo -n "Checking cluster connectivity... "
|
||||
if kubectl cluster-info &>/dev/null; then
|
||||
echo -e "${GREEN}OK${NC}"
|
||||
else
|
||||
echo -e "${RED}FAILED${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Node status
|
||||
echo ""
|
||||
echo "Node Status:"
|
||||
echo "------------"
|
||||
kubectl get nodes -o wide
|
||||
|
||||
# Check for NotReady nodes
|
||||
NOT_READY=$(kubectl get nodes --no-headers | grep -v " Ready" | wc -l)
|
||||
if [ "$NOT_READY" -gt 0 ]; then
|
||||
echo -e "${RED}WARNING: $NOT_READY node(s) not ready${NC}"
|
||||
fi
|
||||
|
||||
# Pod status in namespace
|
||||
echo ""
|
||||
echo "Pod Status in namespace '$NAMESPACE':"
|
||||
echo "--------------------------------------"
|
||||
kubectl get pods -n "$NAMESPACE" -o wide
|
||||
|
||||
# Check for failed pods
|
||||
FAILED_PODS=$(kubectl get pods -n "$NAMESPACE" --no-headers | grep -E "Error|CrashLoopBackOff|ImagePullBackOff" | wc -l)
|
||||
if [ "$FAILED_PODS" -gt 0 ]; then
|
||||
echo -e "${RED}WARNING: $FAILED_PODS pod(s) in error state${NC}"
|
||||
fi
|
||||
|
||||
# Resource usage
|
||||
echo ""
|
||||
echo "Resource Usage:"
|
||||
echo "---------------"
|
||||
kubectl top nodes 2>/dev/null || echo "Metrics server not available"
|
||||
|
||||
# Recent events
|
||||
echo ""
|
||||
echo "Recent Warning Events:"
|
||||
echo "----------------------"
|
||||
kubectl get events -n "$NAMESPACE" --field-selector type=Warning --sort-by='.lastTimestamp' | tail -10
|
||||
|
||||
# PVC status
|
||||
echo ""
|
||||
echo "PersistentVolumeClaim Status:"
|
||||
echo "-----------------------------"
|
||||
kubectl get pvc -n "$NAMESPACE" 2>/dev/null || echo "No PVCs found"
|
||||
|
||||
# Service status
|
||||
echo ""
|
||||
echo "Services:"
|
||||
echo "---------"
|
||||
kubectl get svc -n "$NAMESPACE"
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "Health check complete"
|
||||
echo "========================================="
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
# Kubernetes Namespace Cleanup Script
|
||||
# Removes completed jobs, failed pods, and unused resources
|
||||
# Usage: ./namespace-cleanup.sh <namespace> [--dry-run]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
NAMESPACE="${1:-}"
|
||||
DRY_RUN="${2:-}"
|
||||
|
||||
if [ -z "$NAMESPACE" ]; then
|
||||
echo "Usage: $0 <namespace> [--dry-run]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$DRY_RUN" == "--dry-run" ]; then
|
||||
echo "DRY RUN MODE - No changes will be made"
|
||||
DELETE_CMD="echo [DRY RUN] Would delete:"
|
||||
else
|
||||
DELETE_CMD="kubectl delete"
|
||||
fi
|
||||
|
||||
echo "========================================="
|
||||
echo "Namespace Cleanup: $NAMESPACE"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Delete completed jobs
|
||||
echo "Cleaning up completed Jobs..."
|
||||
COMPLETED_JOBS=$(kubectl get jobs -n "$NAMESPACE" -o jsonpath='{.items[?(@.status.succeeded==1)].metadata.name}' 2>/dev/null)
|
||||
if [ -n "$COMPLETED_JOBS" ]; then
|
||||
for job in $COMPLETED_JOBS; do
|
||||
$DELETE_CMD job "$job" -n "$NAMESPACE" 2>/dev/null || true
|
||||
done
|
||||
else
|
||||
echo "No completed jobs found"
|
||||
fi
|
||||
|
||||
# Delete failed pods
|
||||
echo ""
|
||||
echo "Cleaning up failed Pods..."
|
||||
FAILED_PODS=$(kubectl get pods -n "$NAMESPACE" --field-selector status.phase=Failed -o name 2>/dev/null)
|
||||
if [ -n "$FAILED_PODS" ]; then
|
||||
for pod in $FAILED_PODS; do
|
||||
$DELETE_CMD "$pod" -n "$NAMESPACE" 2>/dev/null || true
|
||||
done
|
||||
else
|
||||
echo "No failed pods found"
|
||||
fi
|
||||
|
||||
# Delete evicted pods
|
||||
echo ""
|
||||
echo "Cleaning up evicted Pods..."
|
||||
EVICTED_PODS=$(kubectl get pods -n "$NAMESPACE" -o json | jq -r '.items[] | select(.status.reason=="Evicted") | .metadata.name' 2>/dev/null)
|
||||
if [ -n "$EVICTED_PODS" ]; then
|
||||
for pod in $EVICTED_PODS; do
|
||||
$DELETE_CMD pod "$pod" -n "$NAMESPACE" 2>/dev/null || true
|
||||
done
|
||||
else
|
||||
echo "No evicted pods found"
|
||||
fi
|
||||
|
||||
# Delete orphaned ReplicaSets (0 replicas, no owner)
|
||||
echo ""
|
||||
echo "Cleaning up orphaned ReplicaSets..."
|
||||
kubectl get rs -n "$NAMESPACE" -o json | jq -r '.items[] | select(.spec.replicas==0) | .metadata.name' 2>/dev/null | while read rs; do
|
||||
if [ -n "$rs" ]; then
|
||||
$DELETE_CMD rs "$rs" -n "$NAMESPACE" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "Cleanup complete"
|
||||
echo "========================================="
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
# Kubernetes Pod Debugging Script
|
||||
# Usage: ./pod-debug.sh <pod-name> [namespace]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
POD_NAME="${1:-}"
|
||||
NAMESPACE="${2:-default}"
|
||||
|
||||
if [ -z "$POD_NAME" ]; then
|
||||
echo "Usage: $0 <pod-name> [namespace]"
|
||||
echo ""
|
||||
echo "Available pods in namespace '$NAMESPACE':"
|
||||
kubectl get pods -n "$NAMESPACE" --no-headers | awk '{print " " $1}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "========================================="
|
||||
echo "Debugging Pod: $POD_NAME"
|
||||
echo "Namespace: $NAMESPACE"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Pod details
|
||||
echo "Pod Details:"
|
||||
echo "------------"
|
||||
kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o wide
|
||||
|
||||
# Pod describe
|
||||
echo ""
|
||||
echo "Pod Description:"
|
||||
echo "----------------"
|
||||
kubectl describe pod "$POD_NAME" -n "$NAMESPACE"
|
||||
|
||||
# Container logs
|
||||
echo ""
|
||||
echo "Container Logs (last 50 lines):"
|
||||
echo "--------------------------------"
|
||||
CONTAINERS=$(kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o jsonpath='{.spec.containers[*].name}')
|
||||
for CONTAINER in $CONTAINERS; do
|
||||
echo ""
|
||||
echo "=== Container: $CONTAINER ==="
|
||||
kubectl logs "$POD_NAME" -n "$NAMESPACE" -c "$CONTAINER" --tail=50 2>/dev/null || echo "No logs available"
|
||||
done
|
||||
|
||||
# Previous container logs (if crashed)
|
||||
echo ""
|
||||
echo "Previous Container Logs (if any):"
|
||||
echo "----------------------------------"
|
||||
for CONTAINER in $CONTAINERS; do
|
||||
echo ""
|
||||
echo "=== Container: $CONTAINER (previous) ==="
|
||||
kubectl logs "$POD_NAME" -n "$NAMESPACE" -c "$CONTAINER" --previous --tail=20 2>/dev/null || echo "No previous logs"
|
||||
done
|
||||
|
||||
# Resource usage
|
||||
echo ""
|
||||
echo "Resource Usage:"
|
||||
echo "---------------"
|
||||
kubectl top pod "$POD_NAME" -n "$NAMESPACE" 2>/dev/null || echo "Metrics not available"
|
||||
|
||||
# Events for this pod
|
||||
echo ""
|
||||
echo "Related Events:"
|
||||
echo "---------------"
|
||||
kubectl get events -n "$NAMESPACE" --field-selector involvedObject.name="$POD_NAME" --sort-by='.lastTimestamp'
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "Debug information complete"
|
||||
echo "========================================="
|
||||
Reference in New Issue
Block a user