{T}

📅 原文发布:2018-2019 | 本次更新:2025-06 | 更新等级:🔴全面重写增强 📌 v2 结构化升级:2026-08 | 升级范围:补齐 6 节标准骨架、Mermaid 图加标题、术语英文对照、参考资料融入进阶延展

15 | 开发和测试争抢环境?是时候进行多环境建设了

一、导言

在上一期文章里,笔者介绍了多环境下的应用配置管理问题,从这期开始,会分两期文章详细探讨多环境建设的问题:到底需要哪些环境?这些环境都有什么作用?环境建设的思路和方式是怎样的?

本文就结合笔者的经验和理解与读者探讨持续交付中的 线下多环境建设(Offline Multi-Environment Construction)

问题背景

比较典型的场景就是,测试人员正在验证一个功能,突然发现应用停止运行了——原来开发为了验证和尽快发布新功能,更新了代码。这样就阻塞了测试的正常工作;但不更新代码,开发的工作又会停滞下来。开发与测试在同一套环境下相互争抢,是持续交付体系建设中最早暴露的痛点之一。

核心矛盾

环境建设本质上要解决的是 "环境数量有限" 与 "使用方需求冲突" 之间的矛盾。在云原生(Cloud Native)时代,这一矛盾的解法已经从"物理/虚拟机独立部署"演化为 "Kubernetes Namespace + GitOps" 的弹性模式。


二、核心方法论

环境分类

通常,主要按照环境所起到的作用,将环境分为两大类:

  • 线下环境(Offline Environment):测试验收用
  • 线上环境(Online Environment):为用户提供服务

从建设角度来说,线下环境和线上环境,在网段上是要严格隔离的。这一点在做环境建设时就要确定网络规划,同时在网络设备或者虚拟网络的访问策略上要严格限定两个环境的互通。如果限制不严格,就极易引起线上故障,甚至是信息安全问题。

图表渲染中…

线下环境三层模型(保留价值)

原版将线下环境分为三层,这个分层思路在 2025 年依然有效,但实现方式发生了根本变化:

层级定位2019 实现2025 实现
集成测试环境(Integration/Staging)最重要,与生产同步独立物理环境 + 手工发布ArgoCD Application 自动 sync main 分支
开发测试环境(Development)日常开发联调一套共享开发环境每开发者/每分支独立 Preview Environment
项目环境(Project/Epic)大型项目独立联调按需申请 VM 部署ApplicationSet + Webhook 自动创建销毁

核心矛盾依然存在

原版描述的经典场景在今天依然成立,但解法已经根本性改变:从"如何在一套共享环境下协调开发与测试" 转向 "如何让每个开发者都能独立拥有一套环境"。


三、关键流程

技术演进时间线

图表渲染中…

2025 年环境架构全景

图表渲染中…

流程一:集成测试环境建设流程

集成测试环境(Integration/Staging)是整个线下环境中 最重要 的一环,定位是供测试使用,最大程度与线上版本保持同步,作为功能、需求、业务流程正式上线前验证的主要环境。

2025 年实现方式

yaml
# ArgoCD Application for Staging
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-staging
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/org/my-app.git
    targetRevision: main          # 追踪main分支
    path: k8s/overlays/staging
  destination:
    server: https://kubernetes.default.svc
    namespace: staging
  syncPolicy:
    automated:
      prune: true                 # 自动清理多余资源
      selfHeal: true              # 自动修复漂移
    syncOptions:
    - CreateNamespace=true

关键要求(2025版)

  • 与生产环境使用相同的镜像 tag 策略(如固定 digest)
  • 共用生产环境的有状态服务(DB、缓存等),数据真实
  • 有严格的发布准入规则(CI 全部通过才能 sync)
  • 配置完整的可观测性(日志、监控、链路追踪)
  • 稳定性保障:不允许随意变更,变更需走 PR 流程

流程二:开发测试环境 - 从"一套"到"每人一套"

