2014-01-11 56 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" 

這樣,既保證了服務的初始啓動有配置文件,在每次運行該服務正在運行第二個執行塊,如果有任何配置文件發生變化,我們重新啓動服務來獲取更改。然而,如果廚師運行發生在服務的初始狀態停止的地方(例如在第一次運行或者發生了不良事件時),並且配置文件已經改變(特別是在第一次運行時,但可能爲其他運行),則第一個執行塊將導致服務以正確的配置文件啓動,然後在運行結束時,服務將不必要地重新啓動。 (當然假設初始啓動後的資源不會導致服務重啓)

更改通知的目標操作似乎不起作用(因爲即時通知仍會立即發生,則延遲通知仍會發生) ,而且不會是正確的。

此外,我們不能訂閱第二個執行到服務啓動,因爲如果它已經運行,我們會結束不執行它。

這是非常挑剔的,但有沒有更好的模式,可以遵循最小化初始運行的服務重啓?或者在採取特定行動時取消延遲通知的機制?

回答

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通知,則兩者都將按照Chef遇到它們的順序執行。因此,您看到的代碼示例是來自execute塊的初始: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資源以訂閱:start動作的service[myservice]資源,以便在調用:start操作時只會執行此命令。我們還在那裏添加一些冪等性,以確保它不會每次運行都重新創建init腳本。

最後,我們在service[myservice]的正常通知中添加所有模板。

+0

你通過訂閱'執行[生成初始化腳本]'服務[myservice]'實現了什麼?如果沒有init腳本,你將無法啓動服務。 –

+0

哎呦。我的意思是爲了訂閱附加到'服務[myservice]'資源。我將編輯我的帖子。 由於如果初始化腳本不存在,'服務'資源將無法執行,因此我們將它訂閱到execute塊,以在第一個「執行」塊創建之後立即觸發。如果init腳本已經存在,那麼not_if可以防止再次觸發該命令。 –

4

廚師的目的是表達配置策略(系統狀態),這與表示一系列要執行的任務稍有不同。

幸運的是,由於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 

這將改寫服務資源有「行動[:啓用:重啓]」而不是「行動[:啓用:開始]」,如果任何模板資源,改變這種狀態運行。所以訂單保持不變,您只能通過服務資源獲得一次呼叫,而不是三次。

+0

這是一個有趣的想法。我還沒有機會試用它......我應該在幾天內有一些時間。 – Charlie

+0

我跳了一下槍,根據我們解決的其他不完全相同的問題探索了一個想法。我其實今天試了一下,發現它並不像我想的那樣工作。但原則基本上是合理的。我編輯了上面的示例ruby_block來顯示。 – bear