Ich verarbeite meine Buildchain via Gitlab CI. Neben dem eigentlichen Build der Applikation, der Frontend-Assets werden zahlreiche Tests ausgeführt, die Code-Qualität geprüft und am Ende die fertige Website deployed. Da kommen einige Jobs zusammen. Wie schön wäre es, wenn immer genügend Gitlab-Runner zur Verfügung stehen würden? Wir brauchen autoscale Gitlab-Runner. Eine Anleitung.
Gitlab-Runner: Autoscaling in der HETZNER-Cloud.
Wofür brauche ich einen Gitlab-Runner?
Jeder Job innerhalb der Gitlab CI wird von einem sogenannten Runner ausgeführt. Dieser Runner ist an und für sich nichts besonderes; er erhält vom Gitlab-Server eine Aufgabe (z.B. "Baue die Applikation", "Teste Syntax auf Gültigkeit" oder "Deploye das Ergebnis auf den Produktiv-Server") und die passenden Daten (in der Regel das Gitlab-Repository) und arbeitet sie ab - das Ergebnis wird (auf Wunsch) zursückgeschickt und steht dann nachfolgenden Jobs zur Verfügung.
Ein Gitlab-Runner hat in der Regel kein Gedächtnis, kann sich aber Dinge merken (insbesondere wichtig für das Caching).
Nun kann man Gitlab Runner problemlos auf einem Server registrieren, um erste Gehversuche mit Gitlab CI zu machen. Sobald man dieses Tool aber ernsthaft benutzt, stellt man fest, dass Jobs zu lange warten müssen, weil kein Runner frei ist. Wir wollen die Buildchain aber so schnell wie möglich abarbeiten und warten ist tote Zeit.
Mehr Runner!
Die erste Reaktion auf einen Mangel ist: Mehr davon! Wir brauchen Runner! Spätestens wenn diese Runner aber über mehrere Server verteilt sind - und an diesen Punkt kommt man schneller, als man denkt: Runner können sehr viel Last auf einem Server erzeugen! - gibt es ein neues Problem: Runner auf unterschiedlichen Servern können sich nicht so ohne weiteres einen Cache teilen. Das macht die Buildchain aber wieder langsamer. Ein Dilemma.
Hinzu kommt ein wirtschaftlicher Aspekt: Die wenigsten von uns werden rund um die Uhr arbeiten. Wie überall gibt es Phasen, in denen die Luft brennt und man Runner ohne Ende braucht; dann ist es aber (typischerweise nachts und am Wochenende) auch komplett ruhig und es gibt nichts zu tun. Und es gibt normale Arbeitstage, an denen deutlich weniger durch die Build-Chains läuft als sonst.
Alle Runner, die man zu Spitzenzeiten benötigt, ständig vorzuhalten, ist ökonomischer und ökologischer Unsinn.
Autoscaling!
Das Ziel ist also, immer dann viele Runner zur Verfügung zu haben, wenn wir sie brauchen. Und wenn wir sie nicht brauchen, sollen diese sich abschalten. Wir brauchen Autoscaling!
Gitlab Runner sind ein ausgezeichnetes Beispiel, wo aus meiner Sicht Cloud-Computing sinnvoll ist. Die Runner selbst haben untereinander keine Abhängigkeiten; es ist einfach eine kleine Software-Armee, die auf Arbeit wartet und diese erledigt. Ob es einen, drei oder fünfhundert Runner gibt, ist für die Buildchain egal.
Die Auswahl des richtigen Cloud-Anbieters
Hier gibt es im eigentlichen Sinn kein richtig oder falsch. Grundsätzlich sind alle Anbieter von Cloud-Lösungen dafür geeignet, sofern sie eine entsprechende API zur Verfügung stellen, um Server automatisiert zu starten, konfigurieren und wieder zu löschen.
Das ist natürlich bei den Großen der Fall: Amazon AWS, Google Cloud-Front, Microsoft Azure, Akamai, Digital Ocean usw. können das alle. Ich habe mich für das Cloud-Angebot von HETZNER entschieden, weil ich zum einen schon lange Server bei diesem Provider stehen habe und immer gute Erfahrungen mit dem Support gesammelt habe. Zum anderen ist der Serverstandort wählbar, und man kann z.B. Server in Deutschland wählen, wenn man das möchte (was ich tue).
Die Preise von HETZNER sind sehr fair: der kleinste Server ist für knapp 3,- €/Monat zu haben, wenn er ununterbrochen läuft. Da wir u.U. sehr viele Schaltzeiten haben, habe ich Wert darauf gelegt, einen Tarif zu wählen, der nur die reine Laufzeit und keine Setup-Kosten o.ä. berechnet.
Für die Gitlab-Runner habe ich die CX21-Server gewählt. Diese bieten genügend Power für die Abarbeitung der Jobs, sind mit 1 ct/Stunde aber immer noch sehr günstig. Die CX11-Server reichen zum Ausprobieren, bei größeren Jobs kam ich damit aber an die Grenze des Hauptspeichers.
Wer das bei der HETZNER cloud testen möchte, kann sich hierüber anmelden: https://hetzner.cloud/?ref=wNQZvWvSsgiI (Bei Anmeldungen über diesen Link bekomme ich eine kleine Provision in Form von Cloud-Guthaben von HETZNER).
Damit unser Orchester von Gitlab-Runnern funktioniert, benötigen wir einen Dirigenten. Dieser nimmt von Gitlab CI die Jobs entgegen und weist diese den Runnern zu. Gleichzeitig stellt er sicher, dass immer ausreichend Runner bereit stehen und schaltet Runner ab, die nicht mehr benötigt werden.
Ich nenne diese Rolle Broker und habe den Server entsprechend benannt. Mein Broker ist ebenfalls ein Server in der HETZNER Cloud; und hier reicht bislang auch problemlos ein kleiner CX11-Server. Dieser Server läuft die ganze Zeit.
Der Broker übernimmt bei mir noch eine weitere wichtige Rolle: er stellt Speicherplatz zur Verfügung, um Caches zwischenzuspeichern. Dies ist auch der Grund, warum ich einen Cloud-Server für den Broker benutze und diesen Dienst nicht von einem bereits bestehenden Server mit-erledigen lasse. Es ist sinnvoll, dass Broker und Gitlab-Runner netzwerktopologisch nah beiander sind, um Latenzen und Übertragungszeiten gering zu halten. Bei einer Buildchain zählt jede Sekunde und der Preis für den Broker ist sehr gut investiertes Geld.
Damit der Broker nicht aus Versehen abgeschaltet oder gar gelöscht wird, kann man diesen über die Cloud-Verwaltung schützen.
Die Konfiguration des Brokers
Für die Konfiguration des Brokers habe ich ein Gitlab-Runner-Image von mawalu benutzt. Damit kann der Gitlab-Runner einfach in einem Docker-Container gekapselt laufen und macht wenig Probleme bei der Konfiguration. Das Projekt findet ihr hier: https://github.com/mawalu/hetzner-gitlab-runner
Die docker-compose.yml ist simpel:
# docker-compose.yml
version: '2'
services:
hetzner-runner:
image: mawalu/hetzner-gitlab-runner:latest
mem_limit: 128mb
memswap_limit: 256mb
volumes:
- "./hetzner_config:/etc/gitlab-runner"
restart: always
Mit docker-compose up -d wird der Broker gestartet. Anschliessend wird mit docker-compose run hetzner-runner register der Runner beim Gitlab-Server angemeldet und dadurch im Verzeichnis hetzner_config eine config.toml hinterlegt und die Verbindung zu Gitlab CI hergestellt. Diese config.toml werden wir gleich noch modifizieren.
Der Broker wird mit docker-compose run gestartet und ist dann aktiv. Änderungen an der config.toml wirken sich sofort aus; der Broker braucht nicht neu gestartet zu werden!
Meine config.toml sieht so aus (vertrauliche Informationen sind entfernt):
[[runners]]
name = "[HETZNER] Cloud-runner with autoscale"
limit = 15
url = "*************"
token = "*************"
executor = "docker+machine"
environment = ["COMPOSER_CACHE_DIR=/composer-cache"]
[runners.custom_build_dir]
[runners.docker]
tls_verify = false
image = "marcwillmann/codeception"
memory = "2048m"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/var/cache:/cache:rw", "/var/run/docker.sock:/var/run/docker.sock"]
pull_policy = "if-not-present"
shm_size = 536870912
[runners.machine]
IdleCount = 2
IdleTime = 600
MachineDriver = "hetzner"
MachineName = "runner-%s"
MachineOptions = ["hetzner-api-token=*************", "hetzner-image=ubuntu-18.04", "hetzner-server-type=cx21"]
OffPeakPeriods = ["* * 0-8,19-23 * * mon-fri *", "* * * * * sat,sun *"]
OffPeakTimezone = "Europe/Berlin"
OffPeakIdleCount = 1
OffPeakIdleTime = 600
[runners.custom]
run_exec = ""
Den HETZNER-API-Token bekommt man in der Cloud-Console (https://console.hetzner.cloud/), wenn man ein neues Projekt anlegt und dort unter Zugänge -> API-Tokens.
Mit diesem Token darf der Broker nun neue Server starten und bestehende löschen.
In der Konfiguration gibt es den IdleCount. Soviele Runner stellt unser Autoscale immer als Reserve zur Verfügung: in der Cloud-Console kann man das sehr gut beobachten. Direkt nach dem Start werden dort 2 Gitlab-Runner gestartet und warten auf Jobs. Läuft eine Gitlab-CI-Pipeline und wird einem (oder normalerweise mehreren) dieser Runner ein Job zugeteilt, erscheinen neue Server. Mit diesem Wert muss man ein wenig experimentieren. Ist er zu klein gewählt, müssen Jobs warten, bis ein neuer Runner gestartet ist (das dauert einen kleinen Moment, bis er einsatzbereit ist). Ist er zu hoch, verschenkt man Geld, weil unbenötigte Rechenpower vorgehalten wird.
Die IdleTime gibt an, wie lange ein Runner behalten wird, wenn er mit einem Job fertig ist. Kommt in der Zwischenzeit ein neuer Job, wird er wiederverwendet. Kommt kein Job, wird der Runner gelöscht.
Ich habe gute Erfahrungen mit einer IdleTime von 600 gemacht; der IdleCount steht bei mir im Produktivsystem momentan auf 5.
Weil wir alle hoffentlich einigermaßen geregelte Arbeitszeiten haben und nicht die ganze Nacht durcharbeiten, gibt es in der Konfiguration noch die OffPeak-Einstellungen. Hier können Zeiten angegeben werden, wenn die Pipeline nicht oder nur wenig gefordert wird (nach Feierabend, am Wochenende). In diesen Zeiten kann man dann einen eigenen OffPeakIdleCount (z.B. 0 oder 1) konfigurieren, um die Kosten zu reduzieren.
Übrigens: auch ein IdleCount=0 heisst nicht, dass nicht gearbeitet werden kann. Es werden nur keine Reserven vorgehalten, d.h. es dauert etwas länger, bis der Job anläuft. Für einen normalen NightlyBuild, bei dem es nicht auf Sekunden ankommt, ist das aber kein Problem.
Zeit für Verbesserungen
Damit läuft das grundsätzliche Setup schon mal. Jobs im Gitlab werden an den Broker verteilt, der dafür sorgt, dass immer genügend Runner bereit stehen und versorgt diese mit den Aufgaben. Die Zahl der Runner wird nachskaliert.
Die Runner selbst haben aber kein Gedächtnis: die Jobs selbst laufen leider momentan eher langsam. Das liegt aber nicht an fehlender Power: in der Job-Ausgabe fällt auf, dass z.B. unser Application-Build-Job kein Paket im Composer-Cache findet. Das ist auch logisch, der Server für den Runner wurde ja gerade erst gestartet und kann keinen Cache haben. Und von dem Cache, den ein anderer Runner gerade erst aufgebaut hat, weiß unser Runner nichts. Das müssen wir ändern!
Schritt 1: Platz bereitstellen
Wir bauen einen zentralen Cache auf, auf den alle Runner lesend und schreibend zugreifen dürfen. Welcher Platz dafür wäre besser geeignet als der Broker: der steht netzwerktopologisch direkt neben den Runnern, ist immer verfügbar und die Runner können ihn auch erreichen.
Damit auf dem Broker genügend Platz verfügbar ist und dieser auch einen Delete/Rebuild des Broker-Servers überlebt, habe ich ein Volume angehängt. Das ist ein persistenter Dateispeicher, den man jederzeit problemlos vergrößern kann. Momentan nutze ich ein 25GB-Volume als gitlab-runner-cache.
Das Volume kann über die Hetzner Console einfach angehängt werden und ist vom System aus dann unter /dev/disk/by-id/scsi-0HC_VolumeXXXX sichtbar. Dort verhält es sich wie eine normale Festplatte und kann mit dem Filesystem der Wahl (ext4 in meinem) formatiert und gemountet werden.
Auch das ist in der Hetzner Console nachzulesen, der Vollständigkeit halber nochmals auf einen Blick:
sudo mkfs.ext4 -F /dev/disk/by-id/scsi-0HC_Volume_XXXXXXX
sudo mkdir /export
sudo mount -o discard,defaults /dev/disk/by-id/scsi-0HC_Volume_XXXXXXX /export
sudo echo "/dev/disk/by-id/scsi-0HC_Volume_XXXXXXX /export ext4 discard,nofail,defaults 0 0" >> /etc/fstab
Falls man das Volume später in der Größe ändert, muss das im Linux-System natürlich auch bekannt gemacht werden:
sudo resize2fs /export/
Schritt 2: S3-Storage bereitstellen
Leider gibt es bei Hetzner aktuell noch keine S3-kompatible Storage. Aber das ist kein Problem; wir nutzen das gerade angelegte Volume und lassen den Broker diese zur Verfügung stellen. Mit minio gibt es ein schlankes Docker-Image, das einen S3-kompatiblen Dienst zur Verfügung stellt. Auch der ist schnell gestartet:
docker run -it -d --restart always -p 9005:9000 -v /.minio:/root/.minio -v /export:/export --name minio minio/minio:latest server /export
Und mit
cat /export/.minio.sys/config/config.json | grep Key
erhalten wir die S3-Zugangsdaten.
Schritt 3: Multi-Runner Cache einrichten
Damit haben wir alles zusammen, um unseren Runnern einen gemeinsamen Cache zur Verfügung zu stellen. In der config.toml richten wir diesen ein:
[runners.cache]
Type = "s3"
Shared = true
[runners.cache.s3]
ServerAddress = "###IP_BROKER###:9005"
AccessKey = "***************"
SecretKey = "************************************"
BucketName = "runner"
Insecure = true
[runners.cache.gcs]
und freuen uns, dass künftig der Cache persistiert wird und unsere Jobs deutlich schneller laufen. Das ist insbesondere bei den Build-Jobs (composer und npm) deutlich spürbar; hier kann man teilweise die Ausführungszeit um eine Größenordnung beschleunigen!
Docker auf Speed
Wir sind aber noch nicht am Ende der Optimierung angekommen. Unsere Gitlab-Runner laufen als docker+machine-Typ, d.h. jeder Job wird an einen Docker-Container übergeben, der auf dem Runner-Server gestartet wird. Welches Image verwendet wird, geben wir in der Job-Konfiguration in der .gitlab-ci.yml an.
Naturgemäß ist das bei einem Frontend-Build-Job ein anderer als bei einem Quality-Gate-Job und das Deployment wird wieder auf einen anderen Container setzen.
Und wir stellen fest: das Ziehen des Docker-Images ist nun einer der zeitaufwändigsten Teile eines jeden unseres Jobs. Auch hierfür brauchen wir eine Lösung.
Docker-Images cachen
Hierfür richten wir einen Proxy auf dem Broker ein, der sich für die Runner wie ein Docker-Repository verhält. Hat der Broker das gewünschte Image im Cache, wird es direkt ausgeliefert; andernfalls vom offiziellen Repo angefordert und weitergereicht - und natürlich in den Cache gelegt.
Hört sich kompliziert an, ist es aber nicht:
sudo docker run -d -p 6005:5000 -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io --restart always --name registry registry:2
macht den Job. ¯\_(ツ)_/¯
In der config.toml des Brokers machen wir dieses neue Repository für die Runner bekannt:
[runners.machine]
...
MachineOptions = ["hetzner-api-token=**************", "hetzner-image=ubuntu-18.04", "hetzner-server-type=cx21", "engine-registry-mirror=http://###IP_BROKER###:6005"]
...
und freuen uns über deutlich schnellere Pipelines.
Debugging
Wichtiger Hinweis: Am 10.12.2020 erschien ein Docker-Update, das Probleme mit den hier nachfolgend beschriebenen docker+machine-Gitlab-Runnern verursacht. Ich vermute, dass der Bug demnächst behoben sein wird, aber da die meisten von uns auf funktionierende Pipelines jetzt angewiesen sind, teile ich gerne meine Erkenntnisse vom gestrigen Arbeitstag:
Im Wesentlichen besteht das Problem darin, dass der Gitlab-Runner wie gewünscht eine neue Maschine startet, dort auf den Docker-Stack wartet und diesen nicht findet. Die Maschine wird dann verworfen (aber dummerweise auch nicht gelöscht, sondern läuft weiter) und eine neue gestartet, mit der dann das gleiche Passiert. Die Pipelines in Gitlab sind stuck und laufen einfach nicht los, weil eben keine Maschine vorhanden ist. Die letzte Nachricht in Gitlab war dann meist die Zeile
Preparing the "docker+machine" executor
und dann passierte gar nichts mehr.
Das ganze Setup konstruktiv zu debuggen, ist gar nicht so einfach - es kann einfach an vielen Stellen eine Kleinigkeit schief gehen. Auf die falsche Fährte lockte mich zudem ein von HETZNER gemeldetes Problem mit den Cloud-Servern, bei denen ein Netzwerkproblem gemeldet wurde. Wie sich herausgestellt hatte, war das aber - wie so oft - nur zufällig zeitgleich und zumindest meine Runner waren von diesem Netzsegment auch nicht betroffen.
Auf die richtige Spur hat mich schließlich gebracht, nicht nur in die Logs zu sehen (der Gitlab-Broker loggen nach /var/log/syslog), sondern den Gitlab-Broker herunterzufahren und im Non-Daemon-Mode zu starten:
docker-compose down
docker-compose up
Dort stieß ich dann auf die Fehlermeldungen
WARNING: Failed to process runner builds=1 error=failed to update executor: no free machines that can process builds executor=docker+machine
und mit dieser dann auf den Hinweis, dass das neue Docker-Update diese Probleme verursacht, weil wohl ein Timing-Problem vorliegt und die Gitlab-Runner zumindest nicht lange genug auf den Dokcer-Stack warten.
Ob da nun Docker oder Gitlab ein entsprechendes Update nachliefern werden, bleibt abzuwarten. Damit die Pipelines wieder laufen, kann die vorherige Docker-Version benutzt werden. Die Maschinen werden ja automatisch provisioniert, weshalb wir in der config.toml (s.o.) die entsprechende Konfiguration setzen müssen:
MachineOptions = ["hetzner-api-token=*****", ..., "engine-install-url=https://releases.rancher.com/install-docker/19.03.9.sh"]
Ich hoffe, das hilft dem Einen oder Anderen, der sich anhand dieser Anleitung ein ähnliches Setup aufgebaut hat.
Kommentare (16)
Theo Hilgers
am 18.06.2020Ich habe einen Fehler gefunden:
docker-compose run hetzner_runner register müsste zu
docker-compose run hetzner-runner register geändert werden.
Mein Broker (Manager) legt bei Hetzner Server an. Jedoch bekomme ich in Gitlab immer diese Fehlermeldung. Eine Idee was falsch ist oder wo ich suchen kann?
https://drive.google.com/uc?id=14riIELQad7wqHRSq9dv5L1R47fk3cyOh
Marc Willmann
am 18.06.2020vielen Dank für den Hinweis - ist korrigiert.
Zu Deinem Fehler: Ist im Gitlab der Runner aktiv (/admin/runners -> letzter Kontakt)?
Hast Du vielleicht eine Firewall, die die Verbindung von Gitlab zu den Runnern/dem Broker unterbindet?
Stimmt die Version von Gitlab und den Runnern?
Theo Hilgers
am 18.06.2020gerne :)
Ich sehe den Manager im Gitlab unter /admin/runners dort wird mir die Version 13.0.1 angezeigt. Das hat auch mein Gitlab. Habe aber jetzt ein Update gemacht auf 13.0.6-ee. Problem besteht leider weiterhin.
Bezüglich Firewall
Der Broker ist einfach ein Server bei Hetzner. Dort habe ich nur docker und docker-compose installiert und den Broker Container von dir gestartet und Konfiguriert. Ich sehe wie bei Hetzner runners gestartet werden.
Grüße
Theo
René
am 15.09.2020danke für diesen Artikel, ich hab mir vorgenommen, dass die Tage mal auszuprobieren.
Ich hab zu den Cache Servern eine Frage: So wie es in dem Artikel steht, sind die jeweils unter der öffentlichen IP des Broker Servers erreichbar, oder? Das sehe ich bei dem S3 Server aufgrund der Authentifizierung nicht als problematisch an, anders aber bei dem Docker Cache Server.
Der scheint ohne Authentifizierung öffentlich erreichbar, das würde ein Einfallstor für DoS Attacken liefern, wenn mir zum Beispiel jemand den Cache mit Docker Images vollmüllt.
Eine Lösung wäre, nur ein privates Netz, welches man ja bei Hetzner erstellen kann, zu nutzen. Dafür müsste man die Worker Server jedoch auch automatisch in dieses Netz bewegen. Gibt es dazu eine Konfigurationsmöglichkeit in der genutzten Software? Ich konnte auf die Schnelle nichts finden, aber vielleicht hast Du Dir da auch schon Gedanken drüber gemacht.
Viele Grüße
René
Marc Willmann
am 29.09.2020Du kannst in den machine-options über die Cloud-API die Netzwerknamen angeben, die dem Server zugeordnet werden sollen (https://docs.hetzner.cloud/#servers-create-a-server). Wenn Du also ein privates Netz beim Broker erstellst und in der config.toml dieses beim Erstellen der Runner mitgibst, sollte das klappen. Ich probier das in den nächsten Tagen mal aus.
Vielen Dank für den Hinweis
Marc
Marc Willmann
am 11.12.2020ich schulde Dir noch eine Antwort auf den sicheren Umgang mit einem eigenen Registry-Server. Unter https://docs.docker.com/registry/deploying/ ist gut beschrieben, wie man eine eigene Registry aufsetzt und auch, wie man diese absichern kann. Ich hoffe, das hilft :)
Marc
Jochen Schultz
am 12.12.2020Ich habe auch noch eines: OffPeakPeriods sind offenbar deprecated:
[runners.machine]
MachineName = "runner-%s"
MachineDriver = "hetzner"
MachineOptions = [
"hetzner-api-token=xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"hetzner-image=ubuntu-20.04",
"hetzner-server-type=cx21",
"engine-registry-mirror=http://xxx.xxx.xxx.xxx:6005"
]
IdleCount = 1
IdleTime = 30
[[runners.machine.autoscaling]]
Periods = ["* * 9-17 * * mon-fri *"]
IdleCount = 1
IdleTime = 30
Timezone = "UTC"
[[runners.machine.autoscaling]]
Periods = ["* * * * * sat,sun *"]
IdleCount = 1
IdleTime = 30
Timezone = "UTC"
Wollte das eigentlich testen und das Dockerupgrade kam wohl zeitgleich. Logisch wohin einen das dann erstmal treibt!
Marc Willmann
am 12.12.2020Patrick
am 15.05.2021Lassen sich die Machine Options irgendwie (leicht) parametrisieren? Für die meisten Jobs reicht uns ein cx21 - der eine oder andere ist jedoch etwas aufwendiger und braucht bisschen mehr RAM.
Derzeit fällt mir nur die Möglichkeit ein, den Builder-Container zu duplizieren und 2 Runner zu konfigurieren.
Grüße
Patrick
Barry
am 02.03.2023Bei mir klappt leider noch was nicht, wollte dich fragen ob du in letzter Zeit mal selber Gitlab Runner aufsetzen musstest bei Hetzner?
Ich sehe den Runner, aber immer mit dem Hinweis, dass kein Kontakt stattgefunden hat bislang.
Marc Willmann
am 02.03.2023Kay Strobach
am 26.06.2023https://docs.hetzner.cloud/#deprecation-notices-%E2%9A%A0%EF%B8%8F
Ich habe derzeit immer mal Server, die dann idlen und nicht mehr vom Runner coordinator erreichbar sind, hast du sowas auch schon festgestellt?
ERROR: could not get server handle: server ID was 0 name=runner-pmhd8x2i-g.com-1687810179-216211cf operation=stop
Das führt dann zum Treffen des Resource limits und damit zu einem Stop der Runner 😅
Marc
am 26.06.2023Den beschriebenen Fehler habe ich so noch nicht beobachtet; wir hatten ab und an mal das Problem, dass die Docker-Zertifikate nicht mehr akzeptiert werden. Mit einem Neustart des Brokers läuft das dann aber wieder problemlos.
Kay Strobach
am 26.06.2023Max
am 11.05.2024vielen Dank für dein tolles Tutorial hier. Das hat für uns sehr einfach und schnell funktioniert.
Nach etwas rumsuchen und GPT fragen konnte ich aber eine Frage noch nicht klären:
Kann ich das setup oben so einstellen, dass auf einem "physischen" hetzner server mehrere docker+machine VMs gestartet werden, statt das für jeden neuen Job ein neuer server aufgesetzt wird?
Oder lieber einfach die hetzner server configuration klein genug wählen, dass es kostenmäßig keinen Unterschied macht?
Danke dir schon jetzt für deine Antwort!
Liebe Grüße,
Guido
vor 6 Tagenhttps://docs.gitlab.com/runner/configuration/autoscale.html
"Docker Machine autoscaler creates one container per VM, regardless of the limit and concurrent configuration."
Danke Marc für die Anleitung! Mit ein paar Feintunings läuft das Runner-Autoscaling bei uns jetzt top.