シェフ通知からサービスの再起動を最小限に抑える?

StackOverflow https://stackoverflow.com//questions/21066591

  •  26-12-2019
  •  | 
  •  

質問

現在この問題のような構造化されている属性のある私のレシピ:

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"
.

これを行うことで、サービスの最初の開始が設定ファイルを持っていることを確認し、実行中の実行中にServiceが実行されていて、設定ファイルが変更された場合は、サービスを再開して変更を開始します。 。

しかし、サービスの初期状態が停止されている場合(最初の実行や不正な場合など)、設定ファイルが変更された場合(特に最初の実行には可能ですが、その他の場合は可能です。 RUNS)、最初のExecuteブロックはサービスをすでに適用している正しい設定ファイルでサービスを開始させます。その後、実行の最後に、サービスは不必要に再起動します。 (もちろん、最初の開始後のリソースはサービスの再起動を引き起こさない)

通知のターゲット動作の変更は機能しないように見えない(即時の通知が依然として即時起こり、遅れている通知が依然として起こる)、そのほかに正しくないでしょう。

すでに実行されている場合以降、サービスの開始に2nd Executeを購読することはできません。巻き込まないでください。

それは非常にニットであるが、最初の実行のためのサービスの再起動を最小限に抑えるために従うことができるより良いパターンはありますか?または特定のアクションが取られたときに遅延通知をキャンセルするためのメカニズム?

役に立ちましたか?

解決

これを達成するためにフラグファイルを使用しました。

「APT-GET UPDATE」は1回実行されません。

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
.

他のヒント

Chef is designed to express configuration policy (system state), which is a slightly different thing than expressing a sequence of tasks to perform.

Fortunately since the DSL is ruby-based, resources can be redefined at runtime.

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

This will rewrite the service resource to have "action [:enable, :restart]" instead of "action [:enable, :start]", if any of the template resources change state this run. So the ordering stays the same, and you only get one call through the service resource, instead of potentially three.

I am not sure, if will solve your problems with restarting the service too many times, but this structure seems more logical to me.

#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"

Every resource that changes the configuration file(s), should notify the service to restart.

I guess Chef is clever enough not to restart the service it just started. (I didn't pay attention to that before, but it seems to me that I would have, if there were unnecessary restarts)

Chef will only execute an action per resource, regardless of the number of times it's notified. It is, however, specific to each action. So if you send it a action :restart and also a action :start notification, then both will be executed in the order in which Chef encountered them. So what you are seeing with your code example is the initial :start notification from the execute block, followed by the template :restart notifications.

You should be able to avoid this by restructuring your recipe a bit and using subscribes if I'm following correctly.

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"

First, we move the service resource to the bottom of the recipe so that it is only called once all other resources have been evaluated. Then we change the execute resource to subscribe to the :start action of the service[myservice] resource so that it will only ever execute this command when the :start action is called. We also add a bit of idempotency in there to make sure it doesn't just re-create the init script every run.

Finally, we add in all the templates with the normal notifications for service[myservice].

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top