Ejemplos de UDN de red local para la virtualización de Red Hat OpenShift

Conecta las máquinas virtuales de virtualización de « OpenShift » a las subredes de « IBM Cloud VPC » mediante las redes «CUDN Localnet» para un tráfico respaldado por VLAN y aislado por espacios de nombres.

Este tutorial muestra cómo crear una aplicación de tres capas de ejemplo utilizando subredes de la Nube Privada Virtual (VPC), redes definidas por el usuario en clúster (CUDN), redes locales y espacios de nombres en Red Hat OpenShift on IBM Cloud en IBM Cloud. El ejemplo muestra cómo conectar servidores virtuales que se ejecutan en la virtualización de « Red Hat OpenShift » directamente a subredes de VPC mediante redes «localnet» respaldadas por redes de área local virtuales (VLAN). Para obtener más información sobre los tipos de red, consulta la sección «Redes Open Virtual Network(OVN)» en Red Hat OpenShift, dirigida a los administradores de vSphere®.

Visión general

En este ejemplo se implementa una aplicación de tres capas con segmentos de red independientes para las capas web, de base de datos y de aplicación. Cada nivel utiliza una subred VPC dedicada y una red local CUDN con un ID de VLAN único. Los niveles de web y de base de datos se ubican en un único espacio de nombres (green), mientras que el nivel de aplicación se ubica en un espacio de nombres independiente (red) para demostrar el aislamiento basado en espacios de nombres.

Datos sobre la red, el espacio de nombres y el servidor virtual

La siguiente tabla resume el esquema de red del ejemplo.

Ejemplo de estructura de CUDN, espacio de nombres y servidor virtual en Localnet
Localnet CUDN Espacio de nombres ID de VLAN Subred de VPC Servidores virtuales
vlan20-prod green 20 198.18.0.0/24 plant-web00, plant-web01
vlan21-db green 21 198.18.1.0/24 plant-db00, plant-db01
vlan22-app red 22 198.18.2.0/24 plant-app00, plant-app01

Esquema de la configuración final

Configuración de una aplicación de tres capas en Localnet
Configuración de una aplicación de tres capas en Localnet

Cada bloque de código de la guía se puede copiar en un archivo y aplicar con el comando « oc apply -f <file-name>.yml ». Es posible que algunos bloques de código se extiendan más allá de los límites de la página en los formatos PDF y Word, y que algunas líneas largas se ajusten a la página en dichos formatos.

La guía utiliza « ic » como abreviatura de « ibmcloud » en comandos de la CLI de « IBM Cloud ». Define « alias ic=ibmcloud » en tu terminal, o sustituye « ibmcloud » por « ic » en los comandos que siguen.

Antes de empezar

Asegúrate de que dispones de los siguientes elementos:

  • Una cuenta de IBM Cloud con permisos para gestionar recursos de VPC y Red Hat OpenShift.
  • La CLI de « IBM Cloud » está instalada.
  • Los complementos « container-service » y « vpc-infrastructure » están instalados.

El complemento « container-service » proporciona los comandos « ic ks » que utiliza la guía para asociar interfaces de red virtuales (VNI) de VLAN al clúster. El complemento « vpc-infrastructure » proporciona los comandos « ic is » que utiliza la guía para crear subredes de VPC, interfaces de red virtual (VNI) y otros elementos de infraestructura.

Si necesitas instalar los complementos de la CLI necesarios, utiliza los siguientes comandos.

ibmcloud plugin install container-service
ibmcloud plugin install vpc-infrastructure

Revisar los requisitos previos de la red

Si utilizas Red Hat OpenShift on IBM Cloud, consulta Red Hat OpenShift on IBM Cloud los requisitos previos de red de OVN UDN/CUDN antes de empezar. Red Hat OpenShift El Servicio de Virtualización incluye estos requisitos previos de forma predeterminada.

Creación de un espacio de nombres y de una red secundaria CUDN Localnet para el nivel «green»

Las redes «localnet» pueden coexistir con redes primarias de tipo « Layer 2 », redes secundarias de tipo « Layer 2 » y otras redes «localnet» dentro de un espacio de nombres. Cada red local necesita un VLAN ID. Actualmente, solo se puede utilizar una subred por VLAN.

La VLAN no crea un dominio « Layer 2 » entre los trabajadores. La VLAN se utiliza dentro de cada nodo de trabajo, no dentro de la VPC.

Crea el espacio de nombres green y las redes vlan20-prod y vlan21-db. Aplica el manifiesto con el comando « oc apply -f step1.yml ».

---
apiVersion: v1
kind: Namespace
metadata:
  name: green
