Chapter 10. Creating the data plane for SR-IOV and DPDK environments


You can deploy Red Hat OpenStack Services on OpenShift (RHOSO) environments that take advantage of the performance and throughput advantages of SR-IOV and DPDK.

The Red Hat OpenStack Services on OpenShift (RHOSO) data plane consists of RHEL 9.4 or 9.6 nodes. Use the OpenStackDataPlaneNodeSet custom resource definition (CRD) to create the custom resources (CRs) that define the nodes and the layout of the data plane. After you have defined your OpenStackDataPlaneNodeSet CRs, you create an OpenStackDataPlaneDeployment CR that deploys each of your OpenStackDataPlaneNodeSet CRs.

An OpenStackDataPlaneNodeSet CR is a logical grouping of nodes of a similar type. A data plane typically consists of multiple OpenStackDataPlaneNodeSet CRs to define groups of nodes with different configurations and roles. You can use pre-provisioned or unprovisioned nodes in an OpenStackDataPlaneNodeSet CR:

  • Pre-provisioned node: You have used your own tools to install the operating system on the node before adding it to the data plane.
  • Unprovisioned node: The node does not have an operating system installed before you add it to the data plane. The node is provisioned by using the Cluster Baremetal Operator (CBO) as part of the data plane creation and deployment process.
Note

You cannot include both pre-provisioned and unprovisioned nodes in the same OpenStackDataPlaneNodeSet CR.

To create and deploy a data plane, you must perform the following tasks:

  1. Create a Secret CR for each node set for Ansible to use to run commands on the data plane nodes.
  2. Create the OpenStackDataPlaneNodeSet CRs that define the nodes and layout of the data plane.
  3. Create the OpenStackDataPlaneDeployment CR that triggers the Ansible execution that deploys and configures the software for the specified list of OpenStackDataPlaneNodeSet CRs.

The following procedures create two simple node sets, one with pre-provisioned nodes, and one with bare-metal nodes that must be provisioned during the node set deployment. The procedures aim to get you up and running quickly with a data plane environment that you can use to troubleshoot issues and test the environment before adding all the customizations you require. You can add additional node sets to a deployed environment, and you can customize your deployed environment by updating the common configuration in the default ConfigMap CR for the service, and by creating custom services.

10.1. Prerequisites

  • A functional control plane, created with the OpenStack Operator.
  • You are logged on to a workstation that has access to the Red Hat OpenShift Container Platform (RHOCP) cluster as a user with cluster-admin privileges.

10.2. Creating the data plane secrets

Create the Secret custom resources (CRs) that the data plane requires to operate. The Secret CRs secure access between nodes, register the operating systems with the Red Hat Customer Portal, enable node repositories, and provide Compute nodes with access to libvirt.

To enable secure access between nodes, you must generate two SSH keys and create an SSH key Secret CR for each key:

  • An SSH key to enable Ansible to manage the RHEL nodes on the data plane. Ansible executes commands with this user and key. You can create an SSH key for each OpenStackDataPlaneNodeSet CR in your data plane.

    • An SSH key to enable migration of instances between Compute nodes.

Prerequisites

  • Pre-provisioned nodes are configured with an SSH public key in the $HOME/.ssh/authorized_keys file for a user with passwordless sudo privileges. For more information, see Managing sudo access in the RHEL Configuring basic system settings guide.

Procedure

  1. For unprovisioned nodes, create the SSH key pair for Ansible:

    $ ssh-keygen -f <key_file_name> -N "" -t rsa -b 4096
    • Replace <key_file_name> with the name to use for the key pair.
  2. Create the Secret CR for Ansible and apply it to the cluster:

    $ oc create secret generic dataplane-ansible-ssh-private-key-secret \
    --save-config \
    --dry-run=client \
    --from-file=ssh-privatekey=<key_file_name> \
    --from-file=ssh-publickey=<key_file_name>.pub \
    [--from-file=authorized_keys=<key_file_name>.pub] -n openstack \
    -o yaml | oc apply -f -
    • Replace <key_file_name> with the name and location of your SSH key pair file.
    • Optional: Only include the --from-file=authorized_keys option for bare-metal nodes that must be provisioned when creating the data plane.
  3. If you are creating Compute nodes, create a secret for migration.

    1. Create the SSH key pair for instance migration:

      $ ssh-keygen -f ./nova-migration-ssh-key -t ecdsa-sha2-nistp521 -N ''
    2. Create the Secret CR for migration and apply it to the cluster:

      $ oc create secret generic nova-migration-ssh-key \
      --save-config \
      --from-file=ssh-privatekey=nova-migration-ssh-key \
      --from-file=ssh-publickey=nova-migration-ssh-key.pub \
      -n openstack \
      -o yaml | oc apply -f -
  4. For nodes that have not been registered to the Red Hat Customer Portal, create the Secret CR for subscription-manager credentials to register the nodes:

    $ oc create secret generic subscription-manager \
    --from-literal rhc_auth='{"login": {"username": "<subscription_manager_username>", "password": "<subscription_manager_password>"}}'
    • Replace <subscription_manager_username> with the username you set for subscription-manager.
    • Replace <subscription_manager_password> with the password you set for subscription-manager.
  5. Create a Secret CR that contains the Red Hat registry credentials:

    $ oc create secret generic redhat-registry --from-literal edpm_container_registry_logins='{"registry.redhat.io": {"<username>": "<password>"}}'
    • Replace <username> and <password> with your Red Hat registry username and password credentials.

      For information about how to create your registry service account, see the Knowledge Base article Creating Registry Service Accounts.

  6. If you are creating Compute nodes, create a secret for libvirt.

    1. Create a file on your workstation named secret_libvirt.yaml to define the libvirt secret:

      apiVersion: v1
      kind: Secret
      metadata:
       name: libvirt-secret
       namespace: openstack
      type: Opaque
      data:
       LibvirtPassword: <base64_password>
      • Replace <base64_password> with a base64-encoded string with maximum length 63 characters. You can use the following command to generate a base64-encoded password:

        $ echo -n <password> | base64
        Tip

        If you do not want to base64-encode the username and password, you can use the stringData field instead of the data field to set the username and password.

    2. Create the Secret CR:

      $ oc apply -f secret_libvirt.yaml -n openstack
  7. Verify that the Secret CRs are created:

    $ oc describe secret dataplane-ansible-ssh-private-key-secret
    $ oc describe secret nova-migration-ssh-key
    $ oc describe secret subscription-manager
    $ oc describe secret redhat-registry
    $ oc describe secret libvirt-secret

10.3. Creating a custom SR-IOV Compute service

You must create a custom SR-IOV Compute service for NFV in a RHOSO environment.

This SR-IOV Compute service is an Ansible service that runs on the data plane. This custom service performs the following tasks on the SR-IOV Compute nodes:

  • Applies CPU pinning parameters.
  • Performs PCI passthrough.

To create the SR-IOV custom service, you must perform these actions:

  • Create a ConfigMap for CPU pinning that maps a CPU pinning configuration to a specified set of SR-IOV Compute nodes.
  • Create a ConfigMap for PCI passthrough that maps a PCI passthrough configuration to a specified set of SR-IOV Compute nodes.
  • Create the actual SR-IOV custom service that will implement the configMaps on your data plane.

Prerequisites

  • You have the oc command line tool installed on your workstation.
  • You are logged on to a workstation that has access to the RHOSO control plane as a user with cluster-admin privileges.

Procedure

  1. Create a ConfigMap CR that defines configurations for CPU pinning and PCI passthrough, and save it to a YAML file on your workstation, for example, pinning-passthrough.yaml.

    Change the values (in boldface) as appropriate for your environment:

    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cpu-pinning-nova
    data:
      25-cpu-pinning-nova.conf: |
        [DEFAULT]
        reserved_host_memory_mb = 4096
        [compute]
        cpu_shared_set = 0-3,24-27
        cpu_dedicated_set = 8-23,32-47
        [neutron]
        physnets = <network_name1>, <network_name2>
        [neutron_physnet_<network_name1>]
        numa_nodes = <ID list>
        [neutron_physnet_<network_name2>]
        numa_nodes = <ID list>
        [neutron_tunnel]
        numa_nodes = <ID list>
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: sriov-nova
    data:
      26-sriov-nova.conf: |
        [libvirt]
        cpu_power_management=false
        [pci]
        passthrough_whitelist = {"address": "0000:05:00.2", "physical_network":"sriov-1", "trusted":"true"}
        passthrough_whitelist = {"address": "0000:05:00.3", "physical_network":"sriov-2", "trusted":"true"}
    ---
    • cpu_shared_set: enter a comma-separated list or range of physical host CPU numbers used to provide vCPU inventory, determine the host CPUs that unpinned instances can be scheduled to, and determine the host CPUs that instance emulator threads should be offloaded to for instances configured with the share emulator thread policy.
    • cpu_dedicated_set: enter a comma-separated list or range of physical host CPU numbers to which processes for pinned instance CPUs can be scheduled. For example, 4-12,^8,15 reserves cores from 4-12 and 15, excluding 8.
    • <network_name_n_>: replace <network_name1> and <network_name2> with the names of the physical networks that your gateways are on. (This network is set in the neutron network provider:*name field.)
    • numa_nodes = <ID list>: replace <ID list> with a comma-separated list of IDs of the NUMA nodes associated with this physnet. For example: 0,1. For example:

      [neutron]
      physnets = foo,bar
      
      [neutron_physnet_foo]
      numa_nodes = 0
      
      [neutron_physnet_bar]
      numa_nodes = 2, 3

      This configuration ensures that instances using one or more L2-type networks with provider:physical_network=foo must be scheduled on host cores from NUMA node 0, while instances using one or more networks with provider:physical_network=bar must be scheduled on host cores from both NUMA nodes 2 and 3. For the latter case, it will be necessary to split the guest across two or more host NUMA nodes using the hw:numa_nodes extra spec.

    • passthrough_whitelist: specify valid NIC addresses and names for "address" and "physical_network".
  2. Create the ConfigMap object, using the ConfigMap CR file:

    Example
    $ oc create -f sriov-pinning-passthru.yaml -n openstack
  3. Create an OpenStackDataPlaneService CR that defines the SR-IOV custom service, and save it to a YAML file on your workstation, for example nova-custom-sriov.yaml:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneService
    metadata:
      name: nova-custom-sriov
  4. Add the ConfigMap CRs to the custom service, and specify the Secret CR for the cell that the node set that runs this service connects to:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneService
    metadata:
      name: nova-custom-sriov
    spec:
      label: dataplane-deployment-nova-custom-sriov
      dataSources:
        - configMapRef:
            name: cpu-pinning-nova
        - configMapRef:
            name: sriov-nova
        - secretRef:
            name: nova-cell1-compute-config
        - secretRef:
            name: nova-migration-ssh-key
      tlsCerts:
        default:
          contents:
            - dnsnames
            - ips
          networks:
            - ctlplane
          issuer: osp-rootca-issuer-internal
      caCerts: combined-ca-bundle
  5. Specify the Ansible commands to create the custom service, by referencing an Ansible Playbook or by including the Ansible play in the playbookContents field:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneService
    metadata:
      name: nova-custom-sriov
    spec:
      label: dataplane-deployment-nova-custom-sriov
      edpmServiceType: nova
      dataSources:
        - configMapRef:
            name: cpu-pinning-nova
        - configMapRef:
            name: sriov-nova
        - secretRef:
            name: nova-cell1-compute-config
        - secretRef:
            name: nova-migration-ssh-key
      playbook: osp.edpm.nova
      tlsCerts:
        default:
          contents:
            - dnsnames
            - ips
          networks:
            - ctlplane
          issuer: osp-rootca-issuer-internal
      caCerts: combined-ca-bundle
  6. Create the custom-nova-sriov service:

    $ oc apply -f nova-custom-sriov.yaml -n openstack
  7. Verify that the custom service is created:

    $ oc get openstackdataplaneservice nova-custom-sriov -o yaml -n openstack

10.4. Create a custom OVS-DPDK Compute service

You must create a custom OVS-DPDK Compute service for NFV in a RHOSO environment.

The OVS-DPDK Compute service is an Ansible service that is run on the data plane. This custom service applies various parameters on the OVS-DPDK Compute nodes, including CPU pinning parameters, a block migration parameter, and a NUMA-aware vswitch feature that allows instances to create in the NUMA node that is connected to the NIC used by the OVS bridge.

To create the OVS-DPDK custom service, you must perform these actions:

  • Create a ConfigMap that maps the configurations to a specified set of OVS-DPDK Compute nodes.
  • Create the actual OVS-DPDK custom service that will implement the ConfigMap on your data plane.

Prerequisites

  • You have the oc command line tool installed on your workstation.
  • You are logged on to a workstation that has access to the RHOSO control plane as a user with cluster-admin privileges.

