2014-01-11 5 views
5

Derzeit mein Rezept mit Attributen, die so strukturiert ist Materie:Minimieren Sie den Dienst von den Benachrichtigungen des Kochs neu?

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" 

Auf diese Weise stellen wir sicher, dass die anfängliche Start des Dienstes die Konfigurationsdateien hat, während jeder den Dienst laufen für die zweite läuft ausführen blockieren, und wenn eine Konfigurationsdatei geändert wird, starten wir den Dienst neu, um die Änderungen zu übernehmen.

Wenn jedoch ein Chef ausgeführt wird, wo der anfängliche Status des Dienstes angehalten wird (wie beim ersten Ausführen oder wenn etwas Schlimmes passiert ist) und Konfigurationsdateien geändert haben (insbesondere beim ersten Durchlauf, aber möglich für andere Runs), bewirkt der erste Ausführungsblock, dass der Dienst mit den korrekten Konfigurationsdateien beginnt, die bereits vorhanden sind. Am Ende des Laufs wird der Dienst dann unnötigerweise neu gestartet. (Angenommen natürlich, dass Ressourcen nach dem ersten Start keinen Neustart des Dienstes verursachen)

Die Zielaktion von Benachrichtigungen zu ändern scheint nicht zu funktionieren (da sofortige Benachrichtigungen immer noch sofort passieren, dann treten verzögerte Benachrichtigungen immer noch auf) und außerdem wäre das nicht korrekt.

Auch können wir nicht die zweite Ausführung an den Service-Start abonnieren, denn wenn es bereits läuft, würden wir es nicht ausführen.

Es ist sehr pingelig, aber gibt es ein besseres Muster, das verfolgt werden könnte, um Neustarts eines Dienstes für den ersten Lauf zu minimieren? Oder ein Mechanismus, um verzögerte Benachrichtigungen zu stornieren, wenn eine bestimmte Aktion ausgeführt wird?

Antwort

3

Ich habe eine Flag-Datei verwendet, um dies zu erreichen.

Wie unten wird "apt-get update" nicht einmal ausgeführt.

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

Ich bin mir nicht sicher, ob Sie Ihre Probleme mit dem Neustart des Dienstes zu oft lösen, aber diese Struktur scheint mir logischer.

Jede Ressource, die die Konfigurationsdatei (en) ändert, sollte den Dienst zum Neustart benachrichtigen.

Ich schätze, Chef ist schlau genug, den Dienst, den er gerade begonnen hat, nicht neu zu starten. (Ich habe das vorher nicht beachtet, aber es scheint mir, dass ich hätte, wenn es unnötige Neustarts gab)

+1

Geben Sie einen Schuss, leider ist Chef nicht so schlau, es macht immer noch einen Doppelstart. Was die logische Struktur anbetrifft, war die Art und Weise, wie ich darüber nachdachte, dass ich die (Service-) Ressource deklarierte, bevor ich Benachrichtigungen für dieselbe Ressource deklarierte. Es ist definitiv mehr eine stilistische Vorliebe als eine Korrektheitspräferenz obwohl :) – Charlie

0

Chef wird nur eine Aktion pro Ressource ausführen, unabhängig von der Anzahl der Meldungen. Es ist jedoch spezifisch für jede Aktion. Wenn Sie also eine action :restart und auch eine action :start Benachrichtigung senden, werden beide in der Reihenfolge ausgeführt, in der der Chef sie gefunden hat. Was Sie also mit Ihrem Codebeispiel sehen, ist die anfängliche :start Benachrichtigung vom Ausführungsblock, gefolgt von der Vorlage :restart Benachrichtigungen.

Sie sollten in der Lage sein, dies zu vermeiden, indem Sie Ihr Rezept ein wenig umbauen und subscribes verwenden, wenn ich richtig folge.

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" 

Zuerst bewegen wir die service-Ressource auf dem Boden des Rezepts, so dass es nur einmal alle anderen Ressourcen ausgewertet wurden aufgerufen wird. Dann ändern wir die Ressource execute, um die :start Aktion der service[myservice] Ressource zu abonnieren, so dass es nur diesen Befehl immer ausführen wird, wenn die :start Aktion aufgerufen wird. Wir fügen auch etwas Idempotenz hinzu, um sicherzustellen, dass es nicht jedes Mal das Init-Skript neu erstellt.

Schließlich fügen wir alle Vorlagen mit den normalen Benachrichtigungen für service[myservice] hinzu.

+0

Und was erreichen Sie, indem Sie 'execute [generate-init-script]' bis 'service [myservice]' abonnieren? Und Sie können den Dienst nicht starten, wenn kein Init-Skript vorhanden ist. –

+0

Whoops. Ich meinte damit Abonnenten, die an die 'Service [myservice]' Ressource angehängt werden. Ich werde meinen Beitrag bearbeiten. Da die Service-Ressource nicht ausgeführt werden kann, wenn ein Init-Skript nicht existiert, abonnieren wir es für den execute-Block, um sofort auszulösen, nachdem es vom ersten Ausführungsblock erstellt wurde. Das not_if soll verhindern, dass der Befehl jemals wieder ausgelöst wird, wenn das init-Skript bereits existiert. –

4

Chef wurde entwickelt, um Konfigurationsrichtlinien (Systemstatus) auszudrücken, was eine etwas andere Sache ist, als eine Sequenz von Aufgaben auszudrücken.

Glücklicherweise können die Ressourcen zur Laufzeit neu definiert werden, da die DSL rubinbasiert ist.

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 

Dies wird die Service-Ressource neu schreiben "Aktion [: Aktivieren: Neustart]" haben, statt "action [: Aktivieren: Start]", wenn eine der Vorlage Ressourcen Zustand diesen Lauf ändern. Die Reihenfolge bleibt also gleich, und Sie erhalten nur einen Anruf über die Serviceressource statt über drei.

+0

Dies ist eine interessante Idee. Ich hatte noch keine Gelegenheit, es auszuprobieren ... Ich sollte in ein paar Tagen Zeit haben. – Charlie

+0

Ich bin ein bisschen gesprungen und habe eine Idee untersucht, die auf anderen, nicht ganz identischen Problemen basiert, die wir gelöst haben. Ich habe das heute tatsächlich ausprobiert und festgestellt, dass es nicht genau so funktioniert, wie ich dachte. Aber das Prinzip ist grundsätzlich gesund. Ich habe das obige Beispiel ruby_block editiert. – bear

Verwandte Themen