ping6.net

IPv6 no Docker e Kubernetes: Guia de Rede de Contêineres

Configure IPv6 para aplicações em contêineres. Cobre configurações do daemon Docker, dual-stack do Kubernetes, plugins CNI e exposição de serviços.

ping6.net14 de dezembro de 202411 min read
IPv6DockerKubernetescontêineresredeDevOps

A rede de contêineres assume IPv4 por padrão. Isso é um problema se está a executar cargas de trabalho de produção em 2024.

TL;DR - Resumo rápido

Pontos-chave:

  • Docker e Kubernetes assumem IPv4-only por padrão; IPv6 requer configuração explícita
  • Docker precisa de alterações em daemon.json e redes personalizadas com flag --ipv6
  • Kubernetes 1.23+ suporta dual-stack estável com IPv6 para pods e serviços
  • Plugins CNI (Calico, Cilium, Flannel) lidam com dual-stack de forma diferente

Ir para: Configuração Docker | Dual-Stack Kubernetes | Plugins CNI | Testes


Por Que IPv6 em Contêineres#

Os seus contêineres podem estar apenas em IPv4 enquanto o resto da Internet migra para IPv6. Redes móveis, ISPs e fornecedores de cloud são IPv6-first. Se os seus serviços em contêineres não suportam IPv6, está a adicionar latência através de gateways NAT64 ou pior — a perder clientes completamente.

Plataformas de orquestração de contêineres (Docker, Kubernetes, ECS, Nomad) foram construídas durante a era IPv4. O suporte IPv6 chegou mais tarde como uma reflexão tardia. Os padrões ainda assumem rede apenas IPv4.

Ativar IPv6 não é difícil, mas requer configuração explícita em múltiplas camadas: daemon, rede, contêiner e serviço. Falhe numa camada e terá conectividade parcial que quebra misteriosamente.

Configuração IPv6 do Docker#

O daemon Docker não ativa IPv6 por padrão. Precisa de o configurar em /etc/docker/daemon.json.

Configuração do Daemon#

Crie ou modifique /etc/docker/daemon.json:

{
  "ipv6": true,
  "fixed-cidr-v6": "fd00::/80",
  "experimental": false,
  "ip6tables": true
}

Analisando isto:

  • "ipv6": true ativa o suporte IPv6
  • "fixed-cidr-v6" define a sub-rede para contêineres (use prefixo ULA ou GUA)
  • "ip6tables": true ativa regras de firewall IPv6 (Docker 20.10+)

Para produção com endereços globalmente roteáveis, use o prefixo atribuído pelo seu fornecedor:

{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1234::/64"
}

Reinicie o Docker para aplicar as alterações:

sudo systemctl restart docker

Verifique se IPv6 está ativado:

docker network inspect bridge | grep IPv6

Deve ver "EnableIPv6": true.

Rede Bridge Padrão#

A rede bridge padrão não obtém IPv6 automaticamente mesmo após a configuração do daemon. Crie uma rede personalizada:

docker network create --ipv6 \
  --subnet=172.20.0.0/16 \
  --subnet=fd00:dead:beef::/48 \
  mynetwork

Execute contêineres nesta rede:

docker run -d --network mynetwork nginx

Os contêineres agora recebem endereços IPv4 e IPv6.

Redes Definidas pelo Utilizador#

Redes bridge definidas pelo utilizador suportam dual-stack:

docker network create --ipv6 \
  --subnet=10.1.0.0/24 \
  --gateway=10.1.0.1 \
  --subnet=fd00:cafe::/64 \
  --gateway=fd00:cafe::1 \
  appnetwork

Contêineres nesta rede podem comunicar via IPv6:

# Terminal 1
docker run -it --rm --network appnetwork --name container1 alpine sh
 
# Terminal 2
docker run -it --rm --network appnetwork alpine sh
ping6 container1

O resolvedor DNS embutido do Docker retorna registos AAAA para nomes de contêineres quando IPv6 está ativado.

NAT IPv6 e Roteamento#

Por padrão, o Docker usa NAT para IPv4 mas pode não fazer NAT para IPv6. Isto depende da sua configuração fixed-cidr-v6.

Com prefixos ULA (fd00::/8), precisa de NAT para acesso à Internet:

# Ativar encaminhamento IPv6
sudo sysctl -w net.ipv6.conf.all.forwarding=1
 
# Adicionar regra masquerade
sudo ip6tables -t nat -A POSTROUTING -s fd00::/80 ! -o docker0 -j MASQUERADE

Com prefixos GUA (globalmente roteáveis), roteie diretamente sem NAT:

# Adicionar rota para sub-rede de contêineres
sudo ip -6 route add 2001:db8:1234::/64 via <docker-host-ipv6>

Configure o roteador upstream para rotear a sua sub-rede de contêineres para o host Docker.

Docker Compose IPv6#

Docker Compose requer configuração explícita de IPv6 na definição de rede.

Exemplo docker-compose.yml:

version: '3.8'
 
services:
  web:
    image: nginx
    networks:
      - frontend
    ports:
      - "80:80"
      - "[::]:8080:80"  # Vincular IPv6 explicitamente
 
  app:
    image: myapp:latest
    networks:
      - frontend
      - backend
 
  db:
    image: postgres:14
    networks:
      - backend
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
 
networks:
  frontend:
    enable_ipv6: true
    ipam:
      config:
        - subnet: 172.20.0.0/16
          gateway: 172.20.0.1
        - subnet: fd00:1::/64
          gateway: fd00:1::1
 
  backend:
    enable_ipv6: true
    ipam:
      config:
        - subnet: 172.21.0.0/16
        - subnet: fd00:2::/64

A flag enable_ipv6: true é necessária por rede. A configuração IPAM (IP Address Management) atribui sub-redes IPv4 e IPv6.

Sintaxe de vinculação de portas para IPv6:

ports:
  - "80:80"              # IPv4 e IPv6
  - "0.0.0.0:8080:80"    # Apenas IPv4
  - "[::]:8081:80"       # Apenas IPv6
  - "127.0.0.1:8082:80"  # IPv4 localhost
  - "[::1]:8083:80"      # IPv6 localhost

Inicie os serviços:

docker-compose up -d

Verifique se os contêineres têm IPv6:

docker-compose exec web ip -6 addr show

Dual-Stack do Kubernetes#

O Kubernetes suporta rede dual-stack a partir da versão 1.21 (beta) e 1.23 (estável).

Pré-requisitos#

  1. Kubernetes 1.23 ou posterior
  2. Plugin CNI que suporte dual-stack (Calico, Cilium, Flannel, Weave)
  3. kube-proxy com modo dual-stack
  4. Suporte do fornecedor de cloud (para serviços LoadBalancer)

Ativar Dual-Stack#

Para novos clusters, ative dual-stack durante a inicialização. Com kubeadm:

# kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
networking:
  podSubnet: "10.244.0.0/16,fd00:10:244::/56"
  serviceSubnet: "10.96.0.0/16,fd00:10:96::/112"

Inicialize o cluster:

kubeadm init --config kubeadm-config.yaml

Para Kubernetes gerido (EKS, GKE, AKS), ative dual-stack durante a criação do cluster:

# EKS
eksctl create cluster \
  --name mycluster \
  --ip-family ipv4,ipv6
 
# GKE
gcloud container clusters create mycluster \
  --enable-ip-alias \
  --stack-type=IPV4_IPV6
 
# AKS
az aks create \
  --resource-group myResourceGroup \
  --name mycluster \
  --network-plugin azure \
  --ip-families IPv4,IPv6

Verifique se dual-stack está ativado:

kubectl get nodes -o jsonpath='{.items[*].spec.podCIDRs}'

Deve ver CIDRs IPv4 e IPv6.

Rede de Pods#

Os pods recebem endereços de ambas as famílias automaticamente. Nenhuma configuração especial necessária na maioria dos casos.

Exemplo de pod:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: nginx
    image: nginx

Implemente e verifique os endereços:

kubectl apply -f pod.yaml
kubectl get pod test-pod -o jsonpath='{.status.podIPs}'

A saída mostra IPv4 e IPv6:

[{"ip":"10.244.1.5"},{"ip":"fd00:10:244:1::5"}]

As aplicações dentro dos pods devem vincular-se a :: (todos os endereços) ou 0.0.0.0 especificamente:

# Exemplo Python - vincular a IPv4 e IPv6
import socket
 
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
sock.bind(("::", 8080))
sock.listen(5)

Ou vincule a 0.0.0.0 para IPv4 e :: para IPv6 separadamente.

Configuração de Serviços#

Os serviços podem ser apenas IPv4, apenas IPv6 ou dual-stack. Controle isto com os campos ipFamilyPolicy e ipFamilies.

Serviço dual-stack (padrão em clusters dual-stack):

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ipFamilyPolicy: RequireDualStack
  ipFamilies:
    - IPv4
    - IPv6
  selector:
    app: myapp
  ports:
    - port: 80
      targetPort: 8080

Serviço apenas IPv4:

apiVersion: v1
kind: Service
metadata:
  name: myservice-v4
spec:
  ipFamilyPolicy: SingleStack
  ipFamilies:
    - IPv4
  selector:
    app: myapp
  ports:
    - port: 80

Serviço apenas IPv6:

apiVersion: v1
kind: Service
metadata:
  name: myservice-v6
spec:
  ipFamilyPolicy: SingleStack
  ipFamilies:
    - IPv6
  selector:
    app: myapp
  ports:
    - port: 80

Verifique os IPs do serviço:

kubectl get svc myservice -o jsonpath='{.spec.clusterIPs}'

Saída:

["10.96.100.5","fd00:10:96::a5"]

Serviços LoadBalancer#

Os serviços LoadBalancer provisionam balanceadores de carga em cloud com frontends dual-stack (se o fornecedor de cloud suportar).

apiVersion: v1
kind: Service
metadata:
  name: web-lb
spec:
  type: LoadBalancer
  ipFamilyPolicy: RequireDualStack
  ipFamilies:
    - IPv4
    - IPv6
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080

Verifique os IPs externos:

kubectl get svc web-lb

Saída:

NAME     TYPE           CLUSTER-IP      EXTERNAL-IP                        PORT(S)
web-lb   LoadBalancer   10.96.100.10    203.0.113.10,2001:db8:1234::10    80:30123/TCP

Nem todos os fornecedores de cloud suportam balanceadores de carga dual-stack ainda. Verifique o suporte para a sua plataforma.

Controladores Ingress#

O suporte Ingress para IPv6 depende da implementação do controlador.

Controladores populares com suporte IPv6:

  • nginx-ingress: Suporta dual-stack, escuta em IPv4 e IPv6
  • Traefik: Suporte completo dual-stack
  • HAProxy Ingress: Suporta IPv6
  • Contour: Capaz de dual-stack

Configure nginx-ingress para dual-stack:

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: LoadBalancer
  ipFamilyPolicy: RequireDualStack
  ipFamilies:
    - IPv4
    - IPv6
  selector:
    app.kubernetes.io/name: ingress-nginx
  ports:
    - name: http
      port: 80
      targetPort: http
    - name: https
      port: 443
      targetPort: https

Os recursos Ingress não precisam de configuração especial IPv6 — funcionam automaticamente se o controlador o suportar.

Políticas de Rede#

Os recursos NetworkPolicy suportam blocos CIDR IPv6:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ipv6
spec:
  podSelector:
    matchLabels:
      app: myapp
  ingress:
    - from:
      - ipBlock:
          cidr: 2001:db8::/32
      - ipBlock:
          cidr: fd00::/8
  egress:
    - to:
      - ipBlock:
          cidr: ::/0
          except:
            - fc00::/7  # Bloquear ULA

Regras IPv4 e IPv6 podem coexistir na mesma política.

Considerações sobre Plugins CNI#

Plugins CNI diferentes lidam com dual-stack de forma diferente.

Calico#

O Calico suporta dual-stack com pools de IP:

apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: ipv4-pool
spec:
  cidr: 10.244.0.0/16
  ipipMode: Never
  natOutgoing: true
  nodeSelector: all()
 
---
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: ipv6-pool
spec:
  cidr: fd00:10:244::/56
  natOutgoing: false
  nodeSelector: all()

Ative IPv6 no Calico:

kubectl set env daemonset/calico-node -n kube-system IP6=autodetect
kubectl set env daemonset/calico-node -n kube-system FELIX_IPV6SUPPORT=true

