如何在使用 opsworks 部署时仅在特定层中的第一个实例上运行命令?

Posted

技术标签:

【中文标题】如何在使用 opsworks 部署时仅在特定层中的第一个实例上运行命令?【英文标题】:How to run a command on only the first instance in a specific layer on deployment with opsworks? 【发布时间】:2014-06-01 03:38:31 【问题描述】:

我们正在 aws opsworks 上部署一个 Laravel 应用程序,一切运行良好,但是我们还需要做两件事:

1) 在每次部署时,我们要运行 php artisan migrate 来安装数据库更新。 2)我们有一个文件(app/database/run.list),其中包含一个类名列表,对于我们要运行的文件中的每一行php artisan db:seed --class=line from file。 例如

run.list 包含

NewSystemSeed
NewUserSeed
CreateDefaultTemplatesSeed

我们想跑

php artisan db:seed --class=NewSystemSeed
php artisan db:seed --class=NewUserSeed
php artisan db:seed --class=CreateDefaultTemplatesSeed

那部分并不难(虽然我有点卡在最后一个)。 我坚持的部分是,我们只想在特定层(php-app 层)的第一个实例上执行此操作。

我们显然不想最终为每个实例都植入数据库!

有没有办法自动化这个,或者我们必须创建另一个配方,然后在部署后手动触发实例上的这个配方?

【问题讨论】:

注意,我不确定 SO 是否是解决这个问题的最佳 SE 网站,所以如果有更好的网站解决与 devops 相关的问题,请告诉我! 好问题。您可以在播种机运行时向数据库写入一些内容并在启动时检查它吗?这样,其他服务器就会看到该标志并跳过种子。 @ceejayoz,这几乎就是迁移的作用,理论上我们可以将种子写成迁移,但我们的种子通常是幂等的,所以假设我们想更新角色列表,我们的种子会清除所有角色并重新插入每个角色,因此它们是可重用的。 我知道在带有 ebextensions 的弹性 beantalk 中有一个 leader_only 概念,这将是完美的.. 【参考方案1】:

您可以从应用层中的 Opsworks 实例列表中选择第一个实例,并始终在那里进行迁移.这使您可以保持配置不变,并确保您始终在正在运行的实例上运行迁移,因为失败的实例不会出现在列表中。

migrations_instance_hostname = node[:opsworks][:layers]['app-layer'][:instances].keys.sort.first

if migrations_instance_hostname == node[:opsworks][:instance][:hostname]
  # do migrations
end

【讨论】:

【参考方案2】:

您可以在 OpsWorks 中使用层作为标签来表示配方。

创建一个新层(可能是“db-seeder”)。不要在该层中添加新实例,而是从您的 PHP 层添加一个现有实例。

创建一个新的自定义配方,如下所示:

if node[:opsworks][:instance][:layers].include?("db-seeder")
  config_file = 'app/database/run.list'
  bash "migrate db" do
    code %Q^
      php artisan migrate
      for clz in `cat #config_file` do;
        php artisan db::seed --class=$clz;
      done^
  end
end

上述配方将仅在“db-seeder”层中的实例上运行。 将此自定义配方添加到 PHP 应用层的“部署”事件中。

【讨论】:

以上是关于如何在使用 opsworks 部署时仅在特定层中的第一个实例上运行命令?的主要内容,如果未能解决你的问题,请参考以下文章

如何访问 OpsWorks ECS 层中的私有 Docker 存储库?

如何增加 AWS Opsworks 的部署超时限制?

如何终止 AWS Opsworks 中的部署?

AWS OpsWorks新增Amazon RDS支持

如何在按住空格键时仅在Leaflet中启用地图拖动?

如何在handsontable上过滤时仅在下拉菜单上显示不包含HTML内容的文本?