---
apiVersion: k8s.ovn.org/v1
kind: ClusterUserDefinedNetwork
metadata:
  name: "vlan20-prod"
spec:
  namespaceSelector:
    matchExpressions:
    - key: kubernetes.io/metadata.name
      operator: In
      values:
      - "green"
  network:
    topology: Localnet
    localnet:
      role: "Secondary"
      physicalNetworkName: "vpc-vlans"
      ipam:
        mode: Disabled
      vlan:
        mode: Access
        access:
          id: 20
---
apiVersion: k8s.ovn.org/v1
kind: ClusterUserDefinedNetwork
metadata:
  name: "vlan21-db"
spec:
  namespaceSelector:
    matchExpressions:
    - key: kubernetes.io/metadata.name
      operator: In
      values:
      - "green"
  network:
    topology: Localnet
    localnet:
      role: "Secondary"
      physicalNetworkName: "vpc-vlans"
      ipam:
        mode: Disabled
      vlan:
        mode: Access
        access:
          id: 21

Ten en cuenta las siguientes consideraciones:

  • La subred no está definida en la configuración de Localnet.
  • No utilices VLAN 1.
  • Utiliza VLANs en el rango de 2 a 500. Las VLAN del 501 al 4094 están restringidas actualmente.

Creación de otro espacio de nombres y de una red secundaria CUDN Localnet para el nivel rojo

Crea el espacio de nombres red y la red vlan22-app. Aplica el manifiesto con el comando « oc apply -f step2.yml ».

---
apiVersion: v1
kind: Namespace
metadata:
  name: red
---
apiVersion: k8s.ovn.org/v1
kind: ClusterUserDefinedNetwork
metadata:
  name: "vlan22-app"
spec:
  namespaceSelector:
    matchExpressions:
    - key: kubernetes.io/metadata.name
      operator: In
      values:
      - "red"
  network:
    topology: Localnet
    localnet:
      role: "Secondary"
      physicalNetworkName: "vpc-vlans"
      ipam:
        mode: Disabled
      vlan:
        mode: Access
        access:
          id: 22

Creación de direcciones IP reservadas y VNI en tu cuenta de VPC

Este paso crea una dirección IP reservada en cada subred; a continuación, crea la VNI utilizando esa dirección IP reservada y asigna un nombre de interfaz de red virtual ( MAC address ) a cada interfaz de red virtual (VNI).

Ten en cuenta las siguientes consideraciones:

  • En este paso no se incluye el « VLAN ID ».
  • Debes consultar cuál es el grupo de seguridad que debes utilizar en este paso. Ejecuta el comando « ic is sgs » para ver la lista de grupos de seguridad disponibles.
  • Puedes ejecutar este paso de forma masiva.
  • El límite máximo es de 256 VNI por host. Mantén el uso por debajo del 85 % para permitir la conmutación por error y las migraciones desde otros servidores.

Creación de direcciones IP reservadas en cada subred

En primer lugar, crea una dirección IP reservada en cada subred para tus servidores virtuales:

ic is subnet-reserved-ip-create zone1-vm-prod --address 198.18.0.20 --name zone1-web00 --auto-delete false
ic is subnet-reserved-ip-create zone1-vm-db --address 198.18.1.20 --name zone1-db00 --auto-delete false
ic is subnet-reserved-ip-create zone1-vm-app --address 198.18.2.20 --name zone1-app00 --auto-delete false

Creación de VNI utilizando las direcciones IP reservadas

Ahora crea las VNI utilizando los nombres de IP reservados del paso anterior:

ic is virtual-network-interface-create --name zone1-web00 --allow-ip-spoofing false --auto-delete false --protocol-state-filtering-mode disabled --enable-infrastructure-nat true --subnet zone1-vm-prod --vpc my-vpc --rip zone1-web00 --sgs handclap-roundworm-clique-eccentric --resource-group-name Default
ic is virtual-network-interface-create --name zone1-db00 --allow-ip-spoofing false --auto-delete false --protocol-state-filtering-mode disabled --enable-infrastructure-nat true --subnet zone1-vm-db --vpc my-vpc --rip zone1-db00 --sgs handclap-roundworm-clique-eccentric --resource-group-name Default
ic is virtual-network-interface-create --name zone1-app00 --allow-ip-spoofing false --auto-delete false --protocol-state-filtering-mode disabled --enable-infrastructure-nat true --subnet zone1-vm-app --vpc my-vpc --rip zone1-app00 --sgs handclap-roundworm-clique-eccentric --resource-group-name Default

Asignación del VNI de la VLAN al clúster