Procedure

  1. Create a ConfigMap CR that defines a configuration for the parameters, and save it to a YAML file on your workstation, for example, dpdk-custom.yaml.

    Change the values (in boldface) as appropriate for your environment:

    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: dpdk-custom-nova
      namespace: openstack
    data:
      25-dpdk-custom-nova.conf: |
        [DEFAULT]
        reserved_host_memory_mb = 4096
        [compute]
        cpu_shared_set = 0-3,24-27
        cpu_dedicated_set = 8-23,32-47
        [neutron]
        physnets = <network_name1>, <network_name2>
        [neutron_physnet_<network_name1>]
        numa_nodes = <ID list>
        [neutron_physnet_<network_name2>]
        numa_nodes = <ID list>
        [neutron_tunnel]
        numa_nodes = <ID list>
        [libvirt]
        live_migration_permit_post_copy=false
    ---
    • cpu_shared_set: enter a comma-separated list or range of physical host CPU numbers used to provide vCPU inventory, determine the host CPUs that unpinned instances can be scheduled to, and determine the host CPUs that instance emulator threads should be offloaded to for instances configured with the share emulator thread policy.
    • cpu_dedicated_set: enter a comma-separated list or range of physical host CPU numbers to which processes for pinned instance CPUs can be scheduled. For example, 4-12,^8,15 reserves cores from 4-12 and 15, excluding 8.
    • <network_name_n_>: replace <network_name1> and <network_name2> with the names of the physical networks that your gateways are on, for which you need to configure NUMA affinity. (This network is set in the neutron network provider:*name field.)
    • <ID list>: replace <ID list> with a comma-separated list of IDs of the NUMA nodes associated with this physnet. For example: 0,1. For example:

      [neutron]
      physnets = foo,bar
      
      [neutron_physnet_foo]
      numa_nodes = 0
      
      [neutron_physnet_bar]
      numa_nodes = 2, 3

      This configuration ensures that instances using one or more L2-type networks with provider:physical_network=foo` must be scheduled on host cores from NUMA node 0, while instances using one or more networks with provider:physical_network=bar` must be scheduled on host cores from both NUMA nodes 2 and 3. For the latter case, it will be necessary to split the guest across two or more host NUMA nodes using the hw:numa_nodes extra` spec.

    • live_migration_permit_post_copy=false: necessary for successful block live migration of instances attached to a Geneve network with DPDK.
  2. Create the ConfigMap object, using the ConfigMap CR file:

    Example
    $ oc create -f dpdk-custom.yaml -n openstack
  3. Create an OpenStackDataPlaneService CR that defines the OVS-DPDK custom service, and save it to a YAML file on your workstation, for example nova-custom-ovsdpdk.yaml:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneService
    metadata:
      name: nova-custom-ovsdpdk
      namespace: openstack
  4. Add the ConfigMap CR to the custom service, and specify the Secret CR for the cell that the node set that runs this service connects to:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneService
    metadata:
      name: nova-custom-ovsdpdk
      namespace: openstack
    spec:
      label: dataplane-deployment-nova-custom-ovsdpdk
      edpmServiceType: nova
      dataSources:
        - configMapRef:
            name: dpdk-custom-nova
        - secretRef:
            name: nova-cell1-compute-config
        - secretRef:
            name: nova-migration-ssh-key
      tlsCerts:
        default:
          contents:
            - dnsnames
            - ips
          networks:
            - ctlplane
          issuer: osp-rootca-issuer-internal
      caCerts: combined-ca-bundle
  5. Specify the Ansible commands to create the custom service, by referencing an Ansible Playbook or by including the Ansible play in the playbookContents field:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneService
    metadata:
      name: nova-custom-ovsdpdk
      namespace: openstack
    spec:
      label: dataplane-deployment-nova-custom-ovsdpdk
      edpmServiceType: nova
      dataSources:
        - configMapRef:
            name: dpdk-custom-nova
        - secretRef:
            name: nova-cell1-compute-config
        - secretRef:
            name: nova-migration-ssh-key
      playbook: osp.edpm.nova
      tlsCerts:
        default:
          contents:
            - dnsnames
            - ips
          networks:
            - ctlplane
          issuer: osp-rootca-issuer-internal
      caCerts: combined-ca-bundle
  6. Create the nova-custom-ovsdpdk service:

    $ oc apply -f nova-custom-ovsdpdk.yaml -n openstack
  7. Verify that the custom service is created:

    $ oc get openstackdataplaneservice nova-custom-ovsdpdk -o yaml -n openstack

Define an OpenStackDataPlaneNodeSet custom resource (CR) for each logical grouping of pre-provisioned nodes in your data plane, for example, nodes grouped by hardware, location, or networking.

You can define as many node sets as necessary for your deployment. Each node can be included in only one OpenStackDataPlaneNodeSet CR. Each node set can be connected to only one Compute cell. By default, node sets are connected to cell1. If you customize your control plane to include additional Compute cells, you must specify the cell to which the node set is connected. For more information on adding Compute cells, see Connecting an OpenStackDataPlaneNodeSet CR to a Compute cell in the Customizing the Red Hat OpenStack Services on OpenShift deployment guide.

You use the nodeTemplate field to configure the properties that all nodes in an OpenStackDataPlaneNodeSet CR share, and the nodeTemplate.nodes field for node-specific properties. Node-specific configurations override the inherited values from the nodeTemplate.

Procedure

  1. Create a file on your workstation named openstack_preprovisioned_node_set.yaml to define the OpenStackDataPlaneNodeSet CR:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneNodeSet
    metadata:
      name: openstack-data-plane
      namespace: openstack
    spec:
      env:
        - name: ANSIBLE_FORCE_COLOR
          value: "True"
    • name - The OpenStackDataPlaneNodeSet CR name must be unique, contain only lower case alphanumeric characters and - (hyphens) or . (periods), start and end with an alphanumeric character, and have a maximum length of 53 characters. Update the name in this example to a name that reflects the nodes in the set.
    • env - Optional: a list of environment variables to pass to the pod.
  2. Specify that the nodes in this set are pre-provisioned:

      preProvisioned: true
  3. Add the SSH key secret that you created to enable Ansible to connect to the data plane nodes:

      nodeTemplate:
        ansibleSSHPrivateKeySecret: <secret-key>
    • Replace <secret-key> with the name of the SSH key Secret CR you created for this node set in Creating the data plane secrets, for example, dataplane-ansible-ssh-private-key-secret.
  4. Create a Persistent Volume Claim (PVC) in the openstack namespace on your Red Hat OpenShift Container Platform (RHOCP) cluster to store logs. Set the volumeMode to Filesystem and accessModes to ReadWriteOnce. Do not request storage for logs from a PersistentVolume (PV) that uses the NFS volume plugin. NFS is incompatible with FIFO and the ansible-runner creates a FIFO file to write to store logs. For information about PVCs, see Understanding persistent storage in the RHOCP Storage guide and Red Hat OpenShift Container Platform cluster requirements in Planning your deployment.
  5. Enable persistent logging for the data plane nodes:

      nodeTemplate:
        ansibleSSHPrivateKeySecret: <secret-key>
        extraMounts:
          - extraVolType: Logs
            volumes:
            - name: ansible-logs
              persistentVolumeClaim:
                claimName: <pvc_name>
            mounts:
            - name: ansible-logs
              mountPath: "/runner/artifacts"
    • Replace <pvc_name> with the name of the PVC storage on your RHOCP cluster.
  6. Add the common configuration for the set of nodes in this group under the nodeTemplate section. Each node in this OpenStackDataPlaneNodeSet inherits this configuration. For information about the properties you can use to configure common node attributes, see OpenStackDataPlaneNodeSet CR spec properties.
  7. Register the operating system of the nodes that are not registered to the Red Hat Customer Portal, and enable repositories for your nodes. The following steps demonstrate how to register your nodes to CDN. For details on how to register your nodes with Red Hat Satellite 6.13, see Managing Hosts.

    1. Create a Secret CR that contains the subscription-manager credentials:

      apiVersion: v1
      kind: Secret
      metadata:
        name: subscription-manager
      data:
        username: <base64_encoded_username>
        password: <base64_encoded_password>
    2. Create a Secret CR that contains the Red Hat registry credentials:

      $ oc create secret generic redhat-registry --from-literal edpm_container_registry_logins='{"registry.redhat.io": {"<username>": "<password>"}}'
      • Replace <username> and <password> with your Red Hat registry username and password credentials.

    For information about how to create your registry service account, see the Red Hat Knowledgebase article Creating Registry Service Accounts.

    1. Specify the Secret CRs to use to source the usernames and passwords:

        nodeTemplate:
          ansible:
            ...
            ansibleVarsFrom:
              - prefix: subscription_manager_
                secretRef:
                  name: subscription-manager
              - secretRef:
                  name: redhat-registry
            ansibleVars:
             rhc_release: 9.4
             rhc_repositories:
               - {name: "*", state: disabled}
               - {name: "<repository_name1>", state: enabled}
               - {name: "<repository_name2>", state: enabled}
               - {name: "<repository_name3>", state: enabled}
               - {name: "<repository_name4>", state: enabled}
               - {name: "<repository_name5>", state: enabled}
               - {name: "<repository_name6>", state: enabled}

      where:

      <repository_name1>, <repository_name2>, <repository_name3>, <repository_name4>, <repository_name5>, <repository_name6>
      Specifies the name of the repository to enable. For more information about which repositories are required, see Required repositories for Red Hat OpenStack Services on OpenShift 18.0.
  8. Define each node in this node set:

      nodes:
        edpm-compute-0:
          hostName: edpm-compute-0
          networks:
            - name: ctlplane
              subnetName: subnet1
              defaultRoute: true
              fixedIP: 192.168.122.100
            - name: internalapi
              subnetName: subnet1
              fixedIP: 172.17.0.100
            - name: storage
              subnetName: subnet1
              fixedIP: 172.18.0.100
            - name: tenant
              subnetName: subnet1
              fixedIP: 172.19.0.100
          ansible:
            ansibleHost: 192.168.122.100
            ansibleUser: cloud-admin
            ansibleVars:
              fqdn_internal_api: edpm-compute-0.example.com
              edpm_network_config_nmstate: true
        edpm-compute-1:
          hostName: edpm-compute-1
          networks:
            - name: ctlplane
              subnetName: subnet1
              defaultRoute: true
              fixedIP: 192.168.122.101
            - name: internalapi
              subnetName: subnet1
              fixedIP: 172.17.0.101
            - name: storage
              subnetName: subnet1
              fixedIP: 172.18.0.101
            - name: tenant
              subnetName: subnet1
              fixedIP: 172.19.0.101
          ansible:
            ansibleHost: 192.168.122.101
            ansibleUser: cloud-admin
            ansibleVars:
              fqdn_internal_api: edpm-compute-1.example.com
    • edpm-compute-0 - The node definition reference, for example, edpm-compute-0. Each node in the node set must have a node definition.
    • networks - Defines the IPAM and the DNS records for the node.
    • fixedIP - Specifies a predictable IP address for the network that must be in the allocation range defined for the network in the NetConfig CR.
    • ansibleVars - Node-specific Ansible variables that customize the node.

      Note
      • Nodes defined within the nodes section can configure the same Ansible variables that are configured in the nodeTemplate section. Where an Ansible variable is configured for both a specific node and within the nodeTemplate section, the node-specific values override those from the nodeTemplate section.
      • You do not need to replicate all the nodeTemplate Ansible variables for a node to override the default and set some node-specific values. You only need to configure the Ansible variables you want to override for the node.
      • When you define the networkData Secret for an individual node (such as edpm-compute-0), it acts as a complete override rather than a supplemental configuration. Because node-specific configurations override the inherited default values from the nodeTemplate section, you must ensure that your node-specific networkData Secret contains the full set of required network configurations for that node, not just the unique values.
      • Many ansibleVars include edpm in the name, which stands for "External Data Plane Management".
    • edpm_network_config_nmstate - Sets the os-net-config provider to nmstate. The default value is true. Change it to false only if a specific limitation of the nmstate provider requires you to use the ifcfg provider. For more information on advantages and limitations of the nmstate provider, see https://docs.redhat.com/en/documentation/red_hat_openstack_services_on_openshift/18.0/html/planning_your_deployment/plan-networks_planning#plan-os-net-config_plan-network in Planning your deployment.

      For more information, see:

    • OpenStackDataPlaneNodeSet CR properties
    • Network interface configuration options
    • Example custom network interfaces for NFV
  9. In the services section, add the list of services that will run on the data plane node. Ensure that you replace nova with nova-custom-sriov, or nova-custom-ovsdpdk, or both:

    ...
      services:
      - bootstrap
      - download-cache
      - reboot-os
      - configure-ovs-dpdk
      - configure-network
      - validate-network
      - install-os
      - configure-os
      - ssh-known-hosts
      - run-os
      - install-certs
      - ovn
      - neutron-ovn
      - neutron-ovn-igmp
      - neutron-metadata
      - libvirt
      - nova-custom-sriov
      - nova-custom-ovsdpdk
      - telemetry
    ...
  10. Save the openstack_preprovisioned_node_set.yaml definition file.
  11. Create the data plane resources:

    $ oc create -f openstack_preprovisioned_node_set.yaml -n openstack
  12. Verify that the data plane resources have been created:

    $ oc get openstackdataplanenodeset -n openstack
    Sample output
    NAME           		STATUS MESSAGE
    openstack-data-plane 	False  Deployment not started

    For information about the meaning of the returned status, see Data plane conditions and states.

  13. Verify that the Secret resource was created for the node set:

    $ oc get secret | grep openstack-data-plane

    Sample output

    dataplanenodeset-openstack-data-plane Opaque 1 3m50s
  14. Verify the services were created:

    $ oc get openstackdataplaneservice -n openstack

    Sample output

    NAME                AGE
    configure-network   6d7h
    configure-os        6d6h
    install-os          6d6h
    run-os              6d6h
    validate-network    6d6h
    ovn                 6d6h
    libvirt             6d6h
    nova                6d6h
    telemetry           6d6h

Review examples to learn how to create a node set from pre-provisioned Compute nodes.

The following example OpenStackDataPlaneNodeSet CR creates a node set from pre-provisioned Compute nodes with some node-specific configuration. The example includes optional fields. Review the example and update the optional fields to the correct values for your environment or remove them before using the example in your Red Hat OpenStack Services on OpenShift (RHOSO) deployment.

Note

The example that follows for an OpenStackDataPlaneNodeSet CR assumes that the node contains a single NIC.

Update the name of the OpenStackDataPlaneNodeSet CR in this example to a name that reflects the nodes in the set. The OpenStackDataPlaneNodeSet CR name must be unique, contain only lower case alphanumeric characters and - (hyphens) or . (periods), start and end with an alphanumeric character, and have a maximum length of 53 characters.

Note

The following variables are autogenerated from IPAM and DNS and are not provided by the user:

  • ctlplane_dns_nameservers
  • dns_search_domains
  • ctlplane_host_routes
apiVersion: dataplane.openstack.org/v1beta1
kind: OpenStackDataPlaneNodeSet
metadata:
  name: openstack-data-plane
  namespace: openstack
spec:
  env:
    - name: ANSIBLE_FORCE_COLOR
      value: "True"
  networkAttachments:
    - ctlplane
  preProvisioned: true
  nodeTemplate:
    ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret
    extraMounts:
      - extraVolType: Logs
        volumes:
        - name: ansible-logs
          persistentVolumeClaim:
            claimName: <pvc_name>
        mounts:
        - name: ansible-logs
          mountPath: "/runner/artifacts"
    managementNetwork: ctlplane
    ansible:
      ansibleUser: cloud-admin
      ansiblePort: 22
      ansibleVarsFrom:
        - secretRef:
            name: subscription-manager
        - secretRef:
            name: redhat-registry
      ansibleVars:
        timesync_ntp_servers:
          - hostname: ntp.example.com
            iburst: true
          - hostname: ntp2.example.com
            iburst: false
        rhc_release: 9.4
        rhc_repositories:
            - {name: "*", state: disabled}
            - {name: "<repository_name1>", state: enabled}
            - {name: "<repository_name2>", state: enabled}
            - {name: "<repository_name3>", state: enabled}
            - {name: "<repository_name4>", state: enabled}
            - {name: "<repository_name5>", state: enabled}
            - {name: "<repository_name6>", state: enabled}
        edpm_bootstrap_release_version_package: []
        edpm_network_config_os_net_config_mappings:
          edpm-compute-0:
            nic1: 52:54:04:60:55:22
        neutron_physical_bridge_name: br-ex
        neutron_public_interface_name: eth0
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          - type: ovs_bridge
            name: {{ neutron_physical_bridge_name }}
            mtu: {{ min_viable_mtu }}
            use_dhcp: false
            dns_servers: {{ ctlplane_dns_nameservers }}
            domain: {{ dns_search_domains }}
            addresses:
            - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }}
            routes: {{ ctlplane_host_routes }}
            members:
            - type: interface
              name: nic1
              mtu: {{ min_viable_mtu }}
              # force the MAC address of the bridge to this interface
              primary: true
          {% for network in nodeset_networks %}
            - type: vlan
              mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }}
              vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }}
              addresses:
              - ip_netmask:
                  {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }}
              routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }}
          {% endfor %}
  nodes:
    edpm-compute-0:
      hostName: edpm-compute-0
      networks:
      - name: ctlplane
        subnetName: subnet1
        defaultRoute: true
        fixedIP: 192.168.122.100
      - name: internalapi
        subnetName: subnet1
        fixedIP: 172.17.0.100
      - name: storage
        subnetName: subnet1
        fixedIP: 172.18.0.100
      - name: tenant
        subnetName: subnet1
        fixedIP: 172.19.0.100
      ansible:
        ansibleHost: 192.168.122.100
        ansibleUser: cloud-admin
        ansibleVars:
          fqdn_internal_api: edpm-compute-0.example.com
    edpm-compute-1:
      hostName: edpm-compute-1
      networks:
      - name: ctlplane
        subnetName: subnet1
        defaultRoute: true
        fixedIP: 192.168.122.101
      - name: internalapi
        subnetName: subnet1
        fixedIP: 172.17.0.101
      - name: storage
        subnetName: subnet1
        fixedIP: 172.18.0.101
      - name: tenant
        subnetName: subnet1
        fixedIP: 172.19.0.101
      ansible:
        ansibleHost: 192.168.122.101
        ansibleUser: cloud-admin
        ansibleVars:
          fqdn_internal_api: edpm-compute-1.example.com
  services:
  - bootstrap
  - download-cache
  - reboot-os
  - configure-ovs-dpdk
  - configure-network
  - validate-network
  - install-os
  - configure-os
  - ssh-known-hosts
  - run-os
  - install-certs
  - ovn
  - neutron-ovn
  - neutron-ovn-igmp
  - neutron-metadata
  - libvirt
  - nova-custom-sriov
  - nova-custom-ovsdpdk
  - telemetry

where:

<repository_name1>, <repository_name2>, <repository_name3>, <repository_name4>, <repository_name5>, <repository_name6>
Specifies the name of the repository to enable. For more information about which repositories are required, see Required repositories for Red Hat OpenStack Services on OpenShift 18.0.

Define an OpenStackDataPlaneNodeSet custom resource (CR) for each logical grouping of unprovisioned nodes in your data plane, for example, nodes grouped by hardware, location, or networking.

You can define as many node sets as necessary for your deployment. Each node can be included in only one OpenStackDataPlaneNodeSet CR. Each node set can be connected to only one Compute cell. By default, node sets are connected to cell1. If you customize your control plane to include additional Compute cells, you must specify the cell to which the node set is connected. For more information on adding Compute cells, see Connecting an OpenStackDataPlaneNodeSet CR to a Compute cell in the Customizing the Red Hat OpenStack Services on OpenShift deployment guide.

You use the nodeTemplate field to configure the properties that all nodes in an OpenStackDataPlaneNodeSet CR share, and the nodeTemplate.nodes field for node-specific properties. Node-specific configurations override the inherited values from the nodeTemplate.

For more information about provisioning bare-metal nodes, see Planning provisioning for bare-metal data plane nodes in Planning your deployment.

Prerequisites

  • Cluster Baremetal Operator (CBO) is installed and configured for provisioning. For more information, see Planning provisioning for bare-metal data plane nodes in Planning your deployment.
  • A BareMetalHost CR is registered and inspected for each bare-metal data plane node. Each bare-metal node must be in the Available state after inspection.

Procedure

  1. Create a file on your workstation named openstack_unprovisioned_node_set.yaml to define the OpenStackDataPlaneNodeSet CR:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneNodeSet
    metadata:
      name: openstack-data-plane
      namespace: openstack
    spec:
      tlsEnabled: true
      env:
        - name: ANSIBLE_FORCE_COLOR
          value: "True"
    • name - The OpenStackDataPlaneNodeSet CR name must be unique, contain only lower case alphanumeric characters and - (hyphens) or . (periods), start and end with an alphanumeric character, and have a maximum length of 53 characters. Update the name in this example to a name that reflects the nodes in the set.
    • env - Optional: a list of environment variables to pass to the pod.
  2. Define the baremetalSetTemplate field to describe the configuration of the bare-metal nodes:

      preProvisioned: false
      baremetalSetTemplate:
        deploymentSSHSecret: dataplane-ansible-ssh-private-key-secret
        bmhNamespace: <bmh_namespace>
        cloudUserName: <ansible_ssh_user>
        bmhLabelSelector:
          app: <bmh_label>
        ctlplaneInterface: <interface>
    • Replace <bmh_namespace> with the namespace defined in the corresponding BareMetalHost CR for the node.
    • Replace <ansible_ssh_user> with the username of the Ansible SSH user.
    • Replace <bmh_label> with the metadata label defined in the corresponding BareMetalHost CR for the node, for example, openstack. Metadata labels, such as app, workload, and nodeName are key-value pairs for labelling nodes. Set the bmhLabelSelector field to select data plane nodes based on one or more labels that match the labels in the corresponding BareMetalHost CR.
    • Replace <interface> with the control plane interface the node connects to, for example, enp6s0.
  3. The BMO manages BareMetalHost CRs in the openshift-machine-api namespace by default. You must update the Provisioning CR to watch all namespaces:

    $ oc patch provisioning provisioning-configuration --type merge -p '{"spec":{"watchAllNamespaces": true }}'
  4. Add the SSH key secret that you created to enable Ansible to connect to the data plane nodes:

      nodeTemplate:
        ansibleSSHPrivateKeySecret: <secret-key>
    • Replace <secret-key> with the name of the SSH key Secret CR you created in Creating the data plane secrets, for example, dataplane-ansible-ssh-private-key-secret.
  5. Create a Persistent Volume Claim (PVC) in the openstack namespace on your RHOCP cluster to store logs. Set the volumeMode to Filesystem and accessModes to ReadWriteOnce. Do not request storage for logs from a PersistentVolume (PV) that uses the NFS volume plugin. NFS is incompatible with FIFO and the ansible-runner creates a FIFO file to write to store logs. For information about PVCs, see Understanding persistent storage in the RHOCP Storage guide and Red Hat OpenShift Container Platform cluster requirements in Planning your deployment.
  6. Enable persistent logging for the data plane nodes:

      nodeTemplate:
        ansibleSSHPrivateKeySecret: <secret-key>
        extraMounts:
          - extraVolType: Logs
            volumes:
            - name: ansible-logs
              persistentVolumeClaim:
                claimName: <pvc_name>
            mounts:
            - name: ansible-logs
              mountPath: "/runner/artifacts"
    • Replace <pvc_name> with the name of the PVC storage on your RHOCP cluster.
  7. Add the common configuration for the set of nodes in this group under the nodeTemplate section. Each node in this OpenStackDataPlaneNodeSet inherits this configuration.

    For more information, see:

  8. Define each node in this node set:

      nodes:
        edpm-compute-0:
          hostName: edpm-compute-0
          networks:
            - name: ctlplane
              subnetName: subnet1
              defaultRoute: true
              fixedIP: 192.168.122.100
            - name: internalapi
              subnetName: subnet1
            - name: storage
              subnetName: subnet1
            - name: tenant
              subnetName: subnet1
          ansible:
            ansibleHost: 192.168.122.100
            ansibleUser: cloud-admin
            ansibleVars:
              fqdn_internal_api: edpm-compute-0.example.com
              edpm_network_config_nmstate: true
        edpm-compute-1:
          hostName: edpm-compute-1
          networks:
            - name: ctlplane
              subnetName: subnet1
              defaultRoute: true
              fixedIP: 192.168.122.101
            - name: internalapi
              subnetName: subnet1
            - name: storage
              subnetName: subnet1
            - name: tenant
              subnetName: subnet1
          ansible:
            ansibleHost: 192.168.122.101
            ansibleUser: cloud-admin
            ansibleVars:
              fqdn_internal_api: edpm-compute-1.example.com
    • edpm-compute-0 - The node definition reference, for example, edpm-compute-0. Each node in the node set must have a node definition.
    • networks - Defines the IPAM and the DNS records for the node.
    • fixedIP - Specifies a predictable IP address for the network that must be in the allocation range defined for the network in the NetConfig CR.
    • ansibleVars - Node-specific Ansible variables that customize the node.

      Note
      • Nodes defined within the nodes section can configure the same Ansible variables that are configured in the nodeTemplate section. Where an Ansible variable is configured for both a specific node and within the nodeTemplate section, the node-specific values override those from the nodeTemplate section.
      • You do not need to replicate all the nodeTemplate Ansible variables for a node to override the default and set some node-specific values. You only need to configure the Ansible variables you want to override for the node.
      • When you define the networkData Secret for an individual node (such as edpm-compute-0), it acts as a complete override rather than a supplemental configuration. Because node-specific configurations override the inherited default values from the nodeTemplate section, you must ensure that your node-specific networkData Secret contains the full set of required network configurations for that node, not just the unique values.
      • Many ansibleVars include edpm in the name, which stands for "External Data Plane Management".
    • edpm_network_config_nmstate - Sets the os-net-config provider to nmstate. The default value is true. Change it to false only if a specific limitation of the nmstate provider requires you to use the ifcfg provider. For more information on advantages and limitations of the nmstate provider, see https://docs.redhat.com/en/documentation/red_hat_openstack_services_on_openshift/18.0/html/planning_your_deployment/plan-networks_planning#plan-os-net-config_plan-network in Planning your deployment.

      For information about the properties you can use to configure node attributes, see OpenStackDataPlaneNodeSet CR properties.

  9. In the services section, add the list of services that will run on the data plane node. Ensure that you replace nova with nova-custom-sriov, or nova-custom-ovsdpdk, or both:

    ...
      services:
      - bootstrap
      - download-cache
      - reboot-os
      - configure-ovs-dpdk
      - configure-network
      - validate-network
      - install-os
      - configure-os
      - ssh-known-hosts
      - run-os
      - install-certs
      - ovn
      - neutron-ovn
      - neutron-ovn-igmp
      - neutron-metadata
      - libvirt
      - nova-custom-sriov
      - nova-custom-ovsdpdk
      - telemetry
    ...
  10. Save the openstack_unprovisioned_node_set.yaml definition file.
  11. Create the data plane resources:

    $ oc create -f openstack_unprovisioned_node_set.yaml -n openstack
  12. Verify that the data plane resources have been created:

    $ oc get openstackdataplanenodeset -n openstack
    NAME           		STATUS MESSAGE
    openstack-data-plane 	False  Deployment not started

    For information on the meaning of the returned status, see Data plane conditions and states.

  13. Verify that the Secret resource was created for the node set:

    $ oc get secret -n openstack | grep openstack-data-plane
    dataplanenodeset-openstack-data-plane Opaque 1 3m50s
  14. Verify the services were created:

    $ oc get openstackdataplaneservice -n openstack
    NAME                AGE
    configure-network   6d7h
    configure-os        6d6h
    install-os          6d6h
    run-os              6d6h
    validate-network    6d6h
    ovn                 6d6h
    libvirt             6d6h
    nova                6d6h
    telemetry           6d6h

Review examples to learn how to create a node set from unprovisioned Compute nodes.

The following example OpenStackDataPlaneNodeSet CR creates a node set from unprovisioned Compute nodes with some node-specific configuration. The unprovisioned Compute nodes are provisioned when the node set is created. The example includes optional fields. Review the example and update the optional fields to the correct values for your environment or remove them before using the example in your Red Hat OpenStack Services on OpenShift (RHOSO) deployment.

Update the name of the OpenStackDataPlaneNodeSet CR in this example to a name that reflects the nodes in the set. The OpenStackDataPlaneNodeSet CR name must be unique, contain only lower case alphanumeric characters and - (hyphens) or . (periods), start and end with an alphanumeric character, and have a maximum length of 53 characters.

Note

The following variables are autogenerated from IPAM and DNS and are not provided by the user:

  • ctlplane_dns_nameservers
  • dns_search_domains
  • ctlplane_host_routes
apiVersion: dataplane.openstack.org/v1beta1
kind: OpenStackDataPlaneNodeSet
metadata:
  name: openstack-data-plane
  namespace: openstack
spec:
  env:
    - name: ANSIBLE_FORCE_COLOR
      value: "True"
  networkAttachments:
    - ctlplane
  preProvisioned: false
  baremetalSetTemplate:
    deploymentSSHSecret: dataplane-ansible-ssh-private-key-secret
    bmhNamespace: openstack
    cloudUserName: cloud-admin
    bmhLabelSelector:
      app: openstack
    ctlplaneInterface: enp1s0
  nodeTemplate:
    ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret
    extraMounts:
      - extraVolType: Logs
        volumes:
        - name: ansible-logs
          persistentVolumeClaim:
            claimName: <pvc_name>
        mounts:
        - name: ansible-logs
          mountPath: "/runner/artifacts"
    managementNetwork: ctlplane
    ansible:
      ansibleUser: cloud-admin
      ansiblePort: 22
      ansibleVarsFrom:
        - secretRef:
            name: subscription-manager
        - secretRef:
            name: redhat-registry
      ansibleVars:
        timesync_ntp_servers:
          - hostname: ntp.example.com
            iburst: true
          - hostname: ntp2.example.com
            iburst: false
        rhc_release: 9.4
        rhc_repositories:
            - {name: "*", state: disabled}
            - {name: "<repository_name1>", state: enabled}
            - {name: "<repository_name2>", state: enabled}
            - {name: "<repository_name3>", state: enabled}
            - {name: "<repository_name4>", state: enabled}
            - {name: "<repository_name5>", state: enabled}
            - {name: "<repository_name6>", state: enabled}
        edpm_bootstrap_release_version_package: []
        edpm_network_config_os_net_config_mappings:
          edpm-compute-0:
            nic1: 52:54:04:60:55:22
          edpm-compute-1:
            nic1: 52:54:04:60:55:22
        neutron_physical_bridge_name: br-ex
        neutron_public_interface_name: eth0
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          - type: ovs_bridge
            name: {{ neutron_physical_bridge_name }}
            mtu: {{ min_viable_mtu }}
            use_dhcp: false
            dns_servers: {{ ctlplane_dns_nameservers }}
            domain: {{ dns_search_domains }}
            addresses:
            - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }}
            routes: {{ ctlplane_host_routes }}
            members:
            - type: interface
              name: nic1
              mtu: {{ min_viable_mtu }}
              # force the MAC address of the bridge to this interface
              primary: true
          {% for network in nodeset_networks %}
            - type: vlan
              mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }}
              vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }}
              addresses:
              - ip_netmask:
                  {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }}
              routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }}
          {% endfor %}
  nodes:
    edpm-compute-0:
      hostName: edpm-compute-0
      networks:
      - name: ctlplane
        subnetName: subnet1
        defaultRoute: true
        fixedIP: 192.168.122.100
      - name: internalapi
        subnetName: subnet1
      - name: storage
        subnetName: subnet1
      - name: tenant
        subnetName: subnet1
      ansible:
        ansibleHost: 192.168.122.100
        ansibleUser: cloud-admin
        ansibleVars:
          fqdn_internal_api: edpm-compute-0.example.com
      bmhLabelSelector:
        nodeName: edpm-compute-0
    edpm-compute-1:
      hostName: edpm-compute-1
      networks:
      - name: ctlplane
        subnetName: subnet1
        defaultRoute: true
        fixedIP: 192.168.122.101
      - name: internalapi
        subnetName: subnet1
      - name: storage
        subnetName: subnet1
      - name: tenant
        subnetName: subnet1
      ansible:
        ansibleHost: 192.168.122.101
        ansibleUser: cloud-admin
        ansibleVars:
          fqdn_internal_api: edpm-compute-1.example.com
      bmhLabelSelector:
        nodeName: edpm-compute-1
  services:
  - bootstrap
  - download-cache
  - reboot-os
  - configure-ovs-dpdk
  - configure-network
  - validate-network
  - install-os
  - configure-os
  - ssh-known-hosts
  - run-os
  - install-certs
  - ovn
  - neutron-ovn
  - neutron-ovn-igmp
  - neutron-metadata
  - libvirt
  - nova-custom-sriov
  - nova-custom-ovsdpdk
  - telemetry

where:

<repository_name1>, <repository_name2>, <repository_name3>, <repository_name4>, <repository_name5>, <repository_name6>
Specifies the name of the repository to enable. For more information about which repositories are required, see Required repositories for Red Hat OpenStack Services on OpenShift 18.0.

10.7. OpenStackDataPlaneNodeSet CR spec properties

The following sections detail the OpenStackDataPlaneNodeSet CR spec properties you can configure.

10.7.1. nodeTemplate

Defines the common attributes for the nodes in this OpenStackDataPlaneNodeSet. You can override these common attributes in the definition for each individual node.

Expand
Table 10.1. nodeTemplate properties
FieldDescription

ansibleSSHPrivateKeySecret

Name of the private SSH key secret that contains the private SSH key for connecting to nodes.

Secret name format: Secret.data.ssh-privatekey

For more information, see Creating an SSH authentication secret.

Default: dataplane-ansible-ssh-private-key-secret

managementNetwork

Name of the network to use for management (SSH/Ansible). Default: ctlplane

networks

Network definitions for the OpenStackDataPlaneNodeSet.

ansible

Ansible configuration options. For more information, see ansible properties.

extraMounts

The files to mount into an Ansible Execution Pod.

userData

UserData configuration for the OpenStackDataPlaneNodeSet.

networkData

NetworkData configuration for the OpenStackDataPlaneNodeSet.

10.7.2. nodes

Defines the node names and node-specific attributes for the nodes in this OpenStackDataPlaneNodeSet. Overrides the common attributes defined in the nodeTemplate.

Expand
Table 10.2. nodes properties
FieldDescription

ansible

Ansible configuration options. For more information, see ansible properties.

extraMounts

The files to mount into an Ansible Execution Pod.

hostName

The node name.

managementNetwork

Name of the network to use for management (SSH/Ansible).

networkData

NetworkData configuration for the node.

networks

Instance networks.

userData

Node-specific user data.

10.7.3. ansible

Defines the group of Ansible configuration options.

Expand
Table 10.3. ansible properties
FieldDescription

ansibleUser

The user associated with the secret you created in Creating the data plane secrets. Default: rhel-user

ansibleHost

SSH host for the Ansible connection.

ansiblePort

SSH port for the Ansible connection.

ansibleVars

The Ansible variables that customize the set of nodes. You can use this property to configure any custom Ansible variable, including the Ansible variables available for each edpm-ansible role. For a complete list of Ansible variables by role, see the edpm-ansible documentation.

Note

The ansibleVars parameters that you can configure for an OpenStackDataPlaneNodeSet CR are determined by the services defined for the OpenStackDataPlaneNodeSet. The OpenStackDataPlaneService CRs call the Ansible Playbooks from the edpm-ansible playbook collection, which include the roles that are executed as part of the data plane service.

ansibleVarsFrom

A list of sources to populate Ansible variables from. Values defined by an AnsibleVars with a duplicate key take precedence. For more information, see ansibleVarsFrom properties.

10.7.4. ansibleVarsFrom

Defines the list of sources to populate Ansible variables from.

Expand
Table 10.4. ansibleVarsFrom properties
FieldDescription

prefix

An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.

configMapRef

The ConfigMap CR to select the ansibleVars from.

secretRef

The Secret CR to select the ansibleVars from.

When configuring your data plane nodes, you can provide node-specific network configurations using the networkData parameter, which refers to a Secret that contains the configuration. You can define networkData at two levels within the OpenStackDataPlaneNodeSet CR: under the nodeTemplate properties and under the individual nodes properties. The nodeTemplate field is used to configure the common baseline properties applied to all nodes in the node set. However, if you apply the networkData property to a specific node within the nodes section, this node-specific configuration overrides the inherited default values from the nodeTemplate. This override mechanism allows you to establish a broad default network configuration for a group of nodes, while safely overriding those defaults for specific nodes that require unique, node-specific network setups.

10.8. Network interface configuration options

You have many options for configuring network interfaces.

Most of these options can be sorted into the following categories:

Note

Linux bridges are not supported in RHOSO. Instead, use methods such as Linux bonds and dedicated NICs for RHOSO traffic.

10.8.1. interface

Defines a single network interface. The network interface name uses either the actual interface name (eth0, eth1, enp0s25) or a set of numbered interfaces (nic1, nic2, nic3). The network interfaces of hosts within a role do not have to be exactly the same when you use numbered interfaces such as nic1 and nic2, instead of named interfaces such as eth0 and eno2. For example, one host might have interfaces em1 and em2, while another has eno1 and eno2, but you can refer to the NICs of both hosts as nic1 and nic2.

The order of numbered interfaces corresponds to the order of named network interface types:

  • ethX interfaces, such as eth0, eth1, and so on.

    Names appear in this format when consistent device naming is turned off in udev.

  • enoX and emX interfaces, such as eno0, eno1, em0, em1, and so on.

    These are usually on-board interfaces.

  • enX and any other interfaces, sorted alpha numerically, such as enp3s0, enp3s1, ens3, and so on.

    These are usually add-on interfaces.

The numbered NIC scheme includes only live interfaces, for example, if the interfaces have a cable attached to the switch. If you have some hosts with four interfaces and some with six interfaces, use nic1 to nic4 and attach only four cables on each host.

Expand
Table 10.5. interface options
OptionDefaultDescription

name

 

Name of the interface. The network interface name uses either the actual interface name (eth0, eth1, enp0s25) or a set of numbered interfaces (nic1, nic2, nic3).

use_dhcp

False

Use DHCP to get an IP address.

use_dhcpv6

False

Use DHCP to get a v6 IP address.

addresses

 

A list of IP addresses assigned to the interface.

routes

 

A list of routes assigned to the interface. For more information, see Section 10.8.7, “routes”.

mtu

1500

The maximum transmission unit (MTU) of the connection.

primary

False

Defines the interface as the primary interface. Required only when the interface is a member of a bond.

persist_mapping

False

Write the device alias configuration instead of the system names.

dhclient_args

None

Arguments that you want to pass to the DHCP client.

dns_servers

None

List of DNS servers that you want to use for the interface.

ethtool_opts

 

Set this option to "rx-flow-hash udp4 sdfn" to improve throughput when you use VXLAN on certain NICs.

Example
...
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          - type: interface
            name: nic2
            ...

10.8.2. vlan

Defines a VLAN. Use the VLAN ID and subnet passed from the parameters section.

vlan options
Expand
OptionDefaultDescription

vlan_id

 

The VLAN ID.

device

 

The parent device to attach the VLAN. Use this parameter when the VLAN is not a member of an OVS bridge. For example, use this parameter to attach the VLAN to a bonded interface device.

use_dhcp

False

Use DHCP to get an IP address.

use_dhcpv6

False

Use DHCP to get a v6 IP address.

addresses

 

A list of IP addresses assigned to the VLAN.

routes

 

A list of routes assigned to the VLAN. For more information, see Section 10.8.7, “routes”.

mtu

1500

The maximum transmission unit (MTU) of the connection.

primary

False

Defines the VLAN as the primary interface.

persist_mapping

False

Write the device alias configuration instead of the system names.

dhclient_args

None

Arguments that you want to pass to the DHCP client.

dns_servers

None

List of DNS servers that you want to use for the VLAN.

Example
...
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          ...
            - type: vlan
              device: nic{{ loop.index + 1 }}
              mtu: {{ lookup(vars, networks_lower[network] ~ _mtu) }}
              vlan_id: {{ lookup(vars, networks_lower[network] ~ _vlan_id) }}
              addresses:
              - ip_netmask:
                  {{ lookup(vars, networks_lower[network] ~ _ip) }}/{{ lookup(vars, networks_lower[network] ~ _cidr) }}
              routes: {{ lookup(vars, networks_lower[network] ~ _host_routes) }}
...
Example - creating a VLAN on an ovs_bridge

To create a VLAN on an ovs_bridge, you must place the VLAN configuration under the members section:

...
network_config:
- type: ovs_bridge
  name: br0
  use_dhcp: false
  members:
  - type: interface
    name: nic5
  - type: vlan
    vlan_id: 138
    use_dhcp: false
...
Example - creating a VLAN on an ovs_user_bridge

To create a VLAN on an ovs_user_bridge, you must place the VLAN configuration under the members section. The members must be either an ovs_dpdk_bond or and ovs_dpdk_port:

...
network_config:
-type: ovs_user_bridge
 name: br-link
 members:
   -type: ovs_dpdk_bond
    name: dpdkbond0
    mtu: 9000
    rx_queue: 4
    members:
      -type: ovs_dpdk_port
       name: dpdk0
       members:
         -type: interface
          name: nic2
      -type: ovs_dpdk_port
       name: dpdk1
       members:
         -type: interface
          name: nic3
   -type: vlan
    vlan_id:138
    use_dhcp: false
...

10.8.3. ovs_bridge

Defines a bridge in Open vSwitch (OVS), which connects multiple interface, ovs_bond, and vlan objects together.

The network interface type, ovs_bridge, takes a parameter name.

Important

Placing Control group networks on the ovs_bridge interface can cause downtime. The OVS bridge connects to the Networking service (neutron) server to obtain configuration data. If the OpenStack control traffic, typically the Control Plane and Internal API networks, is placed on an OVS bridge, then connectivity to the neutron server is lost whenever you upgrade OVS, or the OVS bridge is restarted by the admin user or process. If downtime is not acceptable in these circumstances, then you must place the Control group networks on a separate interface or bond rather than on an OVS bridge:

  • You can achieve a minimal setting when you put the Internal API network on a VLAN on the provisioning interface and the OVS bridge on a second interface.
  • To implement bonding, you need at least two bonds (four network interfaces). Place the control group on a Linux bond. If the switch does not support LACP fallback to a single interface for PXE boot, then this solution requires at least five NICs.
Note

If you have multiple bridges, you must use distinct bridge names other than accepting the default name of bridge_name. If you do not use distinct names, then during the converge phase, two network bonds are placed on the same bridge.

ovs_bridge options
Expand
OptionDefaultDescription

name

 

Name of the bridge.

use_dhcp

False

Use DHCP to get an IP address.

use_dhcpv6

False

Use DHCP to get a v6 IP address.

addresses

 

A list of IP addresses assigned to the bridge.

routes

 

A list of routes assigned to the bridge. For more information, see Section 10.8.7, “routes”.

mtu

1500

The maximum transmission unit (MTU) of the connection.

members

 

A sequence of interface, VLAN, and bond objects that you want to use in the bridge.

ovs_options

 

A set of options to pass to OVS when creating the bridge.

ovs_extra

 

A set of options to set as the OVS_EXTRA parameter in the network configuration file of the bridge.

defroute

True

Use a default route provided by the DHCP service. Only applies when you enable use_dhcp or use_dhcpv6.

persist_mapping

False

Write the device alias configuration instead of the system names.

dhclient_args

None

Arguments that you want to pass to the DHCP client.

dns_servers

None

List of DNS servers that you want to use for the bridge.

Example
...
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          - type: ovs_bridge
            name: br-bond
            dns_servers: {{ ctlplane_dns_nameservers }}
            domain: {{ dns_search_domains }}
            members:
            - type: ovs_bond
              name: bond1
              mtu: {{ min_viable_mtu }}
              ovs_options: {{ bound_interface_ovs_options }}
              members:
              - type: interface
                name: nic2
                mtu: {{ min_viable_mtu }}
                primary: true
              - type: interface
                name: nic3
                mtu: {{ min_viable_mtu }}
                ...

10.8.4. Network interface bonding

You can bundle multiple physical NICs together to form a single logical channel known as a bond. You can configure bonds to provide redundancy for high availability systems or increased throughput.

Red Hat OpenStack Platform supports Open vSwitch (OVS) kernel bonds, OVS-DPDK bonds, and Linux kernel bonds.

Expand
Table 10.6. Supported interface bonding types
Bond typeType valueAllowed bridge typesAllowed members

OVS kernel bonds

ovs_bond

ovs_bridge

interface

OVS-DPDK bonds

ovs_dpdk_bond

ovs_user_bridge

ovs_dpdk_port

Linux kernel bonds

linux_bond

ovs_bridge

interface

Important

Do not combine ovs_bridge and ovs_user_bridge on the same node.

ovs_bond

Defines a bond in Open vSwitch (OVS) to join two or more interfaces together. This helps with redundancy and increases bandwidth.

Expand
Table 10.7. ovs_bond options
OptionDefaultDescription

name

 

Name of the bond.

use_dhcp

False

Use DHCP to get an IP address.

use_dhcpv6

False

Use DHCP to get a v6 IP address.

addresses

 

A list of IP addresses assigned to the bond.

routes

 

A list of routes assigned to the bond. For more information, see Section 10.8.7, “routes”.

mtu

1500

The maximum transmission unit (MTU) of the connection.

primary

False

Defines the interface as the primary interface.

members

 

A sequence of interface objects that you want to use in the bond.

ovs_options

 

A set of options to pass to OVS when creating the bond. For more information, see Table 10.8, “ovs_options parameters for OVS bonds”.

ovs_extra

 

A set of options to set as the OVS_EXTRA parameter in the network configuration file of the bond.

defroute

True

Use a default route provided by the DHCP service. Only applies when you enable use_dhcp or use_dhcpv6.

persist_mapping

False

Write the device alias configuration instead of the system names.

dhclient_args

None

Arguments that you want to pass to the DHCP client.

dns_servers

None

List of DNS servers that you want to use for the bond.

Expand
Table 10.8. ovs_options parameters for OVS bonds
ovs_optionDescription

bond_mode=balance-slb

Source load balancing (slb) balances flows based on source MAC address and output VLAN, with periodic rebalancing as traffic patterns change. When you configure a bond with the balance-slb bonding option, there is no configuration required on the remote switch. The Networking service (neutron) assigns each source MAC and VLAN pair to a link and transmits all packets from that MAC and VLAN through that link. A simple hashing algorithm based on source MAC address and VLAN number is used, with periodic rebalancing as traffic patterns change. The balance-slb mode is similar to mode 2 bonds used by the Linux bonding driver. You can use this mode to provide load balancing even when the switch is not configured to use LACP.

bond_mode=active-backup

When you configure a bond using active-backup bond mode, the Networking service keeps one NIC in standby. The standby NIC resumes network operations when the active connection fails. Only one MAC address is presented to the physical switch. This mode does not require switch configuration, and works when the links are connected to separate switches. This mode does not provide load balancing.

lacp=[active | passive | off]

Controls the Link Aggregation Control Protocol (LACP) behavior. Only certain switches support LACP. If your switch does not support LACP, use bond_mode=balance-slb or bond_mode=active-backup.

other-config:lacp-fallback-ab=true

Set active-backup as the bond mode if LACP fails.

other_config:lacp-time=[fast | slow]

Set the LACP heartbeat to one second (fast) or 30 seconds (slow). The default is slow.

other_config:bond-detect-mode=[miimon | carrier]

Set the link detection to use miimon heartbeats (miimon) or monitor carrier (carrier). The default is carrier.

other_config:bond-miimon-interval=100

If using miimon, set the heartbeat interval (milliseconds).

bond_updelay=1000

Set the interval (milliseconds) that a link must be up to be activated to prevent flapping.

other_config:bond-rebalance-interval=10000

Set the interval (milliseconds) that flows are rebalancing between bond members. Set this value to zero to disable flow rebalancing between bond members.

Example - OVS bond
...
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          ...
            members:
              - type: ovs_bond
                name: bond1
                mtu: {{ min_viable_mtu }}
                ovs_options: {{ bond_interface_ovs_options }}
                members:
                - type: interface
                  name: nic2
                  mtu: {{ min_viable_mtu }}
                  primary: true
                - type: interface
                  name: nic3
                  mtu: {{ min_viable_mtu }}
Example - OVS DPDK bond

In this example, a bond is created as part of an OVS user space bridge:

        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          ...
            members:
            - type: ovs_user_bridge
              name: br-dpdk0
              members:
              - type: ovs_dpdk_bond
                name: dpdkbond0
                rx_queue: {{ num_dpdk_interface_rx_queues }}
                members:
                - type: ovs_dpdk_port
                  name: dpdk0
                  members:
                  - type: interface
                    name: nic4
                - type: ovs_dpdk_port
                  name: dpdk1
                  members:
                  - type: interface
                    name: nic5

10.8.5. LACP with OVS bonding modes

You can use Open vSwitch (OVS) bonds with the optional Link Aggregation Control Protocol (LACP). LACP is a negotiation protocol that creates a dynamic bond for load balancing and fault tolerance.

Use the following table to understand support compatibility for OVS kernel and OVS-DPDK bonded interfaces in conjunction with LACP options.

Important

Do not use OVS bonds on control and storage networks. Instead, use Linux bonds with VLAN and LACP.

If you use OVS bonds, and restart the OVS or the neutron agent for updates, hot fixes, and other events, the control plane can be disrupted.

Expand
Table 10.9. LACP options for OVS kernel and OVS-DPDK bond modes

Objective

OVS bond mode

Compatible LACP options

Notes

High availability (active-passive)

active-backup

active, passive, or off

 

Increased throughput (active-active)

balance-slb

active, passive, or off

  • Performance is affected by extra parsing per packet.
  • There is a potential for vhost-user lock contention.

balance-tcp

active or passive

  • As with balance-slb, performance is affected by extra parsing per packet and there is a potential for vhost-user lock contention.
  • LACP must be configured and enabled.
  • Set lb-output-action=true. For example:

    ovs-vsctl set port <bond port> other_config:lb-output-action=true

10.8.6. linux_bond

Defines a Linux bond that joins two or more interfaces together. This helps with redundancy and increases bandwidth. Ensure that you include the kernel-based bonding options in the bonding_options parameter.

Expand
Table 10.10. linux_bond options
OptionDefaultDescription

name

 

Name of the bond.

use_dhcp

False

Use DHCP to get an IP address.

use_dhcpv6

False

Use DHCP to get a v6 IP address.

addresses

 

A list of IP addresses assigned to the bond.

routes

 

A list of routes assigned to the bond. See Section 10.8.7, “routes”.

mtu

1500

The maximum transmission unit (MTU) of the connection.

members

 

A sequence of interface objects that you want to use in the bond.

bonding_options

 

A set of options when creating the bond. See bonding_options parameters for Linux bonds.

defroute

True

Use a default route provided by the DHCP service. Only applies when you enable use_dhcp or use_dhcpv6.

persist_mapping

False

Write the device alias configuration instead of the system names.

dhclient_args

None

Arguments that you want to pass to the DHCP client.

dns_servers

None

List of DNS servers that you want to use for the bond.

bonding_options parameters for Linux bonds
The bonding_options parameter sets the specific bonding options for the Linux bond. See the Linux bonding examples that follow this table:
Expand
Table 10.11. bonding_options
bonding_optionsDescription

mode

Sets the bonding mode, which in the example is 802.3ad or LACP mode. For more information about Linux bonding modes, see Configuring a network bond in Red Hat Enterprise Linux 9, Configuring and managing networking.

lacp_rate

Defines whether LACP packets are sent every 1 second, or every 30 seconds.

updelay

Defines the minimum amount of time that an interface must be active before it is used for traffic. This minimum configuration helps to mitigate port flapping outages.

miimon

The interval in milliseconds that is used for monitoring the port state using the MIIMON functionality of the driver.

Example - Linux bond
...
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          - type: linux_bond
            name: bond1
            mtu: {{ min_viable_mtu }}
            bonding_options: "mode=802.3ad lacp_rate=fast updelay=1000 miimon=100 xmit_hash_policy=layer3+4"
            members:
              type: interface
              name: ens1f0
              mtu: {{ min_viable_mtu }}
              primary: true
            type: interface
              name: ens1f1
              mtu: {{ min_viable_mtu }}
              ...
Example - Linux bond: bonding two interfaces
...
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          - type: linux_bond
            name: bond1
            members:
            - type: interface
              name: nic2
            - type: interface
              name: nic3
            bonding_options: "mode=802.3ad lacp_rate=[fast|slow] updelay=1000 miimon=100"
            ...
Example - Linux bond set to active-backup mode with one VLAN
....
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          - type: linux_bond
            name: bond_api
            bonding_options: "mode=active-backup"
            use_dhcp: false
            dns_servers:
              get_param: DnsServers
            members:
            - type: interface
              name: nic3
              primary: true
            - type: interface
              name: nic4

            - type: vlan
              vlan_id: {{ lookup(vars, networks_lower[network] ~ _vlan_id) }}
              device: bond_api
              addresses:
              - ip_netmask:
                  get_param: InternalApiIpSubnet
Example - Linux bond on OVS bridge

In this example, the bond is set to 802.3ad with LACP mode and one VLAN:

...
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          -  type: ovs_bridge
              name: br-tenant
              use_dhcp: false
              mtu: 9000
              members:
                - type: linux_bond
                  name: bond_tenant
                  bonding_options: "mode=802.3ad updelay=1000 miimon=100"
                  use_dhcp: false
                  dns_servers:
                    get_param: DnsServers
                  members:
                  - type: interface
                    name: p1p1
                    primary: true
                  - type: interface
                    name: p1p2
                - type: vlan
                  vlan_id: {get_param: TenantNetworkVlanID}
                  addresses:
                    - ip_netmask: {get_param: TenantIpSubnet}
                    ...

10.8.7. routes

Defines a list of routes to apply to a network interface, VLAN, bridge, or bond.

Expand
Table 10.12. routes options
OptionDefaultDescription

ip_netmask

None

IP and netmask of the destination network.

default

False

Sets this route to a default route. Equivalent to setting ip_netmask: 0.0.0.0/0.

next_hop

None

The IP address of the router used to reach the destination network.

Example - routes
...
        edpm_network_config_template: |
          ---
          {% set mtu_list = [ctlplane_mtu] %}
          {% for network in nodeset_networks %}
          {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
          {%- endfor %}
          {% set min_viable_mtu = mtu_list | max %}
          network_config:
          -  type: ovs_bridge
              name: br-tenant
              ...
              routes: {{ [ctlplane_host_routes] | flatten | unique }}
              ...

Use edpm-ansible variables to to optimize CPU and memory performance for OVS-DPDK and SR-IOV workloads on Red Hat OpenStack Services on OpenShift (RHOSO) data plane nodes.

Note

Always pair CPU sibling threads, or logical CPUs, together in the physical core when allocating CPU cores.

Use the variables to align your hardware configuration with host, guest instance, and OVS-DPDK process needs.

10.9.2. Data plane (EDPM) Ansible variables

You can use a set of Ansible variables to optimize CPU and memory parameters for performance on data plane nodes with OVS-DPDK and SR-IOV.

You can use the following Ansible roles variables in a custom resource (CR).

edpm_ovs_dpdk
Enables you to add, modify, and delete OVS-DPDK configurations, by using values defined in the OVS-DPDK edpm Ansible variables.
edpm_ovs_dpdk_pmd_core_list
Provides the CPU cores that are used for the DPDK poll mode drivers (PMD). Choose CPU cores that are associated with the local NUMA nodes of the DPDK interfaces.
edpm_ovs_dpdk_enable_tso
Enables (true) or disables (false) the TCP segmentation offloading (TSO) for DPDK feature. The default is false.
edpm_tuned_profile
Name of the custom TuneD profile. The default value is throughput-performance.
edpm_tuned_isolated_cores
A set of CPU cores isolated from the host processes.
edpm_ovs_dpdk_socket_memory

Specifies the amount of memory in MB to pre-allocate from the hugepage pool, per NUMA node. dpm_ovs_dpdk_socket_memory is the other_config:dpdk-socket-mem value in OVS:

  • Provide as a comma-separated list.
  • For a NUMA node without a DPDK NIC, use the static value of 1024MB (1GB).
  • Calculate the edpm_ovs_dpdk_socket_memory value from the MTU value of each NIC on the NUMA node. The following equation approximates the value:

    MEMORY_REQD_PER_MTU = (ROUNDUP_PER_MTU + 800) * (4096 * 64) Bytes
    • 800 is the overhead value.
    • 4096 * 64 is the number of packets in the mempool.
  • Add the MEMORY_REQD_PER_MTU for each of the MTU values set on the NUMA node and add another 512MB as buffer. Round the value up to a multiple of 1024.
edpm_ovs_dpdk_memory_channels

Maps memory channels in the CPU per NUMA node. edpm_ovs_dpdk_memory_channels is the other_config:dpdk-extra="-n <value>" value in OVS:

  • Use dmidecode -t memory or your hardware manual to determine the number of memory channels available.
  • Use ls /sys/devices/system/node/node* -d to determine the number of NUMA nodes.
  • Divide the number of memory channels available by the number of NUMA nodes.
edpm_ovs_dpdk_vhost_postcopy_support
Enable or disable OVS-DPDK vhost post-copy support. Setting this to true enables post-copy support for all vhost user client ports.
edpm_nova_libvirt_qemu_group
Set edpm_nova_libvirt_qemu_group to hugetlbfs`so that the `ovs-vswitchd and qemu processes can access the shared huge pages and UNIX socket that configures the virtio-net device. This value is role-specific and should be applied to any role leveraging OVS-DPDK.
edpm_ovn_bridge_mappings

List of bridge and DPDK ports mappings.

Example:

 edpm_ovn_bridge_mappings:
   - "datacentre:br-ex"
edpm_kernel_args
Provides multiple kernel arguments to /etc/default/grub for the compute nodes at boot time.

10.9.3. Configuration map parameters

You can set various parameters in the ConfigMap section of a custom resource (CR) to configure the CPU and memory for optimum performance on data plane nodes for OVS-DPDK and SR-IOV.

cpu_shared_set
List or range of host CPU cores used to determine the host CPUs that instance emulator threads should be offloaded to for instances configured with the share emulator thread policy (hw::emulator_threads_policy=share).
cpu_dedicated_set

A comma-separated list or range of physical host CPU numbers to which processes for pinned instance CPUs can be scheduled.

  • Exclude all cores from the edpm_ovs_dpdk_pmd_core_list.
  • Include all remaining cores.
  • Pair the sibling threads together.
reserved_host_memory_mb
Reserves memory in MB for tasks on the host. Use the static value of 4096MB.

10.10. Example custom network interfaces for NFV

Example templates demonstrate how to customize network interfaces for NFV in RHOSO environments.

10.10.1. Example template - non-partitioned NIC

This template example configures the RHOSO networks on a NIC that is not partitioned.

apiVersion: v1
data:
 25-igmp.conf: |
   [ovs]
   igmp_snooping_enable = True
kind: ConfigMap
metadata:
 name: neutron-igmp
 namespace: openstack
---
apiVersion: v1
data:
 25-cpu-pinning-nova.conf: |
   [DEFAULT]
   reserved_host_memory_mb = 4096
   [compute]
   cpu_shared_set = "0,20,1,21"
   cpu_dedicated_set = "8-19,28-39"
   [neutron]
   physnets = dpdkdata1
   [neutron_physnet_dpdkdata1]
   numa_nodes = 1
   [libvirt]
   cpu_power_management=false
kind: ConfigMap
metadata:
 name: ovs-dpdk-sriov-cpu-pinning-nova
 namespace: openstack
---
apiVersion: v1
data:
 03-sriov-nova.conf: |
   [pci]
   device_spec = {"address": "0000:05:00.2", "physical_network":"sriov-1", "trusted":"true"}
   device_spec = {"address": "0000:05:00.3", "physical_network":"sriov-2", "trusted":"true"}
   device_spec = {"address": "0000:07:00.0", "physical_network":"sriov-3", "trusted":"true"}
   device_spec = {"address": "0000:07:00.1", "physical_network":"sriov-4", "trusted":"true"}
kind: ConfigMap
metadata:
 name: sriov-nova
 namespace: openstack
---
apiVersion: v1
data:
 NodeRootPassword: cmVkaGF0Cg==
kind: Secret
metadata:
 name: baremetalset-password-secret
 namespace: openstack
type: Opaque
---
apiVersion: v1
data:
 authorized_keys: ZWNkc2Etc2hhMi1uaXN0cDUyMSBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEExTWpFQUFBQUlibWx6ZEhBMU1qRUFBQUNGQkFBVFdweE5LNlNYTEo0dnh2Y0F4N0t4c3FLenI0a3pEalRpT0dQa3pyZWZnTjdVcmo2RUZPUXlBRWk5cXNnYkRVYXp0MktpdzJqc3djbG5TYW1zUDE0V2x3RkN2a1NuU1o4cTZwWGJTbGpNa3Z1R3FiVXZoSTVxTVlMTDNlRWpyU21nNDlWcTBWZkdFQmxIWUx6TGFncVBlN1FKR0NCMGlWTVk5b3N0TFdPM1NKbXVuZz09IGNpZm13X3JlcHJvZHVjZXJfa2V5Cg==
 ssh-privatekey: LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUFyQUFBQUJObFkyUnpZUwoxemFHRXlMVzVwYzNSd05USXhBQUFBQ0c1cGMzUndOVEl4QUFBQWhRUUFFMXFjVFN1a2x5eWVMOGIzQU1leXNiS2lzNitKCk13NDA0amhqNU02M240RGUxSzQraEJUa01nQkl2YXJJR3cxR3M3ZGlvc05vN01ISlowbXByRDllRnBjQlFyNUVwMG1mS3UKcVYyMHBZekpMN2hxbTFMNFNPYWpHQ3k5M2hJNjBwb09QVmF0Rlh4aEFaUjJDOHkyb0tqM3UwQ1JnZ2RJbFRHUGFMTFMxagp0MGlacnA0QUFBRVl0cGNtdHJhWEpyWUFBQUFUWldOa2MyRXRjMmhoTWkxdWFYTjBjRFV5TVFBQUFBaHVhWE4wY0RVeU1RCkFBQUlVRUFCTmFuRTBycEpjc25pL0c5d0RIc3JHeW9yT3ZpVE1PTk9JNFkrVE90NStBM3RTdVBvUVU1RElBU0wycXlCc04KUnJPM1lxTERhT3pCeVdkSnFhdy9YaGFYQVVLK1JLZEpueXJxbGR0S1dNeVMrNGFwdFMrRWptb3hnc3ZkNFNPdEthRGoxVwpyUlY4WVFHVWRndk10cUNvOTd0QWtZSUhTSlV4ajJpeTB0WTdkSW1hNmVBQUFBUWdHTWZobWFSblZFcnhjZ2Z6aVRpdzFnClBjYXBBV21TMHh5dDNyclhoSnExd0pRMys3ZFp0Y3l0alg5VVVuNnh0NlE1M0JTT1ZvaWR2L2pZK2krYytNVVhUZ0FBQUIKUmphV1p0ZDE5eVpYQnliMlIxWTJWeVgydGxlUUVDQXdRRkJnPT0KLS0tLS1FTkQgT1BFTlNTSCBQUklWQVRFIEtFWS0tLS0tCg==
 ssh-publickey: ZWNkc2Etc2hhMi1uaXN0cDUyMSBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEExTWpFQUFBQUlibWx6ZEhBMU1qRUFBQUNGQkFBVFdweE5LNlNYTEo0dnh2Y0F4N0t4c3FLenI0a3pEalRpT0dQa3pyZWZnTjdVcmo2RUZPUXlBRWk5cXNnYkRVYXp0MktpdzJqc3djbG5TYW1zUDE0V2x3RkN2a1NuU1o4cTZwWGJTbGpNa3Z1R3FiVXZoSTVxTVlMTDNlRWpyU21nNDlWcTBWZkdFQmxIWUx6TGFncVBlN1FKR0NCMGlWTVk5b3N0TFdPM1NKbXVuZz09IGNpZm13X3JlcHJvZHVjZXJfa2V5Cg==
kind: Secret
metadata:
 name: dataplane-ansible-ssh-private-key-secret
 namespace: openstack
type: Opaque
---
apiVersion: v1
data:
 LibvirtPassword: MTIzNDU2Nzg=
kind: Secret
metadata:
 name: libvirt-secret
 namespace: openstack
type: Opaque
---
apiVersion: v1
data:
 ssh-privatekey: LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUFyQUFBQUJObFkyUnpZUwoxemFHRXlMVzVwYzNSd05USXhBQUFBQ0c1cGMzUndOVEl4QUFBQWhRUUFwWTlSRzV5a2pLR3p2c295dWlDZm1zakEwZkFYCmkvS0hQT3R3Zm9NZjRQZXpRSFFNOHFJZ0pGc0svaVlwNVJIWmNVQlcwVVBCNnBpazQ1L3k0QVF4bmVBQWRrN0JQbTc0dG8KSkxoVjY2U3pzV2pHR1NFdzVXVFBwVUVpaXdQMlNiL1l4dXloNWlLbUJyTE5SRWpYTEJvbjJJZWRBbEJMaC9FaGpkdFZjUwo5ZzczQ0tvQUFBRVFoeS9PODRjdnp2TUFBQUFUWldOa2MyRXRjMmhoTWkxdWFYTjBjRFV5TVFBQUFBaHVhWE4wY0RVeU1RCkFBQUlVRUFLV1BVUnVjcEl5aHM3N0tNcm9nbjVySXdOSHdGNHZ5aHp6cmNINkRIK0QzczBCMERQS2lJQ1JiQ3Y0bUtlVVIKMlhGQVZ0RkR3ZXFZcE9PZjh1QUVNWjNnQUhaT3dUNXUrTGFDUzRWZXVrczdGb3hoa2hNT1ZrejZWQklvc0Q5a20vMk1icwpvZVlpcGdheXpVUkkxeXdhSjlpSG5RSlFTNGZ4SVkzYlZYRXZZTzl3aXFBQUFBUWdEQ0lEdHFqZ0JNam8rbG1rRnhzV3NvCkxKOGxBSWF0a0ZTdDkxcGJHWWIrVFRnS0NSOGhqbXdjalNoRzFlNlRaZWZNTkc5TklzVlRYYjNjTkYvaThJTHV1UUFBQUEKNXViM1poSUcxcFozSmhkR2x2YmdFQ0F3UT0KLS0tLS1FTkQgT1BFTlNTSCBQUklWQVRFIEtFWS0tLS0tCg==
 ssh-publickey: ZWNkc2Etc2hhMi1uaXN0cDUyMSBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEExTWpFQUFBQUlibWx6ZEhBMU1qRUFBQUNGQkFDbGoxRWJuS1NNb2JPK3lqSzZJSitheU1EUjhCZUw4b2M4NjNCK2d4L2c5N05BZEF6eW9pQWtXd3IrSmlubEVkbHhRRmJSUThIcW1LVGpuL0xnQkRHZDRBQjJUc0UrYnZpMmdrdUZYcnBMT3hhTVlaSVREbFpNK2xRU0tMQS9aSnY5akc3S0htSXFZR3NzMUVTTmNzR2lmWWg1MENVRXVIOFNHTjIxVnhMMkR2Y0lxZz09IG5vdmEgbWlncmF0aW9uCg==
kind: Secret
metadata:
 name: nova-migration-ssh-key
 namespace: openstack
type: kubernetes.io/ssh-auth
---
apiVersion: dataplane.openstack.org/v1beta1
kind: OpenStackDataPlaneNodeSet
metadata:
 name: openstack-edpm
 namespace: openstack
spec:
 baremetalSetTemplate:
   bmhLabelSelector:
     app: openstack
   cloudUserName: cloud-admin
   ctlplaneInterface: enp130s0f0
   passwordSecret:
     name: baremetalset-password-secret
     namespace: openstack
   provisioningInterface: enp5s0
 env:
 - name: ANSIBLE_FORCE_COLOR
   value: "True"
 networkAttachments:
 - ctlplane
 nodeTemplate:
   ansible:
     ansiblePort: 22
     ansibleUser: cloud-admin
     ansibleVars:
       dns_search_domains: []
       rhc_release: 9.4
       rhc_repositories:
         - {name: "*", state: disabled}
         - {name: "<repository_name1>", state: enabled}
         - {name: "<repository_name2>", state: enabled}
         - {name: "<repository_name3>", state: enabled}
         - {name: "<repository_name4>", state: enabled}
         - {name: "<repository_name5>", state: enabled}
         - {name: "<repository_name6>", state: enabled}
       edpm_fips_mode: check
       edpm_kernel_args: default_hugepagesz=1GB hugepagesz=1G hugepages=64 iommu=pt
         intel_iommu=on tsx=off isolcpus=2-19,22-39
       edpm_network_config_hide_sensitive_logs: false
       edpm_network_config_os_net_config_mappings:
         edpm-compute-0:
           dmiString: system-product-name
           id: PowerEdge R730
           nic1: eno1
           nic2: eno2
           nic3: enp130s0f0
           nic4: enp130s0f1
           nic5: enp130s0f2
           nic6: enp130s0f3
           nic7: enp5s0f0
           nic8: enp5s0f1
           nic9: enp5s0f2
           nic10: enp5s0f3
           nic11: enp7s0f0np0
           nic12: enp7s0f1np1
         edpm-compute-1:
           dmiString: system-product-name
           id: PowerEdge R730
           nic1: eno1
           nic2: eno2
           nic3: enp130s0f0
           nic4: enp130s0f1
           nic5: enp130s0f2
           nic6: enp130s0f3
           nic7: enp5s0f0
           nic8: enp5s0f1
           nic9: enp5s0f2
           nic10: enp5s0f3
           nic11: enp7s0f0np0
           nic12: enp7s0f1np1
       edpm_network_config_template: |
         ---
         {% set mtu_list = [ctlplane_mtu] %}
         {% for network in nodeset_networks %}
         {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
         {%- endfor %}
         {% set min_viable_mtu = mtu_list | max %}
         network_config:
         - type: interface
           name: nic1
           use_dhcp: false
         - type: interface
           name: nic2
           use_dhcp: false
         - type: linux_bond
           name: bond_api
           use_dhcp: false
           bonding_options: "mode=active-backup"
           dns_servers: {{ ctlplane_dns_nameservers }}
           members:
             - type: interface
               name: nic3
               primary: true
           addresses:
           - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }}
           routes:
           - default: true
             next_hop: {{ ctlplane_gateway_ip }}
         - type: vlan
           vlan_id: {{ lookup(vars, networks_lower[internalapi] ~ _vlan_id) }}
           device: bond_api
           addresses:
           - ip_netmask: {{ lookup(vars, networks_lower[internalapi] ~ _ip) }}/{{ lookup(vars, networks_lower[internalapi] ~ _cidr) }}
         - type: vlan
           vlan_id: {{ lookup(vars, networks_lower[storage] ~ _vlan_id) }}
           device: bond_api
           addresses:
           - ip_netmask: {{ lookup(vars, networks_lower[storage] ~ _ip) }}/{{ lookup(vars, networks_lower[storage] ~ _cidr) }}
         - type: ovs_user_bridge
           name: br-link0
           use_dhcp: false
           ovs_extra: "set port br-link0 tag={{ lookup(vars, networks_lower[tenant] ~ _vlan_id) }}"
           addresses:
           - ip_netmask: {{ lookup(vars, networks_lower[tenant] ~ _ip) }}/{{ lookup(vars, networks_lower[tenant] ~ _cidr) }}
           mtu: {{ lookup(vars, networks_lower[tenant] ~ _mtu) }}
           members:
           - type: ovs_dpdk_bond
             name: dpdkbond0
             mtu: 9000
             rx_queue: 2
             ovs_extra: "set port dpdkbond0 bond_mode=balance-slb"
             members:
             - type: ovs_dpdk_port
               name: dpdk0
               members:
               - type: interface
                 name: nic7
             - type: ovs_dpdk_port
               name: dpdk1
               members:
               - type: interface
                 name: nic8
         - type: ovs_user_bridge
           name: br-dpdk0
           mtu: 9000
           use_dhcp: false
           members:
           - type: ovs_dpdk_bond
             name: dpdkbond1
             mtu: 9000
             rx_queue: 3
             ovs_options: "bond_mode=balance-tcp lacp=active other_config:lacp-time=fast other-config:lacp-fallback-ab=true other_config:lb-output-action=true"
             members:
               - type: ovs_dpdk_port
                 name: dpdk2
                 members:
                   - type: interface
                     name: nic5
               - type: ovs_dpdk_port
                 name: dpdk3
                 members:
                   - type: interface
                     name: nic6
         - type: ovs_user_bridge
           name: br-dpdk1
           mtu: 9000
           use_dhcp: false
           members:
             - type: ovs_dpdk_port
               name: dpdk4
               mtu: 9000
               rx_queue: 3
               members:
                 - type: interface
                   name: nic4
         - type: sriov_pf
           name: nic9
           numvfs: 10
           mtu: 9000
           use_dhcp: false
           promisc: true
         - type: sriov_pf
           name: nic10
           numvfs: 10
           mtu: 9000
           use_dhcp: false
           promisc: true
         - type: sriov_pf
           name: nic11
           numvfs: 5
           mtu: 9000
           use_dhcp: false
           promisc: true
         - type: sriov_pf
           name: nic12
           numvfs: 5
           mtu: 9000
           use_dhcp: false
           promisc: true
       edpm_neutron_sriov_agent_SRIOV_NIC_physical_device_mappings: sriov-1:enp5s0f2,sriov-2:enp5s0f3,sriov-3:enp7s0f0np0,sriov-4:enp7s0f1np1
       edpm_nodes_validation_validate_controllers_icmp: false
       edpm_nodes_validation_validate_gateway_icmp: false
       edpm_nova_libvirt_qemu_group: hugetlbfs
       edpm_ovn_bridge_mappings:
       - dpdkmgmt:br-link0
       - dpdkdata0:br-dpdk0
       - dpdkdata1:br-dpdk1
       edpm_ovs_dpdk_memory_channels: "4"
       edpm_ovs_dpdk_pmd_auto_lb: "true"
       edpm_ovs_dpdk_pmd_core_list: 2,3,4,5,6,7,22,23,24,25,26,27
       edpm_ovs_dpdk_pmd_improvement_threshold: "25"
       edpm_ovs_dpdk_pmd_load_threshold: "70"
       edpm_ovs_dpdk_pmd_rebal_interval: "2"
       edpm_ovs_dpdk_socket_memory: 4096,4096
       edpm_ovs_dpdk_vhost_postcopy_support: "true"
       edpm_selinux_mode: enforcing
       edpm_sshd_allowed_ranges:
       - 192.168.122.0/24
       edpm_sshd_configure_firewall: true
       edpm_tuned_isolated_cores: 2-19,22-39
       edpm_tuned_profile: cpu-partitioning-powersave
       enable_debug: false
       gather_facts: false
       neutron_physical_bridge_name: br-access
       neutron_public_interface_name: nic1
       service_net_map:
         nova_api_network: internalapi
         nova_libvirt_network: internalapi
       timesync_ntp_servers:
       - hostname: clock.redhat.com
   ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret
   managementNetwork: ctlplane
   networks:
   - defaultRoute: true
     name: ctlplane
     subnetName: subnet1
   - name: internalapi
     subnetName: subnet1
   - name: storage
     subnetName: subnet1
   - name: tenant
     subnetName: subnet1
 nodes:
   edpm-compute-0:
     hostName: compute-0
   edpm-compute-1:
     hostName: compute-1
 preProvisioned: false
 services:
 - redhat
 - bootstrap
 - download-cache
 - reboot-os
 - configure-ovs-dpdk
 - configure-network
 - validate-network
 - install-os
 - configure-os
 - ssh-known-hosts
 - run-os
 - install-certs
 - ovn
 - neutron-ovn-igmp
 - neutron-metadata
 - neutron-sriov
 - libvirt
 - nova-custom-ovsdpdksriov
 - telemetry
---
apiVersion: dataplane.openstack.org/v1beta1
kind: OpenStackDataPlaneService
metadata:
 name: neutron-ovn-igmp
 namespace: openstack
spec:
 caCerts: combined-ca-bundle
 dataSources:
 - configMapRef:
     name: neutron-igmp
 - secretRef:
     name: neutron-ovn-agent-neutron-config
 edpmServiceType: neutron-ovn
 label: neutron-ovn-igmp
 playbook: osp.edpm.neutron_ovn
 tlsCerts:
   default:
     contents:
     - dnsnames
     - ips
     issuer: osp-rootca-issuer-ovn
     keyUsages:
     - digital signature
     - key encipherment
     - client auth
     networks:
     - ctlplane
---
apiVersion: dataplane.openstack.org/v1beta1
kind: OpenStackDataPlaneService
metadata:
 name: nova-custom-ovsdpdksriov
 namespace: openstack
spec:
 caCerts: combined-ca-bundle
 dataSources:
 - configMapRef:
     name: ovs-dpdk-sriov-cpu-pinning-nova
 - configMapRef:
     name: sriov-nova
 - secretRef:
     name: nova-cell1-compute-config
 - secretRef:
     name: nova-migration-ssh-key
 edpmServiceType: nova
 label: nova-custom-ovsdpdksriov
 playbook: osp.edpm.nova
 tlsCerts:
   default:
     contents:
     - dnsnames
     - ips
     issuer: osp-rootca-issuer-internal
     networks:
     - ctlplane
  • edpm-compute-n - Defines the edpm_network_config_os_net_config_mappings variable to map the actual NICs. You identify each NIC by specifying the MAC address or the device name on each compute node to the NIC ID that the RHOSO os-net-config tool uses which is typically, `nic`n.
  • linux_bond - Creates a control-plane Linux bond for an isolated network. In this example, a Linux bond is created with mode active-backup on nic3 and nic4.
  • type: vlan - Assigns VLANs to Linux bonds. In this example, the VLAN ID of the internalapi and storage networks is assigned to bond-api.
  • ovs_user_bridge - Sets a bridge with OVS-DPDK ports. In this example, an OVS user bridge is created with a DPDK bond that has two DPDK ports that correspond to nic7 and nic8 for the tenant network. A GENEVE tunnel is used.
  • sriov_pf - Creates SR-IOV VFs. In this example, an interface type of sriov_pf is configured as a physical function that the host can use.
  • numvfs - Sets the number of VFs that are required.
  • <repository_name1>, <repository_name2>, <repository_name3>, <repository_name4>, <repository_name5>, <repository_name6>: Specifies the name of the repository to enable. For more information about which repositories are required, see Required repositories for Red Hat OpenStack Services on OpenShift 18.0.

10.10.2. Example template - partitioned NIC

This template example configures the RHOSO networks on a NIC that is partitioned. This example only shows the portion of the custom resource (CR) definition where the NIC is partitioned.

       edpm_network_config_os_net_config_mappings:
         dellr750:
           dmiString: system-product-name
           id: PowerEdge R750
           nic1: eno8303
           nic2: ens1f0
           nic3: ens1f1
           nic4: ens1f2
           nic5: ens1f3
           nic6: ens2f0np0
           nic7: ens2f1np1
       edpm_network_config_template: |
         ---
         {% set mtu_list = [ctlplane_mtu] %}
         {% for network in nodeset_networks %}
         {{ mtu_list.append(lookup(vars, networks_lower[network] ~ _mtu)) }}
         {%- endfor %}
         {% set min_viable_mtu = mtu_list | max %}
         network_config:
         - type: interface
           name: nic1
           use_dhcp: false
         - type: interface
           name: nic2
           use_dhcp: false
           addresses:
           - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }}
           routes:
           - default: true
             next_hop: {{ ctlplane_gateway_ip }}
         - type: sriov_pf
           name: nic3
           mtu: 9000
           numvfs: 5
           use_dhcp: false
           defroute: false
           nm_controlled: true
           hotplug: true
         - type: sriov_pf
           name: nic4
           mtu: 9000
           numvfs: 5
           use_dhcp: false
           defroute: false
           nm_controlled: true
           hotplug: true
         - type: linux_bond
           name: bond_api
           use_dhcp: false
           bonding_options: "mode=active-backup"
           dns_servers: {{ ctlplane_dns_nameservers }}
           members:
           - type: sriov_vf
             device: nic3
             vfid: 0
             vlan_id: {{ lookup(vars, networks_lower[internalapi] ~ _vlan_id) }}
           - type: sriov_vf
             device: nic4
             vfid: 0
             vlan_id: {{ lookup(vars, networks_lower[internalapi] ~ _vlan_id) }}
           addresses:
           - ip_netmask: {{ lookup(vars, networks_lower[internalapi] ~ _ip) }}/{{ lookup(vars, networks_lower[internalapi] ~ _cidr) }}
         - type: linux_bond
           name: storage_bond
           use_dhcp: false
           bonding_options: "mode=active-backup"
           dns_servers: {{ ctlplane_dns_nameservers }}
           members:
           - type: sriov_vf
             device: nic3
             vfid: 1
             vlan_id: {{ lookup(vars, networks_lower[storage] ~ _vlan_id) }}
           - type: sriov_vf
             device: nic4
             vfid: 1
             vlan_id: {{ lookup(vars, networks_lower[storage] ~ _vlan_id) }}
           addresses:
           - ip_netmask: {{ lookup(vars, networks_lower[storage] ~ _ip) }}/{{ lookup(vars, networks_lower[storage] ~ _cidr) }}
         - type: linux_bond
           name: mgmtst_bond
           use_dhcp: false
           bonding_options: "mode=active-backup"
           dns_servers: {{ ctlplane_dns_nameservers }}
           members:
           - type: sriov_vf
             device: nic3
             vfid: 2
             vlan_id: {{ lookup(vars, networks_lower[storagemgmt] ~ _vlan_id) }}
           - type: sriov_vf
             device: nic4
             vfid: 2
             vlan_id: {{ lookup(vars, networks_lower[storagemgmt] ~ _vlan_id) }}
           addresses:
           - ip_netmask: {{ lookup(vars, networks_lower[storagemgmt] ~ _ip) }}/{{ lookup(vars, networks_lower[storagemgmt] ~ _cidr) }}
         - type: ovs_user_bridge
           name: br-link0
           use_dhcp: false
           mtu: 9000
           ovs_extra: "set port br-link0 tag={{ lookup(vars, networks_lower[tenant] ~ _vlan_id) }}"
           addresses:
           - ip_netmask: {{ lookup(vars, networks_lower[tenant] ~ _ip) }}/{{ lookup(vars, networks_lower[tenant] ~ _cidr) }}
           members:
           - type: ovs_dpdk_bond
             name: dpdkbond0
             mtu: 9000
             rx_queue: 1
             members:
             - type: ovs_dpdk_port
               name: dpdk0
               members:
               - type: sriov_vf
                 device: nic3
                 vfid: 3
             - type: ovs_dpdk_port
               name: dpdk1
               members:
               - type: sriov_vf
                 device: nic4
                 vfid: 3
         - type: ovs_user_bridge
           name: br-dpdk0
           use_dhcp: false
           mtu: 9000
           rx_queue: 1
           members:
             - type: ovs_dpdk_port
               name: dpdk2
               members:
                 - type: interface
                   name: nic5
         - type: sriov_pf
           name: nic6
           mtu: 9000
           numvfs: 5
           use_dhcp: false
           defroute: false
         - type: sriov_pf
           name: nic7
           mtu: 9000
           numvfs: 5
           use_dhcp: false
           defroute: false

10.11. Deploying the data plane

Use the OpenStackDataPlaneDeployment CRD and custom resources (CRs) to configure the services on the data plane nodes and deploy the data plane.

You control the execution of Ansible on the data plane by creating OpenStackDataPlaneDeployment custom resources (CRs). Each OpenStackDataPlaneDeployment CR models a single Ansible execution.

When the OpenStackDataPlaneDeployment successfully completes execution, it does not automatically run the Ansible again, even if the OpenStackDataPlaneDeployment or related OpenStackDataPlaneNodeSet resources are changed. To start another Ansible execution, you must create another OpenStackDataPlaneDeployment CR.

Create an OpenStackDataPlaneDeployment (CR) that deploys each of your OpenStackDataPlaneNodeSet CRs.

Procedure

  1. Create a file on your workstation named openstack_data_plane_deploy.yaml to define the OpenStackDataPlaneDeployment CR:

    apiVersion: dataplane.openstack.org/v1beta1
    kind: OpenStackDataPlaneDeployment
    metadata:
      name: openstack-data-plane
    • name - The OpenStackDataPlaneDeployment CR name must be unique, must consist of lower case alphanumeric characters, - (hyphen) or . (period), and must start and end with an alphanumeric character. Update the name in this example to a name that reflects the node sets in the deployment.
  2. Add all the OpenStackDataPlaneNodeSet CRs that you want to deploy.

    spec:
      nodeSets:
        - openstack-data-plane
        - <nodeSet_name>
        - ...
        - <nodeSet_name>
      services:
      ...
    • Replace <nodeSet_name> with the names of the OpenStackDataPlaneNodeSet CRs that you want to include in your data plane deployment, for example, openstack_preprovisioned_node_set.yaml or openstack_unprovisioned_node_set.yaml.
  3. Save the openstack_data_plane_deploy.yaml deployment file.
  4. Deploy the data plane:

    $ oc create -f openstack_data_plane_deploy.yaml -n openstack

    You can view the Ansible logs while the deployment executes:

    $ oc get pod -l app=openstackansibleee -w
    $ oc logs -l app=openstackansibleee -f --max-log-requests 10
  5. Confirm that the data plane is deployed:

    $ oc get openstackdataplanedeployment -n openstack
    Sample output
    NAME                   STATUS   MESSAGE
    openstack-data-plane   True     Setup Complete
  6. Repeat the oc get command until you see the NodeSet Ready message:

    $ oc get openstackdataplanenodeset -n openstack
    Sample output
    NAME                   STATUS   MESSAGE
    openstack-data-plane   True     NodeSet Ready

    For information about the meaning of the returned status, see Data plane conditions and states.

    If the status indicates that the data plane has not been deployed, then troubleshoot the deployment. For information, see Troubleshooting the data plane creation and deployment.

  7. Map the Compute nodes to the Compute cell that they are connected to:

    $ oc rsh nova-cell0-conductor-0 nova-manage cell_v2 discover_hosts --verbose

    If you did not create additional cells, this command maps the Compute nodes to cell1.

Verification

  • Access the remote shell for the openstackclient pod and confirm that the deployed Compute nodes are visible on the control plane:

    $ oc rsh -n openstack openstackclient
    $ openstack hypervisor list

10.12. Data plane conditions and states

Each data plane resource has a series of conditions within their status subresource that indicates the overall state of the resource, including its deployment progress.

For an OpenStackDataPlaneNodeSet, until an OpenStackDataPlaneDeployment has been started and finished successfully, the Ready condition is False. When the deployment succeeds, the Ready condition is set to True. A subsequent deployment sets the Ready condition to False until the deployment succeeds, when the Ready condition is set to True.

Expand
Table 10.13. OpenStackDataPlaneNodeSet CR conditions
ConditionDescription

Ready

  • "True": The OpenStackDataPlaneNodeSet CR is successfully deployed.
  • "False": The deployment is not yet requested or has failed, or there are other failed conditions.

SetupReady

"True": All setup tasks for a resource are complete. Setup tasks include verifying the SSH key secret, verifying other fields on the resource, and creating the Ansible inventory for each resource. Each service-specific condition is set to "True" when that service completes deployment. You can check the service conditions to see which services have completed their deployment, or which services failed.

DeploymentReady

"True": The NodeSet has been successfully deployed.

InputReady

"True": The required inputs are available and ready.

NodeSetDNSDataReady

"True": DNSData resources are ready.

NodeSetIPReservationReady

"True": The IPSet resources are ready.

NodeSetBaremetalProvisionReady

"True": Bare-metal nodes are provisioned and ready.

Expand
Table 10.14. OpenStackDataPlaneNodeSet status fields
Status fieldDescription

Deployed

  • "True": The OpenStackDataPlaneNodeSet CR is successfully deployed.
  • "False": The deployment is not yet requested or has failed, or there are other failed conditions.

DNSClusterAddresses

 

CtlplaneSearchDomain

 
Expand
Table 10.15. OpenStackDataPlaneDeployment CR conditions
ConditionDescription

Ready

  • "True": The data plane is successfully deployed.
  • "False": The data plane deployment failed, or there are other failed conditions.

DeploymentReady

"True": The data plane is successfully deployed.

InputReady

"True": The required inputs are available and ready.

<NodeSet> Deployment Ready

"True": The deployment has succeeded for the named NodeSet, indicating all services for the NodeSet have succeeded.

<NodeSet> <Service> Deployment Ready

"True": The deployment has succeeded for the named NodeSet and Service. Each <NodeSet> <Service> Deployment Ready specific condition is set to "True" as that service completes successfully for the named NodeSet. Once all services are complete for a NodeSet, the <NodeSet> Deployment Ready condition is set to "True". The service conditions indicate which services have completed their deployment, or which services failed and for which NodeSets.

Expand
Table 10.16. OpenStackDataPlaneDeployment status fields
Status fieldDescription

Deployed

  • "True": The data plane is successfully deployed. All Services for all NodeSets have succeeded.
  • "False": The deployment is not yet requested or has failed, or there are other failed conditions.
Expand
Table 10.17. OpenStackDataPlaneService CR conditions
ConditionDescription

Ready

"True": The service has been created and is ready for use. "False": The service has failed to be created.

To troubleshoot a deployment when services are not deploying or operating correctly, you can check the job condition message for the service, and you can check the logs for a node set.

Each data plane deployment has associated services with a job condition message that reflects the current AnsibleEE job status. You can use this information to troubleshoot services that are not deploying or operating correctly.

Procedure

  1. Determine the name and status of all deployments:

    $ oc get openstackdataplanedeployment

    The following example output shows two deployments currently in progress:

    $ oc get openstackdataplanedeployment
    
    NAME                   NODESETS             STATUS   MESSAGE
    edpm-compute   ["openstack-edpm-ipam"]   False    Deployment in progress
  2. Retrieve and inspect Ansible execution jobs.

    The Kubernetes jobs are labeled with the name of the OpenStackDataPlaneDeployment. You can list jobs for each OpenStackDataPlaneDeployment by using the label:

     $ oc get job -l openstackdataplanedeployment=edpm-compute
     NAME                                                 STATUS     COMPLETIONS   DURATION   AGE
     bootstrap-edpm-compute-openstack-edpm-ipam           Complete   1/1           78s        25h
     configure-network-edpm-compute-openstack-edpm-ipam   Complete   1/1           37s        25h
     configure-os-edpm-compute-openstack-edpm-ipam        Complete   1/1           66s        25h
     download-cache-edpm-compute-openstack-edpm-ipam      Complete   1/1           64s        25h
     install-certs-edpm-compute-openstack-edpm-ipam       Complete   1/1           46s        25h
     install-os-edpm-compute-openstack-edpm-ipam          Complete   1/1           57s        25h
     libvirt-edpm-compute-openstack-edpm-ipam             Complete   1/1           2m37s      25h
     neutron-metadata-edpm-compute-openstack-edpm-ipam    Complete   1/1           61s        25h
     nova-edpm-compute-openstack-edpm-ipam                Complete   1/1           3m20s      25h
     ovn-edpm-compute-openstack-edpm-ipam                 Complete   1/1           78s        25h
     run-os-edpm-compute-openstack-edpm-ipam              Complete   1/1           33s        25h
     ssh-known-hosts-edpm-compute                         Complete   1/1           19s        25h
     telemetry-edpm-compute-openstack-edpm-ipam           Complete   1/1           2m5s       25h
     validate-network-edpm-compute-openstack-edpm-ipam    Complete   1/1           16s        25h

    You can check logs by using oc logs -f job/<job-name>, for example, if you want to check the logs from the configure-network job:

     $ oc logs -f jobs/configure-network-edpm-compute-openstack-edpm-ipam | tail -n2
     PLAY RECAP *********************************************************************
     edpm-compute-0             : ok=22   changed=0    unreachable=0    failed=0    skipped=17   rescued=0    ignored=0

10.13.1.1. Job condition messages

AnsibleEE jobs have an associated condition message that indicates the current state of the service job. This condition message is displayed in the MESSAGE field of the oc get job <job_name> command output. Jobs return one of the following conditions when queried:

  • Job not started: The job has not started.
  • Job not found: The job could not be found.
  • Job is running: The job is currently running.
  • Job complete: The job execution is complete.
  • Job error occurred <error_message>: The job stopped executing unexpectedly. The <error_message> is replaced with a specific error message.

To further investigate a service that is displaying a particular job condition message, view its logs by using the command oc logs job/<service>. For example, to view the logs for the repo-setup-openstack-edpm service, use the command oc logs job/repo-setup-openstack-edpm.

10.13.2. Checking the logs for a node set

You can access the logs for a node set to check for deployment issues.

Procedure

  1. Retrieve pods with the OpenStackAnsibleEE label:

    $ oc get pods -l app=openstackansibleee
    configure-network-edpm-compute-j6r4l   0/1     Completed           0          3m36s
    validate-network-edpm-compute-6g7n9    0/1     Pending             0          0s
    validate-network-edpm-compute-6g7n9    0/1     ContainerCreating   0          11s
    validate-network-edpm-compute-6g7n9    1/1     Running             0          13s
  2. SSH into the pod you want to check:

    1. Pod that is running:

      $ oc rsh validate-network-edpm-compute-6g7n9
    2. Pod that is not running:

      $ oc debug configure-network-edpm-compute-j6r4l
  3. List the directories in the /runner/artifacts mount:

    $ ls /runner/artifacts
    configure-network-edpm-compute
    validate-network-edpm-compute
  4. View the stdout for the required artifact:

    $ cat /runner/artifacts/configure-network-edpm-compute/stdout
Red Hat logoGithubredditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat Documentation

Legal Notice

Theme

© 2026 Red Hat
Back to top