Add support for OVN provider in Endpoint LBaaS driver

The OVN provider was added to Octavia in addition to
the 'amphora' [1].
When the Octavia Load Balancer provider is set to 'ovn', the
Load balancing is executed by the virtual switch data-path
engine and there is no need to create a VM ('amphora') per LB.

This patch does two things:
1. Allows the user to configure the load balancer provider,
   where the default value is set to Octavia's default provider.
2. Updates  Kubernetes Endpoints LBaaS driver to
   support load balancer provider.

[1] 66502f19f2

Partially Implements: blueprint octavia-ovn-provider

Change-Id: I1d1fc521902a593192e832e324bf68baa943f73f
This commit is contained in:
Yossi Boaron 2018-09-17 17:58:46 +03:00 committed by Luis Tomas Bolivar
parent d712d65f5a
commit 5963d01731
7 changed files with 75 additions and 5 deletions

View File

@ -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'

View File

@ -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
}

View File

@ -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}

View File

@ -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():

View File

@ -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"),

View File

@ -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(

View File

@ -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