Configurar várias interfaces de rede para pods

Este documento descreve como configurar o Google Distributed Cloud (somente software) para VMware para fornecer várias interfaces de rede, várias NICs, para seus pods. O recurso multi-NIC para pods pode ajudar a separar o tráfego do plano de controle do tráfego do plano de dados, criando isolamento entre planos. Outras interfaces de rede também ativam o recurso multicast para os pods. A multi-NIC para pods conta com suporte para clusters de usuário e não é permitida para clusters de administrador.

O isolamento do plano de rede é importante para sistemas que usam funções de virtualização de rede (NFVs), como a rede definida por software em uma rede de longa distância (SD-WAN, na sigla em inglês), um agente de segurança de acesso à nuvem (CASB, na sigla em inglês) e firewalls de última geração (NG-FWs, na sigla em inglês). Esses tipos de NFVs dependem do acesso a várias interfaces para manter os planos de controle e de dados separados.

A configuração de várias interfaces de rede permite associar interfaces de rede a pools de nós, o que pode proporcionar benefícios de desempenho. Por exemplo, um cluster pode conter uma combinação de tipos de nó. Ao agrupar máquinas de alto desempenho em um pool de nós, é possível adicionar outras interfaces ao pool de nós para melhorar o fluxo de tráfego.

Configurar várias interfaces de rede

Geralmente, há três etapas para configurar várias interfaces de rede para seus pods:

  1. ative a multi-NIC no cluster de usuário usando os campos multipleNetworkInterfaces e enableDataplaneV2 no arquivo de configuração do cluster;

  2. especifique interfaces de rede com a seção additionalNodeInterfaces no arquivo de configuração do cluster e crie um ou mais recursos personalizados NetworkAttachmentDefinition;

  3. atribua interfaces de rede a pods com a anotação k8s.v1.cni.cncf.io/networks.

Ativar o recurso de várias NICs

Ative a multi-NIC nos pods definindo os campos multipleNetworkInterfaces e enableDataplaneV2 no arquivo de configuração do cluster de usuário como true.

apiVersion: v1
multipleNetworkInterfaces: true
enableDataplaneV2: true
  ...

Especificar interfaces de rede

No arquivo de configuração do cluster, especifique outras interfaces de rede de nós na seção additionalNodeInterfaces.

Por exemplo, veja uma parte de um arquivo de configuração de cluster de usuário mostrando uma interface de rede de nó adicional:

apiVersion: v1
multipleNetworkInterfaces: true
enableDataplaneV2: true
network:
  serviceCIDR: "10.96.0.0/20"
  podCIDR: "192.168.0.0/16"
  vCenter:
    networkName: network-private310
  ...
  # New multiple network configs
  additionalNodeInterfaces:
  - networkName: "gke-network-1"
    ipBlockFilePath: "my-block-yaml"
    type: static

Depois de criar um cluster com a configuração anterior, você precisa criar um ou mais recursos personalizados NetworkAttachmentDefinition (NAD) no cluster de usuário em que especifica interfaces de rede adicionais. As NetworkAttachmentDefinitions correspondem às redes disponíveis para os pods. O exemplo a seguir mostra um manifesto de uma NetworkAttachmentDefinition:

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-network-1
  namespace: default
spec:
  config: '{
  "cniVersion":"0.3.0",
  "type": "ipvlan",
  "master": "ens224", # defines the node interface that this Pod interface would map to
  "mode": "l2",
  "ipam": {
    "type": "whereabouts",
    "range": "172.16.0.0/24"
   }
}'

Salve o manifesto como um arquivo YAML. Por exemplo, my-nad.yaml, e crie a NetworkAttachmentDefinition:

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] apply -f my-nad.yaml

Atribuir interfaces de rede a um pod

Use a anotação k8s.v1.cni.cncf.io/networks para atribuir uma ou mais interfaces de rede a um pod. Cada interface de rede é especificada com um namespace e o nome de uma NetworkAttachmentDefinition, separados por uma barra (/). Use uma lista separada por vírgulas para especificar várias interfaces de rede.

