Alle Blogposts Hinter den KulissenKnow-how 5 Minuten Lesezeit

Wir stellen vor: die Nine Self-Service API

Cyrill Troxler
Verfasst von
Cyrill Troxler
Veröffentlicht
May 8, 2023
Diesen Blogpost teilen

Zum Launch unserer API möchten wir Ihnen einige technische Einblicke in ihre Entstehung und die Zwecke geben, zu denen sie genutzt werden kann.

In den vergangenen zwei Jahren haben wir überarbeitet, wie wir neue Infrastrukturen bei Nine bereitstellen. Die Hauptziele dabei waren:

  • eine komplette Automatisierung, um es Kunden zu ermöglichen, die Produkte und Services von Nine als Self-Service zu verwalten
  • einen  standardmässigen Ansatz, der von allen internen Teams genutzt werden kann.

Am Anfang stand die Entwicklung von Nine Managed GKE, während der wir uns zunehmend mit dem Programmieren von Kubernetes Controllern in Go vertraut machten. Etwa zur gleichen Zeit entdeckten wir ausserdem Crossplane. Da alles noch in den Anfängen steckte und noch einige Zeit vergehen würde, bis wir Version 1 veröffentlichen würden, waren wir zunächst vorsichtig. Nach ersten Experimenten mit der Verwaltung unserer Terraform Module entschieden wir uns, Crossplane für unseren neuen Object Storage Service zu verwenden und unsere ersten Controller mit Crossplane-Runtime zu entwickeln.

Wir verwenden diesen neuen Ansatz nun bereits seit einiger Zeit und auch unser Frontend Cockpit nutzt die neue API seit der Lancierung des aktualisierten Objektspeichers im Jahr 2021. Während wir immer mehr Services, wie etwa unser Managed Kubernetes NKE, in dieses neue System integrierten, stieg unser Vertrauen in das System, die APIs und Controller, die dahinterstecken. Dadurch konnten wir den nächsten Schritt nehmen und es auch unseren Kunden bereitstellen, damit diese die API direkt verwenden können.

Die Landing Page für die neue API finden Sie über unsere Dokumentation auf docs.nineapis.ch. Die API Definitionen (Go Typen und OpenAPI v2 Spezifikation) finden Sie ausserdem auf GitHub.

CLI

Mit der Lancierung haben wir ausserdem ein neues CLI Tool bereitgestellt, welches die Authentifizierung gegen die API erleichtert. Es nennt sich nctl und die komplette Quellen- und Installationsanleitung finden Sie auf GitHub.

Dabei haben wir einen ähnlichen Login-Prozess wie bei gcloud implementiert. Das bedeutet, dass der Befehl nctl auth login <cockpit account name> Sie zu einem Browser-Fenster weiterleitet, indem Sie Ihre Cockpit-Logindaten eingeben. Nach dem Login können Sie dann einen Service Account erstellen, um aus Ihren eigenen automatisierten Workflows auf die API zuzugreifen.

Die CLI funktioniert momentan nur mit einigen unserer Services. Allerdings ermöglicht sie es Ihnen, ähnlich wie kubectl, jegliche API Objekte aus einer yaml- oder JSON-Datei mit nctl create/apply/delete -f <file> zu erstellen, lesen, aktualisieren und löschen (CRUD).

Schnittstellen

Neben dem Zugriff auf die API über nctl bestehen bereits weitere Schnittstellen, die ohne weiteres funktionieren. Da unsere API auf Kubernetes aufbaut, kann alles, was mit einer Kubernetes Custom Ressource interagieren kann, auch mit der API kommunizieren. So können wir zum Beispiel Terraform nutzen, um Services auf unserer API bereitzustellen, oder wir können kubectl verwenden, um auf ein beliebiges Objekt auf der API zuzugreifen, nachdem wir uns über nctl authentifiziert haben.

Terraform

Der Kubernetes Terraform Provider unterstützt die Anwendung jeglicher Kubernetes-Objekte mithilfe der Ressource kubernetes_manifest. Es folgt ein kleines Beispiel dafür, wie ein Service Account auf unserer API mit Terraform erstellt werden kann. Dabei wird abgewartet, bis signalisiert wird, dass die Ressource bereit ist. Dies kann besonders hilfreich sein, wenn Sie ein von einem Service Account erstelltes Secret später auslesen möchten. 

resource "kubernetes_manifest" "sample_cluster" {
manifest = {
apiVersion = "infrastructure.nine.ch/v1alpha1"
kind = "KubernetesCluster"
metadata = {
name = "sample-cluster"
namespace = "<cockpit account name>"
}
spec = {
forProvider = {
vcluster = {
version = "1.24"
}
nodePools = []
location = "nine-es34"
}
writeConnectionSecretToRef = {
name = "sample-cluster"
namespace = "<cockpit account name>"
}
}
}

wait {
condition {
type = "Ready"
status = "True"
}
}
}

# read secret that the KubernetesCluster creates
data "kubernetes_secret_v1" "example_sa" {
metadata {
name = kubernetes_manifest.sample_cluster.manifest.spec.writeConnectionSecretToRef.name
namespace = kubernetes_manifest.sample_cluster.manifest.spec.writeConnectionSecretToRef.namespace
}
}

# put token into an output. This could then be used by another module for example.
output "kubeconfig" {
sensitive = true
value = data.kubernetes_secret_v1.sample_cluster.data.kubeconfig
}

-> Code <-

Wir können nun wie üblich Terraform anwenden und sehen, dass wir nach Abschluss der Cluster-Erstellung das Secret mit der kubeconfig auslesen können, ohne auf den neuen Cluster zugreifen zu müssen.

$ terraform apply
[...]
kubernetes_manifest.sample_cluster: Creating...
kubernetes_manifest.sample_cluster: Still creating... [10s elapsed]
kubernetes_manifest.sample_cluster: Still creating... [20s elapsed]
kubernetes_manifest.sample_cluster: Still creating... [30s elapsed]
kubernetes_manifest.sample_cluster: Still creating... [40s elapsed]
kubernetes_manifest.sample_cluster: Still creating... [50s elapsed]
kubernetes_manifest.sample_cluster: Still creating... [1m0s elapsed]
kubernetes_manifest.sample_cluster: Still creating... [1m10s elapsed]
kubernetes_manifest.sample_cluster: Creation complete after 1m12s
data.kubernetes_secret_v1.sample_cluster: Reading...
data.kubernetes_secret_v1.sample_cluster: Read complete after 0s [id=nine/sample-cluster]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

kubeconfig = <sensitive>

 -> Code <-

Mehr Beispiele und Anleitungen zur Authentifizierung gegen unsere API mit Terraform finden Sie auf GitHub.

Wie es weitergeht

Unser Ziel ist es, letztlich alle unsere Services über diese API anzubieten. Auch wenn dies noch etwas dauern wird, sind wir bei der Entwicklung neuer Dienste durch diese grundlegende Investition nun schneller denn je. Auch die Notwendigkeit manueller Eingriffe hat sich wesentlich reduziert, was zu einer weiteren Verbesserung unserer Services führt.