This commit is contained in:
Toby
2026-01-27 17:35:45 -05:00
commit 2639af6531
176 changed files with 27104 additions and 0 deletions
+445
View File
@@ -0,0 +1,445 @@
---
name: argocd-gitops
description: Implement GitOps with ArgoCD for declarative Kubernetes deployments. Configure applications, manage sync policies, implement progressive delivery, and automate deployments from Git repositories. Use when implementing GitOps workflows or continuous deployment to Kubernetes.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# ArgoCD GitOps
Implement declarative continuous delivery for Kubernetes with ArgoCD.
## When to Use This Skill
Use this skill when:
- Implementing GitOps workflows for Kubernetes
- Automating deployments from Git repositories
- Managing multiple environments declaratively
- Implementing progressive delivery strategies
- Synchronizing cluster state with Git
## Prerequisites
- Kubernetes cluster with ArgoCD installed
- kubectl configured
- Git repository for manifests
- ArgoCD CLI (optional)
## Installation
```bash
# Create namespace
kubectl create namespace argocd
# Install ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Get admin password
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
# Port forward to access UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Login with CLI
argocd login localhost:8080
```
## Application Definition
### Basic Application
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/myapp-manifests.git
targetRevision: main
path: environments/production
destination:
server: https://kubernetes.default.svc
namespace: myapp
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
```
### Helm Application
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp-helm
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/myapp-chart.git
targetRevision: main
path: charts/myapp
helm:
valueFiles:
- values.yaml
- values-production.yaml
parameters:
- name: replicaCount
value: "3"
- name: image.tag
value: "2.0.0"
destination:
server: https://kubernetes.default.svc
namespace: myapp
syncPolicy:
automated:
prune: true
selfHeal: true
```
### Kustomize Application
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp-kustomize
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/myapp-manifests.git
targetRevision: main
path: overlays/production
kustomize:
images:
- myapp=myregistry/myapp:2.0.0
destination:
server: https://kubernetes.default.svc
namespace: myapp
```
## Projects
```yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: myproject
namespace: argocd
spec:
description: My Project
sourceRepos:
- https://github.com/org/*
destinations:
- namespace: myapp-*
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ''
kind: Namespace
namespaceResourceWhitelist:
- group: '*'
kind: '*'
roles:
- name: developer
description: Developer role
policies:
- p, proj:myproject:developer, applications, get, myproject/*, allow
- p, proj:myproject:developer, applications, sync, myproject/*, allow
groups:
- developers
```
## Application Sets
### Git Generator
```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-environments
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/org/myapp-manifests.git
revision: main
directories:
- path: environments/*
template:
metadata:
name: 'myapp-{{path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/org/myapp-manifests.git
targetRevision: main
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: 'myapp-{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: true
```
### List Generator
```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-clusters
namespace: argocd
spec:
generators:
- list:
elements:
- cluster: production
url: https://prod-cluster.example.com
- cluster: staging
url: https://staging-cluster.example.com
template:
metadata:
name: 'myapp-{{cluster}}'
spec:
project: default
source:
repoURL: https://github.com/org/myapp-manifests.git
targetRevision: main
path: 'environments/{{cluster}}'
destination:
server: '{{url}}'
namespace: myapp
```
### Matrix Generator
```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-matrix
namespace: argocd
spec:
generators:
- matrix:
generators:
- git:
repoURL: https://github.com/org/myapp-manifests.git
revision: main
directories:
- path: apps/*
- list:
elements:
- env: staging
- env: production
template:
metadata:
name: '{{path.basename}}-{{env}}'
spec:
project: default
source:
repoURL: https://github.com/org/myapp-manifests.git
targetRevision: main
path: '{{path}}/overlays/{{env}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}-{{env}}'
```
## Sync Policies
### Automated Sync
```yaml
syncPolicy:
automated:
prune: true # Delete resources not in Git
selfHeal: true # Revert manual changes
allowEmpty: false # Don't sync empty directories
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- PruneLast=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
```
### Sync Waves
```yaml
# In Kubernetes manifests
apiVersion: v1
kind: ConfigMap
metadata:
name: myconfig
annotations:
argocd.argoproj.io/sync-wave: "-1" # Sync first
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
annotations:
argocd.argoproj.io/sync-wave: "0" # Sync second
```
### Sync Hooks
```yaml
apiVersion: batch/v1
kind: Job
metadata:
name: migration
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: myapp:latest
command: ["./migrate.sh"]
restartPolicy: Never
```
## CLI Commands
```bash
# List applications
argocd app list
# Get application details
argocd app get myapp
# Sync application
argocd app sync myapp
# Force sync (ignore differences)
argocd app sync myapp --force
# View diff
argocd app diff myapp
# Rollback
argocd app rollback myapp
# Delete application
argocd app delete myapp
# View logs
argocd app logs myapp
# Hard refresh (clear cache)
argocd app get myapp --hard-refresh
```
## Repository Configuration
```yaml
apiVersion: v1
kind: Secret
metadata:
name: private-repo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
url: https://github.com/org/private-repo.git
username: git
password: ghp_xxxx
---
# SSH key
apiVersion: v1
kind: Secret
metadata:
name: private-repo-ssh
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
url: git@github.com:org/private-repo.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
```
## Notifications
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: $slack-token
template.app-deployed: |
message: Application {{.app.metadata.name}} is now {{.app.status.sync.status}}.
trigger.on-deployed: |
- when: app.status.operationState.phase in ['Succeeded']
send: [app-deployed]
```
## Common Issues
### Issue: Sync Fails with Diff
**Problem**: Resources show differences but are correct
**Solution**: Configure ignore differences
```yaml
spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas
```
### Issue: Repository Not Accessible
**Problem**: ArgoCD cannot clone repository
**Solution**: Check repository secret, verify URL and credentials
### Issue: Application Stuck OutOfSync
**Problem**: Application never becomes synced
**Solution**: Check resource status, review events, verify manifests
### Issue: Health Check Failing
**Problem**: Application shows degraded health
**Solution**: Check custom health checks, verify probe configurations
## Best Practices
- Use ApplicationSets for multi-environment deployments
- Implement sync waves for ordered deployments
- Use projects to isolate applications
- Configure notifications for deployment events
- Implement proper RBAC with projects
- Use health checks for deployment verification
- Enable auto-pruning to remove deleted resources
- Keep manifests in dedicated repositories
## Related Skills
- [kubernetes-ops](../kubernetes-ops/) - K8s fundamentals
- [helm-charts](../helm-charts/) - Helm deployments
- [kustomize](../kustomize/) - Kustomize overlays
@@ -0,0 +1,126 @@
# ArgoCD GitOps Patterns
## Application Definition
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/repo
targetRevision: HEAD
path: k8s/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: myapp
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
```
## Sync Waves
```yaml
metadata:
annotations:
argocd.argoproj.io/sync-wave: "-1" # Deploy first
---
metadata:
annotations:
argocd.argoproj.io/sync-wave: "0" # Default
---
metadata:
annotations:
argocd.argoproj.io/sync-wave: "1" # Deploy last
```
## ApplicationSet
```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-set
spec:
generators:
- list:
elements:
- env: dev
cluster: dev-cluster
- env: prod
cluster: prod-cluster
template:
metadata:
name: 'myapp-{{env}}'
spec:
source:
repoURL: https://github.com/org/repo
path: 'k8s/overlays/{{env}}'
destination:
server: '{{cluster}}'
namespace: myapp
```
## Multi-Cluster
```yaml
apiVersion: v1
kind: Secret
metadata:
name: prod-cluster
labels:
argocd.argoproj.io/secret-type: cluster
stringData:
name: prod
server: https://prod-cluster.example.com
config: |
{
"bearerToken": "...",
"tlsClientConfig": {
"insecure": false,
"caData": "..."
}
}
```
## App of Apps
```yaml
# Root application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root
spec:
source:
path: apps/ # Contains Application manifests
destination:
namespace: argocd
```
## CLI Commands
```bash
# Login
argocd login argocd.example.com
# Sync
argocd app sync myapp
argocd app sync myapp --prune
# Rollback
argocd app rollback myapp
# Diff
argocd app diff myapp
# History
argocd app history myapp
```
+445
View File
@@ -0,0 +1,445 @@
---
name: helm-charts
description: Create, manage, and deploy Helm charts for Kubernetes package management. Build reusable chart templates, manage releases, configure values, and use Helm repositories. Use when packaging Kubernetes applications or managing K8s deployments with Helm.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# Helm Charts
Package and deploy Kubernetes applications using Helm, the package manager for Kubernetes.
## When to Use This Skill
Use this skill when:
- Creating reusable Kubernetes application packages
- Deploying applications with configurable values
- Managing Helm releases and upgrades
- Using third-party Helm charts
- Implementing chart versioning and repositories
## Prerequisites
- Helm 3.x installed
- kubectl configured with cluster access
- Basic Kubernetes knowledge
## Chart Structure
```
mychart/
├── Chart.yaml # Chart metadata
├── values.yaml # Default configuration values
├── charts/ # Chart dependencies
├── templates/ # Kubernetes manifest templates
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── _helpers.tpl # Template helpers
│ ├── NOTES.txt # Post-install notes
│ └── tests/
│ └── test-connection.yaml
└── .helmignore # Files to ignore
```
## Chart.yaml
```yaml
apiVersion: v2
name: myapp
description: A Helm chart for MyApp
type: application
version: 1.0.0
appVersion: "2.0.0"
keywords:
- myapp
- web
maintainers:
- name: DevOps Team
email: devops@example.com
dependencies:
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
```
## values.yaml
```yaml
replicaCount: 2
image:
repository: myapp
tag: "" # Defaults to appVersion
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
className: nginx
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
tls: []
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
postgresql:
enabled: true
auth:
database: myapp
```
## Templates
### Deployment Template
```yaml
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "myapp.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ include "myapp.fullname" . }}-secrets
key: database-url
```
### Helper Functions
```yaml
# templates/_helpers.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "myapp.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "myapp.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "myapp.labels" -}}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
{{ include "myapp.selectorLabels" . }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "myapp.selectorLabels" -}}
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
```
### Conditional Resources
```yaml
# templates/ingress.yaml
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "myapp.fullname" . }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "myapp.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}
```
## Helm Commands
### Installing Charts
```bash
# Install from local chart
helm install myapp ./mychart
# Install with custom values
helm install myapp ./mychart -f custom-values.yaml
# Install with value overrides
helm install myapp ./mychart \
--set replicaCount=3 \
--set image.tag=2.0.0
# Install in specific namespace
helm install myapp ./mychart -n production --create-namespace
# Dry run to preview
helm install myapp ./mychart --dry-run --debug
```
### Managing Releases
```bash
# List releases
helm list
helm list -A # All namespaces
# Upgrade release
helm upgrade myapp ./mychart
helm upgrade myapp ./mychart -f new-values.yaml
# Rollback
helm rollback myapp 1
helm history myapp
# Uninstall
helm uninstall myapp
```
### Chart Development
```bash
# Create new chart
helm create mychart
# Lint chart
helm lint ./mychart
# Template locally (debug)
helm template myapp ./mychart
# Package chart
helm package ./mychart
# Update dependencies
helm dependency update ./mychart
```
## Repositories
```bash
# Add repository
helm repo add bitnami https://charts.bitnami.com/bitnami
# Update repositories
helm repo update
# Search charts
helm search repo postgresql
helm search hub prometheus
# Install from repo
helm install postgres bitnami/postgresql
# Show chart info
helm show values bitnami/postgresql
```
## Advanced Features
### Hooks
```yaml
# templates/pre-install-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "myapp.fullname" . }}-migration
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
spec:
containers:
- name: migrate
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ["./migrate.sh"]
restartPolicy: Never
```
### Tests
```yaml
# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "myapp.fullname" . }}-test-connection"
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "myapp.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
```
```bash
# Run tests
helm test myapp
```
### Library Charts
```yaml
# Chart.yaml
apiVersion: v2
name: mylib
type: library
version: 1.0.0
```
```yaml
# Using library chart
dependencies:
- name: mylib
version: "1.x.x"
repository: "file://../mylib"
```
## OCI Registry Support
```bash
# Login to registry
helm registry login registry.example.com
# Push chart to OCI registry
helm push mychart-1.0.0.tgz oci://registry.example.com/charts
# Pull from OCI registry
helm pull oci://registry.example.com/charts/mychart --version 1.0.0
# Install from OCI
helm install myapp oci://registry.example.com/charts/mychart
```
## Common Issues
### Issue: YAML Indentation Errors
**Problem**: Template renders with wrong indentation
**Solution**: Use `nindent` helper function
```yaml
{{- toYaml .Values.resources | nindent 12 }}
```
### Issue: Values Not Applying
**Problem**: Custom values not reflected
**Solution**: Check value paths, use `--debug` flag
```bash
helm template myapp ./mychart --debug
```
### Issue: Dependency Errors
**Problem**: Chart dependencies not found
**Solution**: Run `helm dependency update`
### Issue: Release Already Exists
**Problem**: Cannot install, release exists
**Solution**: Use `helm upgrade --install`
```bash
helm upgrade --install myapp ./mychart
```
## Best Practices
- Use semantic versioning for charts
- Provide comprehensive default values
- Document all values in values.yaml with comments
- Use helper templates for repeated patterns
- Implement chart tests
- Use .helmignore to exclude unnecessary files
- Pin dependency versions
- Use `helm lint` in CI pipelines
## Related Skills
- [kubernetes-ops](../kubernetes-ops/) - K8s fundamentals
- [argocd-gitops](../argocd-gitops/) - GitOps with Helm
- [kustomize](../kustomize/) - Alternative templating
@@ -0,0 +1,121 @@
# Helm Commands Reference
## Chart Management
```bash
# Create new chart
helm create mychart
# Lint chart
helm lint mychart/
# Package chart
helm package mychart/
# Template (render without installing)
helm template myrelease mychart/ --values values.yaml
```
## Repository
```bash
# Add repo
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add stable https://charts.helm.sh/stable
# Update repos
helm repo update
# Search
helm search repo nginx
helm search hub nginx
```
## Installation
```bash
# Install
helm install myrelease mychart/
helm install myrelease bitnami/nginx --namespace prod --create-namespace
# With values
helm install myrelease mychart/ -f values.yaml
helm install myrelease mychart/ --set image.tag=v1.0
# Dry run
helm install myrelease mychart/ --dry-run --debug
# Wait for completion
helm install myrelease mychart/ --wait --timeout 5m
```
## Upgrade & Rollback
```bash
# Upgrade
helm upgrade myrelease mychart/ -f values.yaml
helm upgrade --install myrelease mychart/ # Install or upgrade
# Rollback
helm rollback myrelease 1 # Rollback to revision 1
helm rollback myrelease # Previous revision
# History
helm history myrelease
```
## Management
```bash
# List releases
helm list
helm list -A # All namespaces
helm list --pending
# Get info
helm get values myrelease
helm get manifest myrelease
helm get all myrelease
# Status
helm status myrelease
# Uninstall
helm uninstall myrelease
helm uninstall myrelease --keep-history
```
## Chart Structure
```
mychart/
├── Chart.yaml # Chart metadata
├── values.yaml # Default values
├── charts/ # Dependencies
├── templates/
│ ├── NOTES.txt # Post-install notes
│ ├── _helpers.tpl # Template helpers
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ingress.yaml
└── .helmignore
```
## Template Functions
```yaml
# Built-in functions
{{ .Values.image.tag | default "latest" }}
{{ .Release.Name | upper }}
{{ include "mychart.fullname" . }}
# Conditionals
{{- if .Values.ingress.enabled }}
# ingress config
{{- end }}
# Loops
{{- range .Values.hosts }}
- host: {{ . }}
{{- end }}
```
@@ -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 "========================================="
+454
View File
@@ -0,0 +1,454 @@
---
name: kustomize
description: Customize Kubernetes manifests without templating using Kustomize. Create base configurations with environment overlays, manage configuration variants, and patch resources declaratively. Use when managing Kubernetes configurations across multiple environments without Helm.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# Kustomize
Customize Kubernetes resources declaratively without templating.
## When to Use This Skill
Use this skill when:
- Managing Kubernetes configs across environments
- Patching existing manifests without modification
- Creating configuration variants from bases
- Customizing third-party manifests
- Preferring declarative over templating approach
## Prerequisites
- kubectl 1.14+ (includes kustomize)
- Or standalone kustomize CLI
- Basic Kubernetes manifest knowledge
## Directory Structure
```
myapp/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ └── configmap.yaml
└── overlays/
├── development/
│ ├── kustomization.yaml
│ └── replica-patch.yaml
├── staging/
│ ├── kustomization.yaml
│ └── namespace.yaml
└── production/
├── kustomization.yaml
├── replica-patch.yaml
└── resource-patch.yaml
```
## Base Configuration
### kustomization.yaml
```yaml
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
commonLabels:
app: myapp
commonAnnotations:
managed-by: kustomize
```
### Base Resources
```yaml
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
```
## Overlays
### Development Overlay
```yaml
# overlays/development/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namespace: myapp-dev
namePrefix: dev-
commonLabels:
environment: development
images:
- name: myapp
newTag: dev-latest
```
### Production Overlay
```yaml
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namespace: myapp-prod
namePrefix: prod-
commonLabels:
environment: production
replicas:
- name: myapp
count: 5
images:
- name: myapp
newName: registry.example.com/myapp
newTag: v2.0.0
patches:
- path: resource-patch.yaml
```
## Patching
### Strategic Merge Patch
```yaml
# overlays/production/resource-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
resources:
requests:
memory: "256Mi"
cpu: "500m"
limits:
memory: "512Mi"
cpu: "1000m"
```
### JSON Patch
```yaml
# kustomization.yaml
patches:
- target:
kind: Deployment
name: myapp
patch: |-
- op: replace
path: /spec/replicas
value: 5
- op: add
path: /spec/template/spec/containers/0/env
value:
- name: LOG_LEVEL
value: info
```
### Inline Patches
```yaml
# kustomization.yaml
patches:
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
target:
kind: Deployment
name: myapp
```
## Configuration Generation
### ConfigMap Generator
```yaml
# kustomization.yaml
configMapGenerator:
- name: myapp-config
literals:
- APP_ENV=production
- LOG_LEVEL=info
files:
- config.yaml
envs:
- config.env
options:
disableNameSuffixHash: false
```
### Secret Generator
```yaml
# kustomization.yaml
secretGenerator:
- name: myapp-secrets
literals:
- api-key=secret123
files:
- tls.crt
- tls.key
type: kubernetes.io/tls
```
## Image Transformations
```yaml
# kustomization.yaml
images:
# Change tag
- name: myapp
newTag: v2.0.0
# Change registry
- name: myapp
newName: registry.example.com/myapp
newTag: v2.0.0
# Use digest
- name: myapp
digest: sha256:abc123...
```
## Resource Transformations
### Name Prefix/Suffix
```yaml
# kustomization.yaml
namePrefix: prod-
nameSuffix: -v2
```
### Namespace
```yaml
# kustomization.yaml
namespace: production
```
### Labels and Annotations
```yaml
# kustomization.yaml
commonLabels:
app.kubernetes.io/name: myapp
app.kubernetes.io/environment: production
commonAnnotations:
example.com/owner: team-a
```
### Replicas
```yaml
# kustomization.yaml
replicas:
- name: myapp
count: 5
- name: worker
count: 3
```
## Components
```yaml
# components/monitoring/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
- servicemonitor.yaml
patches:
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
```
```yaml
# overlays/production/kustomization.yaml
components:
- ../../components/monitoring
```
## Remote Resources
```yaml
# kustomization.yaml
resources:
# Remote Git repository
- https://github.com/org/manifests//base?ref=v1.0.0
# Remote URL
- https://raw.githubusercontent.com/org/repo/main/deployment.yaml
```
## Commands
```bash
# Build and view output
kubectl kustomize overlays/production
# Apply to cluster
kubectl apply -k overlays/production
# Delete resources
kubectl delete -k overlays/production
# View diff
kubectl diff -k overlays/production
# Build with standalone kustomize
kustomize build overlays/production
# Build and apply
kustomize build overlays/production | kubectl apply -f -
```
## Helm Chart Integration
```yaml
# kustomization.yaml
helmCharts:
- name: prometheus
repo: https://prometheus-community.github.io/helm-charts
version: 25.0.0
releaseName: prometheus
namespace: monitoring
valuesFile: values.yaml
includeCRDs: true
```
## Variable Substitution
```yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
replacements:
- source:
kind: ConfigMap
name: myapp-config
fieldPath: data.APP_VERSION
targets:
- select:
kind: Deployment
name: myapp
fieldPaths:
- spec.template.spec.containers.[name=myapp].image
options:
delimiter: ':'
index: 1
```
## Common Issues
### Issue: Name Hash Conflicts
**Problem**: Resources not updating when ConfigMap changes
**Solution**: Enable name suffix hash (default) or use replacement
### Issue: Patch Not Applying
**Problem**: Strategic merge patch doesn't work
**Solution**: Verify resource names match, use JSON patch for complex changes
### Issue: Remote Resource Fails
**Problem**: Cannot fetch remote resources
**Solution**: Check URL, verify ref/tag exists, ensure network access
### Issue: Label Selector Mismatch
**Problem**: commonLabels breaks selectors
**Solution**: Use includeSelectors: false or exclude specific resources
```yaml
commonLabels:
app: myapp
configurations:
- labelExclusions.yaml
```
## Best Practices
- Keep base manifests environment-agnostic
- Use overlays for environment-specific config
- Prefer strategic merge patches for simple changes
- Use components for optional features
- Pin remote resource versions
- Enable ConfigMap/Secret hash suffixes
- Document overlay structure in README
- Test builds before applying
## Related Skills
- [kubernetes-ops](../kubernetes-ops/) - K8s fundamentals
- [helm-charts](../helm-charts/) - Helm alternative
- [argocd-gitops](../argocd-gitops/) - GitOps deployment
+461
View File
@@ -0,0 +1,461 @@
---
name: openshift
description: Manage Red Hat OpenShift clusters and deployments. Configure projects, routes, builds, and deploy applications using OpenShift-specific features. Use when working with OpenShift Container Platform or OKD for enterprise Kubernetes.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# OpenShift
Deploy and manage applications on Red Hat OpenShift Container Platform.
## When to Use This Skill
Use this skill when:
- Deploying applications to OpenShift clusters
- Using OpenShift-specific features (Routes, BuildConfigs)
- Managing projects and RBAC in OpenShift
- Implementing S2I (Source-to-Image) builds
- Working with OpenShift Operators
## Prerequisites
- OpenShift cluster access
- oc CLI installed
- Basic Kubernetes knowledge
## CLI Basics
### Authentication
```bash
# Login to cluster
oc login https://api.cluster.example.com:6443 -u admin -p password
# Login with token
oc login --token=sha256~xxxx --server=https://api.cluster.example.com:6443
# Check current context
oc whoami
oc whoami --show-server
oc whoami --show-context
# Logout
oc logout
```
### Project Management
```bash
# Create project (namespace)
oc new-project myapp --display-name="My App" --description="My Application"
# Switch project
oc project myapp
# List projects
oc projects
# Delete project
oc delete project myapp
```
## Deploying Applications
### From Image
```bash
# Deploy from container image
oc new-app --image=nginx:latest --name=webserver
# Deploy from Docker Hub
oc new-app docker.io/library/nginx:latest
# Deploy with environment variables
oc new-app myimage:latest \
-e DATABASE_URL=postgres://localhost/db \
-e APP_ENV=production
```
### From Source (S2I)
```bash
# Deploy from Git repository
oc new-app https://github.com/org/myapp.git
# Specify builder image
oc new-app nodejs:18~https://github.com/org/nodejs-app.git
# With context directory
oc new-app https://github.com/org/monorepo.git \
--context-dir=backend \
--name=backend-api
```
### From Template
```bash
# List available templates
oc get templates -n openshift
# Deploy from template
oc new-app postgresql-persistent \
-p POSTGRESQL_USER=user \
-p POSTGRESQL_PASSWORD=secret \
-p POSTGRESQL_DATABASE=mydb
```
## Routes
### Creating Routes
```yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: myapp
spec:
host: myapp.apps.cluster.example.com
to:
kind: Service
name: myapp
weight: 100
port:
targetPort: 8080
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
```
```bash
# Create route via CLI
oc expose svc/myapp
# Create with custom hostname
oc create route edge myapp \
--service=myapp \
--hostname=myapp.apps.cluster.example.com
# Create passthrough route (TLS termination at pod)
oc create route passthrough myapp-secure --service=myapp
```
### A/B Testing
```yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: myapp
spec:
to:
kind: Service
name: myapp-v1
weight: 90
alternateBackends:
- kind: Service
name: myapp-v2
weight: 10
```
## Build Configurations
### BuildConfig
```yaml
apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
name: myapp
spec:
source:
type: Git
git:
uri: https://github.com/org/myapp.git
ref: main
strategy:
type: Docker
dockerStrategy:
dockerfilePath: Dockerfile
output:
to:
kind: ImageStreamTag
name: myapp:latest
triggers:
- type: ConfigChange
- type: GitHub
github:
secret: webhook-secret
```
### S2I Build
```yaml
apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
name: myapp
spec:
source:
type: Git
git:
uri: https://github.com/org/myapp.git
strategy:
type: Source
sourceStrategy:
from:
kind: ImageStreamTag
namespace: openshift
name: nodejs:18-ubi8
env:
- name: NPM_RUN
value: start
output:
to:
kind: ImageStreamTag
name: myapp:latest
```
### Build Commands
```bash
# Start build
oc start-build myapp
# Start build from local source
oc start-build myapp --from-dir=.
# Follow build logs
oc start-build myapp --follow
# View build logs
oc logs -f bc/myapp
# Cancel build
oc cancel-build myapp-1
```
## Image Streams
```yaml
apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
name: myapp
spec:
lookupPolicy:
local: true
tags:
- name: latest
from:
kind: DockerImage
name: registry.example.com/myapp:latest
importPolicy:
scheduled: true
```
```bash
# Create image stream
oc create imagestream myapp
# Import image
oc import-image myapp:latest \
--from=docker.io/library/nginx:latest \
--confirm
# Tag image
oc tag myapp:latest myapp:production
```
## Deployment Configs
```yaml
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
name: myapp
spec:
replicas: 3
selector:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
triggers:
- type: ConfigChange
- type: ImageChange
imageChangeParams:
automatic: true
containerNames:
- myapp
from:
kind: ImageStreamTag
name: myapp:latest
strategy:
type: Rolling
rollingParams:
maxSurge: 25%
maxUnavailable: 25%
```
## ConfigMaps and Secrets
```bash
# Create ConfigMap
oc create configmap myapp-config \
--from-literal=APP_ENV=production \
--from-file=config.yaml
# Create Secret
oc create secret generic myapp-secrets \
--from-literal=password=secret123
# Mount as volume
oc set volume dc/myapp \
--add --name=config \
--type=configmap \
--configmap-name=myapp-config \
--mount-path=/etc/config
# Set as environment
oc set env dc/myapp --from=secret/myapp-secrets
```
## Security Context Constraints
```bash
# List SCCs
oc get scc
# View SCC details
oc describe scc restricted
# Grant SCC to service account
oc adm policy add-scc-to-user anyuid -z myapp-sa -n myproject
# Create service account
oc create serviceaccount myapp-sa
```
### Custom SCC
```yaml
apiVersion: security.openshift.io/v1
kind: SecurityContextConstraints
metadata:
name: myapp-scc
allowPrivilegedContainer: false
runAsUser:
type: MustRunAsNonRoot
seLinuxContext:
type: MustRunAs
fsGroup:
type: RunAsAny
volumes:
- configMap
- secret
- persistentVolumeClaim
users:
- system:serviceaccount:myproject:myapp-sa
```
## Operators
```bash
# List available operators
oc get packagemanifests -n openshift-marketplace
# Subscribe to operator
cat <<EOF | oc apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: prometheus
namespace: openshift-operators
spec:
channel: stable
name: prometheus
source: community-operators
sourceNamespace: openshift-marketplace
EOF
# View installed operators
oc get csv -n openshift-operators
```
## Monitoring
```bash
# View pod logs
oc logs -f pod/myapp-1-xyz
# View events
oc get events --sort-by='.lastTimestamp'
# Resource usage
oc adm top pods
oc adm top nodes
# Debug pod
oc debug pod/myapp-1-xyz
```
## Common Issues
### Issue: Build Fails
**Problem**: S2I build cannot find dependencies
**Solution**: Check builder image, verify source repository access
### Issue: Pod Security Violation
**Problem**: Pod fails to start due to SCC
**Solution**: Use appropriate SCC or modify container security context
### Issue: Route Not Working
**Problem**: Cannot access application via route
**Solution**: Verify service selector, check router pods, validate DNS
### Issue: Image Pull Error
**Problem**: Cannot pull image from registry
**Solution**: Create image pull secret, link to service account
```bash
oc create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass
oc secrets link default regcred --for=pull
```
## Best Practices
- Use Projects for isolation (not just namespaces)
- Leverage ImageStreams for image management
- Use BuildConfigs for CI/CD integration
- Implement proper SCCs (avoid privileged)
- Use Routes instead of Ingress
- Leverage OpenShift templates for repeatability
- Monitor with built-in Prometheus
- Use Operators for complex applications
## Related Skills
- [kubernetes-ops](../kubernetes-ops/) - K8s fundamentals
- [helm-charts](../helm-charts/) - Helm deployments
- [container-registries](../../containers/container-registries/) - Image management