Jetzt abonnieren, um Benachrichtigungen über neue Beiträge zu erhalten:

Automatische Generierung des Terraform-Providers von Cloudflare

2024-09-24

Lesezeit: 10 Min.
Dieser Beitrag ist auch auf English, 繁體中文, Français, 日本語, 한국어, Español, und 简体中文 verfügbar.

Im November 2022 haben wir die Umstellung auf OpenAPI-Schemata für die Cloudflare-API bekannt gegeben. Damals hatten wir das ehrgeizige Ziel, die OpenAPI-Schemata zur zuverlässigen Quelle für unser SDK-Ökosystem und unsere Referenzdokumentation zu machen. Während der Developer Week 2024 haben wir dies mit der Ankündigung untermauert, dass unsere SDK-Bibliotheken jetzt automatisch aus diesen OpenAPI-Schemata generiert werden. Wir freuen uns, heute die neuesten Bestandteile des Ökosystems vorstellen zu können, die jetzt automatisch generiert werden: der Terraform-Provider und eine API-Referenzdokumentation.

Sobald unsere Produkte um eine neue Funktion oder ein neues Attribut erweitert werden und das Team dies dokumentiert, können Sie augenblicklich sehen, wie die Neuerung in unserem SDK-Ökosystem verwendet werden soll, und diese sofort nutzen. Verzögerungen und eine mangelnde Abdeckung von API-Endpunkten gehören damit der Vergangenheit an. 

Die neue Dokumentationsseite finden Sie unter https://developers.cloudflare.com/api-next/ und den Preview-Release-Candididate des Terraform-Providers können Sie testen, indem Sie 5.0.0-alpha1 installieren.

Warum Terraform? 

Für diejenigen, die mit Terraform nicht vertraut sind: Es handelt sich um ein Tool zur Verwaltung Ihrer Infrastruktur als Code, ähnlich wie Sie Ihren Anwendungscode verwalten würden. Viele unserer (großen und kleinen) Kunden nutzen Terraform, um ihre Infrastruktur technologieunabhängig zu orchestrieren. Genauer betrachtet handelt es sich im Wesentlichen um einen HTTP-Client mit integrierter Lebenszyklusverwaltung. Das bedeutet, dass unsere öffentlich dokumentierten API auf eine Weise genutzt werden, bei verstanden wurde, wie während der gesamten Lebensdauer der Ressource Code erstellt, gelesen, aktualisiert und gelöscht wird. 

Wie Terraform bisher auf dem neuesten Stand gehalten wurde

Früher hat Cloudflare einen Terraform-Provider manuell verwaltet. Doch da die Interconnections des Providers ihre eigene Vorgehensweise erfordern, lastet die Verantwortung für Wartung und Support in diesem Fall auf den Schultern einer Handvoll Personen. Die Service-Teams hatten aufgrund des hohen kognitiven Aufwands, der für die Bereitstellung einer einzigen Änderung innerhalb des Providers erforderlich war, immer Schwierigkeiten, mit der Anzahl der Änderungen Schritt zu halten. Für einen Wechsel des Providers waren mindestens drei Pull-Anfragen erforderlich (vier, wenn man Support für cf-terraforming hinzufügt).

Selbst nach den vier abgeschlossenen Pull-Anfragen bestand keine Garantie für die Abdeckung aller verfügbaren Attribute. Das bedeutete, dass kleine, aber wichtige Details unter Umständen vergessen wurden und für die Kunden nicht ersichtlich waren. Das sorgte für Frust beim Konfigurieren von Ressourcen.

Um dieses Problem zu lösen, musste unser Terraform-Provider auf dieselben OpenAPI-Schemata zurückgreifen, von denen der Rest unseres SDK-Ökosystems bereits profitierte.

Automatische Aktualisierung von Terraform

Was Terraform von unseren SDK unterscheidet, ist die Verwaltung des Lebenszyklus von Ressourcen. Das bringt eine Reihe neuer Probleme mit sich, die mit bekannten Werten und der Verwaltung von Unterschieden bei den Anfrage- und Antwort-Payloads zusammenhängen. Vergleichen wir die beiden unterschiedlichen Ansätze, einen neuen DNS-Eintrag zu erstellen und ihn abzurufen.

Mit unserem Go-SDK:

// Create the new record
record, _ := client.DNS.Records.New(context.TODO(), dns.RecordNewParams{
	ZoneID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"),
	Record: dns.RecordParam{
		Name:    cloudflare.String("@"),
		Type:    cloudflare.String("CNAME"),
        Content: cloudflare.String("example.com"),
	},
})


