SystemD führt kein ExecStartPre aus, bis ich den Dienst neu lade und neu starte

7

Ich überschreibe das /usr/lib/systemd/system/docker.serviceStartskript, um es mit einer Umgebungsdatei zu erweitern. Ich habe meine Konfigurationsdatei /etc/systemd/system/docker.service.d/docker.confwie folgt definiert:

test -d /etc/systemd/system/docker.service.d || \
    mkdir /etc/systemd/system/docker.service.d

cat > /etc/systemd/system/docker.service.d/docker.conf <<EOF
[Service]
EnvironmentFile=/etc/sysconfig/docker
ExecStartPre=-/usr/local/sbin/generate-docker-config
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd:// --dns=\${LOCAL_IPV4}
EOF

systemctl daemon-reload

Ich führe das obige Skript als Packer- Build-Schritt für eine AMI aus.

Wenn ich mein AMI starte, wird die folgende Statusausgabe über den Docker-Dienst von SystemD angezeigt:

● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/docker.service.d
           └─docker.conf
   Active: active (running) since Mon 2016-03-28 21:16:11 UTC; 6min ago
     Docs: https://docs.docker.com
 Main PID: 858 (docker)
   CGroup: /system.slice/docker.service
           ├─ 858 /usr/bin/docker daemon -H fd:// --dns=10.224.4.178 --log-driver=syslog --log-opt tag={{.ImageName}}

Es hat meine nicht ausgeführt ExecStartPre, wie in der Ausgabe zu sehen. Wenn ich Folgendes mache, sehe ich , dass jetzt das Startskript ausgeführt wurde:

# systemctl daemon-reload && systemctl restart docker.service && \
    systemctl status docker.service
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/docker.service.d
           └─docker.conf
   Active: active (running) since Mon 2016-03-28 22:05:24 UTC; 24ms ago
     Docs: https://docs.docker.com
  Process: 1873 ExecStartPre=/usr/local/sbin/generate-docker-config (code=exited, status=0/SUCCESS)
 Main PID: 1876 (docker)
   CGroup: /system.slice/docker.service
           └─1876 /usr/bin/docker daemon -H fd:// --dns=10.224.4.178 --log-driver=syslog --log-opt tag={{.ImageName}}

Beachten Sie, wie es jetzt die ExecStartPrein der Statusausgabe hat?

Gibt es einen Befehl, den ich in meinem Packer-Build daemon-reloadausführen sollte, um zu veranlassen , dass SystemD die neue Dienstkonfigurationsdatei und das neue ExecStartPreSkript lädt und ausführt ? Sollte ich nur restartden Service im Packer Build erstellen oder gibt es eine bessere, maßgeschneiderte Lösung für das Problem?

HINWEIS: Für mein ExecStartPreSkript muss das Netzwerk curlfür EC2-Instanz-Tags verfügbar sein . In der Docker-Dienstdatei wird angegeben After=network.target docker.socket, dass sie nach dem Start des Netzwerks ausgeführt wird.

Naftuli Kay
quelle

Antworten:

1

Nun, das ist das erwartete Verhalten. Wenn Sie den Docker-Dienst unmittelbar nach dem Überschreiben der Docker-Unit-Datei neu starten möchten, sollten Sie systemctl restart docker.servicedanach systemctl daemon-reloadim Skript aufrufen . Wenn Sie Docket auch nur neu starten möchten, wenn es bereits ausgeführt wird, rufen Sie systemctl try-restart docker.servicestattdessen auf.

Der Zweck von systemctl daemon-reloadBefehlen besteht darin, den systemdDämon anzuweisen, seine gesamte Konfiguration neu zu laden, Einheitendateien neu zu laden und den Dienstabhängigkeitsbaum neu zu generieren. Es wirkt sich jedoch nicht auf andere Dienste im System aus, obwohl die Gerätedateien auf der Festplatte geändert werden.

Anderson Medeiros Gomes
quelle
1
Der unerwartete Teil des Verhaltens ist, dass beim Neustart des Systems das System nicht geladen wird ExecStartPre. Die Packer EC2-Instanz wird heruntergefahren und beim nächsten Start als AMI für eine neue EC2-Instanz ausgeführt. Das Problem besteht darin, dass das Skript in dieser Phase nicht aufgerufen wird.
Naftuli Kay
Dann fürchte ich, ich konnte Ihnen bei dem Problem nicht helfen. Ich weiß, wie man Dienste verwaltet systemd, aber ich weiß nicht, wie ich mit Amazon Compute Clouds umgehen soll. Die einzig mögliche Ursache ist, dass das Skript docker.servicenach dem Überschreiben der Einheitendatei nicht neu gestartet wird und dies auch tun sollte.
Anderson Medeiros Gomes
1

Angenommen, das Netzwerk ist online, nachdem network.servicees nicht 100% zuverlässig ist. Deshalb gibt es eine network-online.target.

Wenn Sie sich auf Curl verlassen und absolut sicher sein möchten, dass das Netzwerk aktiv ist, bevor der Dienst gestartet wird, DNS funktioniert usw., kann das Hinzufügen zu Ihrem docker.confSystem hilfreich sein ...

[Unit]
After=network-online.target

... und da Sie diesen ganzen Post-Boot ausführen, damit das Neue ExecStartPrefunktioniert, sollten Sie entweder systemctl daemon-reload && systemctl restart docker.serviceoder systemctl stop docker.service && systemctl daemon-reload && systemctl start docker.servicein Ihrem Packer-Build-Skript hinzufügen . Letzteres ist am zuverlässigsten.

Wenn Sie einen Dienst stoppen, bevor er geändert und abgeschlossen daemon-reloadwird, wird sichergestellt, dass die gesamte Einheit wie angegeben neu geladen wird. Ich kann Sie in der dritten von Ausgang sehen haben vorgesehen , dass die ExecStartfür docker.servicenicht nicht enthält die Argumente , die Sie in dem Packer Build - Skript angegeben haben. Das liegt an systemctl restart docker.service(versus Stop, Daemon-Reload & Start).

Joseph Tingiris
quelle