kubernetes-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Kubernetes Patterns

Kubernetes 模式

Production-grade Kubernetes patterns for deploying, managing, and debugging workloads reliably.
用于可靠部署、管理和调试工作负载的生产级Kubernetes模式。

When to Activate

适用场景

  • Writing Kubernetes manifests (Deployments, Services, Ingress, Jobs)
  • Configuring resource requests/limits, liveness/readiness probes
  • Setting up RBAC, namespaces, or ServiceAccounts
  • Managing configuration and secrets in K8s
  • Debugging CrashLoopBackOff, OOMKilled, pending pods, or image pull errors
  • Configuring HPA (Horizontal Pod Autoscaler) or PodDisruptionBudgets
  • Reviewing K8s YAML for security or correctness
  • 编写Kubernetes清单(Deployments、Services、Ingress、Jobs)
  • 配置资源请求/限制、存活/就绪探针
  • 设置RBAC、命名空间或ServiceAccount
  • 在K8s中管理配置与密钥
  • 调试CrashLoopBackOff、OOMKilled、Pending Pod或镜像拉取错误
  • 配置HPA(Horizontal Pod Autoscaler)或PodDisruptionBudgets
  • 审核K8s YAML的安全性与正确性

When to Use

使用时机

Same as When to Activate above. This alias satisfies repo skill-format conventions. Use this skill any time you are writing, reviewing, or debugging Kubernetes YAML and workloads.
与上方的适用场景一致。此别名符合仓库技能格式规范。当你编写、审核或调试Kubernetes YAML和工作负载时,均可使用本技能。

How It Works

工作原理

This skill provides copy-pasteable, production-grade YAML patterns and kubectl debugging commands organized by task:
  1. Deployment template — A fully configured production
    Deployment
    with security context, rolling update strategy, all three probe types, resource limits, and environment injection from ConfigMap/Secret.
  2. Probes — Decision table for startup vs liveness vs readiness, with correct
    failureThreshold × periodSeconds
    math.
  3. Services & Ingress — ClusterIP, LoadBalancer, and TLS Ingress patterns with cert-manager annotations.
  4. ConfigMaps & Secrets
    envFrom
    , file-mount, and external secrets guidance.
  5. Resource management — Requests vs limits rules of thumb by workload type (web API, JVM, worker, sidecar).
  6. RBAC — Least-privilege ServiceAccount → Role → RoleBinding chain.
  7. HPA & PDB — Autoscaling and node-drain safety configurations.
  8. Jobs & CronJobs — One-off and scheduled workload patterns with correct
    restartPolicy
    .
  9. kubectl cheatsheet — Logs, exec, rollback, port-forward, dry-run, and common error diagnosis commands.
  10. Anti-patterns & checklist — What NOT to do, and a security/reliability/observability checklist.
本技能提供按任务分类的可直接复制粘贴的生产级YAML模式kubectl调试命令
  1. Deployment模板 — 一个配置完整的生产级
    Deployment
    ,包含安全上下文、滚动更新策略、三种探针类型、资源限制,以及从ConfigMap/Secret注入环境变量的配置。
  2. 探针 — 启动探针、存活探针与就绪探针的决策表,包含正确的
    failureThreshold × periodSeconds
    计算逻辑。
  3. 服务与Ingress — ClusterIP、LoadBalancer和带cert-manager注解的TLS Ingress模式。
  4. ConfigMap与Secret
    envFrom
    、文件挂载和外部密钥管理指南。
  5. 资源管理 — 按工作负载类型(Web API、JVM、Worker、Sidecar)划分的资源请求与限制经验规则。
  6. RBAC — 遵循最小权限原则的ServiceAccount → Role → RoleBinding链式配置。
  7. HPA与PDB — 自动扩缩容和节点排空安全配置。
  8. Jobs与CronJobs — 一次性和定时工作负载模式,包含正确的
    restartPolicy
    配置。
  9. kubectl速查表 — 日志查看、容器执行、回滚、端口转发、试运行和常见错误诊断命令。
  10. 反模式与检查清单 — 禁忌操作,以及安全性/可靠性/可观测性检查清单。

Examples

示例

