Merge "K8S Services: add support for SCTP"

This commit is contained in:
Zuul 2021-01-11 03:01:54 +00:00 committed by Gerrit Code Review
commit e69989c6e4
4 changed files with 38 additions and 5 deletions

View File

@ -383,6 +383,12 @@ function configure_neutron_defaults {
--description "k8s service subnet UDP allowed" \ --description "k8s service subnet UDP allowed" \
--remote-ip "$service_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol udp \ --remote-ip "$service_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol udp \
"$service_pod_access_sg_id" "$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 [[ "$KURYR_K8S_OCTAVIA_MEMBER_MODE" == "L3" ]]; then
if [ -n "$sg_ids" ]; then if [ -n "$sg_ids" ]; then
@ -418,6 +424,12 @@ function configure_neutron_defaults {
--description "k8s pod subnet allowed from k8s-pod-subnet" \ --description "k8s pod subnet allowed from k8s-pod-subnet" \
--remote-ip "$pod_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol udp \ --remote-ip "$pod_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol udp \
"$octavia_pod_access_sg_id" "$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 if [ -n "$sg_ids" ]; then
sg_ids+=",${octavia_pod_access_sg_id}" sg_ids+=",${octavia_pod_access_sg_id}"
else else

View File

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

View File

@ -591,6 +591,10 @@ class KuryrLoadBalancerHandler(k8s_base.ResourceEventHandler):
LOG.warning("Skipping listener creation for %s as another one" LOG.warning("Skipping listener creation for %s as another one"
" already exists with port %s", name, port) " already exists with port %s", name, port)
continue 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( listener = self._drv_lbaas.ensure_listener(
loadbalancer=loadbalancer_crd['status'].get('loadbalancer'), loadbalancer=loadbalancer_crd['status'].get('loadbalancer'),
protocol=protocol, protocol=protocol,

View File

@ -173,11 +173,13 @@ class TestUtils(test_base.TestCase):
def test_get_service_ports(self): def test_get_service_ports(self):
service = {'spec': {'ports': [ service = {'spec': {'ports': [
{'port': 1, 'targetPort': 1}, {'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 = [ expected_ret = [
{'port': 1, 'name': None, 'protocol': 'TCP', 'targetPort': '1'}, {'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) ret = utils.get_service_ports(service)
self.assertEqual(expected_ret, ret) self.assertEqual(expected_ret, ret)