// Wasteful fetch, but shows the point
client.DNS.Records.Get(
	context.Background(),
	record.ID,
	dns.RecordGetParams{
		ZoneID: cloudflare.String("023e105f4ecef8ad9ca31a8372d0c353"),
	},
)

Mit Terraform:

resource "cloudflare_dns_record" "example" {
  zone_id = "023e105f4ecef8ad9ca31a8372d0c353"
  name    = "@"
  content = "example.com"
  type    = "CNAME"
}

Oberflächlich betrachtet wirkt es, als ob der Terraform-Ansatz einfacher ist. Dem ist auch tatsächlich so. Der Aufwand des Erstellens einer neuen Ressource und der Beibehaltung von Änderungen wird Ihnen abgenommen. Das Problem ist aber, dass Terraform diese Abstraktion und Datengarantie nur bieten kann, wenn alle Werte zum Zeitpunkt der Anwendung bekannt sind. Terraform muss den erforderlichen Wert kennen, um ihn in der Zustandsdatei speichern und dieses Attribut in Zukunft verwalten zu können. Das gilt selbst dann, wenn Sie den Proxy-Wert gar nicht verwenden. Den folgenden Fehler beobachten Terraform-Betreiber häufig bei Providern, wenn der Wert zum Zeitpunkt der Anwendung nicht bekannt ist.

Error: Provider produced inconsistent result after apply

When applying changes to example_thing.foo, provider "provider[\"registry.terraform.io/example/example\"]"
produced an unexpected new value: .foo: was null, but now cty.StringVal("").

Wenn Sie bei den SDK ein Feld nicht benötigen, können Sie es einfach auslassen. Sie müssen sich keine Gedanken über die Pflege bekannter Werte machen.

Dieses Problem für unsere OpenAPI-Schemata zu lösen, war keine leichte Aufgabe. Seit Einführung der Unterstützung der Terraform-Generierung hat sich die Qualität unserer Schemata um ein Vielfaches verbessert. Jetzt geben wir explizit sämtliche vorhandenen Standardwerte, variable Antworteigenschaften, die auf dem Anfrage-Payload beruhen, sowie alle serverseitig berechneten Attribute bekannt. Dies bedeutet eine bessere Erfahrung für jeden, der mit unseren API interagiert.

Der Wechsel von terraform-plugin-sdk zu terraform-plugin-framework

Um einen Terraform-Provider aufzubauen und Betreibern Ressourcen oder Datenquellen zur Verfügung zu stellen, benötigt man im Wesentlichen zwei Dinge: einen Provider-Server und einen Provider.

Der Provider-Server kümmert sich um die Offenlegung eines gRPC-Servers, den der Terraform-Core (über die Kommandozeile) zur Kommunikation bei der Verwaltung von Ressourcen oder dem Lesen von Datenquellen aus der vom Provider bereitgestellten Konfiguration verwendet.

Der Provider ist dafür verantwortlich, die Ressourcen und Datenquellen zu verpacken, mit den Remote-Diensten zu kommunizieren und die Zustandsdatei zu verwalten. Zu diesem Zweck greift man entweder auf das terraform-plugin-sdk (gemeinhin als SDKv2 bezeichnet) oder das terraform-plugin-framework zurück. Dieses enthält alle von Terraform bereitgestellten Schnittstellen und Methoden zur korrekten Verwaltung der Interna. Die Entscheidung, welches Plugin Sie verwenden, hängt vom Alter Ihres Providers ab. SDKv2 gibt es schon länger und wird von den meisten Terraform-Providern verwendet, doch aufgrund des Alters und der Komplexität bestehen dabei viele ungelöste Kernprobleme. Diese müssen bestehen bleiben, um die Abwärtskompatibilität für diejenigen zu erleichtern, die darauf zurückgreifen. Bei terraform-plugin-framework handelt es sich um die neue Version, die zwar nicht den gleichen Umfang an Funktionen wie SDKv2, dafür aber einen Go-ähnlichen Ansatz für die Erstellung von Providern bietet und bei der viele der zugrunde liegenden Fehler von SDKv2 behoben wurden.

(Für einen ausführlicheren Vergleich zwischen SDKv2 und dem Framework können Sie sich ein Gespräch zwischen mir und John Bhostwe von Octopus Deploy ansehen.)

