Observação:

Configurar interfaces SR-IOV para pods no OKE usando o Multus CNI

Introdução

SR-IOV é uma especificação que permite que um único dispositivo PCIe pareça ser vários dispositivos físicos PCIe separados. O SR-IOV funciona introduzindo a ideia de funções físicas (PFs) e funções virtuais (VFs). Um PF é usado pelo host e geralmente representa uma única porta NIC. VF é uma versão leve desse PF. Com suporte adequado, o SR-IOV apresenta uma forma de o hardware físico (como um SmartNIC) se apresentar como vários dispositivos distintos (interface de rede). Com contêineres, podemos mover uma dessas interfaces (um VF) do host, para o namespace de rede de um contêiner ou um Pod, para que o contêiner agora possa acessar diretamente a interface. A vantagem que isso oferece é que não obtemos nenhuma sobrecarga com virt-io e obtemos desempenho nativo do dispositivo.

Observação: Os plug-ins e o processo descritos neste tutorial são aplicáveis somente a instâncias bare metal. Para instâncias baseadas em máquina virtual, é necessário um conjunto diferente de plug-ins e uma configuração.

Objetivo

Este tutorial descreve como configurar interfaces de rede baseadas em função virtual SR-IOV secundária para pods em execução em clusters do OKE. Ele utiliza o plug-in SRIOV-CNI para gerenciar funções virtuais SR-IOV como recursos que podem ser alocados em um nó e no Multus meta CNI para adicionar interfaces de rede adicionais aos pods.

Como funciona.

A abordagem tem várias camadas e componentes. Em sua base, um plug-in de dispositivo Kubernetes gerencia um conjunto de funções virtuais e o publica como um recurso alocável no nó. Quando um pod solicita esse recurso, ele pode ser designado a um nó em que o recurso está disponível e um CNI SR-IOV pode encumbir a função virtual no namespace de rede do pod. Um metaplugin de CNI como o Multus trata vários anexos de rede para o Pod para que o Pod possa se comunicar tanto sobre o SR-IOV quanto sobre as redes de sobreposição.

Primeiro, criamos uma série de FVs no SR-IOV capaz de smartNICs, que se apresentará como NICs individuais. Em seguida, configuramos esses VFs com endereços MAC que a Oracle Cloud Infrastructure (OCI) reconhece. Esses VFs são criados fora do Multus, manualmente (conforme descrito neste tutorial) ou usando um script que pode ser chamado no momento da criação do nó. Nesse ponto, temos um pool de VFs identificados pelo host como NIC separada e um endereço MAC do OCI. O grupo de trabalho de plumbing de rede do Kubernetes mantém um plug-in de dispositivo de rede para fins especiais que descobre e publica VFs como recursos de nó alocáveis. O CNI SR-IOV (também do grupo de trabalho de plumbing da rede Kubernetes) funciona ao lado do plug-in do dispositivo e gerencia a atribuição dessas funções virtuais ao pod com base no ciclo de vida do pod.

Agora temos um ou mais nós com um pool de VFs reconhecidos e gerenciados pelo plug-in de dispositivo SR-IOV como recursos de nó alocáveis. Eles podem ser solicitados pelos pods. O SR-IOV CNI plumbe (move) o VF no namespace de rede do Pod na criação do Pod e libera o VF (move-o de volta para o namespace raiz) na exclusão do Pod. Isso torna o VF disponível para ser alocado para outro pod. Um meta plug-in como o Multus pode fornecer as informações do VF ao CNI e gerenciar vários anexos de rede no Pod.

imagem de pod multus

Tarefa 1: Configurar os hosts

