前言
在 Serverless 应用开发中,多环境配置是一个绕不开的话题。从开发、测试到生产,每个环境都有其特定的配置需求。阿里云 Serverless Devs 虽然提供了官方的 env
命令来管理多环境,但在实际使用中,我发现官方方案存在一些局限性。
本文将通过四个实际案例,展示 Serverless FC 多环境配置的演进过程,从基础验证到最终的最佳实践方案。通过对比分析,帮助开发者选择最适合的多环境配置策略。
技术背景
多环境配置的核心挑战
在 Serverless 架构中,多环境配置面临以下挑战:
- 配置复用:避免在不同环境中重复相同的配置
- 环境隔离:确保不同环境的配置相互独立
- 灵活配置:支持动态配置和敏感信息管理
- 维护成本:降低配置管理的复杂度
Serverless Devs 多环境支持现状
Serverless Devs 提供了两种多环境配置方式:
- 官方 env 命令:通过
env.yaml
集中管理所有环境配置 - 自定义方案:通过模板继承、环境变量等方式实现
项目架构设计
项目整体结构
我们的测试项目包含四个不同的多环境配置方案:
p07/
├── a/ # 方案一:模板元数据
│ ├── s.yaml
│ └── code/
├── b/ # 方案二:环境变量配置
│ ├── s.yaml
│ └── code/
├── c/ # 方案三:模板继承
│ ├── s.yaml
│ ├── s-dev.yaml
│ ├── s-prod.yaml
│ └── code/
├── d/ # 方案四:综合方案(推荐)
│ ├── s.yaml
│ ├── s-dev.yaml
│ ├── s-prod.yaml
│ └── code/
└── readme.md
方案验证:从基础到高级
方案一:模板元数据验证
验证目的:理解 template
字段的配置复用能力
# a/s.yaml
edition: 3.0.**0**
name: fc3-example
access: default
vars:
projectName: practice-07
template:
# 模板信息
t1:
# 模板名称
region: cn-shenzhen
timeout: 60
diskSize: 512
internetAccess: true
runtime: python3.10
cpu: 0.35
memorySize: 512
resources:
index:
component: fc3
extend:
name: t1
props:
handler: index.handler
functionName: ${vars.projectName}-${this.name}
code: ./code
运行结果:
$ s preview
edition: 3.0.0
name: fc3-example
access: default
vars:
projectName: practice-07
template:
t1:
region: cn-shenzhen
timeout: 60
diskSize: 512
internetAccess: true
runtime: python3.10
cpu: 0.35
memorySize: 512
resources:
index:
component: fc3
extend:
name: t1
props:
region: cn-shenzhen
timeout: 60
diskSize: 512
internetAccess: true
runtime: python3.10
cpu: 0.35
memorySize: 512
handler: index.handler
functionName: practice-07-index
code: ./code
验证结论:
- ✅ 解决了配置重复问题
- ❌ 缺乏环境差异化能力
- ❌ 所有环境使用相同配置
方案二:环境变量验证
验证目的:理解环境变量的动态配置能力
# b/s.yaml
edition: 3.0.0
name: fc3-example
access: default
vars:
projectName: practice-07
resources:
index:
component: fc3
props:
handler: index.handler
functionName: ${vars.projectName}-${this.name}-${env('DEV_ENV')}
code: ./code
region: cn-shenzhen
runtime: python3.10
environmentVariables:
env: ${env('DEV_ENV')}
tags:
env: ${env('DEV_ENV')}
运行结果:
$ DEV_ENV='abc' s preview
edition: 3.0.0
name: fc3-example
access: default
vars:
projectName: practice-07
resources:
index:
component: fc3
props:
handler: index.handler
functionName: practice-07-index-abc
code: ./code
region: cn-shenzhen
runtime: python3.10
environmentVariables:
env: abc
tags:
env: abc
验证结论:
- ✅ 提供了灵活性
- ✅ 支持动态配置
- ❌ 配置管理复杂
- ❌ 需要手动管理环境变量
💡 对于非常简单的项目,配置是有规律,也是可以使用这种方式进行配置。
方案三:模板继承验证
验证目的:理解 extend
字段的环境隔离能力
# c/s.yaml - 基础配置
edition: 3.0.0
name: fc3-example
access: default
vars:
projectName: practice-07
resources:
index:
component: fc3
props:
handler: index.handler
functionName: ${vars.projectName}-${this.name}
code: ./code
region: cn-shenzhen
internetAccess: true
runtime: python3.10
# c/s-prod.yaml - 生产环境配置
extend: s.yaml
resources:
index:
props:
handler: ${this.name}.handler
functionName: ${vars.projectName}-${this.name}-prod
code: ./code
environmentVariables:
DEV_ENV: env-prod
tags:
TAG1: tag-prod
运行结果:
$ s preview -t s-prod.yaml
edition: 3.0.0
name: fc3-example
access: default
vars:
projectName: practice-07
resources:
index:
component: fc3
props:
handler: index.handler
functionName: practice-07-index-prod
code: ./code
region: cn-shenzhen
internetAccess: true
runtime: python3.10
environmentVariables:
DEV_ENV: env-prod
tags:
TAG1: tag-prod
验证结论:
- ✅ 实现了环境隔离
- ✅ 配置文件结构清晰
- ❌ 仍有配置冗余,当 resources 越来越多的时候,
s.yaml
就会越来越繁琐 - ✅ 有一定的动态配置能力
💡 对于简单的项目,多环境的配置方法,已经是足够了。
最佳实践:方案四深度解析
设计理念
方案四完美结合了前三个方案的优点:
- 模板元数据:解决配置复用问题
- 模板继承:实现环境隔离
- 环境变量:提供灵活配置
代码架构分析
基础配置:d/s.yaml
edition: 3.0.0
name: fc3-example
access: default
vars:
projectName: practice-07
template:
# 模板信息
t1:
# 模板名称
region: cn-shenzhen
internetAccess: true
runtime: python3.10
tags:
project: ${vars.projectName}
resources:
index:
component: fc3
extend:
name: t1
props:
handler: index.handler
functionName: ${vars.projectName}-${this.name}
code: ./code
开发环境配置:d/s-dev.yaml
extend: s.yaml
resources:
index:
props:
environmentVariables:
DEV_ENV: env-dev
tags:
TAG1: tag-dev
生产环境配置:d/s-prod.yaml
extend: s.yaml
resources:
index:
props:
environmentVariables:
DEV_ENV: ${env('DEV_ENV')}
tags:
TAG1: ${env('TAG1')}
运行结果分析
$ TAG1='tag-prod' DEV_ENV='prod' s preview -t s-prod.yaml
edition: 3.0.0
name: fc3-example
access: default
vars:
projectName: practice-07
template:
t1:
region: cn-shenzhen
internetAccess: true
runtime: python3.10
tags:
project: practice-07
resources:
index:
component: fc3
extend:
name: t1
props:
region: cn-shenzhen
internetAccess: true
runtime: python3.10
tags:
project: practice-07
TAG1: tag-prod
handler: index.handler
functionName: practice-07-index
code: ./code
environmentVariables:
DEV_ENV: prod
核心优势
- ✅ 配置复用:通过模板元数据避免重复
- ✅ 环境隔离:通过文件分离实现清晰隔离
- ✅ 灵活配置:通过环境变量处理敏感信息
- ✅ 易于维护:配置文件结构清晰
官方 env 命令的局限性分析
为什么不使用官方的 env
命令呢?
官方方案介绍
Serverless Devs 提供了 env
命令来管理多环境:
# 初始化环境
s env init --name dev
# 设置默认环境
s env default --name dev
# 使用环境部署
s deploy --env dev
核心缺陷
1. 配置集中化问题
所有环境配置都集中在 env.yaml
中,随着环境增多,配置文件变得臃肿难维护。
2. 插入环境变量不够灵活
有些环境的变量是在文件中保存中保存的,有些是从环境变量中来的。
🤬🤬🤬 吐槽一波官方的 yaml
格式,继承和覆盖 过于强绑定,不够灵活,无法沿用之前的 yaml
理解。
方案四的实际应用
开发环境部署
# 开发环境部署,配置都是写死的
s deploy -t s-dev.yaml
生产环境部署
# 生产环境部署,部分的敏感信息可以在环境变量从传入的
TAG1='prod' DEV_ENV='production' s deploy -t s-prod.yaml
环境切换策略
# 快速切换环境
alias deploy-dev="TAG1='dev' DEV_ENV='development' s deploy -t s-dev.yaml"
alias deploy-prod="TAG1='prod' DEV_ENV='production' s deploy -t s-prod.yaml"
高级配置技巧
敏感信息处理
通过环境变量管理密钥、数据库连接等敏感信息:
# s-prod.yaml
extend: s.yaml
resources:
index:
props:
environmentVariables:
DATABASE_URL: ${env('DATABASE_URL')}
API_KEY: ${env('API_KEY')}
SECRET_TOKEN: ${env('SECRET_TOKEN')}
配置验证
使用 s preview
验证配置正确性:
# 验证开发环境配置
s preview -t s-dev.yaml
# 验证生产环境配置
TAG1='prod' DEV_ENV='production' s preview -t s-prod.yaml
最佳实践总结
推荐方案
方案四作为生产环境标准配置,完美解决了多环境配置的核心问题。
配置原则
- 基础配置模板化:通过
template
字段实现配置复用 - 环境差异文件化:增加多个环境的 yaml 文件,通过
extend
字段实现环境隔离,同时每个文件都是独立的 - 敏感信息环境变量化:通过
env()
函数处理敏感配置
文件组织
project/
├── s.yaml # 基础配置 + 模板元数据
├── s-dev.yaml # 开发环境差异配置
├── s-prod.yaml # 生产环境差异配置
└── code/ # 业务代码
部署命令标准化
# 开发环境
DEV_ENV='dev' s deploy -t s-dev.yaml
# 生产环境
DEV_ENV='prod' s deploy -t s-prod.yaml
总结
方案回顾
通过四个方案的演进,我们看到了 Serverless 多环境配置的完整路径:
- 方案一:验证了模板元数据的配置复用能力
- 方案二:验证了环境变量的动态配置能力
- 方案三:验证了模板继承的环境隔离能力
- 方案四:综合前三者优点,形成最佳实践
核心价值
方案四解决了多环境配置的关键问题:
- 配置复用:避免重复配置
- 环境隔离:确保环境独立
- 灵活配置:支持动态配置
- 易于维护:结构清晰,便于管理
寄语
没有方案是完美的,大家可以根据自己情况,挑选一个合适自己的方案。