Blog

Einrichtung von Gradle-Build-Cache-Knoten im Azure Kubernetes Service (AKS)

SEP 19, 2024

In diesem Blogbeitrag stelle ich ein Setup von Gradle-Build-Cache-Knoten vor, mit dem ihr die Build-Zeit eurer Projekte verkürzen könnt. Wenn ihr Teil eines kleineren Teams seid und Gradle-Projekte ohne Enterprise-Edition nutzt, sind die Inhalte dieses Artikels besonders hilfreich für euch.

Alexandra Sedova

Alexandra is a build and infrastructure engineer with extensive experience across diverse industries. She is experienced in cloud migrations and Kubernetes deployments and is an advocate for the "as code" approach and DevOps best practices. Her project work expands proof of concepts, assessments, tool migrations, building new CI/CD pipelines, setting up release processes, driving digital transformations, and initiating "open source" development communities within organizations.

Als Build Engineer stieß ich beim Gradle-Build-Caching auf mehrere Herausforderungen, die eine einfache, kosteneffiziente Alternative zu Gradle Enterprise erforderten und mir Folgendes boten:

  • Kürzere Build-Zeiten durch effizientes Caching.

  • Einfache Skalierung bei wachsendem Projektumfang.

  • Konsistente Builds über verschiedene Umgebungen hinweg.

  • Eine budgetfreundliche Lösung.

  • Volle Kontrolle über meine Caching-Infrastruktur.

Bitte beachtet, dass die beschriebene Implementierung für die Bereitstellung in AKS auf unsere Organisation (Eficode) zugeschnitten ist, sich aber leicht an eine andere Plattform anpassen lässt.

Was ist ein Gradle-Build-Cache?

Ein Gradle-Build-Cache ist eine leistungsstarke Funktion, die die Ergebnisse vorheriger Builds speichert und wiederverwendet. Dadurch verkürzt sich die Dauer nachfolgender Builds erheblich. Das ist besonders vorteilhaft in CI/CD-Umgebungen, in denen mehrere Builds stattfinden.

Projektüberblick

Unser Projekt bietet eine robuste und skalierbare Lösung für die Bereitstellung von Gradle-Build-Cache-Knoten in AKS. Ihr findet das Open-Source-Projekt hier. Zu den wichtigsten Komponenten gehören:

  • Ein Kubernetes StatefulSet mit zwei Replikaten des Build-Cache-Knotens.

  • Ein Kubernetes Service, der den Cache verfügbar macht.

  • Ein Ingress Controller für den externen Zugriff.

  • AzureFile für persistenten Speicher.

Voraussetzungen

Für die Implementierung dieser Lösung benötigt ihr:

  • Einen Azure Kubernetes Service-Cluster.

  • Kubernetes CLI (kubectl).

  • Azure CLI (az).

  • Docker CLI.

Implementierungsschritte

Wir haben AzureFile für das persistente Volume gewählt, da dies für AKS aus unserer Sicht die einfachste Lösung war. Je nach Anforderungen eures Projekts, Teams oder eurer Organisation solltet ihr möglicherweise eine Alternative in Betracht ziehen.

Azure File Share einrichten

Wir begannen mit der Erstellung eines Azure File Share, um persistenten Speicher für unsere Cache-Knoten bereitzustellen. Dazu erstellten wir einen Storage Account, einen File Share und richteten die erforderlichen Kubernetes Secrets ein.

Als Nächstes haben wir das StatefulSet und den Service mithilfe von Kubernetes-Manifesten bereitgestellt. Das StatefulSet stellte sicher, dass unsere Cache-Knoten stabile Netzwerkidentitäten und persistenten Speicher hatten.

kubectl apply -f gradle-cache-stateful-set.yamlkubectl apply -f service.yaml

Ingress konfigurieren

Wir haben eine Ingress-Ressource eingerichtet, um den externen Zugriff auf unsere Cache-Knoten zu verwalten. Dadurch konnten unsere Entwickler von außerhalb des Kubernetes-Clusters mit dem Cache interagieren. Im Beispiel haben wir der Einfachheit halber webapprouting.kubernetes.azure.com als Ingress-Klasse verwendet, da wir keine strengen Anforderungen an den Zugriff auf die Cache-Knoten hatten. Möglicherweise bevorzugt ihr jedoch einen geeigneten HTTPS-Server.

Um den Benutzerzugriff einzuschränken oder zu konfigurieren, könnt ihr auf dem Knoten eine benutzerdefinierte Konfiguration unter «config-dir»/config.yaml bereitstellen. Dies bringt jedoch einige Herausforderungen mit sich.

Wir wollten von Anfang an einen vorkonfigurierten Benutzerzugriff, wobei die Datei config.yaml als Secret hinterlegt ist. Wenn ihr ein Secret oder eine Config Map als Konfigurationsdatei für den Build-Cache-Knoten einbinden möchtet, muss sie beschreibbar sein.

Secrets oder Config Maps können als Lese-/Schreibzugriff eingebunden werden, dafür muss jedoch ein Feature Gate deaktiviert werden. Das hätte globale Auswirkungen und ist daher nicht ratsam.

Für die Generierung gesalzener Passwort-Hashes haben wir folgenden Befehl verwendet:

docker run --interactive --tty gradle/build-cache-node:19.0 hashFür diese Konfiguration haben wir ein Kubernetes-Secret erstellt:

Zugriff auf den Build-Cache-Knoten

Um auf den Cache-Server zuzugreifen, ermittelt die externe IP-Adresse eures Ingress:

Anschließend könnt ihr sie einfach im Browser aufrufen: http://<external-ip>:5071

Euer Gradle-Projekt mit dem Cache-Knoten konfigurieren

Alternative Speicherlösungen

Für unsere Implementierung haben wir zwar Azure File Share gewählt, es gibt jedoch zahlreiche alternative Speicherlösungen, die für unterschiedliche Umgebungen und Anforderungen geeignet sein können. Dazu gehören beispielsweise Amazon Elastic File System, wenn euer Team AWS nutzt, und Google Cloud Filestore für GKE sowie viele Cloud-Anbieter-unabhängige Optionen wie Rook, Longhorn, OpenEBS und weitere.

Berücksichtigt bei der Auswahl einer Alternative folgende Faktoren, damit sie zu eurem Cloud-Anbieter oder eurer On-Premise-Infrastruktur passt:

  • Leistungsanforderungen.

  • Anforderungen an die Skalierbarkeit.

  • Funktionen für Datenreplikation und Backups.

  • Kosten.

  • Einfache Verwaltung und Integration in vorhandene Tools.

Für unser Projekt bot Azure File Share die richtige Balance aus Einfachheit, Leistung und Integration in unsere Azure-basierte Infrastruktur. Die Implementierung eines Gradle-Build-Cache-Knotens in AKS hat unsere Build-Zeiten und die Gesamteffizienz unserer CI/CD deutlich verbessert. Jede Lösung hat jedoch ihre Stärken, und die beste Wahl hängt letztlich von eurem konkreten Anwendungsfall und eurer Umgebung ab.

Durch die Nutzung von Kubernetes StatefulSets und der robusten Cloud-Infrastruktur von Azure konnten wir eine skalierbare, persistente und sichere Lösung für unsere Build-Cache-Anforderungen schaffen.

Ich hoffe, dieser Blogbeitrag dient eurem Team als hilfreiche Referenz, um Gradle-Builds in einer Kubernetes-Umgebung zu optimieren. Die vollständigen Implementierungsdetails findet ihr gerne in unserem GitHub-Repository.

  • Software development
  • DevOps
  • Cloud native

Subscribe to our newsletter