命令 01_migrate 在 Amazon Linux 2 AMI 上失败

Asl*_*Kök 10 django pymysql amazon-elastic-beanstalk amazon-linux amazon-linux-2

我有一个部署到 Elastic Beanstalk Amazon Linux 2 AMI 的 Django 项目。我安装了 PyMySQL 以连接到数据库,并将这些行添加到 settings.py 中,如下所示;

import pymysql

pymysql.version_info = (1, 4, 6, "final", 0)
pymysql.install_as_MySQLdb()
Run Code Online (Sandbox Code Playgroud)

而且我还有一个用于迁移数据库的 .config 文件;

container_commands:
  01_migrate:
    command: "django-admin.py migrate"
    leader_only: true
option_settings:
  aws:elasticbeanstalk:application:environment:
    DJANGO_SETTINGS_MODULE: mysite.settings
Run Code Online (Sandbox Code Playgroud)

通常,我mysqlclient在我的 Linux AMI 上使用这个 .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
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?

Nic*_*ady 14

Amazon Linux 2 的设置与 AL1 完全不同,截至 2020 年 7 月 24 日的当前文档已过时。django-admin由 beanstalk 安装的环境似乎不在路径上,因此您可以获取环境以激活并确保它在路径上。

也在这里留下了我的答案,其中详细介绍了我如何得出这个答案,但解决方案(我不喜欢)是:

container_commands:
    01_migrate:
        command: "source /var/app/venv/*/bin/activate && python3 manage.py migrate"
        leader_only: true
Run Code Online (Sandbox Code Playgroud)

尽管我不喜欢它,但我已经向 AWS Support 证实,这实际上是推荐的方法。您必须提供python 环境,与 AL2 一样,它们使用虚拟环境以保持更一致。


djv*_*jvg 10

@nick-brady回答很好,它提供了基本的解决方案。

但是,关于迁移到 Amazon Linux 2的 AWS 文档建议我们应该使用.platform钩子来做这样的事情:

我们建议使用平台挂钩在您的环境实例上运行自定义代码。您仍然可以在.ebextensions配置文件中使用命令和容器命令,但它们并不那么容易使用。例如,在 YAML 文件中编写命令脚本可能很麻烦且难以测试。

以及来自AWS 知识中心

...最好的做法是使用平台钩子而不是提供文件和命令 .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;
}
Run Code Online (Sandbox Code Playgroud)

你可以对collectstatic等做同样的事情。

请注意,Python 虚拟环境的路径可作为环境变量提供给平台挂钩PYTHONPATH。您可以通过检查/opt/elasticbeanstalk/deployment/env实例上的文件来验证这一点,例如通过 ssh。另见AWS 知识中心

对于那些想知道的人来说,&&shell 脚本中的 是一种条件执行:只有在前面的成功时才执行以下操作。见例如这里

仅领导者

在部署过程中,应该有一个EB_IS_COMMAND_LEADER环境变量,可以测试它以实现钩子中的leader_only行为.platform(基于这篇文章):

...

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

...
Run Code Online (Sandbox Code Playgroud)