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.