我有一个部署到 Elastic Beanstalk Amazon Linux 2 AMI 的 Django 项目。我安装了 PyMySQL 来连接到数据库,并将这些行添加到 settings.py 中,如下所示;
import pymysql
pymysql.version_info = (1, 4, 6, "final", 0)
pymysql.install_as_MySQLdb()
我还有一个用于迁移数据库的 .config 文件;
container_commands:
01_migrate:
command: "django-admin.py migrate"
leader_only: true
option_settings:
aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: mysite.settings
通常,我在我的 Linux AMI 上使用
mysqlclient
和这个 .config 文件,但它在 Linux 2 AMI 上不起作用,所以我安装了 PyMySQL。现在,我正在尝试部署项目的更新版本,但收到如下错误;
Traceback (most recent call last):
File "/opt/aws/bin/cfn-init", line 171, in <module>
worklog.build(metadata, configSets)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/construction.py", line 129, in build
Contractor(metadata).build(configSets, self)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/construction.py", line 530, in build
self.run_config(config, worklog)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/construction.py", line 542, in run_config
CloudFormationCarpenter(config, self._auth_config).build(worklog)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/construction.py", line 260, in build
changes['commands'] = CommandTool().apply(self._config.commands)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/command_tool.py", line 117, in apply
raise ToolError(u"Command %s failed" % name)
ToolError: Command 01_migrate failed
我该如何解决这个问题?
Amazon Linux 2 的设置与 AL1 根本不同,截至 2020 年 7 月 24 日的当前文档已过时。 beanstalk 安装的环境的
django-admin
似乎不在路径上,因此您可以获取要激活的环境并确保它在路径上。
我也在这里留下了我的答案,其中更详细地说明了我如何得出这个答案,但解决方案(我不喜欢)是:
container_commands:
01_migrate:
command: "source /var/app/venv/*/bin/activate && python3 manage.py migrate"
leader_only: true
尽管我不喜欢它,但我已向 AWS Support 核实,这实际上是推荐的执行此操作的方法。您必须
获取Python环境,就像AL2一样,他们使用虚拟环境来保持更加一致。
的 AWS 文档建议我们应该使用 .platform
钩子执行类似的操作:
AWS 知识中心...最好的做法是使用平台挂钩,而不是在.ebextensions
配置文件中使用命令和容器命令,但它们并不那么容易使用。例如,在 YAML 文件中编写命令脚本可能很麻烦且难以测试。
以及来自
.ebextension
配置文件中提供文件和命令。
作为奖励,平台钩子的输出被收集在单独的日志文件(
/var/log/eb-hooks.log
)中,默认情况下包含在捆绑包和尾部日志中。这使得调试变得更容易一些。
基本思想是在应用程序源包中创建一个 shell 脚本,例如.platform/hooks/postdeploy/01_django_migrate.sh
。
扩展 EB Linux 平台的文档中的平台挂钩部分对此进行了更详细的描述。 该文件必须是可执行的,因此:
chmod +x .platform/hooks/postdeploy/01_django_migrate.sh
文件内容可能如下所示(基于 @nick-brady 的回答):
#!/bin/bash
source "$PYTHONPATH/activate" && {
# log which migrations have already been applied
python manage.py showmigrations;
# migrate
python manage.py migrate --noinput;
}
您可以对
collectstatic
等进行同样的操作
请注意,Python 虚拟环境的路径可作为环境变量PYTHONPATH
供平台挂钩使用。您可以通过检查实例上的文件
/opt/elasticbeanstalk/deployment/env
来验证这一点,例如通过 ssh。另请参阅 AWS 知识中心。 对于那些想知道的人来说,shell 脚本中的
&&
是一种条件执行:仅当前面的操作成功时才执行以下操作。 参见例如
这里。 仅限领导者
EB_IS_COMMAND_LEADER
环境变量,可以对其进行测试,以便在
leader_only
钩子中实现 .platform
行为(基于 this post):
...
if [[ $EB_IS_COMMAND_LEADER == "true" ]];
then
python manage.py migrate --noinput;
python manage.py collectstatic --noinput;
else
echo "this instance is NOT the leader";
fi
...
容器命令: 01_迁移: 命令:“django-admin.py 迁移” 仅领导者:正确 02_收集静态: 命令:“django-admin.pycollectstatic--noinput”
我有这个命令:“source /var/app/venv/*/bin/activate && python3 manage.py config 直到 1 月 4 日,突然出现部署错误
问题似乎是当 AL2 运行时
python manage.py migrate
它无法访问我存储数据库连接信息的环境变量。
解决方案是使用以下代码将另一个文件添加到.ebextensions
:
commands:
setvars:
command: /opt/elasticbeanstalk/bin/get-config environment | jq -r 'to_entries | .[] | "export \(.key)=\"\(.value)\""' > /etc/profile.d/sh.local
packages:
yum:
jq: []
我将此文件命名为
setvars.config
来源:https://repost.aws/knowledge-center/elastic-beanstalk-env-variables-shell