Der Großteil des Cloudflare Terraform-Providers ist auf SDKv2 aufgebaut, aber Anfang 2023 haben wir den Schritt gewagt, beides  in unserem Provider anzubieten. Um zu verstehen, warum dies notwendig war, müssen wir uns etwas eingehender mit SDKv2 beschäftigen. Die Art und Weise, wie SDKv2 strukturiert ist, ist nicht wirklich förderlich, um Nullwerte oder nicht gesetzte Werte konsistent und zuverlässig darzustellen. Sie können die experimentelle ResourceData.GetRawConfig verwenden, um zu überprüfen, ob der Wert in der Konfiguration gesetzt, null oder unbekannt ist. Das Zurückschreiben als null wird jedoch nicht wirklich unterstützt.

Diese Einschränkung wurde erstmals deutlich, als die Edge Rules Engine (Rulesets) mit dem Onboarding neuer Dienste begann und diese Dienste API-Antworten unterstützen mussten, die Boolesche Werte in einem nicht gesetzten (oder fehlenden), true- oder false-Zustand enthielten – jeweils mit eigener Überlegung und Zweck. Dies ist kein konventioneller API-Aufbau bei Cloudflare. Es ist jedoch ein gültiger Ansatz, um Dinge zu tun, mit denen wir arbeiten können sollten. Wie jedoch bereits erwähnt, war der SDKv2-Provider dazu nicht in der Lage. Wenn ein Wert nicht in der Antwort vorhanden ist oder nicht in den Zustand eingelesen wird, erhält er einen Go-kompatiblen Nullwert für die Standardeinstellung. Dies zeigte sich darin, dass Werte, die als „False“ geschrieben wurden, nicht mehr zurückgesetzt werden konnten (und umgekehrt).

Die einzige Lösung, die wir hier haben, um die drei Zustände dieser Booleschen Werte zuverlässig zu verwenden, ist die Migration zum terraform-plugin-framework. Dieses verfügt über die korrekte Implementierung des Zurückschreibens nicht gesetzter Werte.

Als wir begonnen haben, weitere Funktionen unter Verwendung von terraform-plugin-framework in dem alten Provider hinzuzufügen, war klar, dass dies eine bessere Entwicklererfahrung bot. Deshalb haben wir eine Sperre hinzugefügt, um die Nutzung von SDKv2 in Zukunft zu verhindern und jedem einen Schritt voraus zu sein, der sich unwissentlich dieses Problem selbst einbrocken könnte.

Als wir beschlossen haben, den Terraform-Provider automatisch zu generieren, war bot es sich an, auch alle Ressourcen auf das terraform-plugin-framework zu beziehen und die Probleme von SDKv2 endgültig hinter uns zu lassen. Dies hat aber die Migration erschwert, da mit den verbesserten Interna auch Änderungen an wichtigen Komponenten wie dem Schema und den CRUD-Operationen einhergingen, mit denen wir uns vertraut machen mussten. Der Aufwand hat sich aber gelohnt, weil wir auf diese Weise das Fundament des Providers zukunftssicher gemacht haben. Wir müssen nun weniger Abstriche beim Terraform-Erlebnis aufgrund fehlerhafter veralteter Interna machen.

Iteratives Aufspüren von Fehlern 

Eines der häufigsten Probleme bei Pipelines zur Codegenerierung ist, dass man ohne vorhandene Tools zur Implementierung einer neuen Sache nur schwer sagen kann, ob etwas funktioniert oder seine Verwendung sinnvoll ist. Sie können natürlich auch Ihre Tests generieren, um die neue Sache auszuprobieren. Doch wenn in der Pipeline ein Fehler besteht, werden Sie ihn sehr wahrscheinlich nicht als solchen erkennen, weil die von Ihnen generierten Test-Assertions zeigen, dass der Fehler dem erwarteten Verhalten entspricht. 

Eine der wichtigsten Feedbackschleifen, die wir hatten, ist die bestehende Akzeptanz-Testsuite. Alle Ressourcen innerhalb des bestehenden Providers wurden einer Mischung aus Regressions- und Funktionstests unterzogen. Das Beste daran: Da die Testsuite echte Ressourcen erstellt und verwaltet, ließ sich ganz leicht erkennen, ob das Ergebnis eine funktionierende Implementierung war oder nicht. Man brauchte sich nur den HTTP-Traffic anzusehen und zu überprüfen, ob die API-Aufrufe von den Remote-Endpunkten akzeptiert wurden. Die Portierung der Testsuite erforderte nur das Kopieren aller vorhandenen Tests und die Überprüfung auf Unterschiede bei den Type Assertions (wie eine Liste und eine einzelne verschachtelte Liste), bevor ein Testlauf gestartet wurde, um zu ermitteln, ob die Ressource korrekt funktionierte. 

