环境变量与配置管理,一篇文章搞懂
前言
随着项目越来越大、依赖越来越多,配置管理将显得越来越重要。
服务应用的哪些应该是配置?哪些写死到代码中?
哪些配置打包到 Dockerfile 镜像中,哪些在容器启动时动态加载?
多环境dev、test、prod下环境变量如何管理?
环境变量的优先级?当环境变量发生变化时,如何做到最小化修改?
为了回答上述问题,我学习相关知识并记录到了本文中。
配置与环境变量
配置是一个广义的概念,指的是一切影响应用程序行为、但又不属于其核心逻辑代码的数据或设置。它回答了这些问题:
- 数据库在哪台机器上?
- 日志级别该多详细?
- 功能A对用户开放吗?
- 缓存多久失效?
让同一份应用程序代码,能在不同的环境(开发、测试、生产)、不同需求下,表现出不同的行为,而无需重新编写和编译代码。存在形式有多种:配置文件、数据库/配置中心、启动参数、环境变量等。
在容器化技术普遍流行的现代开发中,环境变量非常受宠,其与“不可变基础设施”理念契合:可以构建一个纯净的、不包含任何环境信息的 Docker 镜像。在启动容器时,通过环境变量将“它是生产环境”、“它的数据库连接串是XXX”这些信息“注入”进去。镜像不变,环境可变。
配置文件
什么是环境变量,什么是配置?
什么是配置,哪些写死的静态代码,哪些是作为配置?静态配置与动态配置?
云原生核心原则
12-Factor 原则说的那样:把配置彻底从代码里剥离出来。
在现代云原生开发中,遵循 12-Factor App 原则将配置与代码严格分离是构建可扩展、安全应用的基础。本文将探讨环境变量的核心原则、加载优先级以及在 Python 项目中的具体实践。
核心原则
- 不提交敏感配置:.env 文件严禁提交至版本控制系统(Git)。必须在 .gitignore 中忽略,防止 API 密钥、数据库密码泄露。
- 配置与镜像分离:不要将 .env 打包进 Docker 镜像。镜像应保持环境无关性,通过运行时的容器编排工具注入变量。
- Fail-Fast(快速失败):程序启动时必须校验核心配置,若缺失或格式错误应立即报错退出,避免程序在不稳定的配置下运行。
环境变量加载优先级
为了兼顾开发便利性和生产安全性,建议采用以下加载顺序(由低到高,高优先级覆盖低优先级):
代码默认值:在配置类中定义的硬编码默认值(仅限非敏感项)。
.env 文件:本地开发环境的配置文件。
Shell 环境变量:如执行 export APP_PORT=8080。
Docker Compose:environment 块定义的变量。
集群管理工具:Kubernetes Secrets 或 ConfigMaps。
- Python 实践示例
在 Python 中,pydantic-settings 是目前管理配置的事实标准,它提供了自动类型转换、验证和敏感信息保护功能。
3.1 统一配置类
使用 Pydantic 定义配置模型,可以自动从环境变量中读取同名变量。