原版痛点:开发和测试争抢集成测试环境 → 建设第二套开发测试环境。

2025 年的革命性变化:从"一套共享的开发环境"变为 "每个开发者/每个分支一个独立的临时环境"

方案 A:基于 PR 的 Preview Environment(推荐)

图表渲染中…

工具支持

  • ArgoCD Preview —— 原生支持 PR-based preview environments
  • Knative Serving —— Serverless 模式,按需自动缩容到零
  • Tilt / Nixpacks —— 本地开发环境快速启动

方案 B:固定开发命名空间(轻量级)

如果 Preview Environment 成本太高,可以采用固定命名空间方案:

bash
# 每个开发者分配自己的命名空间
kubectl create namespace dev-alice
kubectl create namespace dev-bob
kubectl create namespace dev-charlie

# 通过RBAC限制每个开发者只能操作自己的namespace

关键改进点(对比原版)

  • 不再需要"最小化原则"省资源 —— K8s 资源配额(Request/Limit)+ HPA 自动解决
  • 不再需要手动维护 hosts —— Kubernetes Service + Ingress/Gateway API 自动处理 DNS
  • 不再担心环境影响他人 —— Namespace 天然隔离

流程三:项目环境生命周期

原版场景:大促期间多项目并行,需要独立的项目环境。

2025 年的做法

图表渲染中…

自动化实现(ArgoCD ApplicationSet + Webhook)

yaml
# 当Jira Epic创建时,通过webhook触发环境创建
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: project-environments
spec:
  generators:
  - pullRequest:
      github:
        owner: org
        repo: my-app
        tokenRef:
          secretName: github-token
          key: token
      rebase: false
  template:
    metadata:
      name: 'project-pr-{{number}}'
    spec:
      source:
        repoURL: https://github.com/org/my-app.git
        targetRevision: '{{head_sha}}'
        path: k8s/overlays/project
      destination:
        server: https://kubernetes.default.svc
        namespace: 'project-{{number}}'
      syncPolicy:
        automated: {}           # PR关闭后自动清理

成本控制机制

  • 设置 ResourceQuota 限制项目环境总资源
  • 使用 HPA 让空闲环境自动缩容
  • 项目结束后 7 天自动销毁(可延期)
  • 只有公司级战略项目才允许创建独立项目环境

四、工具与实战

关键技术点演进(2019 → 2025)

原版提到四个关键技术点:网段规划、服务化框架单元化调用、域名访问策略、自动化管理。在 K8s 时代,这些都有了全新的实现方式。

技术点 1:"网段规划" → Namespace + NetworkPolicy

图表渲染中…

NetworkPolicy 示例

yaml
# 生产环境 - 默认拒绝所有入站,只允许特定来源
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: production-deny-all-ingress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress: []  # 空数组 = deny all

---
# 允许ingress controller访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ingress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: my-app
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-nginx
    ports:
    - protocol: TCP
      port: 8080

技术点 2:"服务化框架单元化调用" → K8s Service + DNS

原版的服务化框架单元化调用(基于 ConfigServer 的规则调用),在 K8s 中变得极其简单:

图表渲染中…

核心优势:不需要在 ConfigServer 中维护复杂的调用规则,K8s DNS 天然支持基于 namespace 的服务发现隔离。

技术点 3:"域名访问策略" → Ingress / Gateway API + 自动 DNS

原版提到的四种域名方案(多套 DNS、hosts 绑定、路由劫持等),在 2025 年有了优雅的解决方案:

图表渲染中…

Gateway API(推荐替代 Ingress 的新一代方案)

yaml
# 为不同环境自动生成不同的访问地址
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: my-app-route
  namespace: staging
spec:
  parentRefs:
  - name: internal-gateway
    namespace: network
  hostnames:
  - "myapp.staging.internal"
  rules:
  - backendRefs:
    - name: my-app-svc
      port: 8080