Die zentralisierte Schema-Pipeline stellte eine enorme Steigerung der Produktivität dar, weil die Schema-Fixes fast augenblicklich im gesamten Ökosystem verteilt wurden. Sie konnte uns jedoch nicht helfen, die größte Hürde zu überwinden: das Aufspüren von Fehlern, die andere Fehler verbergen. Das war zeitaufwendig, weil bei der Behebung eines Problems in Terraform ein Fehler an drei Stellen auftreten kann:

  1. Bevor API-Aufrufe erfolgen, führt Terraform eine logische Schema-Validierung durch. Stößt das Tool auf Validierungsfehler, stoppt es sofort.

  2. Schlägt ein API-Aufruf fehl, setzt das Tool bei der CRUD-Operation aus und meldet die Diagnose zurück.

  3. Nach Durchführung der CRUD-Operation führt Terraform Kontrollen durch, um sicherzustellen, dass alle Werte bekannt sind.

Das heißt: Wenn wir den Fehler bei Schritt 1 finden und ihn dann beheben, gibt es keine Garantie oder Möglichkeit, sicherzustellen, dass nicht noch zwei weitere auf uns warten. Ganz zu schweigen davon, dass, wenn wir bei Schritt 2 einen Fehler finden und einen Fix liefern, das Tool dann in der nächsten Testrunde bei Schritt 1 einen Fehler womöglich nicht mehr erkennen würde.

Ein Patentrezept gibt es hier nicht. Unsere Notlösung bestand deshalb darin, Problemmuster im Schemaverhalten zu erkennen und CI-Lint-Regeln innerhalb der OpenAPI-Schemata anzuwenden, bevor das Problem in die Codegenerierungs-Pipeline gelangte. Durch diesen Ansatz wurde die Zahl der Fehler in Schritt 1 und 2 schrittweise reduziert, bis wir es weitgehend nur noch mit dem Typ in Schritt 3 zu tun hatten.

Ein wiederverwendbarer Ansatz für die Modell- und Strukturkonvertierung 

Bei CRUD-Vorgängen von Terraform-Providern sind häufig Textbausteine wie die folgenden zu sehen:

var plan ThingModel
diags := req.Plan.Get(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
	return
}

out, err := r.client.UpdateThingModel(ctx, client.ThingModelRequest{
	AttrA: plan.AttrA.ValueString(),
	AttrB: plan.AttrB.ValueString(),
	AttrC: plan.AttrC.ValueString(),
})
if err != nil {
	resp.Diagnostics.AddError(
		"Error updating project Thing",
		"Could not update Thing, unexpected error: "+err.Error(),
	)
	return
}

result := convertResponseToThingModel(out)
tflog.Info(ctx, "created thing", map[string]interface{}{
	"attr_a": result.AttrA.ValueString(),
	"attr_b": result.AttrB.ValueString(),
	"attr_c": result.AttrC.ValueString(),
})

diags = resp.State.Set(ctx, result)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
	return
}

Auf hoher Ebene:

  • Wir rufen die vorgeschlagenen Aktualisierungen (die als „Plan“ bezeichnet werden) mit req.Plan.Get()

  • Durchführen des Update-API-Aufrufs mit den neuen Werten

  • Die Daten eines Go-Typs in ein Terraform-Modell umwandeln (convertResponseToThingModel)

  • Den Zustand durch den Aufruf von resp.State.Set()festlegen

Auf den ersten Blick scheint das nicht allzu problematisch zu sein. Der dritte Schritt, bei dem wir den Go-Typ in das Terraform-Modell manipulieren, wird jedoch schnell umständlich, fehleranfällig und komplex, da alle Ihre Ressourcen dies tun müssen, um zwischen dem Typ und den zugehörigen Terraform-Modellen zu wechseln.

Damit kein komplexerer Quellcode generiert wird als nötig, besteht eine der Verbesserungen unseres Providers darin, dass alle CRUD-Methoden einheitliche apijson.Marshal-, apijson.Unmarshal- und apijson.UnmarshalComputed -Methoden verwenden. Diese lösen das Problem durch eine Zentralisierung der Konvertierens und Verarbeitens der zugehörigen Logik auf Grundlage der Struct-Tags.

