返回全部 Skills

kubernetes-patterns

开发工具

Kubernetes工作负载模式、资源管理、RBAC、探针、自动扩缩、ConfigMap/Secret处理,以及面向生产级部署的kubectl调试。

25

下载量

AI SkillHub 能力展示图

安装方式

命令行安装

在项目根目录执行以下命令,完成 Skill 安装。

npx bzskills add affaan-m/everything-claude-code --skill kubernetes-patterns

skill.md

name: kubernetes-patterns
description: Kubernetes工作负载模式、资源管理、RBAC、探针、自动扩缩、ConfigMap/Secret处理,以及面向生产级部署的kubectl调试。
metadata:
    origin: ECC

Kubernetes 模式

用于可靠部署、管理和调试工作负载的生产级 Kubernetes 模式。

何时激活

  • 编写 Kubernetes 清单(Deployment、Service、Ingress、Job)
  • 配置资源请求/限制、存活/就绪探针
  • 设置 RBAC、命名空间或 ServiceAccount
  • 管理 Kubernetes 中的配置和密钥
  • 调试 CrashLoopBackOff、OOMKilled、Pending Pod 或镜像拉取错误
  • 配置 HPA(水平 Pod 自动缩放器)或 PodDisruptionBudget
  • 审查 Kubernetes YAML 的安全性或正确性

何时使用

与上面的 何时激活 相同。此别名满足仓库技能格式约定。在编写、审查或调试 Kubernetes YAML 和工作负载时,随时使用此技能。

工作原理

此技能提供可直接复制粘贴的生产级 YAML 模式kubectl 调试命令,按任务组织:

  1. Deployment 模板 — 一个完全配置的生产级 Deployment,包含安全上下文、滚动更新策略、所有三种探针类型、资源限制以及从 ConfigMap/Secret 注入环境变量。
  2. 探针 — startup 与 liveness 与 readiness 的决策表,附带正确的 failureThreshold × periodSeconds 计算。
  3. Service 和 Ingress — ClusterIP、LoadBalancer 和带 cert-manager 注解的 TLS Ingress 模式。
  4. ConfigMap 和 SecretenvFrom、文件挂载和外部密钥指导。
  5. 资源管理 — 按工作负载类型(Web API、JVM、Worker、Sidecar)的请求与限制经验法则。
  6. RBAC — 最小权限 ServiceAccount → Role → RoleBinding 链。
  7. HPA 和 PDB — 自动缩放和节点排空安全配置。
  8. Job 和 CronJob — 一次性工作负载和定时工作负载模式,带有正确的 restartPolicy
  9. kubectl 速查表 — 日志、exec、回滚、端口转发、dry-run 和常见错误诊断命令。
  10. 反模式和检查清单 — 不该做什么,以及安全/可靠性/可观测性检查清单。

示例

请参阅下面的章节获取完整的可运行示例。快速参考:

任务跳转到
完整的生产级 Deployment YAML核心工作负载模式
探针配置探针
RBAC 最小权限设置RBAC
调试 CrashLoopBackOffkubectl 调试速查表
自动缩放HPA

---

核心工作负载模式

Deployment — 生产模板

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          # 更新期间允许额外 1 个 Pod
      maxUnavailable: 0    # 绝不低于期望数量
  template:
    metadata:
      labels:
        app: my-app
        version: "1.0.0"
    spec:
      # Pod 级别的安全上下文
      securityContext:
        runAsNonRoot: true
        runAsUser: 1001
        fsGroup: 1001

      # 优雅关闭
      terminationGracePeriodSeconds: 30

      containers:
        - name: my-app
          image: ghcr.io/org/my-app:1.0.0   # 绝不使用 :latest
          imagePullPolicy: IfNotPresent

          ports:
            - containerPort: 8080
              protocol: TCP

          # 资源请求和限制都需要
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "256Mi"

          # 容器安全上下文
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL

          # 探针(见下方探针部分)
          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

          # 从 ConfigMap 和 Secret 注入环境变量
          envFrom:
            - configMapRef:
                name: my-app-config
          env:
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: my-app-secrets
                  key: db-password

          # 当 readOnlyRootFilesystem: true 时需要可写 tmp 目录
          volumeMounts:
            - name: tmp
              mountPath: /tmp

      volumes:
        - name: tmp
          emptyDir: {}