Começamos com hosts bare metal onde podemos configurar VFs para as interfaces PCIe. Com hosts bare metal, realizamos as seguintes etapas.

  1. Crie VFs: conecte SSH ao nó bare metal. Localize o dispositivo físico e adicione funções virtuais a ele.

    Observação: O script para obter o nome do dispositivo é necessário somente para automação.

    O exemplo aqui cria dois VFs no dispositivo.

    # Gets the physical device. Alterntively, just run `ip addr show` and look at the primary iface to set $PHYSDEV
    URL=http://169.254.169.254/opc/v1/vnics/
    baseAddress=`curl -s ${URL} | jq -r '.[0] | .privateIp'`
    PHYSDEV=`ip -o -4 addr show | grep ${baseAddress} | awk -F: '{gsub(/^[ \t]|[ \t]$/,"",$2);split($2,out,/[ \t]+/);print out[1]}'`
    
    # Add two VFs
    echo "2" > /sys/class/net/${PHYSDEV}/device/sriov_numvfs
    
    # Verify the VFs
    ip link show ${PHYSDEV}
    
  2. Designe endereços MAC do OCI aos VFs.

    Esses VFs terão endereços MAC gerados automaticamente agora (ou 000). Precisamos definir endereços MAC do OCI para que o tráfego desses endereços seja permitido na rede do OCI. Crie o mesmo número de anexos de VNIC no host que o número de VFs criados. Observe os endereços MAC de cada anexo de VNIC. Agora designamos cada um desses endereços MAC que a OCI reconhece ao VFS que criamos.

    # For each MAC address from the VNIC attachments
    
    ip link set ${PHYSDEV} vf <n= 0..numVFs> mac <MAC Address from VNIC attachment> spoofchk off
    
    # verify all VFs have Mac addresses from OCI
    ip link show ${PHYSDEV}
    
    

Isso conclui a configuração do host, que deve, idealmente, ser automatizada, pois precisa ser executada em cada host que precisa fornecer recursos de rede SR-IOV aos pods.

Tarefa 2: Instalar o CNI SR-IOV

Este CNI pode ser instalado em um cluster 1.16+ como um conjunto de daemon. Os nós sem dispositivos SR-IOV são tratados normalmente pelo próprio plug-in de dispositivo.

git clone https://github.com/k8snetworkplumbingwg/sriov-cni.git && cd sriov-cni
kubectl apply -f images/k8s-v1.16/sriov-cni-daemonset.yaml && cd..

Tarefa 3: Instalar o plug-in do dispositivo de rede SR-IOV

Observação: O plug-in de dispositivo não cria os VFs imediatamente, eles devem ser criados separadamente.

O plug-in de dispositivo descobre e anuncia os dispositivos de rede capazes de SR-IOV no nó. Para isso, o plug-in de dispositivo requer uma configuração que a permita criar os pontos de extremidade do plug-in de dispositivo. A configuração identifica os dispositivos e os drivers usados.

  1. Crie um ConfigMap para o pool de recursos SR-IOV. Para configurar o ConfigMap, precisamos saber o ID do fornecedor, o ID do dispositivo e o driver usado pelo dispositivo.

    1. Para localizar o ID do fornecedor e o ID do dispositivo:

      lspci -nn|grep Virtual
      
      31:02.0 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme-E Ethernet Virtual Function [14e4:16dc]
      31:02.1 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme-E Ethernet Virtual Function [14e4:16dc]
      
      
    2. No exemplo acima, temos duas VFs, e a última informação fornece o id do fornecedor (14e4) e o id do dispositivo (16dc). Podemos fazer uma verificação cruzada com os hwdata que lspci usa.

      cat /usr/share/hwdata/pci.ids|grep 16dc
      
    3. Para localizar os drivers usados:

      # filtering based on the PCIe slots.
      find /sys | grep drivers.*31:02.0|awk -F/ '{print $6}'
      
      bnxt_en
      
      
  2. Configure o ConfigMap. O nome ConfigMap deve ser sriovdp-config e deve ter uma chave config.json

    cat << EOF > sriovdp-config.yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: sriovdp-config
      namespace: kube-system
    data:
      config.json: |
        {
          "resourceList": [{
                  "resourceName": "mlnx_sriov_rdma",
                  "resourcePrefix": "mellanox.com",
                  "selectors": {
                    "vendors": ["15b3"],
                    "devices": ["101e"],
                    "drivers": ["mlx5_core"],
                    "isRdma": false
                  }
              },
              {
                  "resourceName": "netxtreme_sriov_rdma",
                  "resourcePrefix": "broadcom.com",
                  "selectors": {
                    "vendors": ["14e4"],
                    "devices": ["16dc"],
                    "drivers": ["bnxt_en"],
                    "isRdma": false
                  }
              }
          ]
        }
    EOF
    
    kubectl create -f sriovdp-config.yaml
    
    
  3. Configure o plug-in de dispositivo. Com o mapa de configuração criado, o plug-in de dispositivo pode ser instalado como um conjunto de daemon.

    git clone https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin.git && cd sriov-network-device-plugin
    kubectl create -f deployments/k8s-v1.16/sriovdp-daemonset.yaml && cd ..
    
  4. Depois que os daemonsets forem implantados, você poderá verificar os logs do contêiner para solucionar problemas. Após uma implantação bem-sucedida, o nó deve listar as funções virtuais como recursos alocáveis.

    kubectl get node <node_name> -o json | jq '.status.allocatable'
    
    {
      "broadcom.com/netxtreme_sriov_rdma": "2",
      "cpu": "128",
      "ephemeral-storage": "37070025462",
      "hugepages-1Gi": "0",
      "hugepages-2Mi": "0",
      "memory": "527632840Ki",
      "pods": "110"
    }
    

