Chef infra 从厨师长通知中最小化服务重启?
目前,我的配方具有重要的属性,其结构如下:Chef infra 从厨师长通知中最小化服务重启?,chef-infra,Chef Infra,目前,我的配方具有重要的属性,其结构如下: service 'myservice' do action :nothing supports :status => true, :start => true, :stop => true, :restart => true end package 'packagename' do ... end template 'configfile1' notifies :restart, 'service[myser
service 'myservice' do
action :nothing
supports :status => true, :start => true, :stop => true, :restart => true
end
package 'packagename' do
...
end
template 'configfile1'
notifies :restart, 'service[myservice]'
end
...
template 'configfileN'
notifies :restart, 'service[myservice]'
end
execute "a command from package which generates and enables the init script" do
notifies :start, 'service[myservice]', :immediately
end
execute "a command that should run once every time, that requires service to be running"
通过这样做,我们确保服务的初始启动具有配置文件,在每次运行期间,服务都在为第二个执行块运行,如果任何配置文件发生更改,我们将重新启动服务以获取更改
但是,如果chef运行发生在服务的初始状态停止的地方(例如,在第一次运行时,或者发生了错误),并且配置文件已更改(特别是在第一次运行时,但可能在其他运行时),则第一个执行块将导致服务在正确的配置文件已就位的情况下启动,然后在运行结束时,服务将不必要地重新启动。(当然,假设初始启动后的资源不会导致服务重新启动)
更改通知的目标操作似乎不起作用(因为即时通知仍然会立即发生,然后延迟通知仍然会发生),而且也不正确
此外,我们无法订阅服务启动的第二个execute,因为如果它已经运行,我们将无法执行它
这是非常挑剔的,但是有没有更好的模式可以用来最小化服务在初始运行时的重启?或者在执行特定操作时取消延迟通知的机制 我不确定,if是否能解决您重启服务太多次的问题,但这种结构对我来说似乎更符合逻辑
#Prepare everything to start the service
package 'packagename' do
...
end
template 'configfile1'
notifies :restart, 'service[myservice]'
end
...
template 'configfileN'
notifies :restart, 'service[myservice]'
end
execute "a command from package which generates and enables the init script" do
notifies :restart, 'service[myservice]'
end
#Start the service
service 'myservice' do
action :start
supports :status => true, :start => true, :stop => true, :restart => true
end
#At this point service is surely running
execute "a command that should run once every time, that requires service to be running"
更改配置文件的每个资源都应通知服务重新启动
我猜Chef足够聪明,不会重新启动刚启动的服务。(我以前没有注意到这一点,但在我看来,如果有不必要的重新启动,我会这样做)厨师只会对每个资源执行一个操作,而不管通知的次数如何。然而,它是特定于每个动作的。因此,如果您向它发送一个
action:restart
和一个action:start
通知,那么两者都将按照Chef遇到它们的顺序执行。因此,您在代码示例中看到的是来自execute块的初始:start
通知,然后是模板:restart
通知
你应该能够避免这一点,通过重新构造你的食谱和使用,如果我遵循正确的
package 'packagename' do
...
end
execute "a command from package which generates and enables the init script" do
not_if File.exists?('/etc/init.d/myservice_script')
end
template 'configfile1'
notifies :restart, 'service[myservice]'
end
...
template 'configfileN'
notifies :restart, 'service[myservice]'
end
service 'myservice' do
supports :status => true, :start => true, :stop => true, :restart => true
subscribes :run, 'execute[a command from package which generates and enables the init script]', :immediately
action :start
end
execute "a command that should run once every time, that requires service to be running"
首先,我们将服务
资源移动到配方的底部,以便仅在对所有其他资源进行评估后调用它。然后,我们将execute
资源更改为订阅服务[myservice]
资源的:start
操作,以便它仅在调用:start
操作时执行此命令。我们还在其中添加了一点幂等性,以确保它不会每次运行时都重新创建init脚本
最后,我们为
服务[myservice]
添加了所有带有正常通知的模板,Chef被设计用来表示配置策略(系统状态),这与表示要执行的任务序列略有不同
幸运的是,由于DSL是基于ruby的,所以可以在运行时重新定义资源
template "configfile1" do
notifies :create, "ruby_block[restart_service1]", :immediately
end
template "configfile2" do
notifies :create, "ruby_block[restart_service1]", :immediately
end
service "service1" do
action [:enable, :start]
end
ruby_block "restart_service1" do
block do
r = resources(:service => "service1")
a = Array.new(r.action)
a << :restart unless a.include?(:restart)
a.delete(:start) if a.include?(:restart)
r.action(a)
end
action :nothing
end
模板“configfile1”do
通知:创建“ruby\u块[重新启动\u服务1],:立即
结束
模板“configfile2”执行
通知:创建“ruby\u块[重新启动\u服务1],:立即
结束
服务“服务1”do
操作[:启用,:启动]
结束
ruby\u块“重新启动\u服务1”do
布洛克道
r=资源(:服务=>“服务1”)
a=数组。新建(r.action)
a我使用了一个标志文件来实现这一点
如下所示,“apt get update”不会执行一次
cookbook_file '/etc/apt/sources.list.d/maven.list' do
source "repo_files/ubuntu_maven.list"
cookbook "fluig-files"
mode 0644
notifies :run, "execute[should_update_repo]", :immediately
end
cookbook_file '/etc/apt/sources.list.d/couchbase.list' do
source "repo_files/ubuntu_couchbase.list"
cookbook "fluig-files"
mode 0644
notifies :run, "execute[should_update_repo]", :immediately
end
execute "apt-key couchbase" do
command "apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A3FAA648D9223EDA"
action :run
not_if "apt-key list | grep couchbase"
notifies :run, "execute[should_update_repo]", :immediately
end
execute "should_update_repo" do
command "touch /tmp/should_update_repo"
action :nothing
end
# Update system
execute "apt-get update" do
command "rm -rf /tmp/should_update_repo && apt-get update"
action :run
only_if "test -f /tmp/should_update_repo"
end
可悲的是,大厨显然没有那么聪明,它仍然在做双重启动。就逻辑结构而言,我思考它的方式是,在针对同一资源声明通知之前,先声明(服务)资源。这显然更像是一种风格偏好,而不是一种正确性偏好:)那么您通过订阅“执行[generate init script]”到“服务[myservice]”能实现什么呢?如果没有init-script,您将无法启动服务。哎哟。我的意思是将订阅附加到“service[myservice]”资源。我会编辑我的帖子。由于如果init脚本不存在,“service”资源将无法执行,因此我们将其订阅到execute块,以便在第一个“execute”块创建后立即触发。如果init脚本已经存在,not_if可以防止再次触发命令。这是一个有趣的想法。我还没有机会尝试一下。。。再过几天我就应该有时间了。我有点仓促行事,根据我们解决的其他不完全相同的问题来探索一个想法。事实上,我今天尝试了一下,发现它并不完全像我想的那样工作。但这一原则基本上是正确的。我编辑了上面的示例ruby_块来显示。