var data *ThingModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
	return
}

dataBytes, err := apijson.Marshal(data)
if err != nil {
	resp.Diagnostics.AddError("failed to serialize http request", err.Error())
	return
}
res := new(http.Response)
env := ThingResultEnvelope{*data}
_, err = r.client.Thing.Update(
	// ...
)
if err != nil {
	resp.Diagnostics.AddError("failed to make http request", err.Error())
	return
}

bytes, _ := io.ReadAll(res.Body)
err = apijson.UnmarshalComputed(bytes, &env)
if err != nil {
	resp.Diagnostics.AddError("failed to deserialize http request", err.Error())
	return
}
data = &env.Result

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)

Anstatt Hunderte von Instanzen von Typ-zu-Modell-Konvertierungsmethoden zu generieren, können wir das Terraform-Modell mit den richtigen Tags ausstatten und das Marshaling und Unmarshaling der Daten konsistent durchführen. Es handelt sich um eine geringfügige Änderung des Quellcodes, die die Generierung auf lange Sicht wiederverwendbarer und lesbarer macht. Für diesen Ansatz spricht auch, dass er sich hervorragend zur Fehlerbehebung eignet. Sobald Sie einen Fehler in einem bestimmten Feldtyp identifiziert haben, wird dieser durch die Behebung in der einheitlichen Benutzeroberfläche auch für andere Fälle behoben, die Sie möglicherweise noch nicht gefunden haben.

Das ist aber noch lange nicht alles (Dokumente)!

Um die Nutzung unseres OpenAPI-Schemas abzurunden, straffen wir die SDK-Integration mit unserer neuen API-Dokumentationsseite. Genutzt wird dieselbe Pipeline, in die wir in den letzten zwei Jahren investiert haben. Gleichzeitig werden aber einige der häufigsten Nutzungsprobleme behoben.

SDK-fähig 

Wenn Sie unsere API-Dokumentationsseite verwendet haben, wissen Sie, dass wir Ihnen Beispiele für die Interaktion mit der API mit Befehlszeilentools wie curl bieten. Das ist ein guter Ausgangspunkt. Wenn Sie aber eine der SDK-Bibliotheken verwenden, müssen Sie sich Gedanken machen, um sie in die gewünschte Methode oder Typdefinition zu konvertieren. Da wir nun dieselbe Pipeline zur Generierung der SDK und der Dokumentation verwenden, lösen wir das Problem, indem wir Beispiele in allen Bibliotheken bereitstellen, die Sie verwenden könnten, also nicht nur curl.

Beispiel für die Verwendung von cURL zum Abrufen aller Zonen.

Beispiel für die Verwendung der Typescript-Bibliothek zum Abrufen aller Zonen.

Beispiel für die Verwendung der Python-Bibliothek zum Abrufen aller Zonen.

Beispiel für die Verwendung der Go-Bibliothek zum Abrufen aller Zonen.

Durch diese Verbesserung merken wir uns auch die Sprachauswahl. Wenn Sie also ausgewählt haben, dass die Dokumentation mit unserer Typescript-Bibliothek angezeigt wird und Sie weiter herumklicken, zeigen wir Ihnen so lange Beispiele mit Typescript, bis es ausgetauscht wird.

Das Beste daran ist, dass diese Dokumentationsseite automatisch mit der Pipeline synchronisiert wird, wenn wir neue Attribute für bestehende Endpunkte einführen oder SDK-Sprachen hinzufügen. Es verlangt keinen großen Aufwand mehr, alles auf dem neuesten Stand zu halten.

Schnelleres und effizienteres Rendern

Ein Problem, mit dem wir schon immer zu kämpfen hatten, ist die schiere Menge an API-Endpunkten und deren Darstellung. Zum Zeitpunkt der Erstellung dieses Beitrags haben wir 1.330 Endpunkte. Für jeden davon gibt es einen Anfrage-Payload, einen Antwort-Payload und mehrere damit verbundene Typen. Wenn es um die Wiedergabe einer so großen Informationsmenge geht, mussten bei den früher von uns verwendeten Lösungen Abstriche gemacht werden, damit Teile der Darstellung funktionieren.