See the sections below for complete, runnable examples. Quick references:
TaskJump to
Full production Deployment YAMLCore Workload Patterns
Probe configurationProbes
RBAC least-privilege setupRBAC
Debug a CrashLoopBackOffkubectl Debugging Cheatsheet
AutoscalingHPA

查看以下章节获取完整可运行示例。快速参考:
任务跳转至
完整生产级Deployment YAML核心工作负载模式
探针配置探针
RBAC最小权限配置RBAC
调试CrashLoopBackOffkubectl调试速查表
自动扩缩容HPA

Core Workload Patterns

核心工作负载模式

Deployment — Production Template

Deployment — 生产级模板

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: my-namespace
  labels:
    app: my-app
    version: "1.0.0"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # Allow 1 extra pod during update
      maxUnavailable: 0    # Never reduce below desired count
  template:
    metadata:
      labels:
        app: my-app
        version: "1.0.0"
    spec:
      # Security context at pod level
      securityContext:
        runAsNonRoot: true
        runAsUser: 1001
        fsGroup: 1001

      # Graceful shutdown
      terminationGracePeriodSeconds: 30

      containers:
        - name: my-app
          image: ghcr.io/org/my-app:1.0.0   # Never use :latest
          imagePullPolicy: IfNotPresent

          ports:
            - containerPort: 8080
              protocol: TCP

          # Resource requests AND limits are both required
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "256Mi"

          # Container security context
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL

          # Probes (see Probes section below)
          startupProbe:
            httpGet:
              path: /health
              port: 8080
            failureThreshold: 30
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 0
            periodSeconds: 30
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
            failureThreshold: 2

          # Environment from ConfigMap and Secret
          envFrom:
            - configMapRef:
                name: my-app-config
          env:
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: my-app-secrets
                  key: db-password

          # Writable tmp directory when readOnlyRootFilesystem: true
          volumeMounts:
            - name: tmp
              mountPath: /tmp

      volumes:
        - name: tmp
          emptyDir: {}

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: my-namespace
  labels:
    app: my-app
    version: "1.0.0"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # Allow 1 extra pod during update
      maxUnavailable: 0    # Never reduce below desired count
  template:
    metadata:
      labels:
        app: my-app
        version: "1.0.0"
    spec:
      # Security context at pod level
      securityContext:
        runAsNonRoot: true
        runAsUser: 1001
        fsGroup: 1001

      # Graceful shutdown
      terminationGracePeriodSeconds: 30

      containers:
        - name: my-app
          image: ghcr.io/org/my-app:1.0.0   # Never use :latest
          imagePullPolicy: IfNotPresent

          ports:
            - containerPort: 8080
              protocol: TCP

          # Resource requests AND limits are both required
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "256Mi"

          # Container security context
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL

          # Probes (see Probes section below)
          startupProbe:
            httpGet:
              path: /health
              port: 8080
            failureThreshold: 30
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 0
            periodSeconds: 30
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
            failureThreshold: 2

          # Environment from ConfigMap and Secret
          envFrom:
            - configMapRef:
                name: my-app-config
          env:
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: my-app-secrets
                  key: db-password

          # Writable tmp directory when readOnlyRootFilesystem: true
          volumeMounts:
            - name: tmp
              mountPath: /tmp

      volumes:
        - name: tmp
          emptyDir: {}

Probes — Liveness, Readiness, Startup

探针 — 存活、就绪、启动

Understanding when to use each probe is critical:
ProbeFailure ActionUse For
startupProbe
Kills container if slow to startSlow-starting apps (JVM, Python)
livenessProbe
Restarts containerDeadlock / hung process detection
readinessProbe
Removes from Service endpointsTemporary unavailability (DB reconnect)
yaml
undefined
理解何时使用每种探针至关重要:
探针失败动作适用场景
startupProbe
若启动缓慢则杀死容器启动缓慢的应用(JVM、Python)
livenessProbe
重启容器死锁/挂起进程检测
readinessProbe
从Service端点移除临时不可用场景(数据库重连)
yaml
undefined

Correct pattern: startupProbe covers slow startup,

Correct pattern: startupProbe covers slow startup,

then liveness/readiness take over

then liveness/readiness take over

