第 6 章:应用程序配置:不只是环境变量
云原生应用程序的配置管理不仅仅是环境变量的简单使用,更需要结合属性文件、配置服务器等模式,确保分布式系统的灵活性和一致性。本文将系统梳理配置层的设计思路与最佳实践。
本章要点
- 对应用程序配置的需求
- 系统配置值和应用程序配置值之间的区别
- 如何正确使用属性文件
- 如何正确使用环境变量
- 配置服务器
在上一章开始时,图 6.1 展示了影响应用程序结果的多种因素,包括请求历史、系统环境和应用程序配置。第 5 章已介绍如何消除请求历史的影响,实现应用程序实例的无状态化。本章将重点讨论系统环境和应用程序配置这两个影响因素。

为什么我们要讨论配置?
虽然开发者普遍认为不应将配置硬编码到软件中,并且属性文件已成为主流实践,但云原生环境带来了新的挑战。分布式架构和动态基础设施要求我们重新审视配置管理模式。
动态伸缩与实例配置一致性
云原生应用通常需要动态伸缩,实例数量可能从几十扩展到数千。传统的“手工”配置方式已无法满足需求,必须确保所有实例配置一致,并支持不停机更新。
此外,应用实例的 IP 地址或端口变化也影响服务发现和连接方式,这些配置具有网络效应,需在后续章节详细讨论。
基础设施变化导致配置变化
云平台基础设施频繁变化,如操作系统升级、硬件故障等,都会影响应用配置。以操作系统升级为例,应用实例会迁移到新节点,IP 地址和端口随之变化,应用需自动适应。

零停机更新应用程序配置
有时仅需更新配置而无需重启应用,如版权信息或密码轮换。理想方式是通过抽象和参数化,将配置值在合适时机注入应用程序,实现可重复、可验证的配置管理模式。
应用程序的配置层
十二要素应用程序(12factor.net)推荐将配置存储在环境变量中,提升可移植性和运维一致性。以 Java 为例,可通过 System.getenv
获取环境变量。
但环境变量并非所有配置的最佳方式。更优雅的做法是引入专门的配置层,将所有配置参数集中定义,便于管理和注入。属性文件是实现配置层的常见方式,各主流语言均有支持。

属性文件的优势在于集中管理所有配置参数,便于开发和运维人员理解和维护。缺点是常被打包进可部署构件,导致不同环境需不同构建流程。建议将属性文件作为配置参数规范,并通过环境变量或其他方式覆盖默认值。
例如,属性文件中的 IP 地址配置可采用如下方式:
ipaddress=${INSTANCE_IP:127.0.0.1}
表示优先使用环境变量 INSTANCE_IP,否则采用默认值 127.0.0.1。

注入系统/环境值
系统值通常由基础设施提供,如实例 IP 地址、端口等。云环境下,应用实例频繁变化,需通过环境变量动态注入这些值。
实际案例:Kubernetes 环境变量配置
在 Kubernetes 部署清单中,可通过 env
字段定义环境变量。例如,将 pod 的 IP 地址注入到应用:
INSTANCE_IP
通过status.podIP
自动赋值。
应用通过属性文件引用该环境变量,实现配置注入。

实际操作中,可通过命令行查看容器内环境变量,验证配置是否正确注入。
注入应用程序配置
应用程序配置如密码、连接信息等,需持久化、版本控制并安全管理。推荐使用源代码控制系统(如 Git)和配置服务器(如 Spring Cloud Configuration Server,SCCS)统一管理。
配置服务器介绍与实践
配置服务器通过 HTTP 接口为应用提供配置数据,支持多环境、多版本管理。实际操作流程如下:
- 在 Git 仓库中维护配置文件(如
mycookbook.properties
),包含服务密码等敏感信息。 - SCCS 部署后,应用通过环境变量指定配置服务器地址,自动拉取并注入配置值。

应用代码通过注解或配置层获取配置服务器注入的参数,实现分布式配置一致性。
安全与最佳实践
- 密码等敏感信息应加密存储,避免明文传递和日志输出。
- 推荐使用专用安全配置仓库(如 Vault)管理敏感配置。
- 配置变更需通过版本控制系统统一管理,避免手动修改。
应用配置与系统配置的统一模式
属性文件作为系统配置和应用配置的公共抽象层,系统配置通过环境变量注入,应用配置通过配置服务器注入。两者模式一致,便于统一管理和扩展。

总结
- 云原生架构需重新评估配置管理技术,结合新旧方法实现最佳实践。
- 属性文件是配置管理的核心,环境变量适合系统配置,配置服务器适合应用配置。
- 应用配置应像源代码一样进行版本控制和访问管理。
- 配置服务器可实现分布式配置注入,提升灵活性和一致性。
- 配置变更需结合应用生命周期,确保多实例和多服务间的协调更新。