No exemplo a seguir, duas interfaces de rede são atribuídas ao samplepod pod. As interfaces de rede são especificadas por nomes de dois NetworkAttachmentDefinitions, gke-network-1 e gke-network-2, que foram criados no namespace default.

---
apiVersion: v1
kind: Pod
metadata:
  name: samplepod
  annotations:
    k8s.v1.cni.cncf.io/networks: default/gke-network-1,default/gke-network-2
spec:
  containers:
  ...

Restringir interfaces de rede a um conjunto de nós

Se você não quiser que uma NetworkAttachmentDefinition seja aplicável a um cluster inteiro, limite a funcionalidade dele a um conjunto de nós.

Você pode agrupar nós do cluster usando o rótulo padrão atribuído no nó ou seu próprio rótulo personalizado. É possível especificar o rótulo do nó no manifesto NetworkAttachmentDefinition usando a anotação k8s.v1.cni.cncf.io/nodeSelector. O Google Distributed Cloud força todos os pods que fazem referência a esse recurso personalizado a serem implantados nos nós que têm esse rótulo.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: LABEL_KEY=LABEL_VALUE
  name: gke-network-1
spec:
...

O exemplo a seguir mostra o rótulo my-label=multinicNP indicado na NetworkAttachmentDefinition e força a implantação de todos os pods que estão atribuídos à rede gke-network-1 para os nós que têm esse rótulo.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: my-label=multinicNP
  name: gke-network-1
spec:
...

Para aplicar um rótulo personalizado a um nó, use o comando kubectl label nodes:

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] label nodes NODE_NAME LABEL_KEY=LABEL_VALUE 

Substitua:

  • NODE_NAME: o nome do nó que você está rotulando.
  • LABEL_KEY: a chave a ser usada para seu rótulo.
  • LABEL_VALUE: o valor do rótulo.

Neste exemplo, o nó my-node recebe o rótulo environment=production:

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] label nodes my-node environment=production

Preocupações com segurança

Uma NetworkAttachmentDefinition fornece acesso total a uma rede. Portanto, os administradores do cluster precisam ter cuidado ao fornecer acesso de criação, atualização ou exclusão a outros usuários. Se determinada NetworkAttachmentDefinition precisar ser isolada, será possível especificar um namespace não padrão ao criá-la, em que apenas os pods desse namespace poderão acessá-la.

No diagrama a seguir, os pods do namespace default não podem acessar a interface de rede no namespace privileged.

Uso de namespaces para isolar o tráfego de rede

Plug-ins CNI compatíveis

Esta seção lista os de plug-ins CNI compatíveis com o recurso de várias NICs do Google Distributed Cloud. Utilize apenas os plug-ins a seguir ao especificar uma NetworkAttachmentDefinition.

Criação da interface:

  • ipvlan
  • macvlan
  • bridge

Plug-ins meta:

  • portmap
  • sbr
  • tuning

Plug-ins IPAM:

  • host-local
  • static
  • whereabouts

Configuração de rota

Um pod com uma ou mais NetworkAttachmentDefinitions atribuídas tem várias interfaces de rede. Por padrão, a tabela de roteamento do pod nessa situação é estendida com as interfaces adicionais disponíveis localmente apenas nas NetworkAttachmentDefinitions atribuídas. Os pacotes vinculados ao gateway padrão ainda estão configurados para usar a interface padrão do pod, eth0. É possível modificar esse comportamento usando os seguintes plug-ins de CNI:

  • sbr
  • static
  • whereabouts

Por exemplo, talvez você queira que a maior parte do tráfego passe pelo gateway padrão, o que significa que ele passará pela interface de rede padrão. No entanto, você quer que um tráfego específico passe por uma das interfaces não padrão. Pode ser difícil diferenciar o tráfego com base no IP de destino (roteamento normal), porque o mesmo endpoint está disponível nos dois tipos de interface. Nesse caso, o roteamento baseado em origem (SBR) pode ajudar.

Plug-in SBR

