Al administrar clusters de Kubernetes, contar con suficientes direcciones IP para los Services de Kubernetes puede convertirse en un aspecto crítico a la hora de escalar y mantener tu infraestructura.
Los Services ofrecen una manera abstracta de exponer una aplicación que corre sobre un conjunto de Pods. Los distintos tipos de Services, como ClusterIP, NodePort y LoadBalancer, usan una dirección IP virtual única a nivel de cluster llamada ClusterIP.
Cada dirección IP de cluster de un Service debe ser única dentro de todo el cluster. Si intentas crear un Service con un ClusterIP que ya fue asignado, vas a obtener un error. A medida que tu despliegue crece, el rango de IP predeterminado para Services puede quedarse corto y derivar en cuellos de botella en los recursos de red.
Antes, no se podían redimensionar ni ampliar los rangos de IP asignados a los Services, lo que causaba problemas cuando había redes superpuestas o cuando el cluster se quedaba sin IP disponibles.
Sin embargo, los kube-apiserver que tengan habilitado el feature gate MultiCIDRServiceAllocator y la API networking.k8s.io/v1alpha1 permiten ampliar dinámicamente la cantidad de IP disponibles para los Services. Esta funcionalidad pasó a fase beta en Kubernetes 1.31 y se recomienda esperar a que llegue a Stable antes de usarla en producción. Consulta KEP-1880—Multiple Service CIDRs para más detalles sobre la implementación.
En este post vamos a ver cómo ampliar el rango de IP de Services en un cluster de Google Kubernetes Engine (GKE). También puedes probar la funcionalidad en otras distribuciones de Kubernetes y revisar las notas de versión específicas para conocer detalles de configuración o limitaciones.
Requisitos previos
Necesitas un cluster de GKE en versión 1.31.1-gke.1361000 o posterior, y asegurarte de que la herramienta de línea de comandos kubectl esté configurada para comunicarse con tu cluster.
Habilitar y verificar las APIs beta
A partir de Kubernetes 1.24, las nuevas APIs beta vienen deshabilitadas por defecto en los nuevos clusters de GKE. Los clusters existentes creados con una versión anterior a la 1.24 mantienen habilitadas las APIs beta existentes.
Puedes habilitar las APIs beta durante la creación del cluster o más adelante. Para habilitar las APIs beta necesarias, sigue las instrucciones de Use Kubernetes beta APIs with GKE clusters.
Comando de ejemplo para habilitar las APIs beta necesarias en un cluster existente:
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>>
Las APIs recién habilitadas crearán un objeto ServiceCIDR con el nombre conocido kubernetes y un rango de direcciones IP basado en el CIDR de servicio inicial.
Ejecuta el siguiente comando para verificar el nuevo objeto ServiceCIDR:
Chimbus-MacBook-Pro:~ chimbu$ kubectl get servicecidr
NAME CIDRS AGE
kubernetes 10.96.0.0/28 98m
Chimbus-MacBook-Pro:~ chimbu$
Agregar un nuevo ServiceCIDR
Para esta prueba, creé un cluster con un rango /28 para servicios, que solo contiene 14 direcciones IP. El Service kubernetes.default siempre se crea, así que en este ejemplo te quedan apenas 13 Services posibles.
Para esta prueba, creé un cluster con un rango /28 para servicios que solo contiene 14 direcciones IP. El Service kubernetes.default siempre se crea, lo que te deja apenas 13 Services posibles.
Si intentas crear más Services de Kubernetes, la solicitud fallará con un error interno una vez que se hayan utilizado todas las IP del rango de servicios.
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$
Ahora puedes ampliar la cantidad de direcciones IP disponibles para los Services creando un nuevo ServiceCIDR que extienda o agregue nuevos rangos de IP.
Durante la fase beta, GKE solo permite crear Service CIDRs dentro del rango de IP reservado
34.118.224.0/20, para evitar posibles problemas con rangos superpuestos.
Aplica el siguiente manifiesto para crear un nuevo ServiceCIDR que agregue un nuevo rango de IP.
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$
Si ahora intentas crear nuevos Services de Kubernetes, la dirección IP de cluster se tomará de este nuevo rango.
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$
Eliminar un ServiceCIDR
Los ServiceCIDRs están protegidos con finalizers para evitar que queden ClusterIPs huérfanos; el finalizer solo se elimina si ninguna IP de la subred está asignada a algún Service.
Por eso, primero debes eliminar todos los Services de Kubernetes que tengan IP del ServiceCIDR y, después, eliminar el objeto ServiceCIDR.
En resumen, a medida que los clusters de Kubernetes crecen, ampliar el rango de IP de Services se vuelve fundamental para evitar el agotamiento de IP y facilitar la escalabilidad. Las nuevas funcionalidades dan flexibilidad a los entornos que con el tiempo necesitan más direcciones IP de servicio, sin arriesgar cuellos de botella en los recursos.
Espero que este post te haya resultado útil. Si quieres saber más o te interesan nuestros servicios, escríbenos aquí.