---

探针 — Liveness、Readiness、Startup

理解何时使用每种探针至关重要:

探针失败时的操作用途
startupProbe如果启动慢则终止容器启动缓慢的应用(JVM、Python)
livenessProbe重启容器检测死锁/挂起进程
readinessProbe从 Service 端点移除临时不可用(数据库重连)
# 正确模式:startupProbe 覆盖慢启动,
# 然后 liveness/readiness 接管
startupProbe:
  httpGet:
    path: /health
    port: 8080
  failureThreshold: 30  # 30 * 5s = 150s 最大启动时间
  periodSeconds: 5

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  periodSeconds: 30
  failureThreshold: 3   # 3 * 30s = 90s 后重启

readinessProbe:
  httpGet:
    path: /ready         # 单独的端点:检查数据库、缓存等
    port: 8080
  periodSeconds: 10
  failureThreshold: 2
# 错误:不带 startupProbe 使用 initialDelaySeconds
# 如果应用需要 60 秒启动,应改用 startupProbe
livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 60   # 不好:任意等待,存在竞态条件

---

Service 和 Ingress

Service 类型

# ClusterIP(默认)— 仅内部
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
# LoadBalancer — 外部流量(云提供商)
spec:
  type: LoadBalancer
  ports:
    - port: 443
      targetPort: 8080

带 TLS 的 Ingress

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

---

ConfigMap 和 Secret

ConfigMap — 非敏感配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app-config
  namespace: my-namespace
data:
  LOG_LEVEL: "info"
  APP_ENV: "production"
  MAX_CONNECTIONS: "100"
  # 作为文件挂载以支持复杂配置
  app.yaml: |
    server:
      port: 8080
      timeout: 30s
# 将 ConfigMap 作为文件挂载
volumes:
  - name: config
    configMap:
      name: my-app-config
      items:
        - key: app.yaml
          path: app.yaml
volumeMounts:
  - name: config
    mountPath: /etc/app
    readOnly: true

Secret — 敏感数据

# 从字面值创建 Secret(CLI 方式,然后存储在 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 -
apiVersion: v1
kind: Secret
metadata:
  name: my-app-secrets
  namespace: my-namespace
type: Opaque
# 值为 base64 编码(未加密——对于真正的加密请使用 Sealed Secrets 或 ESO)
data:
  db-password: czNjcjN0  # 's3cr3t' 的 base64
重要: 原生 Kubernetes Secret 仅经过 base64 编码,除非集群配置了静态加密,否则不会加密存储。对于生产环境,使用 Sealed SecretsExternal Secrets Operator

---

资源请求和限制

resources:
  requests:       # 调度器根据此值放置 Pod
    cpu: "100m"   # 100 毫核 = 0.1 CPU
    memory: "128Mi"
  limits:         # 超过此值时容器会被终止/限流
    cpu: "500m"
    memory: "256Mi"

经验法则:

工作负载类型CPU 请求内存请求说明
Web API100–250m128–256Mi限制设为请求的 2-4 倍
Worker/消费者250–500m256–512Mi为可预测性,内存限制等于请求
JVM 应用500m–1512Mi–2Gi为 JVM 开销在 -Xmx 之上留出空间
Sidecar10–50m32–64Mi保持最小
# 错误:没有设置请求或限制 —— 不可预测的调度,OOM 驱逐
containers:
  - name: app
    image: myapp:latest
    # 缺少 resources: {} —— 生产环境中很危险

# 错误:有限制但没有请求 —— 请求默认等于限制,过度预留容量
resources:
  limits:
    cpu: "2"
    memory: "1Gi"
  # 缺少 requests —— 将默认使用限制值

---

RBAC — 角色和 ServiceAccount

最小权限原则

两种模式,取决于应用是否调用 Kubernetes API:

#### 模式 A — 应用不需要 Kubernetes API(大多数应用)

在 ServiceAccount 上禁用令牌自动挂载。不需要 Role/RoleBinding。

