Blog
Bereinigen von Dateien, die von einer GitHub-Aktion geändert wurden, die in einem Container läuft

Ein häufiges Problem, das wir bei selbst gehosteten Runnern sehen, ist, dass sie Dateien hinterlassen können, die von der Aktion erstellt oder geändert wurden. Das liegt daran, dass die Aktion in einem Container ausgeführt wird und der Container eine root Benutzer, um seine Arbeit zu erledigen.
In der GitHub-Dokumentation steht, dass Sie den Runner-Dienst als root um die Kompatibilität mit den meisten Runnern zu gewährleisten. Das ist keine gute Idee, da es zu Sicherheitsproblemen führen kann. Daher führen viele Leute den Runner-Dienst als Nicht-Root-Benutzer aus. Dies kann zu Problemen mit den Zugriffsrechten führen, wenn die Aktion Dateien im Arbeitsbereichsverzeichnis berührt, das eingehängt wird.
Beispiele
Ein gängiges Beispiel ist der super-linter Aktion. Je nach den durchgeführten Prüfungen können Dateien auf dem Datenträger berührt werden, die dann in den Besitz des root Benutzer.
Ein weiteres Beispiel ist die Ausführung des gesamten Auftrags innerhalb eines Containers mit dem Schlüsselwort container auf Auftragsebene:
jobs:
build:
runs-on: self-hosted
container: ubuntu:22.04
steps:
- uses: actions/checkout@v2
- run: echo "Hello World"
Die Checkout-Aktion erstellt eine .git im Arbeitsbereich-Verzeichnis mit dem Inhalt des Repo, das dem root Benutzer als ubuntu-22.04 Container läuft als root. Der Auftrag selbst wird problemlos abgeschlossen, aber wenn Sie das nächste Mal einen anderen Auftrag für dieses Repository auf demselben Runner ausführen, wird die Checkout-Aktion versuchen, das Verzeichnis $GITHUB_WORKSPACE zu bereinigen, um einen sauberen Ausgangspunkt zu erhalten, und mit einem Berechtigungsfehler scheitern, da der Auftrag nicht als Root läuft, sondern als der Nicht-Root-Benutzer, unter dem der Runner-Dienst ausgeführt wird.
Es gibt mehrere Möglichkeiten, dieses Problem zu lösen:
- Verhindern Sie, dass dies geschieht: Führen Sie den Runner-Dienst als
rootund führen Sie den Auftrag alsrootebenfalls. Dies wird von GitHub empfohlen, um dies zu verhindern, denn so wurde der Dienst konzipiert. Die meisten Leute, mit denen ich spreche, sind damit nicht einverstanden, da der Benutzer zu viele Berechtigungen hat und dies zu Sicherheitsproblemen führen kann. - Ändern Sie die Aktion so, dass sie nicht als root ausgeführt wird, was bei der Verwendung von Aktionen aus dem öffentlichen Marktplatz nicht realistisch ist.
- Bringen Sie den Benutzer dazu, innerhalb des Containers aufzuräumen, oder fügen Sie eine Aufräumaktion zu seinem Auftrag hinzu.
- Fügen Sie die Bereinigungskonfiguration auf der Containerebene im Runner hinzu
- Fügen Sie die Bereinigungskonfiguration in der Läuferkonfiguration selbst hinzu
- Führen Sie den Container nicht mit Persistenz aus: Führen Sie ihn als
ephemeralaus, wobei der Läufer nur für eine einzige Auftragsausführung aktiv ist und dann vollständig gelöscht und aufgeräumt wird, damit er nicht wiederverwendet wird.
In diesem Beitrag gehe ich auf die letzten 4 Optionen ein.
Bringen Sie den Benutzer dazu, innerhalb des Containers aufzuräumen, oder fügen Sie eine Aufräumaktion zu seinem Auftrag hinzu.
Sie könnten nach den Aufträgen suchen, die dieses Problem verursachen, und den Benutzer "auffordern", eine Bereinigungsaktion in den Auftrag selbst einzufügen. Es gibt zum Beispiel eine Säuberungsaktion auf dem Markt erhältlich, das in einem Container läuft, der Root verwendet und das Verzeichnis des Arbeitsbereichs bereinigt. Dies ist keine gute Lösung, da sie viel manuelle Arbeit erfordert und Sie die Aufträge, die dieses Problem verursachen, im Auge behalten müssen. Die folgenden Optionen sind wahrscheinlich besser zu handhaben.
Fügen Sie die Bereinigungskonfiguration auf der Containerebene im Runner hinzu
Sie können den Runner mit bestimmten Anpassungsbefehlen konfigurieren, die vor und nach dem Auftrag ausgeführt werden, sowie mit anderen Optionen:
- prepare_job: Wird aufgerufen, wenn ein Job gestartet wird.
- cleanup_job: Wird am Ende eines Jobs aufgerufen.
- run_container_step: Wird einmal für jede Container-Aktion im Auftrag aufgerufen.
- run_script_step: Führt jeden Schritt aus, der keine Container-Aktion ist. Siehe die gesamte Konfiguration und Beispiele hier. Dies ist ziemlich komplex und eignet sich eher für die Konfiguration von Seitenwagen oder andere komplexe Szenarien. Ich verwende lieber die nächste Option.
Fügen Sie die Bereinigungskonfiguration in der Läuferkonfiguration selbst hinzu
Indem Sie 2 Umgebungsvariablen setzen, bevor der Job startet, können Sie bestimmte Skripte vor und nach dem Start des Jobs ausführen. Der abgeschlossene Job kann dann ein Docker-Run-Befehl sein, der den $GITHUB_WORKSPACE einhängt und alles aufräumt, während er als root. Dies ist meiner Meinung nach die einfachste Option:
- ACTIONS_RUNNER_HOOK_JOB_STARTED: Das in dieser Umgebungsvariablen definierte Skript wird ausgelöst, wenn ein Auftrag einem Runner zugewiesen wurde, aber bevor der Auftrag ausgeführt wird.
- ACTIONS_RUNNER_HOOK_JOB_COMPLETED: Das in dieser Umgebungsvariablen definierte Skript wird ausgelöst, wenn der Auftrag abgeschlossen ist. Weitere Informationen finden Sie in der Dokumentation hier.
Betreiben Sie den Container nicht mit einer Persistenz
Der beste Rat ist, die Läufer immer als ephemeral, bei dem der Runner nur für eine einzige Auftragsausführung aktiv ist und dann vollständig gelöscht und aufgeräumt wird, so dass er nicht wiederverwendet werden kann. Sie müssen einen Mechanismus bereitstellen, um die virtuelle Maschine oder den Container zu bereinigen, auf dem Sie den Runner ausführen. Die beste Methode, die ich gefunden habe, ist die Verwendung von Aktionen Runner Controller in dem der Läufer in einem Container ausgeführt wird, der nach Beendigung des Auftrags gelöscht wird. Dadurch wird verhindert, dass Daten auf dem Läufer verbleiben, und Sie erhalten jedes Mal eine saubere Ausführungsumgebung.
Es mag triftige Gründe geben, einen persistenten Runner zu verwenden, aber ich würde empfehlen, so oft wie möglich ephemere Runner zu verwenden.
Verfasst von
Rob Bos
Rob has a strong focus on ALM and DevOps, automating manual tasks and helping teams deliver value to the end-user faster, using DevOps techniques. This is applied on anything Rob comes across, whether it’s an application, infrastructure, serverless or training environments. Additionally, Rob focuses on the management of production environments, including dashboarding, usage statistics for product owners and stakeholders, but also as part of the feedback loop to the developers. A lot of focus goes to GitHub and GitHub Actions, improving the security of applications and DevOps pipelines. Rob is a Trainer (Azure + GitHub), a Microsoft MVP and a LinkedIn Learning Instructor.
Unsere Ideen
Weitere Blogs
Contact