Tarefa 4: Instalar um plug-in meta CNI (Multus)

Multus é um meta plug-in que pode fornecer as informações de VF a um CNI downstream como o plug-in de CNI SR-IOV para ele tratar o encanamento de recursos de rede enquanto ativa pods ou pods "Multi-homed" com várias interfaces de rede.

  1. Instalar Multus:

    git clone https://github.com/k8snetworkplumbingwg/multus-cni.git && cd multus-cni
    kubectl apply -f images/multus-daemonset.yml && cd ..
    

    Observação:

    • A imagem padrão usada pelo daemonset que está marcado como stable precisa que o kubelet seja v1.20.x. Se estiver instalando em um cluster mais antigo, edite o deamonset no manifesto e use a tag de imagem multus v3.7.1.

    • Esse manifesto cria um novo CRD para o kind:NetworkAttachmentDefinition e fornece o binário multus em todos os nós por meio de um daemonset.

  2. Para anexar interfaces adicionais aos pods, precisamos de uma configuração para que a interface seja anexada. Isso é encapsulado no recurso personalizado do tipo NetworkAttachmentDefinition. Esta configuração é essencialmente uma configuração de CNI empacotada como um recurso personalizado.

    Vamos configurar uma amostra NetworkAttachmentDefinition

    cat << EOF > sriov-net1.yaml
    apiVersion: k8s.cni.cncf.io/v1
    kind: NetworkAttachmentDefinition
    metadata:
      name: sriov-net1
      annotations:
        k8s.v1.cni.cncf.io/resourceName: broadcom.com/netxtreme_sriov_rdma
    spec:
      config: '{
      "type": "sriov",
      "cniVersion": "0.3.1",
      "name": "sriov-network",
      "ipam": {
        "type": "host-local",
        "subnet": "10.20.30.0/25",
        "routes": [{
          "dst": "0.0.0.0/0"
        }],
        "gateway": "10.20.10.1"
      }
    }'
    EOF
    
    kubectl apply -f sriov-net1.yaml
    
    

Tarefa 5: Implantar e testar pods com várias interfaces

Confirmações

Mais Recursos de Aprendizagem

Explore outros laboratórios no site docs.oracle.com/learn ou acesse mais conteúdo de aprendizado gratuito no canal YouTube do Oracle Learning. Além disso, visite education.oracle.com/learning-explorer para se tornar um Oracle Learning Explorer.

Para obter a documentação do produto, visite o Oracle Help Center.