diff --git a/devstack/local.conf.ovn.sample b/devstack/local.conf.ovn.sample index f5889559f..7eaefface 100644 --- a/devstack/local.conf.ovn.sample +++ b/devstack/local.conf.ovn.sample @@ -43,9 +43,25 @@ OVS_HOST_PATH=/usr/local/var/run/openvswitch # OCTAVIA KURYR_K8S_LBAAS_USE_OCTAVIA=True + # Uncomment it to use L2 communication between loadbalancer and member pods # KURYR_K8S_OCTAVIA_MEMBER_MODE=L2 + +# Kuryr K8S-Endpoint driver Octavia provider +# ========================================== +# Kuryr uses LBaaS to provide the Kubernetes services +# functionality. +# In case Octavia is used for LBaaS, you can choose the +# Octavia's Load Balancer provider. +# KURYR_EP_DRIVER_OCTAVIA_PROVIDER=default +# Uncomment the next two to enable ovn provider. Note only L2 mode is +# supported +# KURYR_EP_DRIVER_OCTAVIA_PROVIDER=ovn +# KURYR_K8S_OCTAVIA_MEMBER_MODE=L2 + + + if [[ "$KURYR_K8S_LBAAS_USE_OCTAVIA" == "True" ]]; then # Octavia LBaaSv2 LIBS_FROM_GIT+=python-octaviaclient @@ -248,3 +264,5 @@ fi [[post-config|$OCTAVIA_CONF]] [controller_worker] amp_active_retries=9999 +[api_settings] +enabled_provider_drivers = amphora:'Octavia Amphora driver',ovn:'Octavia OVN driver' diff --git a/devstack/plugin.sh b/devstack/plugin.sh index f98cb4dff..60a0bc179 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -457,6 +457,7 @@ function configure_neutron_defaults { # FIXME(dulek): This might be removed when bug 1753653 is fixed and # Kuryr restarts waiting for LB on timeouts. iniset "$KURYR_CONFIG" neutron_defaults lbaas_activation_timeout 1200 + iniset "$KURYR_CONFIG" kubernetes endpoints_driver_octavia_provider "$KURYR_EP_DRIVER_OCTAVIA_PROVIDER" fi } diff --git a/devstack/settings b/devstack/settings index 871726aa8..127a9433c 100644 --- a/devstack/settings +++ b/devstack/settings @@ -69,6 +69,9 @@ KURYR_CONFIGURE_BAREMETAL_KUBELET_IFACE=${KURYR_CONFIGURE_BAREMETAL_KUBELET_IFAC # Kubernetes containerized deployment KURYR_K8S_CONTAINERIZED_DEPLOYMENT=${KURYR_K8S_CONTAINERIZED_DEPLOYMENT:-False} +# Kuryr Endpoint LBaaS OCTAVIA provider +KURYR_EP_DRIVER_OCTAVIA_PROVIDER=${KURYR_EP_DRIVER_OCTAVIA_PROVIDER:-default} + # Kuryr VIF driver KURYR_POD_VIF_DRIVER=${KURYR_POD_VIF_DRIVER:-neutron-vif} diff --git a/kuryr_kubernetes/clients.py b/kuryr_kubernetes/clients.py index 4cf75e777..a7e3901ce 100644 --- a/kuryr_kubernetes/clients.py +++ b/kuryr_kubernetes/clients.py @@ -66,7 +66,12 @@ def setup_loadbalancer_client(): service_type='load-balancer') lbaas_client.httpclient = octo_httpclient _clients[_LB_CLIENT] = lbaas_client - lbaas_client.cascading_capable = True + # FIXME(ltomasbo): For now ovn provider is not able to work with + # cascade loadbalancer deletion. Remove when fixed + if config.CONF.kubernetes.endpoints_driver_octavia_provider == 'ovn': + lbaas_client.cascading_capable = False + else: + lbaas_client.cascading_capable = True def setup_kubernetes_client(): diff --git a/kuryr_kubernetes/config.py b/kuryr_kubernetes/config.py index 06628d6b8..99d88d0cb 100644 --- a/kuryr_kubernetes/config.py +++ b/kuryr_kubernetes/config.py @@ -143,6 +143,10 @@ k8s_opts = [ deprecated_reason="Default and supported lbaas endpoint is " "now Octavia", deprecated_since="Rocky"), + cfg.StrOpt('endpoints_driver_octavia_provider', + help=_("The Octavia load balancer provider that will be used " + "to support Kubernetes Endpoints"), + default='default'), cfg.StrOpt('vif_pool_driver', help=_("The driver that manages VIFs pools for " "Kubernetes Pods"), diff --git a/kuryr_kubernetes/controller/handlers/lbaas.py b/kuryr_kubernetes/controller/handlers/lbaas.py index d93f902fb..4515d9847 100644 --- a/kuryr_kubernetes/controller/handlers/lbaas.py +++ b/kuryr_kubernetes/controller/handlers/lbaas.py @@ -229,6 +229,15 @@ class LoadBalancerHandler(k8s_base.ResourceEventHandler): self._drv_pod_project = drv_base.PodProjectDriver.get_instance() self._drv_pod_subnets = drv_base.PodSubnetsDriver.get_instance() self._drv_service_pub_ip = drv_base.ServicePubIpDriver.get_instance() + # Note(yboaron) LBaaS driver supports 'provider' parameter in + # Load Balancer creation flow. + # We need to set the requested load balancer provider + # according to 'endpoints_driver_octavia_provider' configuration. + self._lb_provider = None + if (config.CONF.kubernetes.endpoints_driver_octavia_provider + != 'default'): + self._lb_provider = ( + config.CONF.kubernetes.endpoints_driver_octavia_provider) def on_present(self, endpoints): lbaas_spec = self._get_lbaas_spec(endpoints) @@ -573,7 +582,8 @@ class LoadBalancerHandler(k8s_base.ResourceEventHandler): subnet_id=lbaas_spec.subnet_id, ip=lbaas_spec.ip, security_groups_ids=lbaas_spec.security_groups_ids, - service_type=lbaas_spec.type) + service_type=lbaas_spec.type, + provider=self._lb_provider) if lbaas_state.service_pub_ip_info is None: service_pub_ip_info = ( self._drv_service_pub_ip.acquire_service_pub_ip_info( diff --git a/kuryr_kubernetes/tests/unit/controller/handlers/test_lbaas.py b/kuryr_kubernetes/tests/unit/controller/handlers/test_lbaas.py index 02ef3c06b..5b0258676 100644 --- a/kuryr_kubernetes/tests/unit/controller/handlers/test_lbaas.py +++ b/kuryr_kubernetes/tests/unit/controller/handlers/test_lbaas.py @@ -352,12 +352,13 @@ class TestLBaaSSpecHandler(test_base.TestCase): class FakeLBaaSDriver(drv_base.LBaaSDriver): def ensure_loadbalancer(self, name, project_id, subnet_id, ip, - security_groups_ids, service_type): + security_groups_ids, service_type, provider=None): return obj_lbaas.LBaaSLoadBalancer(name=name, project_id=project_id, subnet_id=subnet_id, ip=ip, - id=str(uuid.uuid4())) + id=str(uuid.uuid4()), + provider=provider) def ensure_listener(self, loadbalancer, protocol, port, service_type='ClusterIP'): @@ -446,6 +447,7 @@ class FakeLBaaSDriver(drv_base.LBaaSDriver): class TestLoadBalancerHandler(test_base.TestCase): + @mock.patch('kuryr_kubernetes.config.CONF') @mock.patch('kuryr_kubernetes.controller.drivers.base' '.ServicePubIpDriver.get_instance') @mock.patch('kuryr_kubernetes.controller.drivers.base' @@ -455,17 +457,44 @@ class TestLoadBalancerHandler(test_base.TestCase): @mock.patch('kuryr_kubernetes.controller.drivers.base' '.LBaaSDriver.get_instance') def test_init(self, m_get_drv_lbaas, m_get_drv_project, - m_get_drv_subnets, m_get_drv_service_pub_ip): + m_get_drv_subnets, m_get_drv_service_pub_ip, m_cfg): m_get_drv_lbaas.return_value = mock.sentinel.drv_lbaas m_get_drv_project.return_value = mock.sentinel.drv_project m_get_drv_subnets.return_value = mock.sentinel.drv_subnets m_get_drv_service_pub_ip.return_value = mock.sentinel.drv_lb_ip + m_cfg.kubernetes.endpoints_driver_octavia_provider = 'default' handler = h_lbaas.LoadBalancerHandler() self.assertEqual(mock.sentinel.drv_lbaas, handler._drv_lbaas) self.assertEqual(mock.sentinel.drv_project, handler._drv_pod_project) self.assertEqual(mock.sentinel.drv_subnets, handler._drv_pod_subnets) self.assertEqual(mock.sentinel.drv_lb_ip, handler._drv_service_pub_ip) + self.assertIsNone(handler._lb_provider) + + @mock.patch('kuryr_kubernetes.config.CONF') + @mock.patch('kuryr_kubernetes.controller.drivers.base' + '.ServicePubIpDriver.get_instance') + @mock.patch('kuryr_kubernetes.controller.drivers.base' + '.PodSubnetsDriver.get_instance') + @mock.patch('kuryr_kubernetes.controller.drivers.base' + '.PodProjectDriver.get_instance') + @mock.patch('kuryr_kubernetes.controller.drivers.base' + '.LBaaSDriver.get_instance') + def test_init_provider_ovn(self, m_get_drv_lbaas, m_get_drv_project, + m_get_drv_subnets, m_get_drv_service_pub_ip, + m_cfg): + m_get_drv_lbaas.return_value = mock.sentinel.drv_lbaas + m_get_drv_project.return_value = mock.sentinel.drv_project + m_get_drv_subnets.return_value = mock.sentinel.drv_subnets + m_get_drv_service_pub_ip.return_value = mock.sentinel.drv_lb_ip + m_cfg.kubernetes.endpoints_driver_octavia_provider = 'ovn' + handler = h_lbaas.LoadBalancerHandler() + + self.assertEqual(mock.sentinel.drv_lbaas, handler._drv_lbaas) + self.assertEqual(mock.sentinel.drv_project, handler._drv_pod_project) + self.assertEqual(mock.sentinel.drv_subnets, handler._drv_pod_subnets) + self.assertEqual(mock.sentinel.drv_lb_ip, handler._drv_service_pub_ip) + self.assertEqual('ovn', handler._lb_provider) def test_on_present(self): lbaas_spec = mock.sentinel.lbaas_spec