Configurar várias interfaces de rede para pods

Neste documento, descrevemos como configurar o Google Distributed Cloud 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 é compatível com clusters de usuário, híbridos e independentes. Não é permitido para clusters de tipo 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 área 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 o próximo geração de firewalls (NG-FWs, na sigla em inglês). Esses tipos de NFVs dependem do acesso a várias interfaces para manter os planos de gerenciamento e de dados separados, enquanto são executados como contêineres.

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. Os clusters podem conter uma combinação de tipos de nós. 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 com o campo multipleNetworkInterfaces no recurso personalizado.

  2. Especifique interfaces de rede com recursos personalizados NetworkAttachmentDefinition.

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

São fornecidas informações adicionais para ajudar você a configurar e usar o recurso multi-NIC da maneira que melhor atende às suas necessidades de rede.

Ativar o recurso de várias NICs

Ative a multi-NIC nos pods adicionando o campo multipleNetworkInterfaces à seção clusterNetwork da resposta automática do cluster e definindo-o como true.

  ...
  clusterNetwork:
    multipleNetworkInterfaces: true
    pods:
      cidrBlocks:
      - 192.168.0.0/16
    services:
      cidrBlocks:
      - 10.96.0.0/20
  ...

Especificar interfaces de rede

Use recursos personalizados do NetworkAttachmentDefinition para especificar interfaces de rede adicionais. Os recursos personalizados NetworkAttachmentDefinition correspondem às redes que estão disponíveis para os pods. Especifique os recursos personalizados na configuração do cluster, conforme mostrado no exemplo a seguir. Também é possível criar os recursos personalizados NetworkAttachmentDefinition diretamente.

---
apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: my-cluster
  namespace: cluster-my-cluster
spec:
    type: user
    clusterNetwork:
      multipleNetworkInterfaces: true
...
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-network-1
  namespace: cluster-my-cluster
spec:
  config: '{
  "cniVersion":"0.3.0",
  "type": "ipvlan",
  "master": "enp2342",  # defines the node interface that this pod interface would
                         map to.
  "mode": "l2",
  "ipam": {
    "type": "whereabouts",
    "range": "172.120.0.0/24"
  }
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-network-2
  namespace: cluster-my-cluster
spec:
  config: '{
  "cniVersion":"0.3.0",
  "type": "macvlan",
  "mode": "bridge",
  "master": "vlan102",
  "ipam": {
    "type": "static",
    "addresses": [
      {
        "address": "10.10.0.1/24",
        "gateway": "10.10.0.254"
      }
    ],
    "routes": [
      { "dst": "192.168.0.0/16", "gw": "10.10.5.1" }
    ]
  }
}'

Quando você especifica o recurso personalizado NetworkAttachmentDefinition no arquivo de configuração do cluster, o Google Distributed Cloud usa esse nome para controlar o recurso personalizado NetworkAttachmentDefinition após a criação do cluster. O Google Distributed Cloud trata esse recurso personalizado dentro do namespace do cluster como a fonte da verdade e o reconcilia com o namespace default do cluster de destino.

O diagrama a seguir ilustra como o Google Distributed Cloud reconcilia recursos personalizados NetworkAttachmentDefinition do namespace específico do cluster para o namespace default.

Reconciliação de NetworkAttachmentDefinition

Embora seja opcional, recomendamos que você especifique recursos personalizados NetworkAttachmentDefinition dessa maneira durante a criação do cluster. Os clusters de usuário são mais beneficiados quando você especifica os recursos personalizados durante a criação do cluster, porque é possível controlar os recursos personalizados NetworkAttachmentDefinition no cluster de administrador.

Se você optar por não especificar recursos personalizados NetworkAttachmentDefinition durante a criação do cluster, poderá adicionar recursos NetworkAttachmentDefinition personalizados diretamente a um cluster de destino atual. O Google Distributed Cloud reconcilia recursos personalizados NetworkAttachmentDefinition definidos no namespace do cluster. A reconciliação também acontece após a exclusão. Quando um recurso personalizado NetworkAttachmentDefinition é removido de um namespace de cluster, o Google Distributed Cloud remove o recurso personalizado do cluster de destino.

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 um recurso personalizado NetworkAttachmentDefinition, separado por uma barra (/).