startupProbe: httpGet: path: /health port: 8080 failureThreshold: 30 # 30 * 5s = 150s max startup time periodSeconds: 5
livenessProbe: httpGet: path: /health port: 8080 periodSeconds: 30 failureThreshold: 3 # 3 * 30s = 90s before restart
readinessProbe: httpGet: path: /ready # Separate endpoint: checks DB, cache, etc. port: 8080 periodSeconds: 10 failureThreshold: 2

```yaml
startupProbe: httpGet: path: /health port: 8080 failureThreshold: 30 # 30 * 5s = 150s max startup time periodSeconds: 5
livenessProbe: httpGet: path: /health port: 8080 periodSeconds: 30 failureThreshold: 3 # 3 * 30s = 90s before restart
readinessProbe: httpGet: path: /ready # Separate endpoint: checks DB, cache, etc. port: 8080 periodSeconds: 10 failureThreshold: 2

```yaml

WRONG: initialDelaySeconds without startupProbe

WRONG: initialDelaySeconds without startupProbe

If the app takes 60s to start, set a startupProbe instead

If the app takes 60s to start, set a startupProbe instead

livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 60 # BAD: Arbitrary wait, race condition

---
livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 60 # BAD: Arbitrary wait, race condition

---

Services and Ingress

服务与Ingress

Service Types

服务类型

yaml
undefined
yaml
undefined

ClusterIP (default) — internal-only

ClusterIP (default) — internal-only

apiVersion: v1 kind: Service metadata: name: my-app namespace: my-namespace spec: selector: app: my-app ports: - port: 80 targetPort: 8080 protocol: TCP type: ClusterIP

```yaml
apiVersion: v1 kind: Service metadata: name: my-app namespace: my-namespace spec: selector: app: my-app ports: - port: 80 targetPort: 8080 protocol: TCP type: ClusterIP

```yaml

LoadBalancer — external traffic (cloud providers)

LoadBalancer — external traffic (cloud providers)

spec: type: LoadBalancer ports: - port: 443 targetPort: 8080
undefined
spec: type: LoadBalancer ports: - port: 443 targetPort: 8080
undefined

Ingress with TLS

带TLS的Ingress

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  namespace: my-namespace
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - myapp.example.com
      secretName: my-app-tls
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app
                port:
                  number: 80

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  namespace: my-namespace
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - myapp.example.com
      secretName: my-app-tls
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app
                port:
                  number: 80

ConfigMaps and Secrets

ConfigMap与Secret

ConfigMap — Non-sensitive configuration

ConfigMap — 非敏感配置

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app-config
  namespace: my-namespace
data:
  LOG_LEVEL: "info"
  APP_ENV: "production"
  MAX_CONNECTIONS: "100"
  # Mount as a file for complex config
  app.yaml: |
    server:
      port: 8080
      timeout: 30s
yaml
undefined
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app-config
  namespace: my-namespace
data:
  LOG_LEVEL: "info"
  APP_ENV: "production"
  MAX_CONNECTIONS: "100"
  # Mount as a file for complex config
  app.yaml: |
    server:
      port: 8080
      timeout: 30s
yaml
undefined

Mount ConfigMap as a file

Mount ConfigMap as a file

volumes:
  • name: config configMap: name: my-app-config items: - key: app.yaml path: app.yaml volumeMounts:
  • name: config mountPath: /etc/app readOnly: true
undefined
volumes:
  • name: config configMap: name: my-app-config items: - key: app.yaml path: app.yaml volumeMounts:
  • name: config mountPath: /etc/app readOnly: true
undefined

Secrets — Sensitive data

Secret — 敏感数据

bash
undefined
bash
undefined

Create secret from literal (CLI, then store in Vault/SOPS)

Create secret from literal (CLI, then store in Vault/SOPS)

kubectl create secret generic my-app-secrets
--from-literal=db-password='s3cr3t'
--namespace=my-namespace
--dry-run=client -o yaml | kubectl apply -f -

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-app-secrets
  namespace: my-namespace
type: Opaque
kubectl create secret generic my-app-secrets
--from-literal=db-password='s3cr3t'
--namespace=my-namespace
--dry-run=client -o yaml | kubectl apply -f -

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-app-secrets
  namespace: my-namespace