Obtén el ID de cada VNI que hayas creado en el paso anterior y, a continuación, utiliza el complemento « IBM Cloud » ( container-service ) para asociar el VNI al clúster. Necesitas el ID del clúster, que puedes obtener ejecutando el comando « ic ks cluster ls ».

Ten en cuenta las siguientes consideraciones:

  • Si un trabajador supera su cuota de VNI, la operación asociada falla.
  • Las VNI se pueden asociar al clúster (también conocido como « floating ») o a un trabajador concreto.

Busca los identificadores VNI.

ic is vni zone1-web00 | awk '$1 ~ /^ID/ {print $NF}'
ic is vni zone1-db00 | awk '$1 ~ /^ID/ {print $NF}'
ic is vni zone1-app00 | awk '$1 ~ /^ID/ {print $NF}'

Conecta cada VNI al clúster con el ID de VLAN correspondiente. Sustituye el ID del clúster y los ID de VNI por los valores de tu entorno.

ic ks vni attach baremetal -c <CLUSTER_ID> --vni <VNI_ID_web00> --vlan 20
ic ks vni attach baremetal -c <CLUSTER_ID> --vni <VNI_ID_db00>  --vlan 21
ic ks vni attach baremetal -c <CLUSTER_ID> --vni <VNI_ID_app00> --vlan 22

Añadir servidores virtuales a los espacios de nombres

El siguiente manifiesto es un ejemplo básico de « YAML » para crear un servidor virtual. Puedes actualizar este manifiesto para cada espacio de nombres y cada red. Necesitas el archivo « MAC address » para cada archivo « VNI » que hayas creado. Ejecuta el comando « ic is vnis » para ver la lista y actualiza el campo « macAddress » de la plantilla para que « DHCP » funcione correctamente.

Utiliza los siguientes comandos para encontrar el « MAC address » de cada « VNI ».

ic is vni zone1-web00 | awk '/^Mac Address/ {print $NF}'
ic is vni zone1-db00  | awk '/^Mac Address/ {print $NF}'
ic is vni zone1-app00 | awk '/^Mac Address/ {print $NF}'

Ejemplo de resultado para cada VNI. Vuestros valores son diferentes:

02:00:01:00:98:A0
02:00:02:00:98:A5
02:00:02:00:98:AA

Ten en cuenta las siguientes consideraciones antes de aplicar los manifiestos:

  • Actualiza la contraseña en cada manifiesto.
  • Para iniciar sesión, necesitas introducir una clave pública SSH válida en el campo « ssh_authorized_keys ».
  • No puedes utilizar SSH con contraseña.
  • Sustituye cada valor « macAddress » por la dirección MAC del VNI correspondiente que hayas consultado en los comandos anteriores. El « macAddress » debe coincidir con el VNI para que DHCP asigne la dirección IP esperada.

Aplica cada uno de los siguientes manifiestos con « oc apply -f <file-name>.yml ». Utiliza los siguientes enlaces para acceder directamente a cada manifiesto.

Servidor virtual plant-web00 en el espacio de nombres green en vlan20-prod

# Bare YAML to stand up a Red Hat OpenShift on IBM Cloud virtual machine
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: "plant-web00"
  namespace: "green"
  annotations:
    description: "example vm plant-web00"
  labels:
    app: "plant-web00-green-server"
    kubevirt.io/dynamic-credentials-support: 'true'
    vm.kubevirt.io/template: "centos-stream9-server-small"
    vm.kubevirt.io/template.namespace: openshift
    vm.kubevirt.io/template.revision: '1'
    vm.kubevirt.io/template.version: v0.34.0
spec:
  dataVolumeTemplates:
    - apiVersion: cdi.kubevirt.io/v1beta1
      kind: DataVolume
      metadata:
        creationTimestamp: null
        name: "plant-web00-green-server"
      spec:
        sourceRef:
          kind: DataSource
          name: "centos-stream9"
          namespace: openshift-virtualization-os-images
        storage:
          resources:
            requests:
              storage: 30Gi
  runStrategy: RerunOnFailure
  template:
    metadata:
      annotations:
        vm.kubevirt.io/flavor: "small"
        vm.kubevirt.io/os: "centos-stream9"
        vm.kubevirt.io/workload: "server"
      labels:
        kubevirt.io/domain: example
        kubevirt.io/size: "small"
    spec:
      domain:
        cpu:
          cores: 1
          sockets: 1
          threads: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: rootdisk
            - disk:
                bus: virtio
              name: cloudinitdisk
          interfaces:
            - model: virtio
              name: default
              state: up
              bridge: {}
              macAddress: 02:00:01:00:98:A0 # <- replace with the MAC of VNI zone1-web00
          networkInterfaceMultiqueue: true
          rng: {}
        memory:
          guest: "2Gi"
      hostname: "plant-web00"
      networks:
        - name: default
          multus:
            networkName: vlan20-prod
      terminationGracePeriodSeconds: 180
      volumes:
        - dataVolume:
            name: "plant-web00-green-server"
          name: rootdisk
        - cloudInitNoCloud:
            userData: |-
              #cloud-config
              user: admin
              password: "aRandomPassword9292"
              ssh_authorized_keys:
                 - "ssh-ed25519 AAAA....BBBB....CCCCC.....DDDD put-your-key-here@example.local"
              chpasswd: { expire: False }
              runcmd:
                - [ dnf, install, -y, epel-release ]
                - [ dnf, install, -y, iperf3, nmap-ncat, darkhttpd ]
          name: cloudinitdisk