In der nächsten Version der API-Dokumentationsseite wird dies auf verschiedene Weise behoben:

  • Sie ist als moderne React-Anwendung implementiert, die ein interaktives clientseitiges Erlebnis mit statischen, vorgerenderten Inhalten kombiniert. Das erlaubt ein zügiges erstes Laden und eine schnelle Navigation. (Ja, das funktioniert auch, wenn JavaScript nicht aktiviert ist!)

  • Die zugrundeliegenden Daten werden während des Navigierens schrittweise abgerufen

Durch die Lösung dieses grundlegenden Problems haben wir weitere geplante Optimierungen der Dokumentationsseite und des SDK-Ökosystems ermöglicht, um die Nutzererfahrung zu verbessern, ohne dabei wie in der Vergangenheit Abstriche machen zu müssen. 

Berechtigungen

Eine der am häufigsten nachgefragten Funktionen, die in die Dokumentationsseite reimplementiert werden sollten, waren die erforderlichen Mindestberechtigungen für API-Endpunkte. In einer der vorherigen Iterationen der Dokumentationsseite war dies möglich. Den meisten Nutzern der Lösung war jedoch nicht bekannt, dass die Werte manuell eingegeben wurden und regelmäßig falsch waren, was zu Support-Tickets und Frust bei den Anwendern führte. 

Innerhalb des Identitäts- und Zugriffsverwaltungssystems von Cloudflare lässt sich die Frage „Was brauche ich, um auf diesen Endpunkt zuzugreifen?“ nicht leicht zu beantworten. Der Grund dafür ist, dass wir während des normalen Ablaufs einer Anfrage an die Kontrollebene zwei verschiedene Systeme brauchen, um Teile der Frage zu liefern, die dann zu einer vollständigen Antwort zusammengesetzt werden können. Wir konnten dies anfangs nicht als Teil der OpenAPI-Pipeline automatisieren. Deshalb haben wir uns entschieden, es wegzulassen, anstatt es ohne Überprüfungsmöglichkeit falsch zu machen. 

Heute freuen wir uns, Ihnen mitteilen zu können, dass die Endpunktberechtigungen zurück sind. Wir haben ein neues Tool entwickelt, das die Beantwortung dieser Frage in einer Weise abstrahiert, die wir in unsere Pipeline zur Codegenerierung integrieren können, damit alle Endpunkte diese Informationen automatisch erhalten. Wie der Rest der Plattform zur Codegenerierung liegt auch hier der Schwerpunkt darauf, dass Service-Teams Schemata von hoher Qualität besitzen und pflegen, die wiederverwendet werden können und Mehrwerte schaffen, ohne dass der Kunde dafür etwas tun muss.

Kein Warten mehr auf Updates

Mit diesen Ankündigungen setzen wir dem Warten auf Updates, die im SDK-Ökosystem verfügbar sind, ein Ende. Dank dieser neuen Verbesserungen können wir die Funktionsfähigkeit neuer Attribute und Endpunkte optimieren, sobald sie von den Teams dokumentiert wurden. Worauf warten Sie noch? Werfen Sie jetzt einen Blick auf den Terraform-Provider und die API-Dokumentationsseite.

Wir schützen komplette Firmennetzwerke, helfen Kunden dabei, Internetanwendungen effizient zu erstellen, jede Website oder Internetanwendung zu beschleunigen, DDoS-Angriffe abzuwehren, Hacker in Schach zu halten, und unterstützen Sie bei Ihrer Umstellung auf Zero Trust.

Greifen Sie von einem beliebigen Gerät auf 1.1.1.1 zu und nutzen Sie unsere kostenlose App, die Ihr Internet schneller und sicherer macht.

Wenn Sie mehr über unsere Mission, das Internet besser zu machen, erfahren möchten, beginnen Sie hier. Sie möchten sich beruflich neu orientieren? Dann werfen Sie doch einen Blick auf unsere offenen Stellen.
Birthday Week (DE)API (DE)SDKTerraformOpen APIDeveloper PlatformAgile Developer ServicesEntwickler

Folgen auf X

Jacob Bednarz|@jacobbednarz
Cloudflare|@cloudflare

Verwandte Beiträge

31. Oktober 2024 um 13:00

Moving Baselime from AWS to Cloudflare: simpler architecture, improved performance, over 80% lower cloud costs

Post-acquisition, we migrated Baselime from AWS to the Cloudflare Developer Platform and in the process, we improved query times, simplified data ingestion, and now handle far more events, all while cutting costs. Here’s how we built a modern, high-performing observability platform on Cloudflare’s network. ...