O plug-in sbr permite que o aplicativo controle as decisões de roteamento. O aplicativo controla o que é usado como o endereço IP de origem da conexão estabelecida. Quando o aplicativo opta por usar o endereço IP da NetworkAttachmentDefinition para o IP de origem, os pacotes chegam à tabela de roteamento adicional que sbr configurou. A tabela de roteamento sbr envia tráfego pelo próprio gateway padrão, que passa pela interface do NetworkAttachmentDefinition. O IP do gateway padrão dentro dessa tabela é controlado com o campo gateway dentro dos plug-ins whereabouts ou static. O plug-in sbr é executado como um plug-in encadeado. Para mais informações sobre o plug-in sbr, incluindo informações de uso, consulte Plug-in de roteamento com base na origem.

O exemplo a seguir mostra "gateway":"21.0.111.254" definido em whereabouts e sbr definido como plug-in encadeado após ipvlan:

# ip route
default via 192.168.0.64 dev eth0  mtu 1500
192.168.0.64 dev eth0 scope link
# ip route list table 100
default via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1

Plug-ins estáticos e de localização

O plug-in whereabouts é basicamente uma extensão do plug-in static, e esses dois compartilham a configuração de roteamento. Para um exemplo de configuração, consulte plug-in de gerenciamento de endereço IP estático. É possível definir um gateway e uma rota para adicionar à tabela de roteamento do pod. No entanto, não é possível modificar o gateway padrão do pod dessa maneira.

O exemplo a seguir mostra a adição de "routes": [{ "dst": "172.31.0.0/16" }] na NetworkAttachmentDefinition:

# ip route
default via 192.168.0.64 dev eth0  mtu 1500
172.31.0.0/16 via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1
192.168.0.64 dev eth0 scope link

Exemplos de configuração

Esta seção ilustra algumas das configurações de rede comuns compatíveis com o recurso multi-NIC.

Anexo de rede única usado por vários pods:

Anexo de rede única usado por vários pods

Vários anexos de rede usados por um único pod:

Vários anexos de rede usados por um único pod

Vários anexos de rede que apontam para a mesma interface usada por um único pod:

Vários anexos de rede que apontam para a mesma interface usada por um único pod

Mesmo anexo de rede usado várias vezes por pod único:

Mesmo anexo de rede usado várias vezes por pod único

Resolver problemas

Se outras interfaces de rede estiverem configuradas incorretamente, os pods a que eles foram atribuídos não serão iniciados. Esta seção destaca como encontrar informações para resolver problemas com o recurso multi-NIC.

Verificar eventos do pod

O Multus relata falhas por eventos do pod do Kubernetes. Use o seguinte comando kubectl describe para visualizar eventos de um determinado pod:

kubectl describe pod POD_NAME

Verifique os registros

Para cada nó, é possível encontrar os registros "Whereabouts" e "Multus" nestes locais:

  • /var/log/whereabouts.log
  • /var/log/multus.log

Analisar interfaces de pod

Use o comando kubectl exec para verificar as interfaces do pod. Depois que as NetworkAttachmentDefinitions forem aplicadas, as interfaces do pod ficarão assim:

user@node1:~$ kubectl exec samplepod-5c6df74f66-5jgxs -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: net1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether 00:50:56:82:3e:f0 brd ff:ff:ff:ff:ff:ff
    inet 21.0.103.112/21 scope global net1
       valid_lft forever preferred_lft forever
38: eth0@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 36:23:79:a9:26:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.2.191/32 scope global eth0
       valid_lft forever preferred_lft forever

Receber status do pod

Use o kubectl get para recuperar o status da rede de um determinado pod:

kubectl get pods POD_NAME -oyaml

Veja um exemplo de saída que mostra o status de um pod com várias redes:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    k8s.v1.cni.cncf.io/network-status: |-
      [{
          "name": "",
          "interface": "eth0",
          "ips": [
              "192.168.1.88"
          ],
          "mac": "36:0e:29:e7:42:ad",
          "default": true,
          "dns": {}
      },{
          "name": "default/gke-network-1",
          "interface": "net1",
          "ips": [
              "21.0.111.1"
          ],
          "mac": "00:50:56:82:a7:ab",
          "dns": {}
      }]
    k8s.v1.cni.cncf.io/networks: gke-network-1