Servidor virtual plant-db00 en el espacio de nombres green en vlan21-db

---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: "plant-db00"
  namespace: "green"
  annotations:
    description: "example vm plant-db00"
  labels:
    app: "plant-db00-green-server"
    kubevirt.io/dynamic-credentials-support: 'true'
    vm.kubevirt.io/template: "centos-stream9-server-small"
    vm.kubevirt.io/template.namespace: openshift
    vm.kubevirt.io/template.revision: '1'
    vm.kubevirt.io/template.version: v0.34.0
spec:
  dataVolumeTemplates:
    - apiVersion: cdi.kubevirt.io/v1beta1
      kind: DataVolume
      metadata:
        creationTimestamp: null
        name: "plant-db00-green-server"
      spec:
        sourceRef:
          kind: DataSource
          name: "centos-stream9"
          namespace: openshift-virtualization-os-images
        storage:
          resources:
            requests:
              storage: 30Gi
  runStrategy: RerunOnFailure
  template:
    metadata:
      annotations:
        vm.kubevirt.io/flavor: "small"
        vm.kubevirt.io/os: "centos-stream9"
        vm.kubevirt.io/workload: "server"
      labels:
        kubevirt.io/domain: example
        kubevirt.io/size: "small"
    spec:
      domain:
        cpu:
          cores: 1
          sockets: 1
          threads: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: rootdisk
            - disk:
                bus: virtio
              name: cloudinitdisk
          interfaces:
            - model: virtio
              name: default
              state: up
              bridge: {}
              macAddress: 02:00:01:00:98:A5 # <- replace with the MAC of VNI zone1-db00
          networkInterfaceMultiqueue: true
          rng: {}
        memory:
          guest: "2Gi"
      hostname: "plant-db00"
      networks:
        - name: default
          multus:
            networkName: vlan21-db
      terminationGracePeriodSeconds: 180
      volumes:
        - dataVolume:
            name: "plant-db00-green-server"
          name: rootdisk
        - cloudInitNoCloud:
            userData: |-
              #cloud-config
              user: admin
              password: "aRandomPassword9292"
              ssh_authorized_keys:
                 - "ssh-ed25519 AAAA....BBBB....CCCCC.....DDDD put-your-key-here@example.local"
              chpasswd: { expire: False }
              runcmd:
                - [ dnf, install, -y, epel-release ]
                - [ dnf, install, -y, iperf3, nmap-ncat, darkhttpd ]
          name: cloudinitdisk

Servidor virtual plant-app00 en el espacio de nombres red en vlan22-app

---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: "plant-app00"
  namespace: "red"
  annotations:
    description: "example vm plant-app00"
  labels:
    app: "plant-app00-red-server"
    kubevirt.io/dynamic-credentials-support: 'true'
    vm.kubevirt.io/template: "centos-stream9-server-small"
    vm.kubevirt.io/template.namespace: openshift
    vm.kubevirt.io/template.revision: '1'
    vm.kubevirt.io/template.version: v0.34.0
