2014-01-11 1 views
5

は現在、このように構成されている事柄の属性を持つ私のレシピ:シェフの通知によるサービスの再起動を最小限に抑えますか?

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" 

をこれを行うことにより、我々は、すべてのサービスを実行中に第2の実行のために実行されている、サービスの初期起動が設定ファイルを持っていることを確認します設定ファイルが変更された場合は、サービスを再起動して変更を取得します。

しかし、サービスの初期状態が停止した場所(最初の実行時や何らかの不具合が発生した場合など)に設定ファイルが変更された場合(特に最初の実行時に可能ですが他の実行)、最初の実行ブロックにより、正しい構成ファイルがすでに存在する状態でサービスが開始され、実行の最後にサービスが不必要に再起動します。

通知のターゲットアクションを変更しても動作していないようです(即時通知がただちに発生するため、遅延通知が引き続き発生するため)それ以外は正しいとは言えません。

また、すでに実行している場合は実行しないので、2番目の実行をサービス開始にサブスクライブできません。

これは非常に厄介ですが、最初の実行でサービスを再開するのを最小限に抑えるためのパターンがありますか?または特定のアクションが取られたときに遅延通知を取り消すための仕組みですか?

答えて

3

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

以下のように「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 
1

サービスを何度も再起動しても問題が解決しない場合は、この構造はもっと論理的です。

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

構成ファイルを変更するすべてのリソースは、再起動するようにサービスに通知する必要があります。

私はシェフがちょうど始めたサービスを再起動しないほど賢明だと思います。 (これまでは気にしませんでしたが、不必要な再起動があった場合、私は持っていたようです)

+1

これは、悲しいことに、シェフは賢明ではないようですが、それはまだ二重のスタートをしています。論理構造に関しては、私が考えていた方法は、同じリソースに対して通知を宣言する前に(サービス)リソースを宣言していたことです。しかし、正しさの好みよりももっと文体的な好みが多いです:) – Charlie

0

シェフは、通知された回数にかかわらず、リソースごとにアクションを実行します。しかし、それはそれぞれの行動に固有です。したがって、action :restartaction :startという通知を送信すると、シェフが遭遇した順序で両方が実行されます。コード例では、実行ブロックからの通知である:startの通知と、それに続くテンプレート:restartの通知が表示されます。

レシピを少し再構成し、私が正しく従っている場合はsubscribesを使用してこれを避けることができます。それは一度だけ他のすべてのリソースが評価されたと呼ばれているように、まず

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" 

は、我々はレシピの底にserviceリソースを移動します。次にexecuteリソースをservice[myservice]リソースの:startアクションにサブスクライブするように変更し、:startアクションが呼び出されたときにこのコマンドが実行されるようにします。また、実行するたびにinitスクリプトを再作成するだけではないことを確認するために、そこにidempotencyを少し追加します。

最後に、service[myservice]の通常の通知を含むすべてのテンプレートを追加します。

+0

そして、[サービス[myservice]に[generate-generate-init-script]を購読することで、あなたは何を達成しますか?また、initスクリプトがないとサービスを開始できません。 –

+0

おっと。私はその購読者が 'service [myservice]'リソースにアタッチされることを意図していました。私は自分の投稿を編集します。 initスクリプトが存在しない場合、 'service'リソースは実行に失敗するため、最初の 'execute'ブロックによって作成された直後に実行ブロックに登録されます。 not_ifは、initスクリプトがすでに存在する場合に、コマンドが再度トリガーされるのを防ぐためのものです。 –

4

シェフは、構成ポリシー(システム状態)を表現するように設計されています。これは、実行する一連のタスクを表現することとは少し異なります。

DSLはルビーベースであるため、実行時にリソースを再定義することができます。テンプレートリソースのいずれかの状態にこの実行を変更した場合、

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 

これは、「[:有効、:再起動]アクション」持っているサービスリソースを書き換えます代わりに「アクション[:開始:有効]」。したがって、注文は同じままで、潜在的に3つではなく、サービスリソースを通じて1回の呼び出しだけが得られます。

+0

これは興味深い考えです。私はまだそれを試してみる機会がなかった...私は数日でいくつかの時間を持つ必要があります。 – Charlie

+0

私は、私たちが解決した他の全く同じではない問題に基づいてアイデアを探って、銃を少し飛ばしました。私は実際にそれを今日試して、それが私が思ったように正確に動作しないことを発見しました。しかし原則は基本的には健全です。上記のruby_blockの例を編集して表示しました。 – bear

関連する問題