svc namespace isolation support for different octavia drivers

This patch ensures svc namespace isolation may work with different
types of octavia drivers. Depending on the ownership of the security
group, as well as the tenant kuryr-controller is running on, there
may be a need to create (and apply) a new security group for the
loadbalancer VIP port, or simply update the existing one.

A new configuration option, names sg_mode has been added that
accepts update|create depending on the desired behavior.

As of today, the options will be:
- Amphora driver: needs to 'update' the SG as the VIP port is connected
to the amphora through the allow_address_pair option, and the SG
rules are enforced on the amphora port rather than on the VIP port.
However, as both ports share the same SG, updating it will ensure
the proper isolation. Note the SG in the amphora driver belongs to
the admin tenant instead of the one creating the loadbalancer.
- OVN driver: SG is applied directly on the VIP port, so both
updating or creating a SG will work as the VIP port belongs to the
tenant. However, as of today OVN-driver does not create a SG for
the loadbalancer and the SG applied is the default one. Thus, there
is a need for setting the sg_mode to 'create', so that a new one is
created and the proper rules are applied there.

Implements: blueprint octavia-ovn-provider
Change-Id: I4ad4d55b75ce7a6d5e102b5f35bedc07af4fbb96
This commit is contained in:
Luis Tomas Bolivar 2018-09-24 11:44:36 +02:00
parent 5963d01731
commit 451add3543
5 changed files with 68 additions and 26 deletions

View File

@ -55,10 +55,11 @@ KURYR_K8S_LBAAS_USE_OCTAVIA=True
# 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
# Uncomment the next lines to enable ovn provider. Note L2 mode is used
# to ensure member subnet is added
# KURYR_EP_DRIVER_OCTAVIA_PROVIDER=ovn
# KURYR_K8S_OCTAVIA_MEMBER_MODE=L2
# KURYR_K8S_OCTAVIA_SG_MODE=create

View File

@ -450,6 +450,7 @@ function configure_neutron_defaults {
fi
iniset "$KURYR_CONFIG" neutron_defaults external_svc_net "$ext_svc_net_id"
iniset "$KURYR_CONFIG" octavia_defaults member_mode "$KURYR_K8S_OCTAVIA_MEMBER_MODE"
iniset "$KURYR_CONFIG" octavia_defaults sg_mode "$KURYR_K8S_OCTAVIA_SG_MODE"
if [[ "$use_octavia" == "True" ]]; then
# Octavia takes a very long time to start the LB in the gate. We need
# to tweak the timeout for the LB creation. Let's be generous and give

View File

@ -62,6 +62,7 @@ OPENSHIFT_CNI_BINARY_URL=${OPENSHIFT_CNI_BINARY_URL:-https://github.com/containe
# Octavia
KURYR_K8S_LBAAS_USE_OCTAVIA=${KURYR_K8S_LBAAS_USE_OCTAVIA:-True}
KURYR_K8S_OCTAVIA_MEMBER_MODE=${KURYR_K8S_OCTAVIA_MEMBER_MODE:-L3}
KURYR_K8S_OCTAVIA_SG_MODE=${KURYR_K8S_OCTAVIA_SG_MODE:-update}
# Kuryr_ovs_baremetal
KURYR_CONFIGURE_BAREMETAL_KUBELET_IFACE=${KURYR_CONFIGURE_BAREMETAL_KUBELET_IFACE:-True}

View File

@ -219,6 +219,11 @@ octavia_defaults = [
help=_("Define the communication mode between load balanacer "
"and its members"),
default='L3'),
cfg.StrOpt('sg_mode',
help=_("Define the LBaaS SG policy."),
choices=[('create', 'replace the VIP SG with a new one'),
('update', 'add rules to the existing VIP SG')],
default='update'),
]
cache_defaults = [

View File

@ -89,13 +89,17 @@ class LBaaSv2Driver(base.LBaaSDriver):
self._release(loadbalancer, loadbalancer,
lbaas.delete_loadbalancer, loadbalancer.id)
sg_id = self._find_listeners_sg(loadbalancer)
if sg_id:
try:
neutron.delete_security_group(sg_id)
except n_exc.NeutronClientException:
LOG.exception('Error when deleting loadbalancer security '
'group. Leaving it orphaned.')
sg_id = self._find_listeners_sg(loadbalancer)
if sg_id:
# Note: reusing activation timeout as deletion timeout
self._wait_for_deletion(loadbalancer, _ACTIVATION_TIMEOUT)
try:
neutron.delete_security_group(sg_id)
except n_exc.NeutronClientException:
LOG.exception('Error when deleting loadbalancer security '
'group. Leaving it orphaned.')
except n_exc.NotFound:
LOG.debug('Security group %s already deleted', sg_id)
def _ensure_security_groups(self, loadbalancer, service_type):
# We only handle SGs for legacy LBaaSv2, Octavia handles it dynamically
@ -152,24 +156,45 @@ class LBaaSv2Driver(base.LBaaSDriver):
def _extend_lb_security_group_rules(self, loadbalancer, listener):
neutron = clients.get_neutron_client()
sg_id = self._get_vip_port(loadbalancer).get('security_groups')[0]
if CONF.octavia_defaults.sg_mode == 'create':
sg_id = self._find_listeners_sg(loadbalancer)
# if an SG for the loadbalancer has not being created, create one
if not sg_id:
sg = neutron.create_security_group({
'security_group': {
'name': loadbalancer.name,
'project_id': loadbalancer.project_id,
},
})
sg_id = sg['security_group']['id']
loadbalancer.security_groups.append(sg_id)
vip_port = self._get_vip_port(loadbalancer)
neutron.update_port(
vip_port.get('id'),
{'port': {
'security_groups': loadbalancer.security_groups}})
else:
sg_id = self._get_vip_port(loadbalancer).get('security_groups')[0]
for sg in loadbalancer.security_groups:
try:
neutron.create_security_group_rule({
'security_group_rule': {
'direction': 'ingress',
'port_range_min': listener.port,
'port_range_max': listener.port,
'protocol': listener.protocol,
'security_group_id': sg_id,
'remote_group_id': sg,
'description': listener.name,
},
})
except n_exc.NeutronClientException as ex:
if ex.status_code != requests.codes.conflict:
LOG.exception('Failed when creating security group rule '
'for listener %s.', listener.name)
if sg != sg_id:
try:
neutron.create_security_group_rule({
'security_group_rule': {
'direction': 'ingress',
'port_range_min': listener.port,
'port_range_max': listener.port,
'protocol': listener.protocol,
'security_group_id': sg_id,
'remote_group_id': sg,
'description': listener.name,
},
})
except n_exc.NeutronClientException as ex:
if ex.status_code != requests.codes.conflict:
LOG.exception('Failed when creating security group '
'rule for listener %s.', listener.name)
# ensure routes have access to the services
service_subnet_cidr = self._get_subnet_cidr(loadbalancer.subnet_id)
@ -540,6 +565,15 @@ class LBaaSv2Driver(base.LBaaSDriver):
raise k_exc.ResourceNotReady(loadbalancer)
def _wait_for_deletion(self, loadbalancer, timeout):
lbaas = clients.get_loadbalancer_client()
for remaining in self._provisioning_timer(timeout):
try:
lbaas.show_loadbalancer(loadbalancer.id)
except n_exc.NotFound:
return
def _provisioning_timer(self, timeout):
# REVISIT(ivc): consider integrating with Retry
interval = 3