Cilium#

O Cilium tem suporte dual-stack nativo. Ative durante a instalação:

helm install cilium cilium/cilium \
  --namespace kube-system \
  --set ipv4.enabled=true \
  --set ipv6.enabled=true \
  --set tunnel=disabled \
  --set autoDirectNodeRoutes=true

Flannel#

O Flannel requer modo dual-stack na configuração do DaemonSet:

apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
data:
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "IPv6Network": "fd00:10:244::/56",
      "Backend": {
        "Type": "vxlan"
      }
    }

Weave#

O Weave suporta dual-stack com ambos os modos IPAM:

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')&env.IPALLOC_RANGE=10.244.0.0/16&env.IPALLOC_RANGE=fd00:10:244::/56"

Armadilhas Comuns#

Vinculação de Aplicações#

As aplicações devem escutar explicitamente em endereços IPv6. Vincular a 0.0.0.0 apenas escuta em IPv4.

Errado:

server.bind(("0.0.0.0", 8080))  # Apenas IPv4

Correto:

server.bind(("::", 8080))  # IPv6 (e IPv4 se IPV6_V6ONLY=0)

Muitas linguagens assumem IPv4 por padrão. Consulte a documentação da sua framework.

Resolução DNS#

Consultas DNS em ambientes dual-stack retornam registos A e AAAA. As aplicações devem tentar ambos, preferindo IPv6.

Algumas bibliotecas antigas apenas consultam registos A. Atualize dependências ou configure a resolução DNS explicitamente.

Regras de Firewall#

Firewalls de contêineres (iptables/ip6tables) precisam de regras para ambas as famílias. Docker e Kubernetes lidam com isto automaticamente se configurados corretamente, mas regras personalizadas podem bloquear IPv6.

Verifique regras de firewall IPv6:

sudo ip6tables -L -n -v

Conectividade Externa#

Contêineres com IPv6 precisam de roteamento adequado para redes externas. Se o seu host não tem conectividade IPv6, os contêineres também não terão.

Teste IPv6 do host primeiro:

ping6 google.com

Se isso falhar, corrija a rede do host antes de resolver problemas nos contêineres.

Serviços Headless de StatefulSet#

StatefulSets com serviços headless retornam endereços IPv4 e IPv6 para nomes DNS de pods:

nslookup web-0.myservice.default.svc.cluster.local

Aplicações conectando-se a pods StatefulSet devem lidar com múltiplos endereços graciosamente.

Testar Implementações Dual-Stack#

Implemente uma aplicação de teste:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test
  template:
    metadata:
      labels:
        app: test
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
 
---
apiVersion: v1
kind: Service
metadata:
  name: test-svc
spec:
  type: LoadBalancer
  ipFamilyPolicy: RequireDualStack
  ipFamilies:
    - IPv4
    - IPv6
  selector:
    app: test
  ports:
    - port: 80

Aplique e teste:

kubectl apply -f test-app.yaml
 
# Obter IPs do serviço
kubectl get svc test-svc
 
# Testar IPv4
curl http://<ipv4-external-ip>
 
# Testar IPv6
curl -6 http://[<ipv6-external-ip>]

Dentro de um pod, teste conectividade dual-stack:

kubectl run -it --rm debug --image=alpine --restart=Never -- sh
 
# Dentro do pod
apk add curl bind-tools
nslookup test-svc
curl -4 http://test-svc  # IPv4
curl -6 http://test-svc  # IPv6

Considerações de Produção#

  1. Monitorize ambas as famílias de endereços em ferramentas de observabilidade
  2. Teste comportamento de failover quando uma família não está disponível
  3. Configure verificações de saúde para IPv4 e IPv6
  4. Documente topologia de rede incluindo prefixos IPv6
  5. Planeie alocação de endereços IP para evitar conflitos
  6. Ative IPv6 em pipelines CI/CD para testes
  7. Treine equipa em resolução de problemas dual-stack

Artigos Relacionados#

Verificar Conectividade de Contêineres

Use a nossa Ferramenta Ping e Validador IPv6 para testar se os seus serviços em contêineres estão acessíveis via IPv6.

Recursos Adicionais#