Green Software Patterns
Die Green Software Foundation pflegt die Green Software Patterns: eine kuratierte Sammlung von Praktiken zum Erstellen grünerer Software.
Der Katalog ist nach dem Software-Lebenszyklus organisiert und kann auch nach Rolle erkundet werden:
Die unten aufgeführten Patterns sind die für die DownToZero-Plattform relevantesten. Jede Überschrift verlinkt zur aktuellen Position des Patterns im Katalog, gefolgt davon, wie wir es anwenden — oder wo es bei DownToZero noch nicht gilt.
Muster bei DownToZero
Statische Daten cachen
Aus Sicht der Energieeffizienz ist es besser, den Netzwerkverkehr zu reduzieren, indem Daten lokal über einen Cache gelesen werden, anstatt sie remote über das Netzwerk abzurufen.
Wir cachen an vielen Stellen während der Anfrageverarbeitung, z. B. cached unsere asynchrone Job-Laufzeit lokal docker images, sodass bei jedem Aufruf kein vollständiger Pull nötig ist.
Wir verwenden außerdem so weit wie möglich Image-Hashes für Container-Images, um die Last in Echtzeit beim Instanziieren neuer Container zu reduzieren.
Wähle die Region, die den Nutzern am nächsten ist
Aus Sicht der Energieeffizienz ist es besser, die Distanz, die ein Netzwerkpaket zurücklegt, zu verkürzen, damit weniger Energie für die Übertragung benötigt wird. Ebenso sind wir aus Sicht des eingebetteten Kohlenstoffs effizienter, wenn ein Netzwerkpaket durch weniger Rechenleistungskomponenten läuft.
Da wir nicht multi-regional sind bzw. die regionale Struktur unserer Infrastruktur nicht direkt offenlegen, kann dies von einem Nutzer nicht beeinflusst werden. Intern versuchen wir, so weit wie möglich auf Regionalität zu optimieren, ohne dabei Haltbarkeit und Verfügbarkeit zu opfern.
Komprimiere gespeicherte Daten
Das Speichern zu vieler unkomprimierter Daten kann zu Bandbreitenverschwendung führen und die Anforderungen an die Speicherkapazität erhöhen.
Wir verpflichten uns, nur komprimierte Daten zu speichern.
Sowohl Objectstore als auch Container Registry unterstützen Kompression auf Speicherebene. Dies ist in beiden Diensten integriert.
Der Observability-Service verfügt über einen internen tiering-Mechanismus, der Daten nach einer festen Aufbewahrungsdauer aus einer heißen Speicherebene in ein kälteres, besser komprimiertes Format verschiebt.
Komprimiere übertragene Daten
Aus Sicht der Energieeffizienz ist es besser, die Größe der übertragenen Daten zu minimieren, damit weniger Energie benötigt wird, da der Netzwerkverkehr reduziert wird.
Containerisiere deine Workloads
Container erlauben eine flexiblere Nutzung von Ressourcen, da Workloads einfach zwischen Maschinen verschoben werden können. Container ermöglichen Bin-Packing und benötigen weniger Rechenressourcen als virtuelle Maschinen, was eine Reduktion unnötiger Ressourcenallokation und eine Erhöhung der Auslastung der Rechenressourcen zur Folge hat.
Wir unterstützen ausschließlich containerisierte Workloads. Die Möglichkeit, Workloads zwischen Standorten zu verschieben, ist im Kern von DTZ notwendig, um Workloads bei Bedarf in effizientere Ausführungsumgebungen zu verlagern.
Lösche ungenutzte Speicherressourcen
Aus Sicht des eingebetteten Kohlenstoffs ist es besser, ungenutzte Speicherressourcen zu löschen, sodass wir hardwareeffizient sind und die Speicherebene für die Aufgabe optimiert ist.
Unser Objectstore unterstützt Ablaufzeiten für Objekte, sodass jede Entität bereinigt werden kann, sobald sie nicht mehr verwendet wird. Unsere Container Registry führt ebenfalls konfigurierbare Aufräumjobs aus, um die Menge gespeicherter Objekte zu reduzieren.
Verschlüssele nur, was notwendig ist
Datenschutz durch Verschlüsselung ist ein entscheidender Teil unserer Sicherheitsmaßnahmen. Der Verschlüsselungsprozess kann jedoch auf mehreren Ebenen ressourcenintensiv sein. Erstens variiert die benötigte CPU-Leistung je nach gewähltem Algorithmus, und komplexere Algorithmen erfordern tendenziell mehr Rechenleistung. Außerdem kann Verschlüsselung zu erhöhtem Speicherbedarf führen, da die zu speichernden Daten meist zusätzliche Metadaten und Padding enthalten, was insbesondere bei kleineren Dateien auffällt. Darüber hinaus ist Verschlüsselung eine wiederkehrende Aufgabe, die jedes Mal ausgeführt werden muss, wenn Daten abgerufen oder aktualisiert werden. Diese Wiederholung kann zu einem erhöhten Energieverbrauch beitragen, insbesondere in Systemen mit hohem Durchsatz.
Evaluieren anderer CPU-Architekturen
Anwendungen werden mit einer Softwarearchitektur gebaut, die am besten zu dem Geschäftszweck passt, den sie bedienen. Cloud-Anbieter machen es einfach, andere CPU-Typen zu evaluieren, wie z. B. x86-64, die zusammen mit vielen kosteneffizienten Alternativen bewertet werden können, die eine gute Leistung pro Watt bieten.
Derzeit unterstützen wir nur eine CPU-Architektur, X86. Wir haben aktuell nicht die Ressourcen, verschiedene Architekturen zu evaluieren.
Verwende ein Service Mesh nur bei Bedarf
Ein Service Mesh setzt zusätzliche Container für die Kommunikation ein, typischerweise im Sidecar-Pattern, um mehr operationelle Fähigkeiten bereitzustellen. Dies kann zu erhöhtem CPU-Einsatz und Netzwerkverkehr führen, erlaubt es aber auch, die Anwendung von diesen Fähigkeiten zu entkoppeln und sie von der Anwendungsschicht in die Infrastrukturschicht zu verlagern.
Da unser Netzwerk nicht auf Kubernetes-Abstraktionen beruht, haben wir auch keinen Bedarf an einem Service Mesh.
TLS am Border-Gateway terminieren
Transport Layer Security (TLS) stellt sicher, dass alle Daten, die zwischen Webserver und Webbrowsern ausgetauscht werden, privat und verschlüsselt bleiben. Das Beenden und Wiederherstellen von TLS erhöht jedoch die CPU-Auslastung und kann in bestimmten Architekturen unnötig sein.
Zustandsloses Design umsetzen
Service-Status bezieht sich auf die im Speicher oder auf der Festplatte erforderlichen Daten, damit ein Dienst funktionieren kann. Status umfasst die Datenstrukturen und Member-Variablen, die der Dienst liest und schreibt. Je nach Architektur des Dienstes kann der Status auch Dateien oder andere auf der Festplatte gespeicherte Ressourcen beinhalten.
Unsere bestehenden Dienste, wie Container Services und Container Jobs, basieren auf zustandslosem Design und bieten diese Fähigkeiten auch unseren Nutzern.
Passe deine Service-Level-Objectives an die Geschäftsanforderungen an
Wenn Service-Ausfallzeiten akzeptabel sind, ist es besser, nicht die höchste Verfügbarkeit anzustreben, sondern die Lösung entsprechend den tatsächlichen Geschäftsanforderungen zu gestalten. Niedrigere Verfügbarkeitsgarantien können helfen, den Energieverbrauch zu senken, indem weniger Infrastrukturkomponenten verwendet werden.
Unser SLO ist es, den bestmöglichen Dienst bereitzustellen, ohne Effizienz und Nachhaltigkeit zu beeinträchtigen. Daher sind unsere Dienste stark auf automatische Skalierung angewiesen, um stets ein angemessenes Service-Level mit minimalem Overhead bereitzustellen.
Passe die Auslastungsanforderungen virtueller Maschinen (VMs) an
Es ist besser, eine VM mit höherer Auslastung laufen zu haben als zwei VMs mit niedriger Auslastung, nicht nur in Bezug auf Energieproportionalität, sondern auch hinsichtlich des eingebetteten Kohlenstoffs.
Bisher bieten wir keine VM-basierten Dienste an. Alle unsere Infrastrukturangebote basieren auf Containern, um ein schlankeres Erlebnis zu bieten.
Passe Auslastungsanforderungen mit vorkonfigurierten Servern an
Es ist besser, eine VM mit höherer Auslastung laufen zu haben als zwei VMs mit niedriger Auslastung, nicht nur in Bezug auf Energieproportionalität, sondern auch hinsichtlich des eingebetteten Kohlenstoffs.
Wir streben eine hohe Auslastung unserer Infrastruktur an, aber diese Komponenten werden dem Endnutzer nicht offengelegt. Der Nutzer sieht nur Container als Abstraktion. Da wir Energieeffizienzmetriken bereitstellen, können diese je nach Auslastung der zugrunde liegenden Infrastruktur variieren.
Minimiere die Gesamtzahl bereitgestellter Umgebungen
In einer Anwendung kann es notwendig sein, mehrere Umgebungen im Anwendungsworkflow zu nutzen. Typischerweise wird eine Entwicklungsumgebung für regelmäßige Updates verwendet, während Staging- oder Testumgebungen dazu dienen, sicherzustellen, dass es keine Probleme gibt, bevor Code eine Produktionsumgebung erreicht, auf die Nutzer zugreifen können.
Speichernutzung optimieren
Es ist besser, die Speicherauslastung zu maximieren, sodass die Speicherebene für die Aufgabe optimiert ist, nicht nur in Bezug auf Energieproportionalität, sondern auch hinsichtlich des eingebetteten Kohlenstoffs.
Durchschnittliche CPU-Auslastung optimieren
Die CPU-Nutzung und -Auslastung variiert im Tagesverlauf, manchmal stark für unterschiedliche Berechnungsanforderungen. Je größer die Varianz zwischen dem durchschnittlichen und dem Spitzenwert der CPU-Auslastung ist, desto mehr Ressourcen müssen als Bereitschaftsreserve vorgehalten werden, um diese Verkehrsspitzen abzufangen.
Auswirkungen auf Kundengeräte und -ausrüstung optimieren
Anwendungen laufen auf Kundengeräten oder werden auf diesen dargestellt. Die vom Kunden genutzte Hardware hat einen in der Produktion und im Betrieb eingebetteten Kohlenstoff-Fußabdruck. Die Optimierung von Softwaredesign und -architektur zur Verlängerung der Lebensdauer der Kundengeräte reduziert die Kohlenstoffintensität der Anwendung. Idealerweise kann der Kunde die Hardware bis zu ihrem Ausfall oder bis zur Obsoleszenz nutzen.
Spitze der CPU-Auslastung optimieren
Die CPU-Nutzung und -Auslastung variiert im Tagesverlauf, manchmal stark für unterschiedliche Berechnungsanforderungen. Je größer die Varianz zwischen dem durchschnittlichen und dem Spitzenwert der CPU-Auslastung ist, desto mehr Ressourcen müssen als Bereitschaftsreserve vorgehalten werden, um diese Verkehrsspitzen abzufangen.
Nicht dringende Verarbeitungsanfragen in eine Warteschlange stellen
Alle Systeme haben Phasen mit Spitzen- und Niedriglast. Aus Sicht der Hardwareeffizienz sind wir effizienter mit der Hardware, wenn wir die Auswirkungen von Anfrage-Spitzen minimieren und eine gleichmäßige Auslastung der Komponenten ermöglichen. Aus Sicht der Energieeffizienz sind wir effizienter, wenn wir sicherstellen, dass Leerlaufressourcen minimiert werden.
Unser Dienst Container Jobs ist die Umsetzung dieses Ziels als Service innerhalb von DTZ.
Übertragene Daten reduzieren
Aus Sicht der Energieeffizienz ist es besser, die Größe der übertragenen Daten zu minimieren, damit weniger Energie benötigt wird, da der Netzwerkverkehr reduziert wird.
Unbenutzte Assets entfernen
Überwache und analysiere die Anwendung und die Cloud-Kosten, um Ressourcen zu identifizieren, die nicht mehr verwendet werden oder reduziert werden können.
Kubernetes-Anwendungen bei Nichtbenutzung herunterfahren
Um CO2-Emissionen und Kosten zu reduzieren, können Dev-&-Test-Kubernetes-Cluster außerhalb der Bürozeiten (z. B. nachts und am Wochenende) Knoten (VMs) ausschalten. => damit wird die Optimierung auf Cluster-Ebene umgesetzt.
Wir bieten keine Kubernetes-basierten Dienste an.
Anwendungen bei Nichtbenutzung skalieren
Anwendungen verbrauchen CPU, selbst wenn sie nicht aktiv genutzt werden. Beispielsweise Hintergrund-Timer, Garbage Collection, Health Checks usw. Selbst wenn die Anwendung heruntergefahren ist, verbraucht die zugrunde liegende Hardware Leerlaufleistung. Dies kann auch bei Entwicklungs- und Testanwendungen oder Hardware außerhalb der Bürozeiten passieren.
Bei DownToZero steht — wie der Name sagt — Herunterskalieren im Zentrum unseres Handelns. Daher streben wir an, dass alle Dienste Skalierungen nach unten unterstützen.
Infrastruktur mit der Nutzerlast skalieren
Der Bedarf an Ressourcen hängt zu einem gegebenen Zeitpunkt von der Nutzerlast ab. Dennoch laufen die meisten Anwendungen, ohne dies zu berücksichtigen. Infolgedessen werden Ressourcen unterausgelastet und ineffizient genutzt.
Kubernetes-Workloads anhand relevanter Nachfrage-Metriken skalieren
Standardmäßig skaliert Kubernetes Workloads basierend auf CPU- und RAM-Auslastung. In der Praxis ist es jedoch schwierig, die Nachfrage-Treiber einer Anwendung mit CPU- und RAM-Auslastung zu korrelieren.
Wir bieten keine Kubernetes-Dienste an.
Logische Komponenten unabhängig skalieren
Eine Microservice-Architektur kann die Menge benötigter Rechenressourcen reduzieren, da sie es erlaubt, jede unabhängige Komponente entsprechend ihrer eigenen Nachfrage zu skalieren.
Auf Schwachstellen scannen
Viele Angriffe auf Cloud-Infrastruktur zielen darauf ab, bereitgestellte Ressourcen zu missbrauchen, was zu einem unnötigen Anstieg der Nutzung und der Kosten führt.
Aufbewahrungsrichtlinien für Speicherressourcen setzen
Aus Sicht des eingebetteten Kohlenstoffs ist es besser, einen automatisierten Mechanismus zum Löschen ungenutzter Speicherressourcen zu haben, damit wir hardwareeffizient sind und die Speicherebene für die Aufgabe optimiert ist.
Traffic mit niedrigerer Priorität zurückweisen
Wenn Ressourcen während hoher Verkehrsaufkommen oder bei hoher Kohlenstoffintensität eingeschränkt sind, führt die Bearbeitung aller Anfragen zu höheren Emissionen. Die Bereitstellung zusätzlicher Ressourcen zur Unterstützung erhöht die eingebetteten CO2-Emissionen und den Strombedarf. Die Fortsetzung der Bearbeitung aller Anfragen während Perioden hoher Kohlenstoffintensität erhöht die Gesamtemissionen des Systems. Das Abschneiden von niedriger priorisiertem Traffic in solchen Szenarien spart Ressourcen und CO2-Emissionen. Dieser Ansatz erfordert ein Verständnis des Traffics, einschließlich welche Anfragen kritisch sind und welche am besten Wiederholungsversuche und Ausfälle verkraften können.
Kubernetes-Cronjobs zeitlich verschieben
Die CO2-Emissionen eines Softwaresystems hängen vom Stromverbrauch der Software und von der Kohlenstoffintensität des Stromnetzes ab, auf dem sie läuft. Daher kann es ineffizient sein, energieeffiziente Software in einem kohlenstoffintensiven Stromnetz auszuführen, wenn das Ziel die Reduktion globaler CO2-Emissionen ist.
Obwohl wir keine Kubernetes-Dienste anbieten, bieten unsere Container Jobs die Möglichkeit für ein flexibles Scheduling-Modell. Siehe unsere Docs für weitere Informationen.
Verwende asynchrone Netzwerkaufrufe statt synchroner
Beim Aufrufen über Prozessgrenzen hinweg — sei es zu Datenbanken, Dateisystemen oder REST-APIs — kann das Vertrauen auf synchrone Aufrufe dazu führen, dass der aufrufende Thread blockiert wird und zusätzliche Last auf der CPU entsteht.
Verwende Circuit-Breaker-Muster
Moderne Anwendungen müssen regelmäßig mit anderen Anwendungen kommunizieren. Da diese anderen Anwendungen ihren eigenen Bereitstellungszeitplan, Ausfallzeiten und Verfügbarkeiten haben, kann die Netzwerkverbindung zu diesen Anwendungen Probleme bekommen. Wenn die andere Anwendung nicht erreichbar ist, schlagen alle Netzwerkrequests gegen diese Anwendung fehl und zukünftige Requests sind wenig zielführend.
Verwende cloud-native Netzwerk-Sicherheitswerkzeuge und -Kontrollen
Netzwerk- & Web Application Firewalls bieten Schutz gegen die häufigsten Angriffe und drosseln schädliche Bots. Diese Werkzeuge helfen, unnötige Datenübertragung zu entfernen und die Belastung der Cloud-Infrastruktur zu reduzieren, während sie gleichzeitig weniger Bandbreite und Infrastruktur verwenden.
Verwende DDoS-Schutz
Distributed Denial of Service (DDoS)-Angriffe werden eingesetzt, um die Serverlast zu erhöhen, sodass sie nicht mehr auf legitime Anfragen reagieren können. Dies geschieht in der Regel, um dem Eigentümer des Dienstes oder der Hardware zu schaden. Aufgrund der Natur des Angriffs werden viele Umweltressourcen durch sinnlose Anfragen verbraucht.
Verwende cloud-native Prozessor-VMs
Cloud-VMs verfügen über unterschiedliche Fähigkeiten basierend auf verschiedenen Hardware-Prozessoren. Die Verwendung von VMs basierend auf der Effizienz ihrer Prozessoren wirkt sich daher auf die Hardwareeffizienz aus und reduziert CO2-Emissionen.
Verwende serverlose Cloud-Services
Serverless-Cloud-Services sind Dienste, die der Cloud-Anbieter für die Anwendung verwaltet. Diese skalieren dynamisch mit dem Workload, der zur Erfüllung der Dienstaufgabe benötigt wird, und wenden Best Practices an, um den Ressourcenverbrauch minimal zu halten.
Alle Angebote von DownToZero sind serverlose Cloud-Services.