spec:
  dataVolumeTemplates:
    - apiVersion: cdi.kubevirt.io/v1beta1
      kind: DataVolume
      metadata:
        creationTimestamp: null
        name: "plant-app00-red-server"
      spec:
        sourceRef:
          kind: DataSource
          name: "centos-stream9"
          namespace: openshift-virtualization-os-images
        storage:
          resources:
            requests:
              storage: 30Gi
  runStrategy: RerunOnFailure
  template:
    metadata:
      annotations:
        vm.kubevirt.io/flavor: "small"
        vm.kubevirt.io/os: "centos-stream9"
        vm.kubevirt.io/workload: "server"
      labels:
        kubevirt.io/domain: example
        kubevirt.io/size: "small"
    spec:
      domain:
        cpu:
          cores: 1
          sockets: 1
          threads: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: rootdisk
            - disk:
                bus: virtio
              name: cloudinitdisk
          interfaces:
            - model: virtio
              name: default
              state: up
              bridge: {}
              macAddress: 02:00:01:00:98:AA # <- replace with the MAC of VNI zone1-app00
          networkInterfaceMultiqueue: true
          rng: {}
        memory:
          guest: "2Gi"
      hostname: "plant-app00"
      networks:
        - name: default
          multus:
            networkName: vlan22-app
      terminationGracePeriodSeconds: 180
      volumes:
        - dataVolume:
            name: "plant-app00-red-server"
          name: rootdisk
        - cloudInitNoCloud:
            userData: |-
              #cloud-config
              user: admin
              password: "aRandomPassword9292"
              ssh_authorized_keys:
                 - "ssh-ed25519 AAAA....BBBB....CCCCC.....DDDD put-your-key-here@example.local"
              chpasswd: { expire: False }
              runcmd:
                - [ dnf, install, -y, epel-release ]
                - [ dnf, install, -y, iperf3, nmap-ncat, darkhttpd ]
          name: cloudinitdisk

Comprobación de la configuración de la red

IBM Recomienda que utilices un host de salto de Linux® en la misma VPC que el clúster para estas pruebas. Desde el servidor de inicio, utiliza SSH para conectarte a cada servidor virtual con la clave pública que especificaste en la configuración del servidor virtual.

Configura el reenvío del agente SSH o utiliza una nueva clave alojada en el servidor de enlace. No copies tu clave privada de un sistema a otro.

Desde una sesión de terminal, utiliza SSH para conectarte al servidor virtual del nivel web:

ssh admin@198.18.0.20

Desde otra sesión de terminal, utiliza SSH para conectarte al servidor virtual del nivel de base de datos:

ssh admin@198.18.1.20

Desde otra sesión de terminal, utiliza SSH para conectarte al servidor virtual del nivel de aplicaciones:

ssh admin@198.18.2.20

Pruebas

Realiza las siguientes pruebas para comprobar la configuración de la red.

  1. Inicia un servidor sencillo de HTTP en cada servidor virtual.

    • Desde 198.18.0.20, ejecuta darkhttpd /usr/share/doc/bash --daemon.
    • Desde 198.18.1.20, ejecuta darkhttpd /usr/share/doc/bash --daemon.
    • Desde 198.18.2.20, ejecuta darkhttpd /usr/share/doc/bash --daemon.
  2. Desde 198.18.0.20, ejecuta curl -v http://198.18.1.20:8080.

  3. Desde 198.18.1.20, ejecuta curl -v http://198.18.0.20:8080.

  4. Desde el servidor virtual «jump», ejecuta curl -v http://198.18.2.20:8080.

  5. Desde 198.18.1.20, inicia un servidor de iperf3: iperf3 -s -p 9090.

  6. Desde 198.18.0.20, conéctate al servidor iperf3 en el espacio de nombres green: iperf3 -c 198.18.1.20 -p 9090.

  7. Realiza una prueba de ping desde 198.18.1.20 a 198.18.0.20 y viceversa.

  8. Vuelve a ejecutar las tareas anteriores utilizando 198.18.2.20 y la dirección IP del servidor virtual «jump».

Aplicar una política multired y volver a realizar las pruebas

Aplica una política multired que permita únicamente el acceso a TCP en el puerto 8080 para la red vlan20-prod. Guarda el siguiente manifiesto en un archivo llamado « my-policy.yml ». A continuación, ejecuta « oc apply -f my-policy.yml » para aplicarlo.

---
apiVersion: k8s.ovn.org/v1alpha1
kind: MultiNetworkPolicy
metadata:
  name: allow-8080-tcp
  namespace: green
  annotations:
    k8s.v1.cni.cncf.io/policy-for: vlan20-prod
spec:
  podSelector: {}
  ingress:
    - ports:
        - protocol: TCP
          port: 8080
  egress:
    - ports:
        - protocol: TCP
          port: 8080
  policyTypes:
    - Ingress
    - Egress

Vuelve a ejecutar las pruebas en plant-web00 en vlan20-prod. TCP El puerto 8080 sigue funcionando, pero el resto del tráfico, como ping y la prueba de iperf3 en el puerto 9090, ya no funciona en esa conexión de red.

Ejecuta el comando « oc delete -f my-policy.yml » para eliminar la política y restablecer la conectividad. Las pruebas vuelven a salir bien.