11

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

通常,我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

我该如何解决这个问题?

4

3 回答 3

14

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

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

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

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

于 2020-07-24T13:45:03.340 回答
11

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

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

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

并来自AWS 知识中心

...最好使用平台挂钩而不是在.ebextension配置文件中提供文件和命令。

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

基本思想是在您的应用程序源包中创建一个 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;
}

你可以对collectstaticetc做同样的事情。

请注意,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

...
于 2020-12-08T13:14:47.907 回答
0

在我的情况下,这个 .config

container_commands: 01_migrate: command: "django-admin.py migrate" leader_only: true 02_collectstatic: command: "django-admin.py collectstatic --noinput"

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

于 2022-01-04T13:48:57.343 回答