32f - DevOps Steering 规则与反模式
本文是《AI Agent 实战手册》第 32 章第 6 节。 上一节:32e-AI辅助监控与事件响应 | 下一节:33a-AI辅助移动端开发概览
概述
AI 编码助手正在深刻改变 DevOps 工程师的日常工作——从 Terraform 模块到 Kubernetes manifests,从 CI/CD 管线到监控配置,AI 可以在几秒内生成看似完美的基础设施代码。然而,2025 年的多项研究表明,AI 生成的基础设施代码中约 40-60% 存在安全或运维隐患:宽松的安全组规则(0.0.0.0/0 入站)、过度配置的资源(浪费 60% 以上的云预算)、缺失的健康检查(导致僵尸 Pod 无法自愈)、硬编码的密钥(直接暴露在 Git 历史中)。Steering 规则是解决这些问题的系统化方案:通过在 CLAUDE.md、Kiro Steering 和 Cursor Rules 中注入 DevOps 安全与运维约束,让 AI 在生成基础设施代码时自动遵循最佳实践。本节覆盖完整的 DevOps Steering 规则模板、十大 DevOps 反模式的识别与修复、CI/CD 管线安全、IaC 安全、容器与 Kubernetes 反模式,以及监控告警反模式。
1. DevOps Steering 规则概述
1.1 为什么 DevOps 需要专用 Steering 规则
AI 在生成 DevOps 配置时面临独特的挑战,与生成应用代码的问题截然不同:
- 安全默认值缺失:AI 倾向于生成”能工作”的配置,而非”安全的”配置——安全组默认开放所有端口、数据库默认无加密、密钥直接写在配置文件中
- 资源过度配置:AI 缺乏成本意识,倾向于分配过多的 CPU、内存和存储,导致云账单膨胀
- 运维可观测性不足:AI 生成的服务通常缺少健康检查、结构化日志、指标暴露等运维必需品
- 灾难恢复盲区:AI 很少主动考虑备份策略、故障转移、数据恢复等灾难恢复需求
- 环境差异忽视:AI 生成的配置通常不区分开发/测试/生产环境,导致生产环境使用开发级别的安全设置
- 合规性缺失:AI 不了解组织的合规要求(SOC 2、HIPAA、PCI DSS),生成的配置可能违反审计标准
- 密钥管理不当:AI 经常将 API 密钥、数据库密码等敏感信息直接写入配置文件或环境变量
- 网络隔离不足:AI 生成的网络配置通常过于扁平,缺少子网隔离、VPC 对等和网络策略
1.2 工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| Claude Code | Agentic 编码,CLAUDE.md DevOps 规则 | Max $100/月起(按 token 计费) | 复杂 IaC 生成与审查 |
| Kiro | Spec-Driven 开发,分层 Steering | 免费(预览期) | 需求→基础设施的全链路追溯 |
| Cursor | AI IDE,.cursorrules DevOps 规则 | 免费 / Pro $20/月 | 日常 DevOps 配置编写 |
| GitHub Copilot | IDE 内 YAML/HCL/JSON 补全 | Individual $10/月;Business $19/月 | 日常配置文件编写 |
| Checkov | IaC 静态安全扫描 | 免费(开源);Prisma Cloud 企业版联系销售 | Terraform/K8s/Docker 安全扫描 |
| tfsec / Trivy | Terraform / 容器安全扫描 | 免费(开源) | CI/CD 集成的安全门禁 |
| OPA / Rego | 策略即代码引擎 | 免费(开源) | 自定义合规策略执行 |
| Infracost | IaC 成本估算 | 免费(开源);Cloud $50/月起 | PR 级别的成本预览 |
| Snyk IaC | IaC 安全扫描与修复建议 | 免费层(有限额);Team $25/开发者/月 | 开发者友好的安全扫描 |
| GitGuardian | 密钥泄露检测 | 免费(公共仓库);Business $34/开发者/月 | Git 历史中的密钥扫描 |
| HashiCorp Vault | 密钥管理与动态凭证 | 免费(开源);HCP Vault $0.03/小时起 | 生产级密钥管理 |
| Terraform Sentinel | HashiCorp 策略即代码 | Terraform Cloud Team & Governance $20/用户/月起 | Terraform 专用策略执行 |
2. 完整 DevOps Steering 规则模板
2.1 CLAUDE.md DevOps 规则模板
以下是一个适用于云原生项目的完整 CLAUDE.md DevOps 规则模板:
# CLAUDE.md — DevOps 规则
## 基础设施技术栈
- IaC:Terraform 1.x + AWS Provider
- 容器:Docker + Kubernetes 1.30+
- CI/CD:GitHub Actions
- 监控:Prometheus + Grafana
- 日志:Loki / CloudWatch
- 密钥管理:AWS Secrets Manager / HashiCorp Vault
## DevOps 安全强制规则(最高优先级)
### 网络安全
- 禁止在安全组/防火墙规则中使用 0.0.0.0/0 作为入站源(除 80/443 的公共 ALB 外)
- 禁止在安全组中开放 22(SSH)或 3389(RDP)端口到公网
- 所有数据库必须部署在私有子网,禁止分配公网 IP
- 服务间通信必须使用安全组引用(security_group_id),禁止使用 CIDR 范围
- 所有 HTTPS 端点必须使用 TLS 1.2+,禁止 TLS 1.0/1.1
- Kubernetes 必须配置 NetworkPolicy,默认拒绝所有入站流量
### 密钥管理
- 禁止在任何配置文件、环境变量定义或代码中硬编码密钥、密码、Token
- 所有敏感值必须通过 Secrets Manager / Vault / Sealed Secrets 引用
- Terraform 中的敏感变量必须标记 sensitive = true
- Docker 构建禁止通过 ARG/ENV 传递密钥,必须使用 BuildKit secrets
- CI/CD 中的密钥必须使用平台原生的 secrets 机制(如 GitHub Secrets)
- 禁止在日志中输出任何密钥或 Token 值
### 资源配置
- 所有 Kubernetes 工作负载必须设置 resources.requests 和 resources.limits
- 禁止将 CPU limit 设置为超过 4 核(除非有明确的性能需求文档)
- 禁止将内存 limit 设置为超过 8Gi(除非有明确的性能需求文档)
- EC2/VM 实例类型必须与工作负载匹配,禁止默认使用大型实例
- 数据库实例必须使用合适的实例类型,开发环境使用最小规格
- 所有资源必须添加 cost-center 和 environment 标签
### 健康检查
- 所有 Kubernetes Pod 必须配置 livenessProbe 和 readinessProbe
- 长启动服务必须配置 startupProbe
- 健康检查端点必须检查关键依赖(数据库连接、缓存连接)
- livenessProbe 不应检查外部依赖(避免级联重启)
- readinessProbe 应检查服务是否真正可以处理请求
- Docker Compose 服务必须配置 healthcheck
### 日志与可观测性
- 所有服务必须使用结构化日志(JSON 格式)
- 日志必须包含:timestamp、level、service、trace_id、message
- 禁止使用 print/console.log 作为生产日志方式
- 所有 HTTP 服务必须暴露 /metrics 端点(Prometheus 格式)
- 关键业务操作必须记录审计日志
- 错误日志必须包含堆栈跟踪和上下文信息
### 备份与灾难恢复
- 所有数据库必须配置自动备份(至少每日一次)
- 备份必须存储在不同的区域/可用区
- 必须定义 RTO(恢复时间目标)和 RPO(恢复点目标)
- 有状态服务必须配置 PersistentVolumeClaim 的快照策略
- 关键配置必须版本化存储在 Git 中
- 备份恢复流程必须有文档化的运行手册
### CI/CD 安全
- GitHub Actions 必须固定 action 版本到 SHA(禁止使用 @latest 或 @v1)
- GITHUB_TOKEN 权限必须使用最小权限原则(permissions 字段显式声明)
- 禁止在 CI 日志中输出密钥或敏感信息
- 所有部署必须通过 CI/CD 管线,禁止手动 kubectl apply 到生产环境
- Docker 镜像必须使用特定版本标签,禁止使用 :latest
- 构建产物必须签名验证(Sigstore/cosign)2.2 Kiro Steering DevOps 规则模板
Kiro 的分层 Steering 机制允许按文件类型精确匹配 DevOps 规则:
Terraform 文件规则
---
inclusion: auto
globs: "**/*.tf,**/*.tfvars"
---
# Terraform Steering 规则
## 安全约束
- 安全组 ingress 规则禁止使用 cidr_blocks = ["0.0.0.0/0"](除公共 ALB 的 80/443 外)
- 所有 aws_db_instance 必须设置 storage_encrypted = true
- 所有 aws_s3_bucket 必须配置 server_side_encryption_configuration
- 所有 aws_s3_bucket 必须设置 block_public_access = true
- RDS 实例必须设置 deletion_protection = true(生产环境)
- 所有敏感变量必须标记 sensitive = true
## 资源管理
- 每个资源必须包含 tags 块,至少包含:Name、Environment、Team、CostCenter
- 使用 locals 块定义通用标签,避免重复
- 数据库实例类型必须通过变量控制,按环境区分
- 使用 terraform-aws-modules 官方模块,避免重复造轮子
## 状态管理
- 远程状态必须使用 S3 + DynamoDB 锁定
- 状态文件必须加密(encrypt = true)
- 禁止在本地存储 terraform.tfstate
## 代码组织
- 使用模块化结构:modules/ 目录存放可复用模块
- 每个环境使用独立的 tfvars 文件
- 输出值使用 output 块显式声明Kubernetes 文件规则
---
inclusion: auto
globs: "**/*.yaml,**/*.yml,**/k8s/**,**/kubernetes/**,**/manifests/**"
---
# Kubernetes Manifest Steering 规则
## Pod 安全
- 所有容器必须设置 securityContext.runAsNonRoot = true
- 所有容器必须设置 securityContext.readOnlyRootFilesystem = true(除非需要写入)
- 禁止设置 securityContext.privileged = true
- 禁止使用 hostNetwork、hostPID、hostIPC
- 镜像必须使用特定版本标签,禁止 :latest
- 镜像必须来自可信仓库(私有 ECR/GCR/ACR 或 Docker Official)
## 资源管理
- 所有容器必须设置 resources.requests 和 resources.limits
- requests 和 limits 的比例不应超过 1:2
- 使用 LimitRange 和 ResourceQuota 限制命名空间资源
## 健康检查
- 所有 Deployment/StatefulSet 的容器必须配置 livenessProbe
- 所有 Deployment/StatefulSet 的容器必须配置 readinessProbe
- 启动时间超过 30 秒的服务必须配置 startupProbe
- Probe 的 initialDelaySeconds 必须合理设置
## 网络
- 每个命名空间必须有默认的 deny-all NetworkPolicy
- Service 类型禁止使用 NodePort(生产环境),使用 ClusterIP + Ingress
- Ingress 必须配置 TLS 终止Dockerfile 规则
---
inclusion: auto
globs: "**/Dockerfile,**/Dockerfile.*,**/*.dockerfile"
---
# Dockerfile Steering 规则
## 安全
- 必须使用多阶段构建,最终镜像使用 distroless 或 alpine
- 禁止使用 root 用户运行应用(必须有 USER 指令)
- 禁止通过 ARG 或 ENV 传递密钥
- 基础镜像必须使用特定版本标签(如 node:20.18-alpine),禁止 :latest
- 禁止安装不必要的包(如 vim、curl、wget 等调试工具在生产镜像中)
## 优化
- 合理排列 COPY 指令顺序,利用构建缓存(依赖文件先复制)
- 使用 .dockerignore 排除不必要的文件
- 最终镜像大小应控制在合理范围内(Go < 50MB,Node.js < 200MB,Python < 300MB)
- 使用 HEALTHCHECK 指令定义健康检查
## 最佳实践
- 每个 RUN 指令合并相关命令,减少层数
- 使用 COPY 而非 ADD(除非需要解压)
- 设置合理的 EXPOSE 端口
- 使用 ENTRYPOINT + CMD 组合CI/CD 文件规则
---
inclusion: auto
globs: "**/.github/workflows/*.yml,**/.github/workflows/*.yaml,**/.gitlab-ci.yml"
---
# CI/CD Pipeline Steering 规则
## 安全
- GitHub Actions 必须固定到 commit SHA:uses: actions/checkout@<sha>
- 禁止使用 @latest、@main、@master 引用 action
- GITHUB_TOKEN 必须显式声明最小权限:
permissions:
contents: read
pull-requests: write
- 密钥必须使用 ${{ secrets.XXX }},禁止硬编码
- 禁止在 run 步骤中 echo 密钥值
- 第三方 action 必须审查源码或使用可信发布者
## 质量门禁
- PR 合并前必须通过:lint、test、security scan
- Docker 镜像构建后必须运行 Trivy/Snyk 扫描
- Terraform plan 必须在 PR 中显示变更预览
- IaC 变更必须通过 Checkov/tfsec 安全扫描
- 部署到生产环境必须有人工审批步骤
## 最佳实践
- 使用矩阵策略测试多版本/多平台
- 缓存依赖以加速构建(actions/cache)
- 使用 concurrency 避免重复运行
- 失败时发送通知(Slack/邮件)2.3 Cursor Rules DevOps 规则模板
---
description: DevOps 配置文件的代码生成规则
globs: "**/*.tf,**/*.tfvars,**/Dockerfile,**/*.yaml,**/*.yml,**/.github/**"
---
# DevOps 代码生成规则
## 核心原则
1. 安全优先——默认最小权限,显式开放
2. 成本意识——资源配置匹配实际需求
3. 可观测性——每个服务必须可监控、可追踪、可调试
4. 灾难恢复——数据必须有备份,服务必须可恢复
## 生成 DevOps 配置时的检查清单
- [ ] 安全组/防火墙是否遵循最小权限?
- [ ] 是否有硬编码的密钥或密码?
- [ ] 资源配置是否合理(不过度也不不足)?
- [ ] 是否配置了健康检查?
- [ ] 是否有结构化日志和指标暴露?
- [ ] 是否配置了备份策略?
- [ ] 是否区分了环境(dev/staging/prod)?
- [ ] Docker 镜像是否使用了特定版本标签?
- [ ] CI/CD action 是否固定到 SHA?
- [ ] 是否有网络隔离(私有子网、NetworkPolicy)?
## 禁止事项
- 禁止生成包含 0.0.0.0/0 入站规则的安全组(除公共 LB 的 80/443)
- 禁止在配置中硬编码任何密钥、密码、Token
- 禁止使用 :latest 镜像标签
- 禁止生成没有 resource limits 的 K8s 工作负载
- 禁止生成没有健康检查的容器服务
- 禁止使用 privileged 容器
- 禁止在 CI 中使用 @latest 引用 action操作步骤
步骤 1:评估项目 DevOps 技术栈
在创建 Steering 规则之前,先明确项目的 DevOps 技术栈:
请分析当前项目的 DevOps 技术栈,帮我确定需要哪些 Steering 规则:
## 项目信息
- 云平台:[AWS / GCP / Azure / 多云]
- IaC 工具:[Terraform / Pulumi / CDK / CloudFormation]
- 容器编排:[Kubernetes / ECS / Docker Compose / Nomad]
- CI/CD 平台:[GitHub Actions / GitLab CI / CircleCI / Jenkins]
- 监控栈:[Prometheus+Grafana / Datadog / New Relic / CloudWatch]
- 密钥管理:[Vault / AWS SM / GCP SM / Azure KV / 无]
## 合规要求
- [SOC 2 / HIPAA / PCI DSS / GDPR / 无特殊要求]
## 团队规模
- DevOps 工程师:[人数]
- 开发者:[人数]
请推荐需要创建的 Steering 规则文件列表和优先级。步骤 2:生成定制化规则
根据技术栈生成定制化的 Steering 规则:
请根据以下项目信息,生成完整的 DevOps Steering 规则:
## 技术栈
- 云平台:AWS
- IaC:Terraform 1.9
- 容器:EKS (Kubernetes 1.30)
- CI/CD:GitHub Actions
- 监控:Prometheus + Grafana + Loki
- 密钥:AWS Secrets Manager
## AI 编码工具
[Claude Code / Kiro / Cursor]
## 要求
1. 覆盖网络安全、密钥管理、资源配置、健康检查、日志、备份六大领域
2. 每条规则必须包含"禁止"和"应该"两个方面
3. 规则必须可执行(不是模糊的建议,而是具体的约束)
4. 包含至少 3 个 ❌ 错误示例和 ✅ 正确示例
请按 [CLAUDE.md / Kiro Steering / Cursor Rules] 格式输出。步骤 3:集成安全扫描到 CI/CD
将 Steering 规则与自动化安全扫描结合,形成双重保障:
# .github/workflows/devops-quality-gate.yml
name: DevOps Quality Gate
on:
pull_request:
paths:
- '**/*.tf'
- '**/*.tfvars'
- '**/Dockerfile'
- '**/k8s/**'
- '.github/workflows/**'
jobs:
iac-security:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Checkov IaC Scan
uses: bridgecrewio/checkov-action@48a1bff0e498dd66e3bacb0631ec3ce7e4537346 # v12.2964.0
with:
directory: terraform/
framework: terraform
output_format: sarif
soft_fail: false
- name: tfsec Scan
uses: aquasecurity/tfsec-action@b842aa4d7a21afa3e3ac44b10a5a3a0e3b334998 # v1.0.3
with:
working_directory: terraform/
- name: Trivy Container Scan
uses: aquasecurity/trivy-action@18f2510ee396bbf400402947e0f18c8ea63fd80e # v0.28.0
with:
scan-type: 'config'
scan-ref: '.'
severity: 'CRITICAL,HIGH'
exit-code: '1'
- name: Infracost
uses: infracost/actions/setup@3e3e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e # v3
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: GitGuardian Secret Scan
uses: GitGuardian/ggshield-action@8fefef5e6a0f092e1a50a010a1a3a0b0b0b0b0b0 # v1.32.0
env:
GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }}
GITHUB_PUSH_BASE_SHA: ${{ github.event.base }}
GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }}提示词模板
模板 1:DevOps Steering 规则审查
请审查以下 DevOps 配置文件,检查是否违反了安全和运维最佳实践:
## 配置文件
[粘贴 Terraform/K8s/Docker/CI 配置]
## 检查维度
1. 网络安全:是否有过度开放的安全组/防火墙规则?
2. 密钥管理:是否有硬编码的密钥或敏感信息?
3. 资源配置:资源分配是否合理?
4. 健康检查:是否配置了适当的健康检查?
5. 日志与监控:是否有结构化日志和指标暴露?
6. 备份策略:是否配置了数据备份?
7. 容器安全:是否遵循了容器安全最佳实践?
8. CI/CD 安全:是否固定了 action 版本?权限是否最小化?
对每个发现的问题,请提供:
- 问题类型和严重程度(🔴 高 / 🟡 中 / 🟢 低)
- 具体位置
- 修复建议和修正后的代码模板 2:生成安全的 DevOps 配置
请为以下服务生成完整的 DevOps 配置,必须遵循安全最佳实践:
## 服务信息
- 服务名称:[服务名]
- 技术栈:[语言/框架]
- 部署目标:[AWS EKS / GCP GKE / Azure AKS]
- 环境:[dev / staging / prod]
## 需要生成的配置
1. Dockerfile(多阶段构建,非 root 用户)
2. Kubernetes manifests(Deployment + Service + Ingress + NetworkPolicy)
3. Terraform 模块(网络 + 计算 + 数据库)
4. GitHub Actions 工作流(构建 + 测试 + 部署)
## 安全要求
- 所有密钥通过 Secrets Manager 管理
- 网络遵循最小权限原则
- 容器以非 root 用户运行
- 所有资源有合理的 limits
- 配置健康检查和结构化日志
- 数据库有自动备份
请确保生成的配置可以通过 Checkov 和 tfsec 扫描。3. DevOps 反模式总览
在深入每个反模式之前,先了解 AI 生成 DevOps 配置的系统性问题:
3.1 AI 生成 DevOps 配置的典型问题分类
| 问题类别 | 表现 | 根因 | 检测方法 |
|---|---|---|---|
| 安全漏洞 | 安全组全开、密钥硬编码、无加密 | AI 优先”能工作”而非”安全” | Checkov / tfsec / Trivy |
| 资源浪费 | 过度配置 CPU/内存/存储 | AI 缺乏成本意识 | Infracost / 云账单分析 |
| 运维盲区 | 无健康检查、无日志、无监控 | AI 不考虑运维需求 | K8s 审计 / 手动审查 |
| 灾难风险 | 无备份、无恢复计划、单点故障 | AI 不考虑故障场景 | DR 演练 / 架构审查 |
| 环境混淆 | 开发配置用于生产 | AI 不区分环境 | 环境标签检查 |
| 合规违规 | 不满足 SOC 2/HIPAA 要求 | AI 不了解合规标准 | 合规扫描工具 |
3.2 DevOps 反模式严重程度矩阵
发生频率
低 高
┌──────────┬──────────┐
高 │ 🔴 密钥暴露 │ 🔴 宽松安全组│
影响程度 │ (立即修复) │ (立即修复) │
├──────────┼──────────┤
低 │ 🟢 缺少备份 │ 🟡 过度配置 │
│ (计划修复) │ (优化改进) │
└──────────┴──────────┘💡 核心原则:DevOps 反模式的修复优先级应基于”影响程度 × 发生频率”。安全类问题(密钥暴露、宽松安全组)必须立即修复,资源优化类问题可以计划性改进。
4. 反模式 1:宽松安全组(Overly Permissive Security Groups)
问题描述
AI 生成的安全组/防火墙规则几乎总是过度开放。最常见的问题是使用 0.0.0.0/0(允许所有 IP)作为入站源,以及开放不必要的端口。AI 这样做是因为它优先确保”配置能工作”,而最简单的方式就是允许所有流量。
2025 年 Cloud Security Alliance 的研究表明,AI 生成的 IaC 代码中约 62% 包含安全设计缺陷,其中网络配置过度开放是最常见的问题之一。
危害等级:🔴 严重
- 数据库端口暴露到公网,可被扫描和攻击
- SSH/RDP 端口开放,可被暴力破解
- 内部服务暴露,扩大攻击面
- 违反 SOC 2、PCI DSS 等合规要求
- 一旦被利用,可能导致数据泄露和系统被控制
❌ 错误示例
Terraform — 过度开放的安全组
# ❌ 反模式:所有端口对所有 IP 开放
resource "aws_security_group" "app" {
name = "app-sg"
description = "Application security group"
vpc_id = var.vpc_id
# ❌ SSH 对全网开放——任何人都可以尝试暴力破解
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "SSH access"
}
# ❌ 应用端口对全网开放——应该只允许负载均衡器访问
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "Application port"
}
# ❌ 出站全开——应该限制到必要的目标
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# ❌ 数据库安全组也对全网开放
resource "aws_security_group" "db" {
name = "db-sg"
vpc_id = var.vpc_id
# ❌ 数据库端口对全网开放——这是最危险的配置之一
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "PostgreSQL"
}
}Kubernetes — 缺少 NetworkPolicy
# ❌ 反模式:没有 NetworkPolicy,所有 Pod 可以互相通信
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
spec:
replicas: 3
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
spec:
containers:
- name: payment
image: myapp/payment:v1.2.3
ports:
- containerPort: 8080
# ❌ 没有 NetworkPolicy——任何 Pod 都可以访问支付服务
# ❌ 没有限制出站流量——被入侵后可以自由外联✅ 正确示例
Terraform — 最小权限安全组
# ✅ 正确:最小权限原则
resource "aws_security_group" "alb" {
name = "${var.project}-alb-sg"
description = "ALB security group - public facing"
vpc_id = var.vpc_id
# ✅ 只有 ALB 允许公网访问,且仅限 HTTP/HTTPS
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTPS from internet"
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTP from internet (redirect to HTTPS)"
}
egress {
from_port = 8080
to_port = 8080
protocol = "tcp"
security_groups = [aws_security_group.app.id]
description = "To application instances"
}
tags = local.common_tags
}
resource "aws_security_group" "app" {
name = "${var.project}-app-sg"
description = "Application security group - private"
vpc_id = var.vpc_id
# ✅ 应用只接受来自 ALB 的流量(通过安全组引用)
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
description = "From ALB only"
}
# ✅ 出站限制到必要的目标
egress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.db.id]
description = "To PostgreSQL"
}
egress {
from_port = 6379
to_port = 6379
protocol = "tcp"
security_groups = [aws_security_group.redis.id]
description = "To Redis"
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTPS to external APIs"
}
tags = local.common_tags
}
resource "aws_security_group" "db" {
name = "${var.project}-db-sg"
description = "Database security group - private only"
vpc_id = var.vpc_id
# ✅ 数据库只接受来自应用的流量
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app.id]
description = "From application only"
}
# ✅ 数据库不需要出站访问
# 不定义 egress 规则
tags = local.common_tags
}Kubernetes — 严格的 NetworkPolicy
# ✅ 正确:默认拒绝 + 显式允许
---
# 默认拒绝所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
---
# 只允许 Ingress Controller 访问 payment-service
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-payment
namespace: production
spec:
podSelector:
matchLabels:
app: payment-service
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
ports:
- protocol: TCP
port: 8080
egress:
# 允许访问数据库
- to:
- podSelector:
matchLabels:
app: postgresql
ports:
- protocol: TCP
port: 5432
# 允许 DNS 解析
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53检测方法
# Checkov 扫描 Terraform 安全组
checkov -d terraform/ --check CKV_AWS_24,CKV_AWS_25,CKV_AWS_260
# tfsec 扫描
tfsec terraform/ --include-passed
# OPA/Rego 自定义策略
# policy/security_group.rego
package terraform.security_group
deny[msg] {
resource := input.resource.aws_security_group[name]
ingress := resource.ingress[_]
ingress.cidr_blocks[_] == "0.0.0.0/0"
ingress.from_port != 80
ingress.from_port != 443
msg := sprintf("Security group '%s' allows 0.0.0.0/0 on port %d", [name, ingress.from_port])
}Steering 规则
## 网络安全规则
- 禁止 cidr_blocks = ["0.0.0.0/0"] 用于非 80/443 端口的入站规则
- 服务间通信必须使用 security_groups 引用,禁止 CIDR
- 数据库安全组禁止任何公网入站规则
- SSH 访问必须通过 VPN 或 SSM Session Manager,禁止直接公网 SSH
- 每个安全组规则必须有 description 字段
- Kubernetes 每个命名空间必须有 default-deny NetworkPolicy5. 反模式 2:过度配置(Over-Provisioning)
问题描述
AI 生成的资源配置几乎总是过度分配。当你让 AI 生成 Kubernetes Deployment 时,它可能默认分配 2 核 CPU 和 4Gi 内存给一个简单的 API 服务;当你让它生成 Terraform EC2 实例时,它可能选择 m5.xlarge 而实际只需要 t3.small。AI 这样做是因为它倾向于”安全”地分配更多资源以避免性能问题,但这直接导致云账单膨胀。
Flexera 2025 年云状态报告显示,企业平均浪费约 28-35% 的云支出,而 AI 生成的配置可能进一步加剧这一问题。
危害等级:🟡 中高
- 云账单膨胀 2-5 倍
- 资源利用率低于 20%,浪费严重
- 开发环境使用生产级别的资源规格
- 自动扩缩容配置不合理,最小副本数过高
- 存储过度分配且无法缩减(EBS 卷只能扩不能缩)
❌ 错误示例
Kubernetes — 过度配置的资源
# ❌ 反模式:一个简单的 API 服务分配了过多资源
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-api
spec:
# ❌ 最小 5 个副本——对于低流量服务完全不必要
replicas: 5
selector:
matchLabels:
app: user-api
template:
metadata:
labels:
app: user-api
spec:
containers:
- name: user-api
image: myapp/user-api:v1.0.0
resources:
requests:
# ❌ 请求 2 核 CPU——一个简单 CRUD API 通常只需 100-250m
cpu: "2"
# ❌ 请求 4Gi 内存——Node.js/Go API 通常只需 128-512Mi
memory: "4Gi"
limits:
# ❌ 限制 4 核——过度分配
cpu: "4"
# ❌ 限制 8Gi——过度分配
memory: "8Gi"Terraform — 过度配置的实例
# ❌ 反模式:开发环境使用生产级别的实例
resource "aws_instance" "dev_app" {
# ❌ m5.2xlarge(8 vCPU, 32GB RAM)用于开发环境
instance_type = "m5.2xlarge"
ami = var.ami_id
subnet_id = var.subnet_id
root_block_device {
# ❌ 500GB gp3 用于开发——通常 20-50GB 足够
volume_size = 500
volume_type = "gp3"
# ❌ 高 IOPS 用于开发环境
iops = 10000
throughput = 500
}
tags = {
Name = "dev-app-server"
}
}
# ❌ 开发环境的 RDS 使用生产级别配置
resource "aws_db_instance" "dev_db" {
# ❌ db.r6g.xlarge(4 vCPU, 32GB RAM)用于开发
instance_class = "db.r6g.xlarge"
allocated_storage = 500 # ❌ 500GB 用于开发
max_allocated_storage = 1000
multi_az = true # ❌ 开发环境不需要多可用区
# ❌ 没有按环境区分配置
}✅ 正确示例
Kubernetes — 合理的资源配置
# ✅ 正确:根据实际负载合理配置资源
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-api
spec:
# ✅ 开发环境 1 个副本,生产环境通过 HPA 自动扩缩
replicas: 2
selector:
matchLabels:
app: user-api
template:
metadata:
labels:
app: user-api
spec:
containers:
- name: user-api
image: myapp/user-api:v1.0.0
resources:
requests:
# ✅ 合理的请求值——基于实际观测的 P95 使用量
cpu: "100m"
memory: "256Mi"
limits:
# ✅ limits 是 requests 的 2 倍——允许突发但有上限
cpu: "200m"
memory: "512Mi"
---
# ✅ 使用 HPA 自动扩缩容
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: user-api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: user-api
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80Terraform — 按环境区分的资源配置
# ✅ 正确:按环境区分资源配置
locals {
instance_config = {
dev = {
instance_type = "t3.small" # 2 vCPU, 2GB — 开发足够
volume_size = 30
volume_iops = 3000 # gp3 默认值
db_class = "db.t4g.micro" # 最小规格
db_storage = 20
db_multi_az = false
}
staging = {
instance_type = "t3.medium" # 2 vCPU, 4GB
volume_size = 50
volume_iops = 3000
db_class = "db.t4g.small"
db_storage = 50
db_multi_az = false
}
prod = {
instance_type = "m6i.large" # 2 vCPU, 8GB — 生产合理起步
volume_size = 100
volume_iops = 6000
db_class = "db.r6g.large"
db_storage = 100
db_multi_az = true
}
}
config = local.instance_config[var.environment]
}
resource "aws_instance" "app" {
instance_type = local.config.instance_type
ami = var.ami_id
subnet_id = var.subnet_id
root_block_device {
volume_size = local.config.volume_size
volume_type = "gp3"
iops = local.config.volume_iops
}
tags = merge(local.common_tags, {
Name = "${var.project}-${var.environment}-app"
})
}
resource "aws_db_instance" "main" {
instance_class = local.config.db_class
allocated_storage = local.config.db_storage
max_allocated_storage = local.config.db_storage * 2
multi_az = local.config.db_multi_az
storage_encrypted = true
tags = local.common_tags
}检测方法
# Infracost 估算成本
infracost breakdown --path terraform/
# Infracost 对比 PR 变更的成本影响
infracost diff --path terraform/ --compare-to infracost-base.json
# Kubernetes 资源使用率分析
kubectl top pods -n production --sort-by=cpu
kubectl top pods -n production --sort-by=memory
# 使用 Kubecost 分析集群成本
# https://www.kubecost.com/Steering 规则
## 资源配置规则
- Kubernetes requests/limits 必须基于实际观测数据,而非猜测
- 简单 API 服务的默认 requests:cpu 100m, memory 256Mi
- limits 不应超过 requests 的 2-3 倍
- 开发环境必须使用最小规格实例(t3.small / db.t4g.micro)
- 所有资源必须按环境(dev/staging/prod)参数化配置
- 使用 HPA 自动扩缩容,而非固定高副本数
- 所有资源必须添加 cost-center 和 environment 标签
- PR 中必须包含 Infracost 成本预估6. 反模式 3:缺少健康检查(Missing Health Checks)
问题描述
AI 生成的容器和服务配置经常缺少健康检查(Health Checks)。没有健康检查的服务就像没有体检的员工——看起来在工作,但可能已经处于不健康状态:进程在运行但无法处理请求(僵尸进程)、数据库连接池耗尽但 Pod 仍然接收流量、内存泄漏导致响应越来越慢但 Kubernetes 不知道需要重启。
2026 年 OneUptime 的研究指出,混淆 liveness 和 readiness 探针是最常见的 Kubernetes 健康检查错误——liveness 失败会杀死容器,readiness 失败只是停止发送流量,混用会导致级联重启。
危害等级:🔴 高
- 僵尸 Pod 持续接收流量,导致用户请求失败
- 服务无法自愈,需要人工干预重启
- 滚动更新时新版本未就绪就接收流量,导致短暂不可用
- 依赖服务故障时,上游服务不知道下游已不可用
- Docker Compose 环境中服务启动顺序混乱
❌ 错误示例
Kubernetes — 无健康检查
# ❌ 反模式:完全没有健康检查
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: myapp/order-service:v2.1.0
ports:
- containerPort: 8080
# ❌ 没有 livenessProbe——进程死锁时不会被重启
# ❌ 没有 readinessProbe——启动中就接收流量
# ❌ 没有 startupProbe——慢启动服务可能被 liveness 杀死Kubernetes — 错误的健康检查配置
# ❌ 反模式:健康检查配置错误
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
spec:
replicas: 3
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
spec:
containers:
- name: payment-service
image: myapp/payment:v1.5.0
ports:
- containerPort: 8080
# ❌ liveness 检查外部依赖——数据库故障会导致所有 Pod 被杀死(级联重启)
livenessProbe:
httpGet:
path: /health/full # 这个端点检查数据库、Redis、Kafka
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
# ❌ failureThreshold 太低——一次网络抖动就重启
failureThreshold: 1
# ❌ readiness 和 liveness 使用相同的端点和配置
readinessProbe:
httpGet:
path: /health/full
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 1Docker Compose — 无健康检查
# ❌ 反模式:Docker Compose 无健康检查
version: '3.8'
services:
app:
image: myapp:latest
ports:
- "8080:8080"
depends_on:
# ❌ 只等待容器启动,不等待服务就绪
- postgres
- redis
postgres:
image: postgres:16
# ❌ 没有 healthcheck——app 可能在 postgres 未就绪时就尝试连接
redis:
image: redis:7
# ❌ 没有 healthcheck✅ 正确示例
Kubernetes — 正确的健康检查配置
# ✅ 正确:分层健康检查
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
spec:
replicas: 3
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
spec:
containers:
- name: payment-service
image: myapp/payment:v1.5.0
ports:
- containerPort: 8080
# ✅ startupProbe:处理慢启动(如 JVM 预热、数据库迁移)
startupProbe:
httpGet:
path: /health/startup
port: 8080
# 最多等待 5 * 60 = 300 秒启动
periodSeconds: 5
failureThreshold: 60
# ✅ livenessProbe:只检查进程本身是否健康(不检查外部依赖)
livenessProbe:
httpGet:
path: /health/live # 只检查进程存活,不检查 DB/Redis
port: 8080
periodSeconds: 10
failureThreshold: 3 # 连续 3 次失败才重启
timeoutSeconds: 5
# ✅ readinessProbe:检查服务是否可以处理请求(包括关键依赖)
readinessProbe:
httpGet:
path: /health/ready # 检查 DB 连接池、Redis 连接等
port: 8080
periodSeconds: 5
failureThreshold: 3
successThreshold: 1
timeoutSeconds: 3健康检查端点实现示例(Go)
// ✅ 正确:分层健康检查端点
package health
import (
"context"
"net/http"
"time"
"encoding/json"
)
type HealthChecker struct {
db *sql.DB
redis *redis.Client
}
// /health/live — liveness:只检查进程存活
func (h *HealthChecker) LiveHandler(w http.ResponseWriter, r *http.Request) {
// ✅ 不检查外部依赖,只确认进程能响应
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "alive"})
}
// /health/ready — readiness:检查是否可以处理请求
func (h *HealthChecker) ReadyHandler(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
checks := map[string]string{}
healthy := true
// ✅ 检查数据库连接
if err := h.db.PingContext(ctx); err != nil {
checks["database"] = "unhealthy: " + err.Error()
healthy = false
} else {
checks["database"] = "healthy"
}
// ✅ 检查 Redis 连接
if err := h.redis.Ping(ctx).Err(); err != nil {
checks["redis"] = "unhealthy: " + err.Error()
healthy = false
} else {
checks["redis"] = "healthy"
}
if healthy {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(http.StatusServiceUnavailable)
}
json.NewEncoder(w).Encode(checks)
}
// /health/startup — startup:检查初始化是否完成
func (h *HealthChecker) StartupHandler(w http.ResponseWriter, r *http.Request) {
// ✅ 检查数据库迁移是否完成、缓存是否预热等
if !h.initialized {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
}Docker Compose — 正确的健康检查
# ✅ 正确:Docker Compose 带健康检查
version: '3.8'
services:
app:
image: myapp:v1.0.0
ports:
- "8080:8080"
depends_on:
postgres:
# ✅ 等待 postgres 健康检查通过后再启动
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health/ready"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
postgres:
image: postgres:16-alpine
healthcheck:
# ✅ 使用 pg_isready 检查 PostgreSQL 是否就绪
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s
redis:
image: redis:7-alpine
healthcheck:
# ✅ 使用 redis-cli ping 检查 Redis 是否就绪
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5检测方法
# 检查 Kubernetes 中没有健康检查的 Deployment
kubectl get deployments -A -o json | jq -r '
.items[] |
select(.spec.template.spec.containers[].livenessProbe == null) |
"\(.metadata.namespace)/\(.metadata.name): 缺少 livenessProbe"
'
# Checkov 检查
checkov -d k8s/ --check CKV_K8S_8,CKV_K8S_9 # livenessProbe, readinessProbe
# OPA 策略
# policy/health_check.rego
package kubernetes.health_check
deny[msg] {
container := input.spec.template.spec.containers[_]
not container.livenessProbe
msg := sprintf("Container '%s' missing livenessProbe", [container.name])
}
deny[msg] {
container := input.spec.template.spec.containers[_]
not container.readinessProbe
msg := sprintf("Container '%s' missing readinessProbe", [container.name])
}Steering 规则
## 健康检查规则
- 所有 K8s Deployment/StatefulSet 必须配置 livenessProbe 和 readinessProbe
- livenessProbe 只检查进程存活,禁止检查外部依赖(避免级联重启)
- readinessProbe 检查服务是否可以处理请求(包括关键依赖连接)
- 启动时间超过 30 秒的服务必须配置 startupProbe
- failureThreshold 至少设置为 3(避免网络抖动导致误重启)
- Docker Compose 的 depends_on 必须使用 condition: service_healthy
- 所有数据库和缓存服务必须配置 healthcheck7. 反模式 4:日志不足(Insufficient Logging)
问题描述
AI 生成的服务代码通常使用最基本的日志方式——console.log、print、fmt.Println——输出非结构化的纯文本日志。这些日志在开发环境中看起来没问题,但在生产环境中几乎无法使用:无法被日志聚合系统(Loki、ELK、CloudWatch)有效解析、缺少关键上下文(请求 ID、用户 ID、trace ID)、没有日志级别区分、敏感信息可能被意外记录。
危害等级:🟡 中高
- 生产事件排查困难——无法通过日志定位问题
- 日志聚合系统无法解析非结构化日志
- 缺少 trace ID 导致无法跨服务追踪请求
- 缺少审计日志导致合规审计失败
- 敏感信息(密码、Token)被记录到日志中
- 日志量过大或过小,无法有效监控
❌ 错误示例
Node.js — 非结构化日志
// ❌ 反模式:使用 console.log 输出非结构化日志
app.post('/api/orders', async (req, res) => {
try {
// ❌ 非结构化日志——无法被日志系统解析
console.log('Creating order for user: ' + req.body.userId);
const order = await orderService.create(req.body);
// ❌ 日志中包含敏感信息
console.log('Order created:', JSON.stringify(order));
// ❌ 可能包含信用卡号、地址等敏感数据
res.json(order);
} catch (error) {
// ❌ 只记录错误消息,没有堆栈跟踪和上下文
console.log('Error creating order: ' + error.message);
// ❌ 没有请求 ID、用户 ID 等上下文
// ❌ 没有日志级别区分
res.status(500).json({ error: 'Internal error' });
}
});Go — 缺少上下文的日志
// ❌ 反模式:使用 fmt.Println 和 log.Println
func (h *OrderHandler) CreateOrder(w http.ResponseWriter, r *http.Request) {
// ❌ 非结构化日志
fmt.Println("Received create order request")
var req CreateOrderRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
// ❌ 没有请求上下文(request ID、user ID)
log.Println("Failed to decode request:", err)
http.Error(w, "Bad request", http.StatusBadRequest)
return
}
order, err := h.service.Create(r.Context(), req)
if err != nil {
// ❌ 没有结构化字段,无法在日志系统中过滤
log.Printf("Failed to create order: %v", err)
http.Error(w, "Internal error", http.StatusInternalServerError)
return
}
// ❌ 日志中可能包含敏感的订单数据
log.Printf("Order created: %+v", order)
}✅ 正确示例
Node.js — 结构化日志(使用 Pino)
// ✅ 正确:结构化日志 + 上下文 + 脱敏
import pino from 'pino';
const logger = pino({
level: process.env.LOG_LEVEL || 'info',
// ✅ 结构化 JSON 输出
formatters: {
level: (label) => ({ level: label }),
},
// ✅ 自动脱敏敏感字段
redact: {
paths: ['req.headers.authorization', 'req.body.password',
'req.body.creditCard', '*.token', '*.secret'],
censor: '[REDACTED]',
},
// ✅ 添加服务元数据
base: {
service: 'order-service',
version: process.env.APP_VERSION || 'unknown',
environment: process.env.NODE_ENV || 'development',
},
});
// ✅ 请求级别的日志中间件
app.use((req, res, next) => {
// ✅ 为每个请求生成唯一 ID
req.requestId = req.headers['x-request-id'] || crypto.randomUUID();
// ✅ 创建带上下文的子 logger
req.log = logger.child({
requestId: req.requestId,
method: req.method,
path: req.path,
userId: req.user?.id,
});
next();
});
app.post('/api/orders', async (req, res) => {
try {
// ✅ 结构化日志 + 上下文
req.log.info({ itemCount: req.body.items?.length }, 'Creating order');
const order = await orderService.create(req.body);
// ✅ 只记录必要的非敏感信息
req.log.info(
{ orderId: order.id, total: order.total, itemCount: order.items.length },
'Order created successfully'
);
res.json(order);
} catch (error) {
// ✅ 错误日志包含完整上下文和堆栈跟踪
req.log.error(
{
err: error,
stack: error.stack,
orderData: { itemCount: req.body.items?.length },
},
'Failed to create order'
);
res.status(500).json({ error: 'Internal error', requestId: req.requestId });
}
});Go — 结构化日志(使用 slog)
// ✅ 正确:使用 Go 1.21+ 标准库 slog
package main
import (
"context"
"log/slog"
"net/http"
"os"
)
func setupLogger() *slog.Logger {
// ✅ JSON 格式输出,适合日志聚合系统
handler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
// ✅ 自动脱敏敏感字段
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == "password" || a.Key == "token" || a.Key == "secret" {
a.Value = slog.StringValue("[REDACTED]")
}
return a
},
})
return slog.New(handler).With(
slog.String("service", "order-service"),
slog.String("version", os.Getenv("APP_VERSION")),
slog.String("environment", os.Getenv("ENVIRONMENT")),
)
}
// ✅ 中间件:为每个请求注入上下文
func loggingMiddleware(logger *slog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestID := r.Header.Get("X-Request-ID")
if requestID == "" {
requestID = uuid.New().String()
}
// ✅ 创建带请求上下文的 logger
reqLogger := logger.With(
slog.String("request_id", requestID),
slog.String("method", r.Method),
slog.String("path", r.URL.Path),
slog.String("remote_addr", r.RemoteAddr),
)
ctx := context.WithValue(r.Context(), "logger", reqLogger)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
func (h *OrderHandler) CreateOrder(w http.ResponseWriter, r *http.Request) {
logger := r.Context().Value("logger").(*slog.Logger)
// ✅ 结构化日志 + 上下文
logger.Info("Creating order",
slog.Int("item_count", len(req.Items)),
slog.String("user_id", req.UserID),
)
order, err := h.service.Create(r.Context(), req)
if err != nil {
// ✅ 错误日志包含完整上下文
logger.Error("Failed to create order",
slog.String("error", err.Error()),
slog.String("user_id", req.UserID),
slog.Int("item_count", len(req.Items)),
)
http.Error(w, "Internal error", http.StatusInternalServerError)
return
}
logger.Info("Order created",
slog.String("order_id", order.ID),
slog.Float64("total", order.Total),
)
}检测方法
# 搜索代码中的非结构化日志
grep -rn "console\.log\|console\.error\|fmt\.Print\|log\.Print" src/ --include="*.ts" --include="*.go"
# 检查日志输出是否为 JSON 格式
kubectl logs deployment/order-service -n production --tail=10 | jq . 2>/dev/null || echo "⚠️ 日志不是 JSON 格式"
# 检查日志是否包含必要字段
kubectl logs deployment/order-service -n production --tail=100 | \
jq -r 'select(.request_id == null) | .msg' | head -5
# 如果有输出,说明有日志缺少 request_idSteering 规则
## 日志规则
- 生产代码禁止使用 console.log / fmt.Println / print 作为日志方式
- 必须使用结构化日志库(Pino/Winston/slog/zerolog/structlog)
- 日志必须为 JSON 格式,包含:timestamp、level、service、message
- 每个请求的日志必须包含 request_id(用于跨服务追踪)
- 错误日志必须包含堆栈跟踪和上下文信息
- 禁止在日志中记录密码、Token、信用卡号等敏感信息
- 必须配置日志脱敏(redact)规则
- 关键业务操作(创建、更新、删除)必须记录审计日志
- 日志级别使用规范:DEBUG(调试)、INFO(正常操作)、WARN(异常但可恢复)、ERROR(错误需关注)8. 反模式 5:密钥暴露(Secret Exposure)
问题描述
密钥暴露是 AI 生成代码中最危险的安全问题之一。AI 在生成配置示例时,经常直接在代码中写入示例密钥、API Key、数据库密码等敏感信息。更糟糕的是,开发者可能直接使用这些”示例”值,或者用真实密钥替换后忘记从 Git 历史中清除。
2025 年 GitGuardian 的报告显示,公共 GitHub 仓库中每年新增数百万个泄露的密钥,而 AI 辅助编码正在加速这一趋势。Pixee.ai 的研究发现,AI 辅助的 PR 中密码处理不当的问题比非 AI PR 高出 1.88 倍。
危害等级:🔴 严重
- 数据库被未授权访问,数据泄露
- 云账户被接管,产生巨额账单
- API 密钥被滥用,服务被攻击
- 即使删除文件,密钥仍存在于 Git 历史中
- 违反 SOC 2、PCI DSS、HIPAA 等合规要求
- 一旦泄露,修复成本极高(需要轮换所有相关密钥)
❌ 错误示例
Terraform — 硬编码密钥
# ❌ 反模式:密钥直接写在 Terraform 配置中
resource "aws_db_instance" "main" {
engine = "postgres"
engine_version = "16.3"
instance_class = "db.t4g.medium"
# ❌ 数据库密码硬编码——会被提交到 Git
username = "admin"
password = "SuperSecret123!" # ❌ 严重安全问题
tags = {
Name = "production-db"
}
}
# ❌ API 密钥硬编码
resource "aws_ssm_parameter" "api_key" {
name = "/app/api-key"
type = "String" # ❌ 应该用 SecureString
value = "sk-proj-abc123def456ghi789" # ❌ 真实 API 密钥
}
# ❌ Provider 配置中硬编码凭证
provider "aws" {
region = "us-east-1"
access_key = "AKIAIOSFODNN7EXAMPLE" # ❌ 严重安全问题
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" # ❌ 严重安全问题
}Docker / Docker Compose — 密钥泄露
# ❌ 反模式:Dockerfile 中的密钥
FROM node:20-alpine
WORKDIR /app
COPY . .
# ❌ 通过 ARG 传递密钥——会被记录在镜像层中
ARG DATABASE_URL=postgres://admin:password123@db:5432/myapp
ARG API_KEY=sk-proj-abc123
# ❌ 通过 ENV 设置密钥——会被记录在镜像元数据中
ENV DATABASE_URL=$DATABASE_URL
ENV API_KEY=$API_KEY
RUN npm install
CMD ["node", "server.js"]# ❌ 反模式:docker-compose.yml 中硬编码密钥
version: '3.8'
services:
app:
image: myapp:latest
environment:
# ❌ 密钥直接写在 compose 文件中
DATABASE_URL: "postgres://admin:SuperSecret123!@postgres:5432/myapp"
JWT_SECRET: "my-super-secret-jwt-key-12345"
STRIPE_SECRET_KEY: "sk_live_abc123def456"
AWS_ACCESS_KEY_ID: "AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_ACCESS_KEY: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"GitHub Actions — 密钥泄露
# ❌ 反模式:CI/CD 中的密钥问题
name: Deploy
on: push
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ❌ 密钥硬编码在工作流文件中
- name: Configure AWS
run: |
aws configure set aws_access_key_id AKIAIOSFODNN7EXAMPLE
aws configure set aws_secret_access_key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# ❌ 在日志中输出密钥
- name: Debug
run: |
echo "Using API key: ${{ secrets.API_KEY }}"
# ❌ 虽然用了 secrets,但 echo 会在日志中显示✅ 正确示例
Terraform — 安全的密钥管理
# ✅ 正确:使用 Secrets Manager + 动态引用
# 密码由 Secrets Manager 自动生成和管理
resource "random_password" "db_password" {
length = 32
special = true
}
resource "aws_secretsmanager_secret" "db_password" {
name = "${var.project}/${var.environment}/db-password"
recovery_window_in_days = 7
tags = local.common_tags
}
resource "aws_secretsmanager_secret_version" "db_password" {
secret_id = aws_secretsmanager_secret.db_password.id
secret_string = random_password.db_password.result
}
resource "aws_db_instance" "main" {
engine = "postgres"
engine_version = "16.3"
instance_class = local.config.db_class
# ✅ 用户名通过变量传入
username = var.db_username
# ✅ 密码从 Secrets Manager 引用
password = random_password.db_password.result
# ✅ 标记为敏感值,不在 plan 输出中显示
lifecycle {
ignore_changes = [password]
}
tags = local.common_tags
}
# ✅ 敏感变量标记
variable "db_username" {
type = string
sensitive = true
}
# ✅ 输出也标记为敏感
output "db_endpoint" {
value = aws_db_instance.main.endpoint
sensitive = false
}
output "db_password_secret_arn" {
value = aws_secretsmanager_secret.db_password.arn
sensitive = true
}Docker — 安全的密钥处理
# ✅ 正确:多阶段构建 + BuildKit secrets
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
RUN npm run build
# ✅ 最终镜像不包含任何密钥
FROM node:20-alpine AS runtime
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
# ✅ 不在镜像中设置任何密钥环境变量
# 密钥在运行时通过 Secrets Manager / Vault 注入
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:8080/health/live || exit 1
CMD ["node", "dist/server.js"]# ✅ 正确:docker-compose 使用 secrets 和 .env
version: '3.8'
services:
app:
image: myapp:v1.0.0
environment:
# ✅ 非敏感配置可以直接设置
NODE_ENV: production
PORT: "8080"
# ✅ 敏感值通过 secrets 挂载
secrets:
- db_password
- jwt_secret
- stripe_key
# ✅ secrets 从外部文件或 Docker Swarm secrets 加载
secrets:
db_password:
file: ./secrets/db_password.txt # ✅ 此文件在 .gitignore 中
jwt_secret:
file: ./secrets/jwt_secret.txt
stripe_key:
file: ./secrets/stripe_key.txtGitHub Actions — 安全的密钥使用
# ✅ 正确:安全的 CI/CD 密钥管理
name: Deploy
on:
push:
branches: [main]
# ✅ 最小权限原则
permissions:
contents: read
id-token: write # 用于 OIDC 认证
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# ✅ 使用 OIDC 联合认证,无需长期凭证
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1
# ✅ 使用 OIDC,不需要 access key
# ✅ 密钥通过 GitHub Secrets 注入,不在日志中显示
- name: Deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: |
# ✅ 不 echo 密钥值
echo "Deploying to production..."
./deploy.sh
# ✅ 使用 GitGuardian 扫描密钥泄露
- name: Secret Scan
uses: GitGuardian/ggshield-action@8fefef5e6a0f092e1a50a010a1a3a0b0b0b0b0b0 # v1.32.0
env:
GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }}检测方法
# GitGuardian 扫描 Git 历史
ggshield secret scan repo .
# Trivy 扫描密钥
trivy fs --scanners secret .
# gitleaks 扫描
gitleaks detect --source . --verbose
# 检查 Terraform 中的硬编码密钥
grep -rn "password\s*=\s*\"" terraform/ --include="*.tf" | grep -v "var\." | grep -v "random_password"
grep -rn "secret_key\s*=\s*\"" terraform/ --include="*.tf"
grep -rn "access_key\s*=\s*\"" terraform/ --include="*.tf"
# 检查 Docker 镜像中的密钥
docker history myapp:latest --no-trunc | grep -i "secret\|password\|key\|token"Steering 规则
## 密钥管理规则
- 禁止在任何文件中硬编码密钥、密码、Token、API Key
- Terraform 密码必须使用 random_password + Secrets Manager
- Terraform 敏感变量必须标记 sensitive = true
- Docker 构建禁止通过 ARG/ENV 传递密钥
- docker-compose 敏感值必须使用 secrets 机制或 .env 文件(.env 在 .gitignore 中)
- CI/CD 密钥必须使用平台原生 secrets(GitHub Secrets / GitLab CI Variables)
- 优先使用 OIDC 联合认证,避免长期凭证
- 所有仓库必须配置 pre-commit hook 运行密钥扫描(gitleaks/ggshield)
- 发现密钥泄露后必须立即轮换,不能仅删除文件(Git 历史仍保留)9. 反模式 6:缺少备份(Missing Backups)
问题描述
AI 生成的基础设施配置几乎从不包含备份策略。当你让 AI 生成一个 RDS 实例或 PostgreSQL 部署时,它会配置好连接参数、性能设置,但很少主动添加自动备份、跨区域复制、快照策略或恢复测试计划。AI 不会主动思考”如果数据丢失了怎么办”——它只关注”如何让服务运行起来”。
危害等级:🔴 严重
- 数据库故障导致数据永久丢失
- 勒索软件攻击后无法恢复
- 误操作(如 DROP TABLE)无法回滚
- 灾难恢复时间远超业务容忍度
- 违反数据保留合规要求
- 备份存在但从未测试过恢复流程,关键时刻发现备份损坏
❌ 错误示例
Terraform — 无备份的数据库
# ❌ 反模式:数据库没有备份配置
resource "aws_db_instance" "main" {
identifier = "production-db"
engine = "postgres"
engine_version = "16.3"
instance_class = "db.r6g.large"
allocated_storage = 100
storage_type = "gp3"
username = var.db_username
password = random_password.db.result
# ❌ 没有设置备份保留期——默认可能为 0(无备份)
# ❌ 没有设置备份窗口
# ❌ 没有启用删除保护
# ❌ 没有配置跨区域只读副本
# ❌ 没有设置最终快照
# ❌ 允许直接删除,不创建最终快照
skip_final_snapshot = true
tags = {
Name = "production-db"
}
}
# ❌ S3 存储桶没有版本控制
resource "aws_s3_bucket" "data" {
bucket = "my-important-data"
# ❌ 没有启用版本控制——误删除无法恢复
# ❌ 没有配置生命周期规则
# ❌ 没有跨区域复制
}Kubernetes — 无备份的有状态服务
# ❌ 反模式:StatefulSet 没有备份策略
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgresql
spec:
serviceName: postgresql
replicas: 1 # ❌ 单副本,无高可用
selector:
matchLabels:
app: postgresql
template:
metadata:
labels:
app: postgresql
spec:
containers:
- name: postgresql
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Gi
# ❌ 没有配置 VolumeSnapshot 策略
# ❌ 没有 CronJob 定期备份
# ❌ 没有备份到外部存储(S3/GCS)✅ 正确示例
Terraform — 完整的备份策略
# ✅ 正确:完整的数据库备份策略
resource "aws_db_instance" "main" {
identifier = "${var.project}-${var.environment}-db"
engine = "postgres"
engine_version = "16.3"
instance_class = local.config.db_class
allocated_storage = local.config.db_storage
max_allocated_storage = local.config.db_storage * 2
storage_type = "gp3"
storage_encrypted = true
kms_key_id = aws_kms_key.db.arn
username = var.db_username
password = random_password.db.result
# ✅ 自动备份配置
backup_retention_period = var.environment == "prod" ? 30 : 7 # 生产 30 天,其他 7 天
backup_window = "03:00-04:00" # UTC 凌晨备份
maintenance_window = "Mon:04:00-Mon:05:00" # 维护窗口在备份之后
# ✅ 删除保护
deletion_protection = var.environment == "prod" ? true : false
skip_final_snapshot = var.environment == "prod" ? false : true
final_snapshot_identifier = var.environment == "prod" ? "${var.project}-final-${formatdate("YYYY-MM-DD", timestamp())}" : null
# ✅ 多可用区(生产环境)
multi_az = var.environment == "prod" ? true : false
# ✅ 启用性能洞察(帮助诊断问题)
performance_insights_enabled = true
performance_insights_retention_period = 7
# ✅ 启用增强监控
monitoring_interval = 60
monitoring_role_arn = aws_iam_role.rds_monitoring.arn
tags = merge(local.common_tags, {
BackupRetention = var.environment == "prod" ? "30days" : "7days"
RPO = var.environment == "prod" ? "1hour" : "24hours"
RTO = var.environment == "prod" ? "4hours" : "24hours"
})
}
# ✅ 跨区域只读副本(生产环境灾难恢复)
resource "aws_db_instance" "replica" {
count = var.environment == "prod" ? 1 : 0
identifier = "${var.project}-prod-db-replica"
replicate_source_db = aws_db_instance.main.identifier
instance_class = "db.r6g.large"
storage_encrypted = true
# ✅ 副本也有自己的备份
backup_retention_period = 7
tags = merge(local.common_tags, {
Role = "read-replica"
})
}
# ✅ S3 存储桶带版本控制和跨区域复制
resource "aws_s3_bucket" "data" {
bucket = "${var.project}-${var.environment}-data"
tags = local.common_tags
}
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id
versioning_configuration {
status = "Enabled" # ✅ 启用版本控制
}
}
resource "aws_s3_bucket_lifecycle_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
id = "archive-old-versions"
status = "Enabled"
# ✅ 旧版本 30 天后转到 Glacier
noncurrent_version_transition {
noncurrent_days = 30
storage_class = "GLACIER"
}
# ✅ 旧版本 365 天后删除
noncurrent_version_expiration {
noncurrent_days = 365
}
}
}Kubernetes — 完整的备份策略
# ✅ 正确:使用 CronJob 定期备份 PostgreSQL 到 S3
apiVersion: batch/v1
kind: CronJob
metadata:
name: postgresql-backup
namespace: production
spec:
# ✅ 每天凌晨 3 点备份
schedule: "0 3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 7
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backupLimit: 1
template:
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: postgres:16-alpine
command:
- /bin/sh
- -c
- |
set -e
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="/tmp/backup_${TIMESTAMP}.sql.gz"
echo "Starting backup at ${TIMESTAMP}..."
# ✅ 使用 pg_dump 创建备份
PGPASSWORD="${DB_PASSWORD}" pg_dump \
-h "${DB_HOST}" \
-U "${DB_USER}" \
-d "${DB_NAME}" \
--format=custom \
--compress=9 \
-f "${BACKUP_FILE}"
# ✅ 上传到 S3
aws s3 cp "${BACKUP_FILE}" \
"s3://${BACKUP_BUCKET}/postgresql/${TIMESTAMP}.sql.gz" \
--storage-class STANDARD_IA
# ✅ 验证备份文件
aws s3 ls "s3://${BACKUP_BUCKET}/postgresql/${TIMESTAMP}.sql.gz"
echo "Backup completed: ${BACKUP_FILE}"
# ✅ 清理本地临时文件
rm -f "${BACKUP_FILE}"
env:
- name: DB_HOST
value: "postgresql.production.svc.cluster.local"
- name: DB_USER
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: password
- name: DB_NAME
value: "myapp"
- name: BACKUP_BUCKET
value: "myapp-prod-backups"
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
serviceAccountName: backup-sa # ✅ 使用 IRSA 访问 S3
---
# ✅ VolumeSnapshot 定期快照
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: postgresql-snapshot
namespace: production
spec:
volumeSnapshotClassName: csi-aws-ebs
source:
persistentVolumeClaimName: data-postgresql-0检测方法
# 检查 RDS 实例的备份配置
aws rds describe-db-instances --query \
'DBInstances[*].{ID:DBInstanceIdentifier,Backup:BackupRetentionPeriod,MultiAZ:MultiAZ,Encrypted:StorageEncrypted}' \
--output table
# 检查 S3 存储桶版本控制
aws s3api get-bucket-versioning --bucket my-bucket
# Checkov 检查备份配置
checkov -d terraform/ --check CKV_AWS_16,CKV_AWS_17,CKV_AWS_133
# CKV_AWS_16: RDS 加密
# CKV_AWS_17: RDS 备份保留期
# CKV_AWS_133: RDS 删除保护
# 检查 Kubernetes 中是否有备份 CronJob
kubectl get cronjobs -A | grep -i backupSteering 规则
## 备份与灾难恢复规则
- 所有数据库必须配置自动备份,生产环境保留至少 30 天
- RDS 必须设置 backup_retention_period > 0
- 生产数据库必须设置 deletion_protection = true
- 生产数据库必须设置 skip_final_snapshot = false
- S3 存储桶必须启用版本控制(versioning)
- 关键数据必须有跨区域复制或备份
- 必须定义 RTO 和 RPO 并在资源标签中标注
- Kubernetes 有状态服务必须有 CronJob 备份或 VolumeSnapshot 策略
- 备份恢复流程必须有文档化的运行手册
- 每季度至少进行一次备份恢复演练10. 其他 DevOps 反模式
除了上述六大核心反模式外,以下是 AI 生成 DevOps 配置中常见的其他问题:
10.1 CI/CD 管线反模式
反模式:未固定 Action 版本
# ❌ 使用标签引用——可能被供应链攻击篡改
- uses: actions/checkout@v4
- uses: docker/build-push-action@latest
# ✅ 固定到 commit SHA
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0反模式:过度权限的 GITHUB_TOKEN
# ❌ 默认权限过大
# 不声明 permissions 意味着使用仓库默认权限(通常是 write-all)
# ✅ 最小权限原则
permissions:
contents: read
pull-requests: write
packages: write反模式:单体管线
# ❌ 所有步骤在一个 job 中,失败后全部重跑
jobs:
everything:
runs-on: ubuntu-latest
steps:
- run: npm install # 5 分钟
- run: npm test # 10 分钟
- run: npm run build # 5 分钟
- run: docker build # 5 分钟
- run: docker push # 3 分钟
- run: kubectl apply # 1 分钟
# 如果 kubectl apply 失败,需要重跑全部 29 分钟
# ✅ 分阶段管线,支持部分重跑
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm install && npm test
build:
needs: test
runs-on: ubuntu-latest
steps:
- run: npm run build && docker build && docker push
deploy:
needs: build
runs-on: ubuntu-latest
environment: production # ✅ 需要人工审批
steps:
- run: kubectl apply10.2 Infrastructure as Code 反模式
反模式:状态文件不安全
# ❌ 本地状态文件——团队无法协作,状态可能丢失
# 没有配置 backend
# ✅ 远程状态 + 加密 + 锁定
terraform {
backend "s3" {
bucket = "myproject-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
# ✅ 状态文件加密存储
# ✅ DynamoDB 防止并发修改
}
}反模式:缺少标签
# ❌ 资源没有标签——无法追踪成本和所有权
resource "aws_instance" "app" {
instance_type = "t3.medium"
ami = var.ami_id
}
# ✅ 统一标签策略
locals {
common_tags = {
Project = var.project
Environment = var.environment
Team = var.team
CostCenter = var.cost_center
ManagedBy = "terraform"
CreatedAt = timestamp()
}
}
resource "aws_instance" "app" {
instance_type = "t3.medium"
ami = var.ami_id
tags = merge(local.common_tags, { Name = "${var.project}-app" })
}10.3 容器与 Kubernetes 反模式
反模式:以 root 运行容器
# ❌ 默认以 root 运行
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]
# 容器内进程以 root 运行——被入侵后攻击者获得 root 权限
# ✅ 非 root 用户
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
RUN npm run build
FROM node:20-alpine
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
WORKDIR /app
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
USER appuser
EXPOSE 8080
CMD ["node", "dist/server.js"]反模式:使用 :latest 标签
# ❌ 使用 :latest——不可重现,可能导致意外更新
containers:
- name: app
image: myapp:latest
# ✅ 使用特定版本标签或 SHA
containers:
- name: app
image: myapp:v1.2.3
# 或使用 SHA digest
# image: myapp@sha256:abc123...反模式:缺少 Pod 安全上下文
# ❌ 没有安全上下文
spec:
containers:
- name: app
image: myapp:v1.0.0
# ✅ 完整的安全上下文
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1001
fsGroup: 1001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:v1.0.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL10.4 监控与告警反模式
反模式:告警疲劳
# ❌ 阈值过低,导致大量误报
- alert: HighCPU
expr: node_cpu_usage > 50 # ❌ 50% CPU 就告警——太敏感
for: 1m # ❌ 1 分钟就触发——太短
labels:
severity: critical # ❌ 全部标为 critical——无法区分优先级
# ✅ 合理的告警配置
- alert: HighCPU
expr: |
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 10m # ✅ 持续 10 分钟才触发
labels:
severity: warning # ✅ 合理的严重级别
annotations:
summary: "CPU 使用率持续偏高 - {{ $labels.instance }}"
runbook_url: "https://wiki.example.com/runbooks/high-cpu"反模式:缺少 SLO 驱动的告警
# ❌ 只有基础设施告警,没有业务 SLO 告警
# 知道 CPU 高但不知道用户是否受影响
# ✅ SLO 驱动的告警(错误预算消耗速率)
- alert: SLOErrorBudgetBurnRate
expr: |
(
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m]))
) > (14.4 * 0.001) # 14.4x burn rate for 99.9% SLO
for: 2m
labels:
severity: page
annotations:
summary: "错误预算快速消耗,用户正在受到影响"11. Steering 规则文件实战示例
11.1 完整的 CLAUDE.md DevOps 章节示例
以下是一个真实项目中 CLAUDE.md 的 DevOps 章节完整示例:
# CLAUDE.md
## 项目概述
SaaS 电商平台,部署在 AWS EKS 上,使用 Terraform 管理基础设施。
## DevOps 规则
### 基础设施
- IaC 工具:Terraform 1.9 + AWS Provider 5.x
- 所有基础设施变更必须通过 Terraform,禁止手动操作 AWS Console
- 状态文件存储在 s3://myproject-tfstate/,使用 DynamoDB 锁定
- 模块化结构:terraform/modules/ 存放可复用模块
### 安全红线(违反即阻止合并)
1. 禁止 0.0.0.0/0 入站规则(除 ALB 的 80/443)
2. 禁止硬编码任何密钥、密码、Token
3. 禁止 :latest 镜像标签
4. 禁止 privileged 容器
5. 禁止未加密的数据库和 S3 存储桶
6. 禁止未固定版本的 GitHub Actions
### 资源配置标准
| 环境 | EC2 | RDS | EKS Node |
|------|-----|-----|----------|
| dev | t3.small | db.t4g.micro | t3.medium |
| staging | t3.medium | db.t4g.small | t3.large |
| prod | m6i.large | db.r6g.large | m6i.xlarge |
### 必需配置清单
- [ ] 所有 K8s 工作负载有 livenessProbe + readinessProbe
- [ ] 所有容器有 resources.requests + resources.limits
- [ ] 所有资源有 common_tags(Project, Environment, Team, CostCenter)
- [ ] 数据库有自动备份(生产 30 天,其他 7 天)
- [ ] 所有服务使用结构化 JSON 日志
- [ ] 每个命名空间有 default-deny NetworkPolicy11.2 完整的 Kiro Steering 目录结构
.kiro/
├── steering/
│ ├── devops-terraform.md # Terraform 专用规则
│ ├── devops-kubernetes.md # Kubernetes 专用规则
│ ├── devops-docker.md # Dockerfile 专用规则
│ ├── devops-cicd.md # CI/CD 专用规则
│ └── devops-security.md # 安全通用规则11.3 完整的 .cursorrules DevOps 示例
---
description: DevOps 和基础设施配置的代码生成规则
globs: "**/*.tf,**/*.tfvars,**/Dockerfile,**/*.yaml,**/*.yml,**/.github/**"
---
# DevOps 代码生成规则
## 安全默认值
生成任何 DevOps 配置时,必须默认包含以下安全措施:
- 网络:最小权限,默认拒绝
- 密钥:通过 Secrets Manager 引用,永不硬编码
- 容器:非 root 用户,只读文件系统
- 加密:所有存储和传输加密
- 标签:所有资源必须有标签
## 生成 Terraform 时
- 使用 terraform-aws-modules 官方模块
- 所有变量有 description 和 type
- 敏感变量标记 sensitive = true
- 输出值有 description
- 使用 locals 定义通用标签
## 生成 Kubernetes 时
- 所有 Pod 有 securityContext(runAsNonRoot, readOnlyRootFilesystem)
- 所有容器有 resources(requests + limits)
- 所有 Deployment 有 livenessProbe + readinessProbe
- 使用 Kustomize 或 Helm 管理环境差异
## 生成 Dockerfile 时
- 多阶段构建
- 非 root 用户(USER 指令)
- 特定版本基础镜像(禁止 :latest)
- HEALTHCHECK 指令
- .dockerignore 文件
## 生成 CI/CD 时
- Action 固定到 SHA
- 最小权限 permissions
- 密钥使用 ${{ secrets.XXX }}
- 安全扫描步骤(Trivy/Checkov)12. DevOps Prompt 工程技巧
12.1 DevOps 专用 Prompt 模式
模式 1:安全审查 Prompt
你是一位资深 DevOps 安全工程师。请审查以下基础设施配置,
按 OWASP Infrastructure Security 标准检查安全问题。
## 配置文件
[粘贴配置]
## 审查维度
1. 网络安全(安全组、防火墙、网络隔离)
2. 身份与访问(IAM、RBAC、最小权限)
3. 数据保护(加密、备份、密钥管理)
4. 日志与监控(审计日志、告警、可追溯性)
5. 合规性([SOC 2 / HIPAA / PCI DSS])
## 输出格式
对每个发现的问题:
- 严重程度:🔴 高 / 🟡 中 / 🟢 低
- 问题描述
- 影响分析
- 修复代码
- 对应的 CIS Benchmark 或 Checkov 检查 ID模式 2:成本优化 Prompt
你是一位云成本优化专家。请分析以下基础设施配置的成本效率,
并提供优化建议。
## 当前配置
[粘贴 Terraform/K8s 配置]
## 环境信息
- 环境类型:[dev / staging / prod]
- 预期流量:[描述]
- 预算限制:[月度预算]
## 请提供
1. 当前配置的预估月度成本
2. 过度配置的资源列表
3. 具体的降配建议(保持性能的前提下)
4. 预估优化后的月度成本
5. 优化后的配置代码模式 3:灾难恢复规划 Prompt
你是一位 SRE 专家。请为以下系统设计灾难恢复策略。
## 系统架构
[描述系统架构和关键组件]
## 业务要求
- RTO(恢复时间目标):[例如:4 小时]
- RPO(恢复点目标):[例如:1 小时]
- 数据保留要求:[例如:7 年]
## 请提供
1. 备份策略(频率、存储位置、保留期)
2. 故障转移方案(自动/手动、跨区域/跨可用区)
3. 恢复流程运行手册
4. 恢复测试计划(频率、范围、验证标准)
5. 完整的 Terraform/K8s 配置代码12.2 AI 辅助 DevOps 配置审查工作流
┌─────────────────────────────────────────────────────────────┐
│ AI 辅助 DevOps 配置审查工作流 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 步骤 1: AI 生成配置 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 需求描述 │───▶│ AI 生成 │───▶│ 初始配置 │ │
│ │ + Steering│ │ 配置代码 │ │ 文件 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │
│ 步骤 2: 自动化安全扫描 │
│ ┌──────────┐ ┌──────────┐ ┌────▼─────┐ │
│ │ Checkov │ │ tfsec │ │ Trivy │ │
│ │ 扫描 │ │ 扫描 │ │ 扫描 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ └───────────────┼───────────────┘ │
│ ▼ │
│ 步骤 3: AI 修复扫描发现 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 扫描报告 │───▶│ AI 分析 │───▶│ 修复后 │ │
│ │ + 配置 │ │ 并修复 │ │ 配置 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │
│ 步骤 4: 人工审查 │
│ ┌──────────┐ ┌──────────┐ ┌────▼─────┐ │
│ │ 安全审查 │ │ 成本审查 │ │ 架构审查 │ │
│ │ (安全组) │ │(Infracost)│ │ (设计) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ └───────────────┼───────────────┘ │
│ ▼ │
│ 步骤 5: 合并与部署 │
│ ┌──────────────────────────────────────┐ │
│ │ PR 合并 → CI/CD 管线 → 部署到目标环境 │ │
│ └──────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘实战案例:从零构建安全的 DevOps 配置
案例背景
一个电商 SaaS 项目需要部署到 AWS EKS,包含以下组件:
- Web API(Node.js)
- 后台任务处理(Go)
- PostgreSQL 数据库
- Redis 缓存
- GitHub Actions CI/CD
案例流程
第一步:创建 Steering 规则
在项目根目录创建 .kiro/steering/devops.md(或 CLAUDE.md 中添加 DevOps 章节),包含本文第 2 节中的完整规则模板。
第二步:让 AI 生成基础设施配置
使用以下 Prompt:
请为电商 SaaS 项目生成完整的 AWS EKS 基础设施配置。
## 组件
- Web API(Node.js 20,3 个副本)
- Worker(Go 1.22,2 个副本)
- PostgreSQL 16(RDS)
- Redis 7(ElastiCache)
## 环境
- 当前生成 production 环境配置
- 必须支持 dev/staging/prod 三个环境参数化
## 安全要求
遵循项目 Steering 规则中的所有安全约束。
## 请生成
1. Terraform 模块(VPC + EKS + RDS + ElastiCache + IAM)
2. Kubernetes manifests(Deployment + Service + Ingress + NetworkPolicy + HPA)
3. Dockerfile(多阶段构建)
4. GitHub Actions 工作流(构建 + 测试 + 安全扫描 + 部署)第三步:运行安全扫描
# Terraform 安全扫描
checkov -d terraform/ --output cli --compact
# Kubernetes 安全扫描
checkov -d k8s/ --framework kubernetes --output cli
# Dockerfile 安全扫描
trivy config Dockerfile
# 密钥扫描
gitleaks detect --source . --verbose第四步:AI 修复扫描发现的问题
将扫描报告反馈给 AI:
以下是 Checkov 扫描报告,请修复所有 FAILED 的检查项:
[粘贴 Checkov 输出]
请逐一修复,并解释每个修复的原因。第五步:成本审查
# 生成成本报告
infracost breakdown --path terraform/ --format html --out-file cost-report.html案例分析
通过 Steering 规则 + AI 生成 + 自动化扫描 + 人工审查的四层防护,可以显著提高 AI 生成 DevOps 配置的质量:
- Steering 规则:在 AI 生成阶段就注入安全约束,减少 60-70% 的安全问题
- 自动化扫描:捕获 Steering 规则未覆盖的问题,如特定云服务的安全配置
- AI 修复:快速修复扫描发现的问题,减少人工修复时间
- 人工审查:最终的质量把关,确保架构合理性和业务适配性
避坑指南
❌ 常见错误
-
只依赖 Steering 规则而不做安全扫描
- 问题:Steering 规则是”建议”,AI 可能不完全遵守;且规则无法覆盖所有安全场景
- 正确做法:Steering 规则 + 自动化扫描(Checkov/tfsec/Trivy)双重保障
-
在 Git 中提交了密钥后只删除文件
- 问题:Git 历史中仍然保留密钥,任何人都可以通过
git log查看 - 正确做法:立即轮换泄露的密钥,使用
git filter-branch或 BFG Repo-Cleaner 清理历史,配置 pre-commit hook 防止再次发生
- 问题:Git 历史中仍然保留密钥,任何人都可以通过
-
开发环境和生产环境使用相同的安全配置
- 问题:开发环境的宽松配置被复制到生产环境
- 正确做法:使用环境变量或 tfvars 文件区分环境,生产环境使用更严格的安全设置
-
liveness 探针检查外部依赖
- 问题:数据库故障时所有 Pod 被杀死,导致级联故障
- 正确做法:liveness 只检查进程存活,readiness 检查外部依赖
-
备份从未测试过恢复
- 问题:关键时刻发现备份损坏或恢复流程不可用
- 正确做法:每季度进行备份恢复演练,验证 RTO 和 RPO 是否满足要求
-
CI/CD 使用 @latest 引用 Action
- 问题:供应链攻击可以通过篡改 Action 代码注入恶意代码
- 正确做法:固定到 commit SHA,定期审查和更新
-
所有告警都标为 critical
- 问题:告警疲劳,团队开始忽略告警
- 正确做法:分级告警(info/warning/critical/page),只有真正影响用户的问题才 page
-
Docker 镜像使用 :latest 标签
- 问题:部署不可重现,可能意外引入破坏性变更
- 正确做法:使用语义化版本标签(v1.2.3)或 SHA digest
✅ 最佳实践
- 安全左移:在 AI 生成阶段就通过 Steering 规则注入安全约束,而非事后修复
- 自动化门禁:CI/CD 中集成 Checkov、tfsec、Trivy、GitGuardian 等扫描工具,不通过不合并
- 环境参数化:所有配置通过变量区分环境,禁止硬编码环境特定值
- 最小权限原则:网络、IAM、容器权限都遵循最小权限,显式开放而非默认开放
- 可观测性优先:每个服务必须有结构化日志、健康检查和 Prometheus 指标
- 备份即代码:备份策略写在 Terraform/K8s 配置中,与基础设施一起版本化管理
- 定期演练:每季度进行灾难恢复演练和安全审计
- 成本可见:每个 PR 都显示成本影响(Infracost),让成本成为审查的一部分
相关资源与延伸阅读
- Checkov — IaC 静态分析工具 :开源的 IaC 安全扫描工具,支持 Terraform、Kubernetes、Docker 等,内置 2000+ 安全策略
- tfsec — Terraform 安全扫描 :专注于 Terraform 的安全扫描工具,现已集成到 Trivy
- Infracost — IaC 成本估算 :在 PR 中显示基础设施变更的成本影响,支持 Terraform 和 OpenTofu
- GitGuardian — 密钥泄露检测 :扫描 Git 仓库中的密钥泄露,支持 pre-commit hook 和 CI/CD 集成
- OPA/Rego — 策略即代码 :通用策略引擎,可用于 Kubernetes 准入控制、Terraform 策略执行等
- Kubernetes Security Best Practices — OWASP :OWASP Kubernetes 安全速查表
- CIS Benchmarks :CIS 安全基准,覆盖 AWS、Kubernetes、Docker 等平台的安全配置标准
- HashiCorp Well-Architected Framework — CI/CD Anti-Patterns :HashiCorp 关于 CI/CD 密钥管理反模式的官方指南
- Cloud Security Alliance — AI and Deterministic Security for Infra :CSA 关于 AI 生成 IaC 代码安全性的研究报告(2025)
- Endor Labs — Design Flaws in AI Generated Code :AI 生成代码中的设计缺陷分析(2025)
参考来源
- Cloud Security Alliance — Understanding Security Risks in AI-Generated Code (2025-07)
- Endor Labs — Design Flaws in AI Generated Code (2025-06)
- Pixee.ai — The 2.74× Problem: AI Code Ships With Nearly 3× More Security Flaws (2025-08)
- Palo Alto Networks — AI’s Hidden Security Debt (2025-07)
- HashiCorp — Well-Architected Framework: CI/CD Secrets Anti-Patterns (2025)
- EM360Tech — CI/CD Anti-Patterns: What’s Slowing Down Your Pipeline? (2026-01)
- OneUptime — How to Implement Health Checks That Distinguish Between Liveness and Readiness (2026-02)
- Kubeasy — Understanding Kubernetes Probes: Liveness, Readiness & Startup (2026-02)
- CSO Online — AI coding assistants amplify deeper cybersecurity risks (2026-01)
- InfoQ — AI-Generated Code Creates New Wave of Technical Debt (2025-11)
📖 返回 总览与导航 | 上一节:32e-AI辅助监控与事件响应 | 下一节:33a-AI辅助移动端开发概览