配合 ExternalDNS,每次创建新的 HTTPRoute 时自动在 Cloudflare/Route53 中创建对应的 DNS 记录。

技术点 4:"自动化管理" → GitOps + IaC + Platform API

原版提到要以应用为核心进行管理。2025 年的实现:

图表渲染中…

环境矩阵总结

环境目标用户数据真实性稳定性要求生命周期资源规模自动化程度
Dev (per-dev)开发者个人Mock/部分真实跟随分支极小(按需)全自动(PR触发)
Integration/StagingQA团队接近真实持续运行中等GitOps自动同步
Project/Epic特定项目组接近真实项目周期按需分配申请→自动创建→到期销毁
Pre-productionDev+QA+运维真实(共用有状态)很高持续运行小规模GitOps+人工审批
Canary/Beta少量真实用户完全真实发布期间极小(1-2pod)渐进式交付自动管理
Production所有用户完全真实最高持续运行全量GitOps+渐进式发布
Office Production内部员工完全真实活动期间中小规模GitOps

成本优化策略

原版提到"环境并不是越多越好,反而是越精简越好"。在云原生时代,我们可以更精细地控制成本:

图表渲染中…

具体实践

yaml
# ResourceQuota示例 - 限制dev namespace的总资源
apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: dev
spec:
  hard:
    requests.cpu: "10"
    requests.memory: 20Gi
    limits.cpu: "20"
    limits.memory: 40Gi
    persistentvolumeclaims: "5"
    pods: "50"
yaml
# CronHPA - 工作时间扩展,下班后收缩
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-dev-hpa
  namespace: dev
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 1
  maxReplicas: 3
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  behavior:
    scaleDown:
      policies:
      - type: Percent
        value: 100
        periodSeconds: 60
      stabilizationWindowSeconds: 300
    scaleUp:
      stabilizationWindowSeconds: 0

工具选型矩阵

场景推荐方案替代方案不推荐
环境隔离K8s Namespace + NetworkPolicy单独Cluster(过重)无隔离
Preview环境ArgoCD ApplicationSet (PR generator)Knative Serving, Tilt手动创建namespace
环境同步ArgoCD / FluxCDJenkins X, Rancherkubectl apply手动
DNS管理ExternalDNS + Gateway APIIngress + 手动DNShosts文件绑定
成本监控OpenCost / Kubecost自建Prometheus queries无成本可视
资源配额K8s ResourceQuota + LimitRange无限制
自助服务Backstage (Spotify)Port, Humanitic工单系统
环境模板Golden Path Templates每次从头搭建

落地 Checklist

环境规划

  • 是否确定了完整的环境清单和每种环境的用途
  • 每种环境的网络隔离策略是否明确
  • 是否制定了环境创建/销毁的标准流程

K8s基础设施

  • Namespace 划分方案是否已确定
  • NetworkPolicy 是否已覆盖所有环境(特别 production)
  • ResourceQuota 是否已设置(防止资源滥用)
  • RBAC 权限模型是否符合最小权限原则

GitOps 配置

  • ArgoCD/Flux 是否已部署
  • 每个环境的 Application/ApplicationSet 是否已定义
  • 同步策略是否合理(哪些自动同步,哪些需要审批)
  • 是否配置了健康检查和告警

访问管理

  • 外部访问入口(Ingress/Gateway API)是否已配置
  • ExternalDNS 是否已集成(自动 DNS 记录)
  • TLS 证书管理(cert-manager)是否正常工作
  • 认证鉴权(OAuth/OIDC)是否已配置

开发体验

  • Preview Environment 是否可用(PR 触发自动创建)
  • 开发者是否能自助创建需要的开发环境
  • 环境创建到可用的等待时间是否 < 5 分钟
  • 日志/调试信息是否易于获取

成本控制

  • 是否有各环境的成本可视化面板
  • 空闲环境是否有自动回收机制
  • 是否设置了预算上限和超限告警
  • 定期 review 环境使用率,清理废弃环境