type: Opaque

Values are base64-encoded (NOT encrypted — use Sealed Secrets or ESO for real encryption)

Values are base64-encoded (NOT encrypted — use Sealed Secrets or ESO for real encryption)

data: db-password: czNjcjN0 # base64 of 's3cr3t'

> **Important:** Raw Kubernetes Secrets are only base64-encoded, not encrypted at rest unless your cluster has encryption configured. Use [Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets) or [External Secrets Operator](https://external-secrets.io) for production.

---
data: db-password: czNjcjN0 # base64 of 's3cr3t'

> **重要提示:** 原生Kubernetes Secret仅经过base64编码,并非加密存储,除非你的集群配置了加密功能。生产环境请使用[Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets)或[External Secrets Operator](https://external-secrets.io)。

---

Resource Requests and Limits

资源请求与限制

yaml
resources:
  requests:       # Scheduler uses this to place the pod
    cpu: "100m"   # 100 millicores = 0.1 CPU
    memory: "128Mi"
  limits:         # Container is killed/throttled above this
    cpu: "500m"
    memory: "256Mi"
Rules of thumb:
Workload TypeCPU RequestMemory RequestNotes
Web API100–250m128–256MiSet limits 2-4x requests
Worker/consumer250–500m256–512MiMemory limit = request for predictability
JVM app500m–1512Mi–2GiAllow headroom above
-Xmx
for JVM overhead
Sidecar10–50m32–64MiKeep minimal
yaml
undefined
yaml
resources:
  requests:       # Scheduler uses this to place the pod
    cpu: "100m"   # 100 millicores = 0.1 CPU
    memory: "128Mi"
  limits:         # Container is killed/throttled above this
    cpu: "500m"
    memory: "256Mi"
经验规则:
工作负载类型CPU请求内存请求说明
Web API100–250m128–256Mi限制值设为请求值的2-4倍
Worker/消费者250–500m256–512Mi内存限制与请求值一致以保证可预测性
JVM应用500m–1512Mi–2Gi为JVM预留超出
-Xmx
的内存空间
Sidecar10–50m32–64Mi保持最小配置
yaml
undefined

WRONG: No requests or limits — unpredictable scheduling, OOM evictions

WRONG: No requests or limits — unpredictable scheduling, OOM evictions

containers:
  • name: app image: myapp:latest

    Missing resources: {} — this is dangerous in production

containers:
  • name: app image: myapp:latest

    Missing resources: {} — this is dangerous in production

WRONG: Limits without requests — requests default to limits, over-reserves capacity

WRONG: Limits without requests — requests default to limits, over-reserves capacity

resources: limits: cpu: "2" memory: "1Gi"

requests missing — will default to limits values


---
resources: limits: cpu: "2" memory: "1Gi"

requests missing — will default to limits values


---

RBAC — Roles and ServiceAccounts

RBAC — 角色与ServiceAccount

Principle of Least Privilege

最小权限原则

Two patterns depending on whether the app calls the Kubernetes API:
根据应用是否调用Kubernetes API分为两种模式:

Pattern A — App does NOT need the Kubernetes API (most apps)

模式A — 应用无需调用Kubernetes API(大多数应用)

Disable token automounting on the ServiceAccount. The Role/RoleBinding are not needed.
yaml
undefined
禁用ServiceAccount的令牌自动挂载。无需配置Role/RoleBinding。
yaml
undefined

ServiceAccount with token disabled — safest default

ServiceAccount with token disabled — safest default

apiVersion: v1 kind: ServiceAccount metadata: name: my-app-sa namespace: my-namespace automountServiceAccountToken: false # No K8s API token injected into pods

```yaml
apiVersion: v1 kind: ServiceAccount metadata: name: my-app-sa namespace: my-namespace automountServiceAccountToken: false # No K8s API token injected into pods

```yaml

Reference in Deployment — no token, no API access

Reference in Deployment — no token, no API access

spec: template: spec: serviceAccountName: my-app-sa automountServiceAccountToken: false # Belt-and-suspenders: also set at pod level
undefined
spec: template: spec: serviceAccountName: my-app-sa automountServiceAccountToken: false # Belt-and-suspenders: also set at pod level
undefined

Pattern B — App DOES need the Kubernetes API (operators, controllers, config watchers)

模式B — 应用需要调用Kubernetes API(Operator、控制器、配置监听器)

Enable the token and grant only the permissions actually required.
yaml
undefined
启用令牌并仅授予实际需要的权限。
yaml
undefined

1. ServiceAccount — enable token for this SA

1. ServiceAccount — enable token for this SA

apiVersion: v1 kind: ServiceAccount metadata: name: my-app-sa namespace: my-namespace automountServiceAccountToken: true # Token required: app calls K8s API

```yaml
apiVersion: v1 kind: ServiceAccount metadata: name: my-app-sa namespace: my-namespace automountServiceAccountToken: true # Token required: app calls K8s API

```yaml

2. Role — grant only what the app needs (namespace-scoped)

2. Role — grant only what the app needs (namespace-scoped)

apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: my-app-role namespace: my-namespace rules:
  • apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list", "watch"] # Read-only, specific resource
  • apiGroups: [""] resources: ["secrets"] resourceNames: ["my-app-secrets"] # Restrict to specific secret by name verbs: ["get"]

```yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: my-app-role namespace: my-namespace rules:
  • apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list", "watch"] # Read-only, specific resource
  • apiGroups: [""] resources: ["secrets"] resourceNames: ["my-app-secrets"] # Restrict to specific secret by name verbs: ["get"]

```yaml

3. Bind Role to ServiceAccount

3. Bind Role to ServiceAccount

apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: my-app-rolebinding namespace: my-namespace subjects:
  • kind: ServiceAccount name: my-app-sa namespace: my-namespace roleRef: kind: Role apiGroup: rbac.authorization.k8s.io name: my-app-role

```yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: my-app-rolebinding namespace: my-namespace subjects:
  • kind: ServiceAccount name: my-app-sa namespace: my-namespace roleRef: kind: Role apiGroup: rbac.authorization.k8s.io name: my-app-role

```yaml

4. Reference SA in Deployment

4. Reference SA in Deployment

spec: template: spec: serviceAccountName: my-app-sa # automountServiceAccountToken defaults to true from SA — token is injected

---
spec: template: spec: serviceAccountName: my-app-sa # automountServiceAccountToken defaults to true from SA — token is injected

---

Horizontal Pod Autoscaler (HPA)

Horizontal Pod Autoscaler (HPA)

yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
  namespace: my-namespace
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 2      # Always at least 2 for HA
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70    # Scale up when avg CPU > 70%
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
HPA requires
resources.requests
to be set on all containers — it calculates utilization as
current / request
.

yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
  namespace: my-namespace
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 2      # Always at least 2 for HA
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70    # Scale up when avg CPU > 70%
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
HPA要求所有容器都设置
resources.requests
— 它通过
当前值 / 请求值
计算资源使用率。

PodDisruptionBudget (PDB)

PodDisruptionBudget (PDB)

Prevent too many pods going down during node drains or rolling updates:
yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
  namespace: my-namespace
spec:
  minAvailable: 2           # OR use maxUnavailable: 1
  selector:
    matchLabels:
      app: my-app

防止节点排空或滚动更新期间过多Pod下线:
yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
  namespace: my-namespace
spec:
  minAvailable: 2           # OR use maxUnavailable: 1
  selector:
    matchLabels:
      app: my-app

Namespaces and Multi-Tenancy

命名空间与多租户

bash
undefined
bash
undefined

Create namespace with resource quotas

Create namespace with resource quotas

kubectl create namespace my-namespace
kubectl create namespace my-namespace

Apply ResourceQuota to limit namespace consumption

Apply ResourceQuota to limit namespace consumption

kubectl apply -f - <<EOF apiVersion: v1 kind: ResourceQuota metadata: name: my-namespace-quota namespace: my-namespace spec: hard: requests.cpu: "4" requests.memory: 4Gi limits.cpu: "8" limits.memory: 8Gi pods: "20" EOF

---
kubectl apply -f - <<EOF apiVersion: v1 kind: ResourceQuota metadata: name: my-namespace-quota namespace: my-namespace spec: hard: requests.cpu: "4" requests.memory: 4Gi limits.cpu: "8" limits.memory: 8Gi pods: "20" EOF

---

Jobs and CronJobs

Jobs与CronJobs

yaml
undefined
yaml
undefined

One-off Job (DB migration, data processing)

One-off Job (DB migration, data processing)

apiVersion: batch/v1 kind: Job metadata: name: db-migrate namespace: my-namespace spec: backoffLimit: 3 # Retry up to 3 times on failure ttlSecondsAfterFinished: 3600 # Auto-delete after 1h template: spec: restartPolicy: OnFailure # Never for Jobs (not Always) containers: - name: migrate image: ghcr.io/org/my-app:1.0.0 command: ["python", "manage.py", "migrate"] resources: requests: cpu: "100m" memory: "256Mi"

```yaml
apiVersion: batch/v1 kind: Job metadata: name: db-migrate namespace: my-namespace spec: backoffLimit: 3 # Retry up to 3 times on failure ttlSecondsAfterFinished: 3600 # Auto-delete after 1h template: spec: restartPolicy: OnFailure # Never for Jobs (not Always) containers: - name: migrate image: ghcr.io/org/my-app:1.0.0 command: ["python", "manage.py", "migrate"] resources: requests: cpu: "100m" memory: "256Mi"

```yaml

CronJob

CronJob

apiVersion: batch/v1 kind: CronJob metadata: name: cleanup-job namespace: my-namespace spec: schedule: "0 2 * * *" # 2am daily concurrencyPolicy: Forbid # Don't run if previous still running successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 1 jobTemplate: spec: template: spec: restartPolicy: OnFailure containers: - name: cleanup image: ghcr.io/org/cleanup:1.0.0 resources: requests: cpu: "50m" memory: "64Mi"

---
apiVersion: batch/v1 kind: CronJob metadata: name: cleanup-job namespace: my-namespace spec: schedule: "0 2 * * *" # 2am daily concurrencyPolicy: Forbid # Don't run if previous still running successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 1 jobTemplate: spec: template: spec: restartPolicy: OnFailure containers: - name: cleanup image: ghcr.io/org/cleanup:1.0.0 resources: requests: cpu: "50m" memory: "64Mi"

---

kubectl Debugging Cheatsheet

kubectl调试速查表

bash
undefined
bash
undefined

--- Pod status and logs ---

--- Pod status and logs ---

kubectl get pods -n my-namespace kubectl get pods -n my-namespace -o wide # Show node assignment kubectl describe pod <pod-name> -n my-namespace # Events and state details kubectl logs <pod-name> -n my-namespace # Current logs kubectl logs <pod-name> -n my-namespace --previous # Logs from crashed container kubectl logs <pod-name> -n my-namespace -c <container> # Multi-container pod
kubectl get pods -n my-namespace kubectl get pods -n my-namespace -o wide # Show node assignment kubectl describe pod <pod-name> -n my-namespace # Events and state details kubectl logs <pod-name> -n my-namespace # Current logs kubectl logs <pod-name> -n my-namespace --previous # Logs from crashed container kubectl logs <pod-name> -n my-namespace -c <container> # Multi-container pod

--- Execute into a running container ---

--- Execute into a running container ---

kubectl exec -it <pod-name> -n my-namespace -- sh kubectl exec -it <pod-name> -n my-namespace -- bash
kubectl exec -it <pod-name> -n my-namespace -- sh kubectl exec -it <pod-name> -n my-namespace -- bash

--- Check resource usage ---

--- Check resource usage ---

kubectl top pods -n my-namespace kubectl top nodes
kubectl top pods -n my-namespace kubectl top nodes

--- Deployment operations ---

--- Deployment operations ---

kubectl rollout status deployment/my-app -n my-namespace kubectl rollout history deployment/my-app -n my-namespace kubectl rollout undo deployment/my-app -n my-namespace # Rollback kubectl rollout undo deployment/my-app --to-revision=2 -n my-namespace
kubectl rollout status deployment/my-app -n my-namespace kubectl rollout history deployment/my-app -n my-namespace kubectl rollout undo deployment/my-app -n my-namespace # Rollback kubectl rollout undo deployment/my-app --to-revision=2 -n my-namespace

--- Scale manually ---

--- Scale manually ---

kubectl scale deployment my-app --replicas=5 -n my-namespace
kubectl scale deployment my-app --replicas=5 -n my-namespace

--- Inspect events (cluster-wide issues) ---

--- Inspect events (cluster-wide issues) ---

kubectl get events -n my-namespace --sort-by='.lastTimestamp'
kubectl get events -n my-namespace --sort-by='.lastTimestamp'

--- Port-forward for local debugging ---

--- Port-forward for local debugging ---

kubectl port-forward pod/<pod-name> 8080:8080 -n my-namespace kubectl port-forward svc/my-app 8080:80 -n my-namespace
kubectl port-forward pod/<pod-name> 8080:8080 -n my-namespace kubectl port-forward svc/my-app 8080:80 -n my-namespace

--- Dry-run to validate YAML ---

--- Dry-run to validate YAML ---

kubectl apply -f deployment.yaml --dry-run=client kubectl apply -f deployment.yaml --dry-run=server # Validates against live cluster
undefined
kubectl apply -f deployment.yaml --dry-run=client kubectl apply -f deployment.yaml --dry-run=server # Validates against live cluster
undefined

Diagnosing Common Errors

常见错误诊断

bash
undefined
bash
undefined

CrashLoopBackOff: container keeps crashing

CrashLoopBackOff: container keeps crashing

kubectl logs <pod-name> --previous -n my-namespace # Check crash logs kubectl describe pod <pod-name> -n my-namespace # Check exit code & OOMKilled
kubectl logs <pod-name> --previous -n my-namespace # Check crash logs kubectl describe pod <pod-name> -n my-namespace # Check exit code & OOMKilled

ImagePullBackOff: can't pull image

ImagePullBackOff: can't pull image

kubectl describe pod <pod-name> -n my-namespace # Check Events section
kubectl describe pod <pod-name> -n my-namespace # Check Events section

Causes: wrong image tag, missing imagePullSecret, private registry

Causes: wrong image tag, missing imagePullSecret, private registry

Pending pod: not scheduled

Pending pod: not scheduled

kubectl describe pod <pod-name> -n my-namespace
kubectl describe pod <pod-name> -n my-namespace

Causes: insufficient resources, no matching node selector, taint/toleration mismatch

Causes: insufficient resources, no matching node selector, taint/toleration mismatch

OOMKilled: out of memory

OOMKilled: out of memory

Increase memory limits, check for memory leaks

Increase memory limits, check for memory leaks

kubectl describe pod <pod-name> -n my-namespace | grep -A5 "Last State"

---
kubectl describe pod <pod-name> -n my-namespace | grep -A5 "Last State"

---

Anti-Patterns

反模式

yaml
undefined
yaml
undefined

BAD: Using :latest tag — non-deterministic deployments

BAD: Using :latest tag — non-deterministic deployments

image: myapp:latest
image: myapp:latest

GOOD: Pin to a specific immutable tag (SHA or semver)

GOOD: Pin to a specific immutable tag (SHA or semver)

image: ghcr.io/org/myapp:1.4.2
image: ghcr.io/org/myapp:1.4.2

or

or

image: ghcr.io/org/myapp@sha256:abc123...
image: ghcr.io/org/myapp@sha256:abc123...

---

---

BAD: Running as root

BAD: Running as root

securityContext: {} # Defaults to root
securityContext: {} # Defaults to root

GOOD: Non-root with explicit UID

GOOD: Non-root with explicit UID

securityContext: runAsNonRoot: true runAsUser: 1001
securityContext: runAsNonRoot: true runAsUser: 1001

---

---

BAD: No resource limits — one pod can starve the entire node

BAD: No resource limits — one pod can starve the entire node

containers:
  • name: app image: myapp:1.0.0

    No resources defined

containers:
  • name: app image: myapp:1.0.0

    No resources defined

GOOD: Always set requests and limits

GOOD: Always set requests and limits

resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "500m" memory: "256Mi"
resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "500m" memory: "256Mi"

---

---

BAD: Storing plaintext secrets in ConfigMaps

BAD: Storing plaintext secrets in ConfigMaps

apiVersion: v1 kind: ConfigMap data: DB_PASSWORD: "mysecretpassword" # NEVER — use Secret or external secrets manager
apiVersion: v1 kind: ConfigMap data: DB_PASSWORD: "mysecretpassword" # NEVER — use Secret or external secrets manager

---

---

BAD: ClusterAdmin for application service accounts

BAD: ClusterAdmin for application service accounts

apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding roleRef: kind: ClusterRole name: cluster-admin # Grants god-mode to your app
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding roleRef: kind: ClusterRole name: cluster-admin # Grants god-mode to your app

---

---

BAD: minAvailable: 0 in PDB — defeats the purpose

BAD: minAvailable: 0 in PDB — defeats the purpose

spec: minAvailable: 0
spec: minAvailable: 0

---

---

BAD: restartPolicy: Always in a Job (causes infinite restart loop)

BAD: restartPolicy: Always in a Job (causes infinite restart loop)

spec: restartPolicy: Always # Use OnFailure or Never for Jobs

---
spec: restartPolicy: Always # Use OnFailure or Never for Jobs

---

Best Practices Checklist

最佳实践检查清单

Security

安全性

  • Container runs as non-root (
    runAsNonRoot: true
    ,
    runAsUser
    set)
  • readOnlyRootFilesystem: true
    with
    emptyDir
    for writable paths
  • allowPrivilegeEscalation: false
  • All capabilities dropped (
    capabilities.drop: [ALL]
    )
  • Dedicated ServiceAccount per app, not
    default
  • automountServiceAccountToken: false
    unless needed
  • RBAC follows least privilege (use
    Role
    , not
    ClusterRole
    unless needed)
  • Secrets managed via Sealed Secrets or External Secrets Operator
  • 容器以非root用户运行(设置
    runAsNonRoot: true
    runAsUser
  • 启用
    readOnlyRootFilesystem: true
    并为可写路径配置
    emptyDir
  • 设置
    allowPrivilegeEscalation: false
  • 移除所有权限(
    capabilities.drop: [ALL]
  • 每个应用使用独立的ServiceAccount,而非
    default
  • 除非必要,禁用
    automountServiceAccountToken
  • RBAC遵循最小权限原则(使用
    Role
    而非
    ClusterRole
    ,除非必要)
  • 通过Sealed Secrets或External Secrets Operator管理密钥

Reliability

可靠性

  • All 3 probe types configured (startup + liveness + readiness)
  • Resource requests AND limits set on every container
  • minReplicas: 2+
    for any production workload
  • PodDisruptionBudget defined for stateful or critical services
  • RollingUpdate
    strategy with
    maxUnavailable: 0
  • HPA configured for variable-load services
  • 配置三种探针类型(启动+存活+就绪)
  • 每个容器都设置资源请求与限制
  • 生产级工作负载的
    minReplicas: 2+
  • 为有状态或关键服务定义PodDisruptionBudget
  • 配置
    RollingUpdate
    策略并设置
    maxUnavailable: 0
  • 为可变负载服务配置HPA

Observability

可观测性

  • App exposes
    /health
    (liveness) and
    /ready
    (readiness) endpoints
  • Structured JSON logging (no PII in logs)
  • Resource labels:
    app
    ,
    version
    ,
    environment

  • 应用暴露
    /health
    (存活)和
    /ready
    (就绪)端点
  • 使用结构化JSON日志(日志中不包含PII)
  • 设置资源标签:
    app
    version
    environment

Related Skills

相关技能

  • docker-patterns
    — Multi-stage Dockerfiles and image security
  • deployment-patterns
    — CI/CD pipelines, rollback strategy, health check endpoints
  • security-review
    — Broader security hardening context
  • git-workflow
    — GitOps integration with K8s (ArgoCD / Flux patterns)
  • docker-patterns
    — 多阶段Dockerfile与镜像安全
  • deployment-patterns
    — CI/CD流水线、回滚策略、健康检查端点
  • security-review
    — 更全面的安全加固上下文
  • git-workflow
    — K8s与GitOps的集成(ArgoCD / Flux模式)