# 禁用令牌的 ServiceAccount —— 最安全默认值
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: my-namespace
automountServiceAccountToken: false   # 不会向 Pod 注入 K8s API 令牌
# 在 Deployment 中引用 —— 无令牌,无 API 访问
spec:
  template:
    spec:
      serviceAccountName: my-app-sa
      automountServiceAccountToken: false   # 双重保险:也在 Pod 级别设置

#### 模式 B — 应用确实需要 Kubernetes API(operator、controller、配置监视器)

启用令牌并仅授予实际需要的权限。

# 1. ServiceAccount —— 为此 SA 启用令牌
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: my-namespace
automountServiceAccountToken: true    # 需要令牌:应用调用 K8s API
# 2. Role —— 仅授予应用需要的权限(命名空间作用域)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: my-app-role
  namespace: my-namespace
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list", "watch"]    # 只读,特定资源
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["my-app-secrets"]  # 按名称限制到特定 secret
    verbs: ["get"]
# 3. 将 Role 绑定到 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
# 4. 在 Deployment 中引用 SA
spec:
  template:
    spec:
      serviceAccountName: my-app-sa
      # automountServiceAccountToken 默认为 SA 中的 true —— 令牌被注入

---

水平 Pod 自动缩放器 (HPA)

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      # 高可用至少 2 副本
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70    # 当平均 CPU > 70% 时扩容
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
HPA 要求所有容器设置 resources.requests —— 它计算利用率为 当前值 / 请求值

---

PodDisruptionBudget (PDB)

防止在节点排空或滚动更新期间过多 Pod 下线:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
  namespace: my-namespace
spec:
  minAvailable: 2           # 或者使用 maxUnavailable: 1
  selector:
    matchLabels:
      app: my-app

---

命名空间和多租户

# 创建带资源配额的命名空间
kubectl create namespace my-namespace

# 应用 ResourceQuota 限制命名空间消耗
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

---

Job 和 CronJob

# 一次性 Job(数据库迁移、数据处理)
apiVersion: batch/v1
kind: Job
metadata:
  name: db-migrate
  namespace: my-namespace
spec:
  backoffLimit: 3          # 失败时最多重试 3 次
  ttlSecondsAfterFinished: 3600   # 1 小时后自动删除
  template:
    spec:
      restartPolicy: OnFailure    # Job 使用 Never(不是 Always)
      containers:
        - name: migrate
          image: ghcr.io/org/my-app:1.0.0
          command: ["python", "manage.py", "migrate"]
          resources:
            requests:
              cpu: "100m"
              memory: "256Mi"
# CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cleanup-job
  namespace: my-namespace
spec:
  schedule: "0 2 * * *"         # 每天凌晨 2 点
  concurrencyPolicy: Forbid      # 如果上一个仍在运行则不运行
  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 调试速查表

# --- Pod 状态和日志 ---
kubectl get pods -n my-namespace
kubectl get pods -n my-namespace -o wide          # 显示节点分配
kubectl describe pod <pod-name> -n my-namespace   # 事件和状态详情
kubectl logs <pod-name> -n my-namespace           # 当前日志
kubectl logs <pod-name> -n my-namespace --previous  # 崩溃容器的日志
kubectl logs <pod-name> -n my-namespace -c <container>  # 多容器 Pod

# --- 进入运行中的容器 ---
kubectl exec -it <pod-name> -n my-namespace -- sh
kubectl exec -it <pod-name> -n my-namespace -- bash

# --- 检查资源使用 ---
kubectl top pods -n my-namespace
kubectl top nodes

# --- Deployment 操作 ---
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      # 回滚
kubectl rollout undo deployment/my-app --to-revision=2 -n my-namespace

# --- 手动缩放 ---
kubectl scale deployment my-app --replicas=5 -n my-namespace

# --- 检查事件(集群范围的问题) ---
kubectl get events -n my-namespace --sort-by='.lastTimestamp'

# --- 端口转发用于本地调试 ---
kubectl port-forward pod/<pod-name> 8080:8080 -n my-namespace
kubectl port-forward svc/my-app 8080:80 -n my-namespace

