Build Agents im Netzwerk¶
Jeder Azure-DevOps-Job (ein Build, ein Deployment, alles andere) läuft auf einem Agent. Von Microsoft gehostete Agents werden von Microsoft verwaltet, laufen aber außerhalb deines Netzwerks und erreichen keine private endpoints. Ein selbst gehosteter Agent-Pool im Plattform-Netzwerk kann das. Diese Seite erklärt, wie ein solcher gemeinsamer Pool üblicherweise aufgebaut ist (ein VM-basiertes und ein Container-basiertes Beispiel), wie du ihn nutzt und was zu tun ist, wenn sich das OS-Image des Pools ändert.
Plattformspezifisch
Ob deine Plattform einen gemeinsamen Agent-Pool anbietet, sowie sein Name, seine Größe und sein OS-Image hängen von deiner Plattform ab. Das folgende Pool-Design ist ein Beispiel. Die Pools, die die MCP-pipelines für die Plattform selbst verwenden (siehe Job runners), sind für Plattform-Deployments gedacht. Frag dein Plattform-Team, welchen Pool du verwenden darfst. Die Kurzfassung steht unter Shared Services. Das Plattform-Team betreibt den Pool, oder du betreibst ihn im Eigenbetrieb selbst (Betriebsmodelle).
Beispiel-Design eines gemeinsamen Pools¶
| Thema | Beispiel |
|---|---|
| Compute | Eine Virtual Machine Scale Set in den Shared Services des hub, als Agent-Pool an Azure DevOps angebunden |
| Image | In einer privaten Shared Image Gallery gebaut und nach Zeitplan (zum Beispiel jeden Sonntag) aus derselben Quelle wie das von Microsoft gehostete Agent-Image aktualisiert. Der Pool bietet dieselben Tools wie die von Microsoft gehosteten Agents, Liste der installierten Software. |
| OS | Im Beispiel nur Linux |
| Lebenszyklus | Agents werden nach jeder Nutzung abgebaut, damit keine Secrets oder Zertifikate zurückbleiben |
| Skalierung | Eine maximale Anzahl VMs in der Scale Set, eine Anzahl Agents in Bereitschaft und eine Verzögerung, bevor untätige Agents entfernt werden |
| Netzwerk | Ein dediziertes Subnet im Shared-Services-Netzwerk des hub, über Virtual WAN mit den Spokes verbunden |
| Firewall | HTTPS (und SQL) vom Agent-Subnet zu Azure-Zielen. Alles andere braucht eine Firewallregel. |
| Zugriff auf die Azure-Ressourcen des Pools | Nur das Plattform-Team |
| Ausfall der Image-pipeline | Bestehende Agents funktionieren weiter. Neue Images werden erst ausgerollt, wenn die pipeline repariert ist. Die übliche Ursache ist eine Änderung im Upstream-Image-Repository. |
Sicherheitsmodell. Der Pool steht allen angebundenen Workload-Teams zur Verfügung, aber ein Job kann nur tun, was der Service Principal deiner pipeline darf. Dieser Service Principal wird mit deinem Spoke erstellt und hat die Rechte deines Spokes (Was du bekommst). Wenn eine pipeline eine Service Connection zum ersten Mal verwendet, muss dein Team sie autorisieren, damit die pipeline eines anderen Teams deinen Service Principal nicht nutzen kann. Weil der Agent nach der Nutzung abgebaut wird, lassen sich Zugangsdaten danach nicht mehr aus ihm auslesen.
Den Pool nutzen¶
- Bitte dein Plattform-Team um Zugriff auf den Pool und um den Pool-Namen. Wenn deine pipeline in einem anderen Azure- DevOps-Projekt liegt als dem, dem der Pool gehört, muss der Pool auch für dieses Projekt verfügbar gemacht werden.
- Setze den Pool in deiner YAML-pipeline:
trigger:
batch: true
branches:
include:
- main
pool: <agent pool name>
variables:
- group: "<variable group>"
stages:
# your stages
- Verwende eine Service Connection, die zu deinem Spoke gehört (Azure DevOps).
Pool-Typen und ihre Grenzen (VM-basiert und Container-basiert) sind unter Shared Services beschrieben.
Beispiel: Container-basierter Pool auf Container Apps jobs¶
Ein Container-basierter Pool führt jeden pipeline-Job in einem eigenen Container auf Azure Container Apps jobs aus. Ein Scaler beobachtet die Warteschlange des Azure-DevOps-Pools und startet pro wartendem Job einen Container. Der Container registriert sich als Agent, führt diesen einen Job aus, entfernt sich aus dem Pool und stoppt. Wartet nichts, läuft nichts.
| Thema | Beispiel |
|---|---|
| Lebenszyklus | Ein frischer Container pro Job. Danach bleiben keine Dateien oder Zugangsdaten zurück. |
| Skalierung | Von 0 bis zu einer maximalen Anzahl Container (im Beispiel 25), die Warteschlange wird alle 10 Sekunden geprüft |
| Startzeit | Etwa 50 Sekunden bei warmem Node, 3 bis 4 Minuten bei kaltem Node (erster Job nach einer ruhigen Phase) |
| Größe | 1 vCPU und 2 GiB Arbeitsspeicher pro Job |
| Zeitlimit | Ein Job wird im Beispiel nach 30 Minuten gestoppt |
| Identität | Der Container nutzt eine managed identity, um sein Image zu pullen und sich in Azure DevOps zu registrieren. Was dein Job in Azure darf, kommt wie bei jedem anderen Pool aus deiner Service Connection. |
| Netzwerk | In einem Subnet eines Spokes. Ausgehender Traffic läuft über die hub-Firewall. |
| OS | Linux, als Container-Image |
Cold Starts sind der Preis für Scale-from-zero. Wenn deine Plattform einen Agent dauerhaft laufen lässt, startet der erste Job schneller, zu konstanten Kosten für die Plattform.
Tools im Container-Image¶
Das Beispiel-Image ist klein. Es basiert auf Ubuntu 22.04 und enthält die Azure CLI, PowerShell, git, curl, jq, unzip,
wget, rsync und einen SSH-Client. Der Agent läuft als Nicht-root-Benutzer, und es gibt keinen Docker-Daemon. Das unterscheidet sich vom
VM-basierten Pool, der die Tools des von Microsoft gehosteten Images hat.
- Installiere, was du brauchst, in der pipeline mit den Tasks aus Fehlende Tools in der pipeline installieren. Der Agent kann nur von Zielen herunterladen, die die Firewall erlaubt (im Beispiel HTTPS 443), ein Download von einem anderen Port oder über eine reine HTTP-URL schlägt also fehl. Beantrage eine Firewallregel, wenn du eine andere Quelle brauchst.
- Container-Images ohne Docker-Daemon bauen: siehe die Optionen unter Shared Services.
- Halte Jobs kurz. Teile einen langen Job in Stages auf, denn ein Job, der länger als das Zeitlimit läuft, wird gestoppt.
- Fixiere die Versionen deiner Tools in der pipeline, weil sich das Image des Pools ändern kann.
Einen Container-basierten Pool nutzen¶
- Bitte das Plattform-Team um den Pool-Namen und um Zugriff. Der Pool existiert auf Organisationsebene, also muss er mit deinem Azure-DevOps-Projekt verknüpft werden (Project settings, Pipelines, Agent pools, Add pool, Existing pool).
- Setze den Pool in deiner pipeline, wie unter Den Pool nutzen. Ein erster Lauf kann wegen des Cold Starts einige Minuten dauern.
- Verwende eine Service Connection, die zu deinem Spoke gehört.
| Symptom | Ursache |
|---|---|
| The pool does not exist or has not been authorized for use | Der Pool ist nicht mit deinem Projekt verknüpft, oder deine pipeline darf ihn nicht nutzen |
| Der Job wartet lange, bevor er startet | Ein Cold Start (3 bis 4 Minuten), oder die maximale Anzahl Container ist in Benutzung |
| Der Job stoppt nach 30 Minuten | Das Zeitlimit des Jobs |
| Ein Tool fehlt | Installiere es in der pipeline |
Wie das Plattform-Team diesen Pool deployt und betreibt: Container Agent Pool.
Wenn sich das OS-Image des Pools ändert¶
Das OS des Images läuft irgendwann aus dem Support, und das Plattform-Team ersetzt es (zum Beispiel Ubuntu 20.04 durch 24.04). Die Tools im neuen Image haben andere Versionen, und manche Tools sind nicht mehr installiert. pipelines, die sich darauf verlassen, brechen. Das Plattform-Team sollte die Änderung ankündigen, mit Datum, der Liste der Unterschiede und einer Testmöglichkeit.
Was du tust:
- Lies die Ankündigung und die Liste der Unterschiede. Die Software-Listen der von Microsoft gehosteten Images stehen auf GitHub.
- Führe deine pipelines vor dem Wechsel gegen das neue Image aus, wenn das Plattform-Team einen Test-Pool oder einen Testtermin anbietet.
- Repariere pipelines, die ein fehlendes Tool oder eine fehlende Version verwenden: Installiere es in der pipeline, bevor du es nutzt.
Ein Beispiel dafür, was sich bei einem echten Image-Upgrade (Ubuntu 20.04 auf 24.04) geändert hat:
| Bereich | Änderung |
|---|---|
| Runtimes | Node.js 18 auf 20, Python 3.8 auf 3.12, Ruby 2.7 auf 3.2, Perl, Bash, GNU-Compiler neuer |
| Aus dem Image entfernt | Terraform, NuGet, Mono und MSBuild, Erlang, Sbt, Heroku, einige CLI-Tools (Netlify, Vercel, OpenShift, ORAS, Alibaba Cloud), PhantomJS, R, SVN, MongoDB, sqlcmd und SqlPackage |
| Tools mit neuer Version | Ansible, Bicep, Docker, Podman, Pulumi, OpenSSL, PostgreSQL, Browser |
| .NET | Weniger SDK-Versionen installiert (zum Beispiel damals nur 8.0 auf dem 24.04-Image) |
Verstehe diese Tabelle als Veranschaulichung. Die Liste des Images, das du tatsächlich bekommst, steht auf der
GitHub-Seite des Images (Ubuntu2404-Readme.md für Ubuntu 24.04).
Fehlende Tools in der pipeline installieren¶
| Tool | Task | Hinweise |
|---|---|---|
| Node.js | UseNode@1 |
Setze version, zum Beispiel '18.x' |
| Python | UsePythonVersion@0 |
Das Herunterladen von Python-Versionen wird auf selbst gehosteten Agents nicht unterstützt. Nur vorinstallierte Versionen sind wählbar. |
| NuGet | NuGetCommand@2 |
Um Abhängigkeiten von Projekt oder Solution wiederherzustellen |
| .NET SDK | UseDotNet@2 |
Setze version, zum Beispiel '6.x' |
| Terraform | TerraformInstaller@1 |
Setze terraformVersion auf latest oder eine bestimmte Version |
- task: UseNode@1
displayName: 'Install Node.js'
inputs:
version: '18.x'
- task: UseDotNet@2
displayName: 'Install .NET SDK'
inputs:
version: '6.x'
- task: ms-devlabs.custom-terraform-tasks.custom-terraform-installer-task.TerraformInstaller@1
displayName: 'Install Terraform'
inputs:
terraformVersion: '<version>'
Wenn dein Team gemeinsame pipeline-Templates für Terraform nutzt, prüfe, ob sie einen Parameter für die Terraform-Version haben. Fixiere die Version in deiner pipeline, sobald das neue Image live ist, damit ein späteres Image sie nicht unbemerkt ändert.
Für Plattform-Teams: den Pool betreiben¶
- Kündige OS-Image-Änderungen rechtzeitig vor Ende des Supports an, mit der Tabelle der Unterschiede (erzeuge sie aus den beiden Upstream-Software-Listen) und einem Test-Pool oder Testfenster.
- Überwache die Image-pipeline sowie Größe und Wartezeiten des Pools. Im Beispiel-Design gab es kein aktives Monitoring: Prüfe, ob es für deine Teams ausreicht.
- Beginne mit einfachen Skalierungswerten und passe sie an, wenn mehr Teams den Pool nutzen.
- Prüfe die Firewallregel für das Agent-Subnet, wenn sich die Menge der Spokes ändert.
- Dokumentiere, wer den Pool nutzen darf und wie ein Team Zugriff bekommt.
- Ändere bei einem Container-basierten Pool das Image, indem du einen neuen tag pushst, und kündige die Änderungen an den Tools an wie bei einem VM-Image. Die Agent-Liste des Beispiel-Images ist kurz, die Unterschiede sind also klein. Siehe Container Agent Pool.
Verwandte Themen¶
- Azure DevOps: Setup und Leitprinzipien
- Shared Services
- Build-Agent-Zugriff auf Spokes (wie die Plattform den Netzwerkzugriff öffnet)
- Plattform: Deployment-Tooling und Job runners