Skip to content

Kubernetes Orchestration Patterns

Master Kubernetes orchestration with Cursor IDE and Claude Code. This guide covers manifest generation, Helm charts, service mesh configuration, GitOps workflows, and production-ready deployment patterns with AI assistance.

  1. Initialize Kubernetes Project

    Terminal window
    # Generate Kubernetes manifests
    Agent: "Create Kubernetes deployment for my app with:
    - Deployment with rolling updates
    - Service and Ingress
    - ConfigMap and Secrets
    - HPA for auto-scaling
    - Network policies"
  2. Install Kubernetes MCP Server (optional)

    Terminal window
    # Claude Code
    claude mcp add k8s -- npx -y kubernetes-mcp-server
    # Configure kubeconfig
    export KUBECONFIG=/path/to/kubeconfig
  3. Configure AI Rules

    # .cursorrules or CLAUDE.md
    Kubernetes best practices:
    - Use namespaces for isolation
    - Set resource limits and requests
    - Implement health checks
    - Use ConfigMaps and Secrets properly
    - Follow security best practices
    - Label resources consistently
    - Use declarative configurations
# AI Prompt
Agent: "Create production-ready Kubernetes deployment with:
- Zero-downtime deployments
- Resource management
- Security contexts
- Observability
- High availability"
# Generated deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-backend
namespace: production
labels:
app: backend
tier: api
version: v1.0.0
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: backend
tier: api
template:
metadata:
labels:
app: backend
tier: api
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
prometheus.io/path: "/metrics"
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- backend
topologyKey: kubernetes.io/hostname
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: backend
image: myregistry/backend:v1.0.0
imagePullPolicy: Always
ports:
- name: http
containerPort: 8080
protocol: TCP
- name: metrics
containerPort: 9090
protocol: TCP
env:
- name: NODE_ENV
value: "production"
- name: DB_HOST
valueFrom:
secretKeyRef:
name: db-credentials
key: host
- name: REDIS_URL
valueFrom:
configMapKeyRef:
name: app-config
key: redis.url
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
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
successThreshold: 1
failureThreshold: 3
startupProbe:
httpGet:
path: /health/startup
port: http
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 30
volumeMounts:
- name: config
mountPath: /app/config
readOnly: true
- name: secrets
mountPath: /app/secrets
readOnly: true
- name: cache
mountPath: /app/cache
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumes:
- name: config
configMap:
name: app-config
- name: secrets
secret:
secretName: app-secrets
defaultMode: 0400
- name: cache
emptyDir:
sizeLimit: 1Gi
serviceAccountName: backend-sa
imagePullSecrets:
- name: registry-credentials
service.yaml
# AI Prompt: "Create service mesh-ready networking configuration"
apiVersion: v1
kind: Service
metadata:
name: backend-service
namespace: production
labels:
app: backend
tier: api
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: http
protocol: TCP
- name: grpc
port: 9000
targetPort: grpc
protocol: TCP
selector:
app: backend
tier: api
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: backend-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/rate-limit: "100"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://app.example.com"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls-secret
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 80
---
# networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-network-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: production
- podSelector:
matchLabels:
app: frontend
- podSelector:
matchLabels:
app: nginx-ingress
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector:
matchLabels:
name: production
ports:
- protocol: TCP
port: 5432 # PostgreSQL
- protocol: TCP
port: 6379 # Redis
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
# AI Prompt
Agent: "Create a Helm chart for my application with:
- Multiple environments support
- Dependency management
- Custom values validation
- Hooks for migrations
- Testing templates"
# Generated Chart.yaml
apiVersion: v2
name: my-application
description: A Helm chart for my microservices application
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
- microservices
- api
- backend
home: https://github.com/myorg/my-application
sources:
- https://github.com/myorg/my-application
maintainers:
- name: DevOps Team
email: devops@myorg.com
dependencies:
- name: postgresql
version: "12.x.x"
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
- name: redis
version: "17.x.x"
repository: https://charts.bitnami.com/bitnami
condition: redis.enabled
- name: prometheus
version: "19.x.x"
repository: https://prometheus-community.github.io/helm-charts
condition: monitoring.enabled
# values.yaml
replicaCount: 3
image:
repository: myregistry/backend
pullPolicy: IfNotPresent
tag: "" # Overridden by CI/CD
imagePullSecrets:
- name: registry-credentials
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
annotations: {}
name: ""
podAnnotations: {}
podSecurityContext:
fsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
service:
type: ClusterIP
port: 80
targetPort: 8080
annotations: {}
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rate-limit: "100"
hosts:
- host: api.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: api-tls
hosts:
- api.example.com
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations: []
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- my-application
topologyKey: kubernetes.io/hostname
postgresql:
enabled: true
auth:
username: myapp
database: myapp_db
existingSecret: db-credentials
redis:
enabled: true
auth:
enabled: true
existingSecret: redis-credentials
monitoring:
enabled: true
serviceMonitor:
enabled: true
interval: 30s
path: /metrics
templates/_helpers.tpl
# AI Prompt: "Create reusable Helm template helpers"
{{/*
Expand the name of the chart.
*/}}
{{- define "my-application.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "my-application.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "my-application.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "my-application.labels" -}}
helm.sh/chart: {{ include "my-application.chart" . }}
{{ include "my-application.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "my-application.selectorLabels" -}}
app.kubernetes.io/name: {{ include "my-application.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "my-application.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "my-application.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Validate required values
*/}}
{{- define "my-application.validateValues" -}}
{{- if not .Values.image.repository }}
{{- fail "image.repository is required" }}
{{- end }}
{{- if and .Values.ingress.enabled (not .Values.ingress.hosts) }}
{{- fail "ingress.hosts must be provided when ingress is enabled" }}
{{- end }}
{{- end }}
# AI Prompt
Agent: "Create ArgoCD application for GitOps deployment with:
- Multi-environment support
- Automated sync policies
- Resource hooks
- Health checks
- Rollback configuration"
# argocd-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-application-production
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/myorg/k8s-configs
targetRevision: main
path: applications/my-application/overlays/production
# For Helm charts
# helm:
# valueFiles:
# - values-production.yaml
# parameters:
# - name: image.tag
# value: v1.0.0
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- PruneLast=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
revisionHistoryLimit: 10
# Resource health customization
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas
info:
- name: 'Environment'
value: 'Production'
- name: 'Owner'
value: 'Platform Team'
---
# argocd-appproject.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: my-application
namespace: argocd
spec:
description: My Application project
sourceRepos:
- 'https://github.com/myorg/*'
destinations:
- namespace: 'production'
server: https://kubernetes.default.svc
- namespace: 'staging'
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ''
kind: Namespace
namespaceResourceWhitelist:
- group: '*'
kind: '*'
roles:
- name: admin
policies:
- p, proj:my-application:admin, applications, *, my-application/*, allow
groups:
- my-org:platform-team
- name: developer
policies:
- p, proj:my-application:developer, applications, get, my-application/*, allow
- p, proj:my-application:developer, applications, sync, my-application/*, allow
groups:
- my-org:developers
virtualservice.yaml
# AI Prompt: "Configure Istio service mesh for microservices"
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: backend-vs
namespace: production
spec:
hosts:
- backend-service
- api.example.com
gateways:
- mesh
- backend-gateway
http:
- match:
- headers:
x-version:
exact: v2
route:
- destination:
host: backend-service
subset: v2
weight: 100
- route:
- destination:
host: backend-service
subset: v1
weight: 90
- destination:
host: backend-service
subset: v2
weight: 10
fault:
delay:
percentage:
value: 0.1
fixedDelay: 5s
timeout: 30s
retries:
attempts: 3
perTryTimeout: 10s
retryOn: 5xx
---
# destinationrule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: backend-dr
namespace: production
spec:
host: backend-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 100
http2MaxRequests: 100
maxRequestsPerConnection: 2
loadBalancer:
simple: LEAST_REQUEST
outlierDetection:
consecutiveGatewayErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
minHealthPercent: 50
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
connectionPool:
tcp:
maxConnections: 10
---
# gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: backend-gateway
namespace: production
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: api-tls-secret
hosts:
- api.example.com
- port:
number: 80
name: http
protocol: HTTP
hosts:
- api.example.com
tls:
httpsRedirect: true
# AI Prompt
Ask: "Configure auto-scaling with:
- CPU and memory metrics
- Custom metrics from Prometheus
- Predictive scaling
- Pod disruption budgets
- Cluster autoscaler integration"
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100"
- type: External
external:
metric:
name: queue_messages_ready
selector:
matchLabels:
queue: "orders"
target:
type: AverageValue
averageValue: "30"
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
- type: Pods
value: 2
periodSeconds: 60
selectPolicy: Min
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
---
# vpa.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: backend-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: backend
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: 2
memory: 2Gi
controlledResources: ["cpu", "memory"]
---
# pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: backend-pdb
namespace: production
spec:
minAvailable: 2
selector:
matchLabels:
app: backend
maxUnavailable: 33%
servicemonitor.yaml
# AI Prompt: "Set up comprehensive monitoring with Prometheus"
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: backend-metrics
namespace: production
labels:
app: backend
prometheus: kube-prometheus
spec:
selector:
matchLabels:
app: backend
endpoints:
- port: metrics
interval: 30s
path: /metrics
scheme: http
tlsConfig:
insecureSkipVerify: true
---
# prometheusrule.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: backend-alerts
namespace: production
labels:
prometheus: kube-prometheus
spec:
groups:
- name: backend.rules
interval: 30s
rules:
- alert: HighErrorRate
expr: |
(
sum(rate(http_requests_total{job="backend",status=~"5.."}[5m]))
/
sum(rate(http_requests_total{job="backend"}[5m]))
) > 0.05
for: 5m
labels:
severity: warning
team: backend
annotations:
summary: "High error rate detected"
description: "Error rate is {{ $value | humanizePercentage }} for {{ $labels.job }}"
- alert: HighLatency
expr: |
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket{job="backend"}[5m])) by (le)
) > 0.5
for: 5m
labels:
severity: warning
annotations:
summary: "High latency detected"
description: "95th percentile latency is {{ $value }}s"
- alert: PodCrashLooping
expr: |
rate(kube_pod_container_status_restarts_total{namespace="production",pod=~"backend-.*"}[5m]) > 0
for: 5m
labels:
severity: critical
annotations:
summary: "Pod is crash looping"
description: "Pod {{ $labels.pod }} is crash looping"
# AI Prompt
Agent: "Create GitHub Actions workflow for Kubernetes:
- Build and push images
- Update manifests
- Deploy to multiple environments
- Run smoke tests
- Rollback on failure"
# .github/workflows/deploy.yml
name: Deploy to Kubernetes
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=sha
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy-staging:
needs: build
if: github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
environment: staging
steps:
- name: Checkout configs
uses: actions/checkout@v4
with:
repository: myorg/k8s-configs
token: ${{ secrets.CONFIG_REPO_TOKEN }}
- name: Update image tag
run: |
cd applications/my-app/overlays/staging
kustomize edit set image backend=${{ needs.build.outputs.image-tag }}
- name: Commit and push
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git add .
git commit -m "Update staging image to ${{ needs.build.outputs.image-tag }}"
git push
- name: Wait for ArgoCD sync
run: |
# Wait for ArgoCD to sync and deploy
sleep 60
- name: Run smoke tests
run: |
kubectl run smoke-test --image=curlimages/curl:latest --rm -i --restart=Never -- \
curl -f https://staging-api.example.com/health
deploy-production:
needs: [build, deploy-staging]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout configs
uses: actions/checkout@v4
with:
repository: myorg/k8s-configs
token: ${{ secrets.CONFIG_REPO_TOKEN }}
- name: Update image tag
run: |
cd applications/my-app/overlays/production
kustomize edit set image backend=${{ needs.build.outputs.image-tag }}
- name: Create PR
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.CONFIG_REPO_TOKEN }}
commit-message: "Deploy ${{ needs.build.outputs.image-tag }} to production"
title: "Deploy ${{ needs.build.outputs.image-tag }} to production"
body: |
Automated deployment of ${{ needs.build.outputs.image-tag }} to production.
- Built from: ${{ github.sha }}
- Triggered by: @${{ github.actor }}
branch: deploy-${{ github.sha }}
base: main

Kubernetes Development Guidelines

  1. Resource Management - Always set requests and limits
  2. Health Checks - Implement all three probe types
  3. Security - Run as non-root, use network policies
  4. Observability - Export metrics, use structured logging
  5. High Availability - Use anti-affinity and PDBs
  6. GitOps - Declarative configuration in Git
# AI: "Implement blue-green deployment"
apiVersion: v1
kind: Service
metadata:
name: backend-active
spec:
selector:
app: backend
version: blue # Switch between blue/green
ports:
- port: 80
targetPort: 8080
---
# Script to switch versions
#!/bin/bash
kubectl patch service backend-active -p '{"spec":{"selector":{"version":"green"}}}'
Terminal window
# AI Prompt: "Generate Kubernetes debugging commands"
# Pod debugging
kubectl describe pod <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace> --previous
kubectl exec -it <pod-name> -n <namespace> -- /bin/sh
# Resource analysis
kubectl top nodes
kubectl top pods -n <namespace>
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
# Network debugging
kubectl run debug --image=nicolaka/netshoot -it --rm
kubectl port-forward svc/backend-service 8080:80
# Cluster state
kubectl get all -A
kubectl api-resources --verbs=list -o name | xargs -n 1 kubectl get -A -o wide 2>/dev/null