五、常见误区

code
❌ 陷阱1:"Namespace爆炸"
   症状:几百个namespace没人清理
   根因:只有创建没有销毁机制
   后果:etcd压力大,apiserver变慢,资源浪费
   解法:TTL Controller + 定期审计 + 自动清理策略

❌ 陷阱2:"测试环境与生产环境差异过大"
   症状:测试通过了但上线就挂
   根因:test环境用了mock数据/简化配置
   后果:测试形同虚设
   解法:Staging环境尽量复用生产基础设施和数据结构

❌ 陷阱3:"开发环境互相影响"
   症状:Alice的代码把Bob的环境搞崩了
   根因:共享开发环境没有做资源隔离
   后果:团队协作效率下降
   解法:每人独立namespace + ResourceQuota硬限制

❌ 陷阱4:"环境状态不可重现"
   症状:"我这边好的啊,你那边怎么不行"
   根因:环境配置靠人肉记忆,没有声明式管理
   后果:Debug时间大量浪费
   解法:GitOps + 一切皆代码 + 配置漂移检测

❌ 陷阱5:"忽略预发环境的重要性"
   症状:直接从staging上production
   根因:觉得preprod多余浪费资源
   后果:生产数据相关问题无法提前发现
   解法:Preprod是线上发布的最后一道防线,必须有

❌ 陷阱6:"环境越多越好"
   症状:为每种场景都建独立环境
   根因:缺乏ROI评估
   后果:维护成本指数增长
   解法:定期评估每个环境的使用率和价值,精简合并低价值环境

六、进阶延展

2019 → 2025 核心变化总结

维度2019年2025年
隔离方式物理网段/VLANK8s Namespace + NetworkPolicy
环境创建人工申请+手工部署PR触发自动创建 / 自助Portal申请
DNS/访问hosts绑定 / 路由劫持Gateway API + ExternalDNS自动DNS
服务调用隔离ConfigServer规则K8s DNS + Service FQDN天然隔离
资源管理手工分配VMResourceQuota + HPA自动伸缩
成本控制靠人肉意识OpenCost可视化 + 自动回收
生命周期建了就不拆TTL / PR关闭自动销毁

内部开发者平台(IDP)方向

环境建设的下一阶段是 平台工程(Platform Engineering)内部开发者门户(Internal Developer Portal, IDP) 的融合:

  • Backstage / Port:统一的环境目录与黄金路径(Golden Path)模板
  • Environment as a Service:开发者通过声明式申请单自助获取环境
  • AI 辅助诊断:环境异常自动定位,给出修复建议
  • FinOps 内嵌:环境成本与业务价值直接挂钩,形成闭环

关键术语对照

中文英文
线下多环境建设Offline Multi-Environment Construction
集成测试环境Integration / Staging Environment
预发环境Pre-production Environment
临时环境Ephemeral Environment
平台工程Platform Engineering
内部开发者门户Internal Developer Portal (IDP)
黄金路径Golden Path
资源配额Resource Quota
配置漂移Configuration Drift
软件物料清单Software Bill of Materials (SBOM)

参考资料融入

  • 原版《运维体系管理》系列第 14 期:多环境配置管理(前置阅读)
  • 原版《运维体系管理》系列第 16 期:线上环境建设(后续阅读)
  • ArgoCD 官方文档:ApplicationSet 与 Preview Environment
  • Kubernetes SIG Network:Gateway API 与 NetworkPolicy 最佳实践
  • CNCF 白皮书:Platform Engineering Maturity Model
  • OpenCost / Kubecost:Kubernetes 成本可视化的开源标准

读者互动

最后,在实际操作中,仍然会有很多细节问题,这些问题会跟业务场景有关。读者在环境建设过程中遇到过哪些问题?有什么更好的经验或建议?欢迎在团队内复盘时沉淀属于自己组织的多环境建设手册。