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

Command 01_migrate failed on Amazon Linux 2 AMI

我有一个部署到 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

我该如何解决这个问题?

A​​mazon Linux 2 的设置与 AL1 根本不同,截至 2020 年 7 月 24 日的当前文档已过时。 django-admin beanstalk 安装的环境似乎不在路径上,所以你可以获取环境来激活并确保它是。

我也留下了我的答案 here,其中更详细地说明了我是如何得出这个答案的,但解决方案(我不喜欢)是:

container_commands:
    01_migrate:
        command: "source /var/app/venv/*/bin/activate && python3 manage.py migrate"
        leader_only: true

尽管我不喜欢它,但我已经通过 AWS Support 验证这实际上是推荐的方法。您必须获取python环境,因为在 AL2 中,他们使用虚拟环境来努力保持更加一致。

很棒,它提供了基本的解决方案。

但是,migrating to Amazon Linux 2 上的 AWS 文档建议我们应该使用 .platform 钩子做这样的事情:

We recommend using platform hooks to run custom code on your environment instances. You can still use commands and container commands in .ebextensions configuration files, but they aren't as easy to work with. For example, writing command scripts inside a YAML file can be cumbersome and difficult to test.

和来自 AWS Knowledge Center

... it's a best practice to use platform hooks instead of providing files and commands in .ebextension configuration files.

作为奖励,平台挂钩的输出被收集在一个单独的日志文件 (/var/log/eb-hooks.log) 中,默认情况下包含在 bundle 和 tail 日志中。这使调试更容易一些。

基本思路是在您的应用程序源包中创建一个 shell 脚本,例如.platform/hooks/postdeploy/01_django_migrate.shdocs for extending EB linux platforms.

中的平台挂钩部分对此进行了更详细的描述。

文件必须是可执行的,所以:chmod +x .platform/hooks/postdeploy/01_django_migrate.sh

文件内容可能如下所示(基于 ):

#!/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 knowledge center.

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

仅限领导者

在部署过程中,应该有一个EB_IS_COMMAND_LEADER环境变量,可以对其进行测试,以便在.platform钩子中实现leader_only行为(基于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

...

在我的案例中,这个 .config 有效

container_commands: 01_migrate: 命令:“django-admin.py 迁移” leader_only:真 02_collectstatic: 命令:“django-admin.py collectstatic --noinput”

我有这个命令:“source /var/app/venv/*/bin/activate && python3 manage.py 配置直到 1 月 4 日,突然我得到一个部署错误