Browse Source

K8S Services: add support for SCTP

The Octavia API already supports SCTP, though the support for
Amphora driver and OVN driver is still in development. This change
ensures that Octavia loadbalancer has listeners and pools/members
created with SCTP protocol. Kuryr already handles the case where
listener's protocol is not supported by Octavia.

Partially-Implements: blueprint sctp-support
Change-Id: Ia320760807cdffacb91b45d858b90d79354ef962
changes/36/768336/6
Tabitha Fasoyin 1 month ago
parent
commit
c3e66123a5
4 changed files with 38 additions and 5 deletions
  1. +12
    -0
      devstack/plugin.sh
  2. +18
    -3
      kuryr_kubernetes/controller/drivers/lbaasv2.py
  3. +4
    -0
      kuryr_kubernetes/controller/handlers/loadbalancer.py
  4. +4
    -2
      kuryr_kubernetes/tests/unit/test_utils.py

+ 12
- 0
devstack/plugin.sh View File

@ -383,6 +383,12 @@ function configure_neutron_defaults {
--description "k8s service subnet UDP allowed" \
--remote-ip "$service_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol udp \
"$service_pod_access_sg_id"
# Octavia supports SCTP load balancing, we need to also allow SCTP traffic
openstack --os-cloud devstack-admin --os-region "$REGION_NAME" \
security group rule create --project "$project_id" \
--description "k8s service subnet SCTP allowed" \
--remote-ip "$service_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol sctp \
"$service_pod_access_sg_id"
if [[ "$KURYR_K8S_OCTAVIA_MEMBER_MODE" == "L3" ]]; then
if [ -n "$sg_ids" ]; then
@ -418,6 +424,12 @@ function configure_neutron_defaults {
--description "k8s pod subnet allowed from k8s-pod-subnet" \
--remote-ip "$pod_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol udp \
"$octavia_pod_access_sg_id"
# Octavia supports SCTP load balancing, we need to also support SCTP traffic
openstack --os-cloud devstack-admin --os-region "$REGION_NAME" \
security group rule create --project "$project_id" \
--description "k8s pod subnet allowed from k8s-pod-subnet" \
--remote-ip "$pod_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol sctp \
"$octavia_pod_access_sg_id"
if [ -n "$sg_ids" ]; then
sg_ids+=",${octavia_pod_access_sg_id}"
else


+ 18
- 3
kuryr_kubernetes/controller/drivers/lbaasv2.py View File

@ -48,6 +48,7 @@ _OCTAVIA_TAGGING_VERSION = 2, 5
_OCTAVIA_DL_VERSION = 2, 13
_OCTAVIA_ACL_VERSION = 2, 12
_OCTAVIA_PROVIDER_VERSION = 2, 6
_OCTAVIA_SCTP_VERSION = 2, 23
# HTTP Codes raised by Octavia when a Resource already exists
OKAY_CODES = (409, 500)
@ -63,6 +64,7 @@ class LBaaSv2Driver(base.LBaaSDriver):
self._octavia_acls = False
self._octavia_double_listeners = False
self._octavia_providers = False
self._octavia_sctp = False
# Check if Octavia API supports tagging.
# TODO(dulek): *Maybe* this can be replaced with
# lbaas.get_api_major_version(version=_OCTAVIA_TAGGING_VERSION)
@ -79,6 +81,9 @@ class LBaaSv2Driver(base.LBaaSDriver):
if v >= _OCTAVIA_TAGGING_VERSION:
LOG.info('Octavia supports resource tags.')
self._octavia_tags = True
if v >= _OCTAVIA_SCTP_VERSION:
LOG.info('Octavia API supports SCTP protocol.')
self._octavia_sctp = True
else:
v_str = '%d.%d' % v
LOG.warning('[neutron_defaults]resource_tags is set, but Octavia '
@ -94,6 +99,9 @@ class LBaaSv2Driver(base.LBaaSDriver):
def providers_supported(self):
return self._octavia_providers
def sctp_supported(self):
return self._octavia_sctp
def get_octavia_version(self):
lbaas = clients.get_loadbalancer_client()
region_name = getattr(CONF.neutron, 'region_name', None)
@ -362,9 +370,8 @@ class LBaaSv2Driver(base.LBaaSDriver):
loadbalancer, listener, self._create_listener,
self._find_listener, interval=_LB_STS_POLL_SLOW_INTERVAL)
except os_exc.SDKException:
LOG.exception("Listener creation failed, most probably because "
"protocol %(prot)s is not supported",
{'prot': protocol})
LOG.exception("Failed when creating listener for loadbalancer "
"%r", loadbalancer['id'])
return None
# NOTE(maysams): When ovn-octavia provider is used
@ -726,6 +733,14 @@ class LBaaSv2Driver(base.LBaaSDriver):
return result
except os_exc.BadRequestException:
raise
except os_exc.HttpException as e:
if e.status_code == 501:
LOG.exception("Listener creation failed, most probably "
"because protocol %(prot)s is not supported",
{'prot': obj['protocol']})
return None
else:
raise
except os_exc.SDKException:
pass


+ 4
- 0
kuryr_kubernetes/controller/handlers/loadbalancer.py View File

@ -591,6 +591,10 @@ class KuryrLoadBalancerHandler(k8s_base.ResourceEventHandler):
LOG.warning("Skipping listener creation for %s as another one"
" already exists with port %s", name, port)
continue
if protocol == "SCTP" and not self._drv_lbaas.sctp_supported():
LOG.warning("Skipping listener creation as provider does"
" not support %s protocol", protocol)
continue
listener = self._drv_lbaas.ensure_listener(
loadbalancer=loadbalancer_crd['status'].get('loadbalancer'),
protocol=protocol,


+ 4
- 2
kuryr_kubernetes/tests/unit/test_utils.py View File

@ -173,11 +173,13 @@ class TestUtils(test_base.TestCase):
def test_get_service_ports(self):
service = {'spec': {'ports': [
{'port': 1, 'targetPort': 1},
{'port': 2, 'name': 'X', 'protocol': 'UDP', 'targetPort': 2}
{'port': 2, 'name': 'X', 'protocol': 'UDP', 'targetPort': 2},
{'port': 3, 'name': 'Y', 'protocol': 'SCTP', 'targetPort': 3}
]}}
expected_ret = [
{'port': 1, 'name': None, 'protocol': 'TCP', 'targetPort': '1'},
{'port': 2, 'name': 'X', 'protocol': 'UDP', 'targetPort': '2'}]
{'port': 2, 'name': 'X', 'protocol': 'UDP', 'targetPort': '2'},
{'port': 3, 'name': 'Y', 'protocol': 'SCTP', 'targetPort': '3'}]
ret = utils.get_service_ports(service)
self.assertEqual(expected_ret, ret)


Loading…
Cancel
Save