diff --git a/defaults/main.yml b/defaults/main.yml index 843d147b..23059c3a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -65,6 +65,8 @@ neutron_dynamic_routing_git_repo: https://opendev.org/openstack/neutron-dynamic- neutron_dynamic_routing_git_install_branch: master networking_odl_git_repo: https://opendev.org/openstack/networking-odl networking_odl_git_install_branch: master +networking_ovn_bgp_git_repo: https://opendev.org/openstack/ovn-bgp-agent +networking_ovn_bgp_install_branch: master networking_sfc_git_repo: https://opendev.org/openstack/networking-sfc networking_sfc_git_install_branch: master networking_bgpvpn_git_repo: https://opendev.org/openstack/networking-bgpvpn @@ -164,6 +166,8 @@ neutron_neutron_conf_overrides: {} neutron_nuage_conf_ini_overrides: {} neutron_openvswitch_agent_ini_overrides: {} neutron_openvswitch_agent_init_overrides: {} +neutron_ovn_bgp_agent_ini_overrides: {} +neutron_ovn_bgp_agent_init_overrides: {} neutron_nsx_conf_ini_overrides: {} # Provide a list of access controls to update the default policy.json with. # These changes will be merged @@ -521,6 +525,32 @@ neutron_ovsdb_manager_connection: "{{ [neutron_ovsdb_manager_proto, neutron_ovsd neutron_ovn_sb_inactivity_probe: 60000 neutron_ovn_nb_inactivity_probe: 60000 +# OVN BGP Agent +neutron_ovn_bgp_enable: False +neutron_ovn_bgp_agent_group: "{{ neutron_ovn_distributed_fip | ternary('neutron_ovn_controller', 'neutron_ovn_gateway') }}" +neutron_ovn_bgp_agent_driver: nb_ovn_bgp_driver +neutron_ovn_bgp_exposing_method: underlay +neutron_ovn_bgp_expose_tenant_networks: False +neutron_ovn_bgp_expose_ipv6_gua_tenant_networks: False +# Provide config needed for BGP peering +# neutron_ovn_bgp_config: +# AS: 64999 +# nic: bgp-nic +# vrf: bgp-vrf +# vrf_table_id: 10 +neutron_ovn_bgp_config: {} +neutron_frr_bgp_config: [] +neutron_frr_staticd_routes: [] + +# This section is used when neutron_ovn_bgp_exposing_method +# is set to "ovn". +# This requires a standalone "local" cluster per node where +# ovn-bgp-agent runs. +neutron_ovn_bgp_local_nbdb: tcp:127.0.0.1:6641 +neutron_ovn_bgp_local_nics: [] +neutron_ovn_bgp_local_peers: [] +neutron_ovn_bgp_provider_networks_prefixes: [] + # Storage location for SSL certificate authority neutron_ovn_pki_dir: "{{ openstack_pki_dir }}" # Delegated host for operating the certificate authority diff --git a/doc/source/configure-network-services.rst b/doc/source/configure-network-services.rst index 7d76fd23..cfd47c47 100644 --- a/doc/source/configure-network-services.rst +++ b/doc/source/configure-network-services.rst @@ -200,6 +200,80 @@ Routing plugin. # openstack-ansible os-neutron-install.yml +OVN BGP Agent (optional) +~~~~~~~~~~~~~~~~~~~~~~~~ + +The `OVN BGP Agent`_ exposes VM Floating IPs on provider networks through BGP +by leveraging `FRRouting`_. + +This intends to provide feature-complete replacement for BGP Dynamic Routing +service for environments running OVN as their ml2 plugin. + +`OVN BGP Agent`_ provides multiple drivers and exposure methods which can be +checked on the `BGP Supportability Matrix`_ + +.. NOTE:: + + At the moment of writing only ``underlay`` exposure method is fully + supported by ``os_neutron`` role. + +In order to enable ovn-bgp-agent you need to explicitly configure some +variables: + +.. code-block:: yaml + + neutron_ovn_bgp_enable: True + # This defines an AS to which ovn-bgp-agent will inject an VRF to FRR + neutron_ovn_bgp_config: + AS: 64513 + + # In this variable we define a base configuration for FRR that will be + # deployed as pre-requisite of ovn-bgp-agent + neutron_frr_bgp_config: + - router bgp 64513 + - "bgp router-id {{ ansible_facts['bond0']['ipv4']['address'] }}" + - bgp log-neighbor-changes + - bgp graceful-shutdown + - neighbor uplink peer-group + - neighbor uplink remote-as 64512 + - neighbor uplink ebgp-multihop + - neighbor 203.0.113.10 peer-group uplink + - neighbor 203.0.113.11 peer-group uplink + - neighbor 203.0.113.10 description leaf_1 + - neighbor 203.0.113.11 description leaf_2 + - address-family ipv4 unicast + - " redistribute connected" + - " neighbor uplink activate" + - " neighbor uplink allowas-in origin" + - " neighbor uplink prefix-list only-host-prefixes out" + - "exit-address-family" + - "ip prefix-list only-default permit 0.0.0.0/0" + - "ip prefix-list only-host-prefixes permit 0.0.0.0/0 ge 32" + - route-map rm-only-default permit 10 + - " match ip address prefix-list only-default" + - " set src {{ ansible_facts['bond0']['ipv4']['address'] }}" + - ip protocol bgp route-map rm-only-default + + # This variable might be useful for ebgp-multihop scenarios + neutron_frr_staticd_routes: + - ip route 203.0.113.10/32 198.51.100.1 + - ip route 203.0.113.10/32 198.51.100.1 + + +Once all required variables are set, running +``openstack-ansible os-neutron-install.yml`` should install and configure +FRRouting on all of your ``neutron_ovn_controller`` as well as a new service +``neutron-ovn-bgp-agent`` will appear. + +This service does not use RabbitMQ for communication and listens for events +directly on OVN NB/SB databases, so it will not appear on +``openstack network agent list`` output like one may assume. + +.. _OVN BGP Agent: https://docs.openstack.org/ovn-bgp-agent/latest/index.html +.. _FRRouting: https://docs.frrouting.org/en/latest/bgp.html +.. _BGP Supportability Matrix: https://docs.openstack.org/ovn-bgp-agent/latest/bgp_supportability_matrix.html + + SR-IOV Support (optional) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/files/rootwrap.d/ovn-bgp.filters b/files/rootwrap.d/ovn-bgp.filters new file mode 100644 index 00000000..da3cc0cd --- /dev/null +++ b/files/rootwrap.d/ovn-bgp.filters @@ -0,0 +1,13 @@ +# ovn-bgp-agent-rootwrap command filters for scripts +# This file should be owned by (and only-writable by) the root user + +[Filters] +# privileged/__init__.py: priv_context.PrivContext(default) +# This line ties the superuser privs with the config files, context name, +# and (implicitly) the actual python code invoked. +privsep-rootwrap: RegExpFilter, privsep-helper, root, privsep-helper, --config-file, /etc/(?!\.\.).*, --privsep_context, ovn_bgp_agent.privileged.default, --privsep_sock_path, /tmp/.* + +ovs-vsctl: CommandFilter, ovs-vsctl, root +sysctl: CommandFilter, sysctl, root +ip: IpFilter, ip, root +vtysh: CommandFilter, vtysh, root diff --git a/tasks/neutron_install.yml b/tasks/neutron_install.yml index 42c49c84..485eb649 100644 --- a/tasks/neutron_install.yml +++ b/tasks/neutron_install.yml @@ -52,6 +52,21 @@ delay: 2 with_items: "{{ neutron_remove_distro_packages }}" +- name: Include FRR role for OVN BGP Agent + include_role: + name: frrouting + apply: + tags: + - frrouting + vars: + frr_bgpd_config: "{{ neutron_frr_bgp_config }}" + frr_staticd_routes: "{{ neutron_frr_staticd_routes }}" + when: + - neutron_ovn_bgp_enable | bool + - neutron_services['neutron-ovn-bgp-agent']['group'] in group_names + tags: + - always + # NOTE(jrosser) # ceilometer appears in u-c as is used by networking-odl stats plugin. # the new pip resolver will fail to install ceilometer if two contradictory diff --git a/tasks/providers/setup_ovs_ovn.yml b/tasks/providers/setup_ovs_ovn.yml index 5bfe5d1e..31625b55 100644 --- a/tasks/providers/setup_ovs_ovn.yml +++ b/tasks/providers/setup_ovs_ovn.yml @@ -73,11 +73,16 @@ - neutron_services['neutron-ovn-controller']['group'] in group_names - neutron_provider_networks.network_mappings is defined and (neutron_provider_networks.network_mappings|length > 0) +# NOTE(noonedeadpunk): When ovn-bgp-agent is in use, physical interfaces should not be added the OVS +# bridge directly. - name: Add ports to Network Provider Bridges + vars: + _neutron_attach_ovs_port_for_bgp: >- + {{ (neutron_ovn_bgp_enable and neutron_services['neutron-ovn-bgp-agent']['group'] in group_names) | ternary('absent', 'present') }} openvswitch_port: bridge: "{{ interface_mapping.split(':')[0] }}" port: "{{ interface_mapping.split(':')[1] }}" - state: present + state: "{{ _neutron_attach_ovs_port_for_bgp }}" with_items: "{{ neutron_provider_networks.network_interface_mappings.split(',') }}" loop_control: loop_var: interface_mapping diff --git a/templates/neutron_ovn_bgp_agent.ini.j2 b/templates/neutron_ovn_bgp_agent.ini.j2 new file mode 100644 index 00000000..4e373287 --- /dev/null +++ b/templates/neutron_ovn_bgp_agent.ini.j2 @@ -0,0 +1,38 @@ +[DEFAULT] +debug = {{ debug }} +expose_tenant_networks = {{ neutron_ovn_bgp_expose_tenant_networks }} +expose_ipv6_gua_tenant_networks = {{ neutron_ovn_bgp_expose_ipv6_gua_tenant_networks }} +driver = {{ neutron_ovn_bgp_agent_driver }} +exposing_method = {{ neutron_ovn_bgp_exposing_method }} + +{% for param, value in neutron_ovn_bgp_config.items() %} +bgp_{{ param }} = {{ value }} +{% endfor %} + +ovsdb_connection = {{ neutron_ovsdb_manager_connection }} +ovsdb_connection_timeout = 180 + +[agent] +root_helper=sudo {{ neutron_bin }}/ovn-bgp-agent-rootwrap {{ neutron_conf_dir }}/rootwrap.conf +root_helper_daemon=sudo {{ neutron_bin }}/ovn-bgp-agent-rootwrap-daemon {{ neutron_conf_dir }}/rootwrap.conf + +[ovn] +ovn_nb_connection = {{ neutron_ovn_nb_connection }} +ovn_sb_connection = {{ neutron_ovn_sb_connection }} + +{% if neutron_ovn_ssl %} +ovn_sb_ca_cert={{ [neutron_conf_version_dir, neutron_ovn_ssl_ca_cert] | join('/') }} +ovn_sb_certificate={{ [neutron_conf_version_dir, neutron_ovn_ssl_cert] | join('/') }} +ovn_sb_private_key={{ [neutron_conf_version_dir, neutron_ovn_ssl_key] | join('/') }} +ovn_nb_ca_cert={{ [neutron_conf_version_dir, neutron_ovn_ssl_ca_cert] | join('/') }} +ovn_nb_certificate={{ [neutron_conf_version_dir, neutron_ovn_ssl_cert] | join('/') }} +ovn_nb_private_key={{ [neutron_conf_version_dir, neutron_ovn_ssl_key] | join('/') }} +{% endif %} + +{% if neutron_ovn_bgp_exposing_method == 'ovn' %} +[local_ovn_cluster] +ovn_nb_connection = {{ neutron_ovn_bgp_local_nbdb }} +external_nics = {{ neutron_ovn_bgp_local_nics | join(',') }} +peer_ips = {{ neutron_ovn_bgp_local_peers | join(',') }} +provider_networks_pool_prefixes = {{ neutron_ovn_bgp_provider_networks_prefixes | join(',') }} +{% endif %} diff --git a/templates/sudoers.j2 b/templates/sudoers.j2 index 1b134eac..a58c42fd 100644 --- a/templates/sudoers.j2 +++ b/templates/sudoers.j2 @@ -6,3 +6,8 @@ Defaults:{{ neutron_system_user_name }} secure_path="{{ neutron_bin }}:/usr/loca {{ neutron_system_user_name }} ALL = (root) NOPASSWD: {{ neutron_bin }}/{{ neutron_service_name }}-rootwrap {{ neutron_system_user_name }} ALL = (root) NOPASSWD: {{ neutron_bin }}/{{ neutron_service_name }}-rootwrap-daemon {{ neutron_system_user_name }} ALL = (root) NOPASSWD: {{ neutron_bin }}/privsep-helper + +{% if neutron_ovn_bgp_enable | bool %} +{{ neutron_system_user_name }} ALL = (root) NOPASSWD: {{ neutron_bin }}/ovn-bgp-agent-rootwrap +{{ neutron_system_user_name }} ALL = (root) NOPASSWD: {{ neutron_bin }}/ovn-bgp-agent-rootwrap-daemon +{% endif %} diff --git a/vars/main.yml b/vars/main.yml index 214c8809..ba33ab4f 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -58,6 +58,9 @@ neutron_optional_oslomsg_amqp1_pip_packages: neutron_optional_bgp_pip_packages: - "git+{{ neutron_dynamic_routing_git_repo }}@{{ neutron_dynamic_routing_git_install_branch }}#egg=neutron-dynamic-routing" +neutron_optional_ovn_bgp_pip_packages: + - "git+{{ networking_ovn_bgp_git_repo }}@{{ networking_ovn_bgp_install_branch }}#egg=ovn-bgp-agent" + neutron_optional_fwaas_pip_packages: - "git+{{ neutron_fwaas_git_repo }}@{{ neutron_fwaas_git_install_branch }}#egg=neutron-fwaas" @@ -90,6 +93,10 @@ neutron_venv_packages: >- {%- if neutron_fwaas_v2 | bool %} {%- set _ = pkg_list.extend(neutron_optional_fwaas_pip_packages) %} {%- endif %} + {%- if (neutron_ovn_bgp_enable | bool) and + (neutron_services['neutron-ovn-bgp-agent']['group'] in group_names) %} + {%- set _ = pkg_list.extend(neutron_optional_ovn_bgp_pip_packages) %} + {%- endif %} {%- if neutron_vpnaas | bool %} {%- set _ = pkg_list.extend(neutron_optional_vpnaas_pip_packages) %} {%- endif %} @@ -510,6 +517,19 @@ neutron_services: neutron-ovn-controller: group: neutron_ovn_controller service_en: False + neutron-ovn-bgp-agent: + group: "{{ neutron_ovn_bgp_agent_group }}" + systemd_lock_dir: /run/lock/ovn-bgp-agent + service_name: neutron-ovn-bgp-agent + service_en: "{{ (neutron_plugin_type == 'ml2.ovn') and neutron_ovn_bgp_enable | bool }}" + service_conf_path: "{{ neutron_conf_version_dir }}" + service_conf: neutron_ovn_bgp_agent.ini + service_rootwrap: rootwrap.d/ovn-bgp.filters + execstarts: "{{ neutron_bin }}/ovn-bgp-agent --config-file {{ neutron_conf_dir }}/neutron_ovn_bgp_agent.ini" + config_overrides: "{{ neutron_ovn_bgp_agent_ini_overrides }}" + config_type: "ini" + init_config_overrides: "{{ neutron_ovn_bgp_agent_init_overrides }}" + start_order: 4 neutron-ovn-metadata-agent: group: neutron_ovn_controller systemd_lock_dir: /run/lock/neutron-ovn-metadata