如何在使用 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 部署时仅在特定层中的第一个实例上运行命令?的主要内容,如果未能解决你的问题,请参考以下文章