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
This commit is contained in:
parent
500ff16481
commit
c3e66123a5
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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…
Reference in New Issue
Block a user