在AWS Elastic Beanstalk(EB)环境中,我们经常需要为EC2实例配置环境变量。传统做法是通过EB控制台手动添加,但这种方式存在明显缺陷:每次部署新环境都需要重复操作,无法实现版本控制,也难以保证多环境一致性。通过代码方式管理环境变量,可以完美解决这些问题。
我最近在一个电商项目中就遇到了这个需求:需要为不同环境的EC2实例配置不同的数据库连接字符串。经过多次实践,总结出以下几种可靠方案,特别适合需要自动化部署的场景。
在AWS EB环境中,为EC2添加环境变量主要有三种技术路径:
我们通过一个对比表格来看各方案特点:
| 方案 | 配置复杂度 | 安全性 | 动态更新 | 适用场景 |
|---|---|---|---|---|
| .ebextensions | 低 | 中 | 需重启 | 固定环境变量 |
| User Data | 中 | 低 | 需重启 | 需要复杂初始化逻辑 |
| SSM Parameter Store | 高 | 高 | 实时 | 敏感信息/多服务共享配置 |
对于大多数场景,我推荐使用.ebextensions方案,原因有三:
但当涉及数据库密码等敏感信息时,应优先考虑SSM Parameter Store方案。
这是最经典的实现方式,具体操作步骤如下:
.ebextensions文件夹envvars.config)yaml复制option_settings:
aws:elasticbeanstalk:application:environment:
DB_HOST: "production-db.example.com"
DB_PORT: "5432"
APP_ENV: "production"
关键注意事项:
.config后缀我在实际项目中遇到过因缩进错误导致配置失效的情况,建议使用YAML校验工具检查语法。
对于需要运行时计算的变量,可以使用User Data方案。在.ebextensions中创建如下配置:
yaml复制files:
"/etc/ec2_user_data.sh":
mode: "000755"
content: |
#!/bin/bash
echo 'export CUSTOM_VAR="dynamic_value"' >> /etc/profile
然后在EC2启动配置中执行该脚本。这种方式的优势是可以访问AWS元数据服务:
bash复制INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
echo "export INSTANCE_ID=$INSTANCE_ID" >> /etc/environment
重要提示:User Data脚本最多只能运行16KB的内容,复杂逻辑建议拆分为多个脚本。
对于生产环境,我强烈推荐使用SSM方案。首先在AWS控制台创建参数:
/prod/database/password然后在.ebextensions配置中添加:
yaml复制Resources:
AWSEBAutoScalingGroup:
Metadata:
AWS::CloudFormation::Authentication:
S3Auth:
type: "s3"
roleName:
Fn::GetOptionSetting:
Namespace: "aws:autoscaling:launchconfiguration"
OptionName: "IamInstanceProfile"
DefaultValue: "aws-elasticbeanstalk-ec2-role"
files:
"/etc/profile.d/ssm_params.sh":
mode: "000755"
content: |
#!/bin/bash
export DB_PASSWORD=$(aws ssm get-parameter --name "/prod/database/password" --with-decryption --query "Parameter.Value" --output text)
需要确保EC2实例角色有ssm:GetParameter权限。
通过EB环境变量实现多环境配置:
yaml复制option_settings:
aws:elasticbeanstalk:application:environment:
DB_HOST:
Fn::GetOptionSetting:
Namespace: "aws:elasticbeanstalk:application:environment"
OptionName: "DB_HOST"
DefaultValue: "localhost"
然后在EB环境属性中设置DB_HOST的实际值。
我总结的安全处理流程:
在CI/CD管道中添加变量注入步骤(以GitHub Actions为例):
yaml复制- name: Configure EB Environment
run: |
aws elasticbeanstalk update-environment \
--environment-name ${{ env.EB_ENV_NAME }} \
--option-settings Namespace=aws:elasticbeanstalk:application:environment,OptionName=API_KEY,Value=${{ secrets.PRODUCTION_API_KEY }}
检查清单:
典型错误及解决方案:
| 错误信息 | 解决方案 |
|---|---|
| AccessDenied to SSM parameter | 为实例角色添加ssm:GetParameter权限 |
| Unable to write to /etc/environment | 使用/etc/profile.d/目录替代,或检查User Data执行权限 |
| Invalid YAML in .ebextensions | 使用在线YAML校验工具检查,特别注意缩进和冒号后的空格 |
定期检查实际生效的变量:
bash复制eb printenv
或直接登录EC2查看:
bash复制cat /proc/$(pgrep -f "application name")/environ | tr '\0' '\n'
我建议的变更流程:
需要注意的成本点:
经过多个项目的实践验证,这套方案在保证安全性的同时,提供了足够的灵活性。特别是在微服务架构下,通过代码管理环境变量大大简化了配置管理工作。