---
apiVersion: v1
kind: Pod
metadata:
  name: samplepod
  annotations:
    k8s.v1.cni.cncf.io/networks: NAMESPACE/NAD_NAME
spec:
  containers:
  ...

Substitua:

  • NAMESPACE: o namespace. Use default como namespace padrão, que é o padrão. Consulte Preocupações de segurança para ver uma exceção.
  • NAD_NAME: o nome do recurso personalizado NetworkAttachmentDefinition.

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 recursos personalizados NetworkAttachmentDefinition, gke-network-1 e gke-network-2, no namespace padrão do cluster de destino.

---
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 NodePool

Use a anotação k8s.v1.cni.cncf.io/nodeSelector para especificar o pool de nós em que um recurso personalizado NetworkAttachmentDefinition é válido. O Google Distributed Cloud força a implantação de todos os pods que fazem referência a esse recurso personalizado nesses nós específicos. No exemplo a seguir, o Google Distributed Cloud força a implantação de todos os pods atribuídos à interface de rede gke-network-1 para o pool de nós multinicNP. O Google Distributed Cloud rotula um NodePool com o rótulo baremetal.cluster.gke.io/node-pool conforme necessário.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: baremetal.cluster.gke.io/node-pool=multinicNP
  name: gke-network-1
spec:
...

Você não está limitado a usar os rótulos padrão. É possível criar seus próprios pools personalizados a partir dos nós do cluster aplicando um rótulo personalizado a esses nós. Use o comando kubectl label nodes para aplicar um rótulo personalizado:

kubectl 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 nome do rótulo.

Depois que o nó for rotulado, aplique a anotação baremetal.cluster.gke.io/label-taint-no-sync nele para evitar que o Google Distributed Cloud reconcilie os rótulos. Use o comando kubectl get nodes --show-labels para verificar se um nó está rotulado.

Preocupações com segurança

Um recurso personalizado 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 para outros usuários. Se um determinado recurso personalizado NetworkAttachmentDefinition precisar ser isolada, ela poderá ser colocada em um namespace não padrão, em que apenas os pods desse namespace poderão acessá-lo. Para reconciliar recursos personalizados NetworkAttachmentDefinition especificados no arquivo de configuração do cluster, eles são sempre colocados no namespace padrão.

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

Nesta seção, listamos os plug-ins CNI compatíveis com o recurso de várias placas de rede (NIC) para o Google Distributed Cloud. Use somente os seguintes plug-ins ao especificar um recurso personalizado NetworkAttachmentDefinition.

Criação da interface:

  • ipvlan
  • macvlan
  • bridge
  • sriov

Plug-ins meta:

  • portmap
  • sbr
  • tuning

Plug-ins IPAM:

  • host-local
  • static
  • whereabouts

Configuração de rota

Um pod com um ou mais recursos personalizados atribuídos a NetworkAttachmentDefinition tem várias interfaces de rede. Por padrão, a tabela de roteamento nessa situação é estendida com as interfaces adicionais disponíveis localmente apenas de recursos personalizados NetworkAttachmentDefinition atribuídas. O gateway padrão ainda está configurado para usar a interface mestre/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 todo o tráfego passe pelo gateway padrão, a interface padrão. No entanto, algum tráfego específico passa 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 do recurso personalizado NetworkAttachmentDefinition para o IP de origem, os pacotes chegam à tabela de roteamento adicional sbr configurada. A tabela de roteamento sbr estabelece a interface do recurso personalizado NetworkAttachmentDefinition como gateway padrão. O IP do gateway padrão dentro dessa tabela é controlado com o campo gateway dentro dos plug-ins whereabouts ou static. Forneça o plug-in sbr 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" }] no recurso personalizado 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" nos seguintes 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 os recursos personalizados NetworkAttachmentDefinition forem aplicados, as interfaces do pod terão a seguinte saída:

$ 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