# --- 通过 Dry-run 验证 YAML ---
kubectl apply -f deployment.yaml --dry-run=client
kubectl apply -f deployment.yaml --dry-run=server   # 针对实时集群验证

诊断常见错误

# CrashLoopBackOff:容器不断崩溃
kubectl logs <pod-name> --previous -n my-namespace  # 检查崩溃日志
kubectl describe pod <pod-name> -n my-namespace     # 检查退出码和 OOMKilled

# ImagePullBackOff:无法拉取镜像
kubectl describe pod <pod-name> -n my-namespace     # 检查 Events 部分
# 原因:镜像标签错误,缺少 imagePullSecret,私有仓库

# Pending pod:未调度
kubectl describe pod <pod-name> -n my-namespace
# 原因:资源不足,没有匹配的节点选择器,污点/容忍不匹配

# OOMKilled:内存不足
# 增加内存限制,检查内存泄漏
kubectl describe pod <pod-name> -n my-namespace | grep -A5 "Last State"

---

反模式

# 错误:使用 :latest 标签 —— 不可确定的部署
image: myapp:latest

# 正确:固定到特定的不可变标签(SHA 或 semver)
image: ghcr.io/org/myapp:1.4.2
# 或
image: ghcr.io/org/myapp@sha256:abc123...

# ---

# 错误:以 root 身份运行
securityContext: {}    # 默认 root

# 正确:非 root 并指定 UID
securityContext:
  runAsNonRoot: true
  runAsUser: 1001

# ---

# 错误:没有资源限制 —— 一个 Pod 可能饿死整个节点
containers:
  - name: app
    image: myapp:1.0.0
    # 未定义资源

# 正确:始终设置请求和限制
resources:
  requests:
    cpu: "100m"
    memory: "128Mi"
  limits:
    cpu: "500m"
    memory: "256Mi"

# ---

# 错误:在 ConfigMap 中存储明文密钥
apiVersion: v1
kind: ConfigMap
data:
  DB_PASSWORD: "mysecretpassword"   # 绝对不要 —— 应使用 Secret 或外部密钥管理器

# ---

# 错误:为应用 ServiceAccount 使用 ClusterAdmin
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
roleRef:
  kind: ClusterRole
  name: cluster-admin    # 为应用授予 God 模式

# ---

# 错误:PDB 中 minAvailable: 0 —— 违背目的
spec:
  minAvailable: 0

# ---

# 错误:Job 中使用 restartPolicy: Always(导致无限重启循环)
spec:
  restartPolicy: Always   # Job 应使用 OnFailure 或 Never

---

最佳实践检查清单

安全

  • [ ] 容器以非 root 运行 (runAsNonRoot: true,设置 runAsUser)
  • [ ] readOnlyRootFilesystem: true,配合 emptyDir 用于可写路径
  • [ ] allowPrivilegeEscalation: false
  • [ ] 删除所有 capabilities (capabilities.drop: [ALL])
  • [ ] 每个应用使用专用的 ServiceAccount,而非 default
  • [ ] 除非必要,设置 automountServiceAccountToken: false
  • [ ] RBAC 遵循最小权限(使用 Role,除非需要否则不用 ClusterRole
  • [ ] 通过 Sealed Secrets 或 External Secrets Operator 管理 Secret

可靠性

  • [ ] 配置所有 3 种探针类型 (startup + liveness + readiness)
  • [ ] 每个容器都设置资源请求和限制
  • [ ] 生产工作负载 minReplicas: 2+
  • [ ] 为有状态或关键服务定义 PodDisruptionBudget
  • [ ] RollingUpdate 策略,maxUnavailable: 0
  • [ ] 为负载可变的服务配置 HPA

可观测性

  • [ ] 应用暴露 /health(liveness)和 /ready(readiness)端点
  • [ ] 结构化 JSON 日志(日志中不包含 PII)
  • [ ] 资源标签:appversionenvironment

---

相关技能

  • docker-patterns — 多阶段 Dockerfile 和镜像安全
  • deployment-patterns — CI/CD 流水线、回滚策略、健康检查端点
  • security-review — 更广泛的安全加固上下文
  • git-workflow — 与 Kubernetes 的 GitOps 集成 (ArgoCD / Flux 模式)