Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Escalando Kubernetes: como expandir faixas de IP de Serviços sem fricção

By Chimbu ChinnaduraiNov 18, 20245 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

Ao gerenciar clusters Kubernetes, garantir endereços IP suficientes para os Serviços do Kubernetes pode se tornar um aspecto crítico para escalar e manter sua infraestrutura.

Os Serviços oferecem uma forma abstrata de expor uma aplicação que roda em um conjunto de Pods. Diferentes tipos de Serviços, como ClusterIP, NodePort e LoadBalancer, usam um endereço IP virtual único no escopo do cluster, chamado ClusterIP.

O endereço IP de cada Serviço dentro do cluster precisa ser único. Tentar criar um Serviço com um ClusterIP que já foi alocado vai resultar em erro. À medida que sua implantação cresce, a faixa padrão de IPs para Serviços pode ficar insuficiente e gerar gargalos nos recursos de rede.

Antes, não era possível redimensionar nem ampliar as faixas de IPs atribuídas aos Serviços, o que causava problemas quando havia redes sobrepostas ou quando o cluster ficava sem IPs disponíveis.

Agora, o kube-apiserver com o feature gate MultiCIDRServiceAllocator habilitado e a API networking.k8s.io/v1alpha1 permitem expandir dinamicamente o número de IPs disponíveis para Serviços. Esse recurso foi promovido ao estágio beta no Kubernetes 1.31, e o recomendado é esperar que ele chegue ao estágio Stable antes de usar em produção. Consulte a KEP-1880—Multiple Service CIDRs para mais detalhes sobre a implementação.

Neste blog post, vamos ver como estender a faixa de IP de Serviços em um cluster do Google Kubernetes Engine (GKE). Você também pode testar o recurso em outras distribuições do Kubernetes — basta consultar as notas de versão de cada uma para detalhes de configuração ou limitações.

Pré-requisitos

Você precisa de um cluster GKE na versão 1.31.1-gke.1361000 ou superior, com a ferramenta de linha de comando kubectl configurada para se comunicar com o cluster.

Habilitar e verificar as APIs Beta

A partir da versão 1.24 do Kubernetes, novas APIs beta vêm desabilitadas por padrão em novos clusters GKE. Já os clusters criados em versões anteriores à 1.24 mantêm as APIs beta existentes habilitadas.

Você pode habilitar as APIs beta tanto na criação do cluster quanto depois. Para habilitar as APIs beta necessárias, siga as instruções em Use Kubernetes beta APIs with GKE clusters.

Comando de exemplo para habilitar as APIs beta necessárias em um 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>>

As APIs recém-habilitadas vão criar um objeto ServiceCIDR com o nome conhecido kubernetes e uma faixa de endereços IP baseada no CIDR de serviço inicial.

Rode o comando abaixo para verificar o novo objeto ServiceCIDR:

Chimbus-MacBook-Pro:~ chimbu$ kubectl get servicecidr
NAME         CIDRS          AGE
kubernetes   10.96.0.0/28   98m
Chimbus-MacBook-Pro:~ chimbu$

Adicionando um novo ServiceCIDR

Para fins de teste, criei um cluster com a faixa /28 para serviços, que comporta apenas 14 endereços IP. O Serviço kubernetes.default é sempre criado; neste exemplo, sobram apenas 13 Serviços possíveis.

Para fins de teste, criei um cluster com a faixa /28 para serviços, que comporta apenas 14 endereços IP. O serviço kubernetes.default é sempre criado, o que deixa apenas 13 Serviços possíveis.

Tente criar Serviços adicionais no Kubernetes: a requisição vai falhar com erro interno assim que todos os endereços IP da faixa de serviços estiverem em uso.

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$

Agora dá para expandir o número de endereços IP disponíveis para Serviços criando um novo ServiceCIDR que estenda ou adicione novas faixas de IP.

Durante a fase beta, o GKE só permite criar Service CIDRs dentro da faixa reservada 34.118.224.0/20, para evitar problemas de sobreposição de faixas de IP.

Aplique o manifesto abaixo para criar um novo ServiceCIDR que adicione uma nova faixa de endereços 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$

Tente criar novos Serviços no Kubernetes e o endereço IP do cluster vai ser escolhido a partir dessa nova faixa.

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$

Excluindo um ServiceCIDR

Os ServiceCIDRs são protegidos por finalizers para não deixar ClusterIPs de Serviço órfãos; o finalizer só é removido se nenhum endereço IP estiver atribuído a algum serviço da sub-rede.

Por isso, primeiro exclua todos os Serviços do Kubernetes que contenham endereços IP do ServiceCIDR e, em seguida, exclua o objeto ServiceCIDR.

Em resumo, conforme os clusters Kubernetes crescem, ampliar a faixa de IP de Serviços se torna essencial para evitar o esgotamento de IPs e garantir uma escalabilidade tranquila. Os novos recursos trazem flexibilidade para ambientes que precisam de mais endereços IP de serviço ao longo do tempo, sem o risco de gargalos.

Espero que este blog post tenha trazido insights valiosos. Se quiser saber mais ou tiver interesse nos nossos serviços, fale com a gente aqui.