Beim Betrieb von Kubernetes-Clustern kann die Verfügbarkeit ausreichender IP-Adressen für Kubernetes-Services zum entscheidenden Faktor werden, wenn es um Skalierung und stabilen Betrieb Ihrer Infrastruktur geht.
Services sind eine abstrahierte Möglichkeit, eine Anwendung verfügbar zu machen, die auf einer Gruppe von Pods läuft. Service-Typen wie ClusterIP, NodePort und LoadBalancer nutzen dafür eine eindeutige, clusterweite virtuelle IP-Adresse – die ClusterIP.
Jede Service-ClusterIP muss innerhalb des gesamten Clusters eindeutig sein. Der Versuch, einen Service mit einer bereits vergebenen ClusterIP anzulegen, endet mit einem Fehler. Wächst Ihr Deployment, kann der Standard-Service-IP-Bereich schnell zu klein werden – und zu Engpässen bei den Netzwerkressourcen führen.
Bislang ließen sich die für Services vergebenen IP-Bereiche weder vergrößern noch anpassen. Das führte zu Problemen bei überlappenden Netzwerken oder wenn dem Cluster die verfügbaren IPs ausgingen.
Mit aktiviertem MultiCIDRServiceAllocator-Feature Gate im kube-apiserver sowie der API networking.k8s.io/v1alpha1 lassen sich die für Services verfügbaren IP-Adressen nun jedoch dynamisch erweitern. In Kubernetes 1.31 ist dieses Feature in den Beta-Status übergegangen; für den Produktiveinsatz empfiehlt es sich, auf den Stable-Status zu warten. Weitere Details zur Implementierung finden Sie in KEP-1880 – Multiple Service CIDRs.
In diesem Blogpost zeigen wir, wie Sie den Service-IP-Bereich in einem Google Kubernetes Engine (GKE)-Cluster erweitern. Sie können das Feature auch in anderen Kubernetes-Distributionen testen – Konfigurations- und Limitierungsdetails entnehmen Sie den jeweiligen Release Notes.
Voraussetzungen
Sie benötigen einen GKE-Cluster mit Version 1.31.1-gke.1361000 oder neuer. Außerdem muss das Kommandozeilen-Tool kubectl für die Kommunikation mit Ihrem Cluster konfiguriert sein.
Beta-APIs aktivieren und prüfen
Ab Kubernetes-Version 1.24 sind neue Beta-APIs in neu erstellten GKE-Clustern standardmäßig deaktiviert. Bestehende Cluster, die mit einer Version vor 1.24 erstellt wurden, behalten bereits aktivierte Beta-APIs bei.
Sie können die Beta-APIs entweder direkt beim Erstellen des Clusters oder nachträglich aktivieren. Eine Anleitung dazu finden Sie unter Use Kubernetes beta APIs with GKE clusters.
Beispielbefehl, um die benötigten Beta-APIs in einem bestehenden Cluster zu aktivieren:
gcloud container clusters update <<GKE_CLUSTER_NAME>> \
--enable-kubernetes-unstable-apis=networking.k8s.io/v1beta1/ipaddresses,networking.k8s.io/v1beta1/servicecidrs
--region <<GKE_CLUSTER_REGION>> \
--project <<GCP_PROJECT_NAME>>
Mit den neu aktivierten APIs wird automatisch ein ServiceCIDR-Objekt mit dem reservierten Namen kubernetes angelegt – mit einem IP-Bereich, der dem ursprünglichen Service-CIDR entspricht.
Mit folgendem Befehl prüfen Sie das neue ServiceCIDR-Objekt:
Chimbus-MacBook-Pro:~ chimbu$ kubectl get servicecidr
NAME CIDRS AGE
kubernetes 10.96.0.0/28 98m
Chimbus-MacBook-Pro:~ chimbu$
Ein neues ServiceCIDR hinzufügen
Zu Testzwecken habe ich einen Cluster mit dem Bereich /28 für Services angelegt – das ergibt nur 14 IP-Adressen. Da der Service kubernetes.default immer angelegt wird, bleiben in diesem Beispiel lediglich 13 weitere Services möglich.
Zu Testzwecken habe ich einen Cluster mit dem Bereich /28 für Services angelegt, der nur 14 IP-Adressen umfasst. Da der Service kubernetes.default immer angelegt wird, bleiben Ihnen lediglich 13 weitere mögliche Services.
Wenn Sie weitere Kubernetes-Services anlegen, scheitert die Anfrage mit einem internen Fehler, sobald alle IP-Adressen im Service-Bereich vergeben sind.
Chimbus-MacBook-Pro:~ chimbu$ for i in $(seq 1 13); do kubectl create service clusterip "service-test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
10.96.0.13
10.96.0.11
10.96.0.7
10.96.0.14
10.96.0.3
10.96.0.12
10.96.0.9
10.96.0.4
10.96.0.5
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full
Chimbus-MacBook-Pro:~ chimbu$
Sie können die Anzahl der für Services verfügbaren IP-Adressen jetzt erhöhen, indem Sie ein neues ServiceCIDR anlegen, das den Bereich erweitert oder zusätzliche IP-Bereiche ergänzt.
In der Beta-Phase erlaubt GKE das Anlegen von Service-CIDRs ausschließlich im reservierten IP-Bereich
34.118.224.0/20, um Konflikte durch überlappende IP-Bereiche zu vermeiden.
Wenden Sie das folgende Manifest an, um ein neues ServiceCIDR mit einem zusätzlichen IP-Bereich anzulegen:
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1beta1
kind: ServiceCIDR
metadata:
name: newcidr1
spec:
cidrs:
- 34.118.224.0/20
EOF
Chimbus-MacBook-Pro:~ chimbu$ kubectl get servicecidrs.networking.k8s.io
NAME CIDRS AGE
kubernetes 10.96.0.0/28 104m
newcidr1 34.118.224.0/20 5s
Chimbus-MacBook-Pro:~ chimbu$
Legen Sie nun neue Kubernetes-Services an – die ClusterIP wird aus diesem neuen Bereich vergeben.
Chimbus-MacBook-Pro:~ chimbu$ for i in $(seq 1 13); do kubectl create service clusterip "service-test-new-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
34.118.235.89
34.118.234.162
34.118.230.252
34.118.226.209
34.118.227.183
34.118.227.182
^C
Chimbus-MacBook-Pro:~ chimbu$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 105m
service-test-1 ClusterIP 10.96.0.13 <none> 80/TCP 3m41s
service-test-2 ClusterIP 10.96.0.11 <none> 80/TCP 3m39s
service-test-3 ClusterIP 10.96.0.7 <none> 80/TCP 3m39s
service-test-4 ClusterIP 10.96.0.14 <none> 80/TCP 3m38s
service-test-5 ClusterIP 10.96.0.3 <none> 80/TCP 3m37s
service-test-6 ClusterIP 10.96.0.12 <none> 80/TCP 3m36s
service-test-7 ClusterIP 10.96.0.9 <none> 80/TCP 3m35s
service-test-8 ClusterIP 10.96.0.4 <none> 80/TCP 3m34s
service-test-9 ClusterIP 10.96.0.5 <none> 80/TCP 3m33s
service-test-new-1 ClusterIP 34.118.235.89 <none> 80/TCP 8s
service-test-new-2 ClusterIP 34.118.234.162 <none> 80/TCP 8s
service-test-new-3 ClusterIP 34.118.230.252 <none> 80/TCP 7s
service-test-new-4 ClusterIP 34.118.226.209 <none> 80/TCP 6s
service-test-new-5 ClusterIP 34.118.227.183 <none> 80/TCP 5s
service-test-new-6 ClusterIP 34.118.227.182 <none> 80/TCP 4s
Chimbus-MacBook-Pro:~ chimbu$
Ein ServiceCIDR löschen
ServiceCIDRs sind durch Finalizer geschützt, damit keine verwaisten Service-ClusterIPs zurückbleiben. Der Finalizer wird erst entfernt, wenn keinem Service aus dem zugehörigen Subnetz mehr eine IP-Adresse zugewiesen ist.
Sie müssen also zuerst alle Kubernetes-Services löschen, die IP-Adressen aus dem ServiceCIDR belegen, und können anschließend das ServiceCIDR-Objekt selbst entfernen.
Mit wachsenden Kubernetes-Clustern wird die Erweiterung des Service-IP-Bereichs zum entscheidenden Schritt, um IP-Engpässe zu vermeiden und eine reibungslose Skalierung zu ermöglichen. Die neuen Funktionen bieten die nötige Flexibilität für Umgebungen, die mit der Zeit zusätzliche Service-IP-Adressen benötigen – ohne Risiko für Ressourcenengpässe.
Wir hoffen, dieser Blogpost liefert Ihnen wertvolle Einblicke. Wenn Sie mehr erfahren möchten oder an unseren Services interessiert sind, sprechen Sie uns gerne an. Sie erreichen uns hier.