From ca770736ed427071ff9aa0f38898359d461b36cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dulko?= Date: Fri, 7 Feb 2020 15:47:05 +0100 Subject: [PATCH] Basic IPv6 support in DevStack This commit enables basic support for IPv6 pod and service subnet. Also two gates are added - an OVS and OVN one, both as non-voting at the moment. The DevStack changes are mostly about putting correct --ethertype on SGs, using ip6tables and IPv6 subnetpool. The Kuryr change required putting IPv6 address of K8s API in brackets. Please note that this unblocks just the most basic use case, network policy support will still not work with IPv6. Depends-On: https://review.opendev.org/#/c/707103/ Implements: blueprint kuryr-ipv6-support Change-Id: Id56b622a5038d8e5c072aa00a9f38a2418e6268f --- .zuul.d/octavia.yaml | 11 +++++++++++ .zuul.d/project.yaml | 2 ++ .zuul.d/sdn.yaml | 11 +++++++++++ devstack/lib/kuryr_kubernetes | 31 +++++++++++++++++++++++-------- devstack/plugin.sh | 25 ++++++++++++++++++------- devstack/settings | 2 ++ kuryr_kubernetes/clients.py | 4 ++++ 7 files changed, 71 insertions(+), 15 deletions(-) diff --git a/.zuul.d/octavia.yaml b/.zuul.d/octavia.yaml index ee6e94e09..13d6c5b2d 100644 --- a/.zuul.d/octavia.yaml +++ b/.zuul.d/octavia.yaml @@ -60,6 +60,17 @@ devstack_localrc: KURYR_K8S_CONTAINERIZED_DEPLOYMENT: true +- job: + name: kuryr-kubernetes-tempest-containerized-ipv6 + parent: kuryr-kubernetes-tempest-containerized + description: | + Kuryr-Kubernetes tempest job running kuryr containerized with IPv6 pod + and service networks + vars: + devstack_localrc: + KURYR_IPV6: true + voting: false + - job: name: kuryr-kubernetes-tempest-containerized-lower-constraints parent: kuryr-kubernetes-tempest-containerized diff --git a/.zuul.d/project.yaml b/.zuul.d/project.yaml index 9a274c1e4..c3addc855 100644 --- a/.zuul.d/project.yaml +++ b/.zuul.d/project.yaml @@ -23,6 +23,8 @@ - kuryr-kubernetes-tempest-containerized-ovn - kuryr-kubernetes-tempest-containerized-network-policy - kuryr-kubernetes-tempest-multinode-containerized + - kuryr-kubernetes-tempest-containerized-ipv6 + - kuryr-kubernetes-tempest-containerized-ovn-ipv6 gate: jobs: - kuryr-kubernetes-tempest diff --git a/.zuul.d/sdn.yaml b/.zuul.d/sdn.yaml index f18fd4f94..12a7f8101 100644 --- a/.zuul.d/sdn.yaml +++ b/.zuul.d/sdn.yaml @@ -53,6 +53,17 @@ devstack_localrc: KURYR_K8S_CONTAINERIZED_DEPLOYMENT: true +- job: + name: kuryr-kubernetes-tempest-containerized-ovn-ipv6 + parent: kuryr-kubernetes-tempest-containerized-ovn + description: | + Kuryr-Kubernetes tempest job running kuryr containerized with OVN and + IPv6 pod and service networks + vars: + devstack_localrc: + KURYR_IPV6: true + voting: false + - job: name: kuryr-kubernetes-tempest-dragonflow parent: kuryr-kubernetes-tempest diff --git a/devstack/lib/kuryr_kubernetes b/devstack/lib/kuryr_kubernetes index c6f9f53c0..74744d817 100644 --- a/devstack/lib/kuryr_kubernetes +++ b/devstack/lib/kuryr_kubernetes @@ -84,12 +84,21 @@ function ovs_bind_for_kubelet() { if [ -n "$port_number" ]; then # if openstack-INPUT chain doesn't exist we create it in INPUT (for # local development envs since openstack-INPUT is usually only in gates) - sudo iptables -I openstack-INPUT 1 \ - -p tcp -s 0.0.0.0/0 -d 0.0.0.0/0 --dport $port_number -j ACCEPT || \ - sudo iptables -I INPUT 1 \ - -p tcp -m conntrack --ctstate NEW \ - -m tcp --dport "$port_number" \ - -m comment --comment "kuryr-devstack: Access to OpenShift API" -j ACCEPT + if [ "$KURYR_IPV6" == "False" ]; then + sudo iptables -I openstack-INPUT 1 \ + -p tcp -s 0.0.0.0/0 -d 0.0.0.0/0 --dport $port_number -j ACCEPT || \ + sudo iptables -I INPUT 1 \ + -p tcp -m conntrack --ctstate NEW \ + -m tcp --dport "$port_number" \ + -m comment --comment "kuryr-devstack: Access to OpenShift API" -j ACCEPT + else + sudo ip6tables -I openstack-INPUT 1 \ + -p tcp -s ::/0 -d ::/0 --dport $port_number -j ACCEPT || \ + sudo ip6tables -I INPUT 1 \ + -p tcp -m conntrack --ctstate NEW \ + -m tcp --dport "$port_number" \ + -m comment --comment "kuryr-devstack: Access to OpenShift API" -j ACCEPT + fi fi } @@ -196,6 +205,7 @@ function create_k8s_icmp_sg_rules { security group rule create \ --project "$project_id" \ --protocol icmp \ + --ethertype "$KURYR_ETHERTYPE" \ --"$direction" "$sg_id") die_if_not_set $LINENO icmp_sg_rules \ "Failure creating icmp sg ${direction} rule for ${sg_id}" @@ -212,7 +222,6 @@ function create_k8s_icmp_sg_rules { # split_allocation - Whether to allocate on all the subnet or only the # latter half function create_k8s_subnet { - # REVISIT(apuimedo): add support for IPv6 local project_id=$1 local net_name="$2" local subnet_name="$3" @@ -224,7 +233,13 @@ function create_k8s_subnet { split_allocation="${6:-False}" - subnet_params+="--ip-version 4 " + if [ "$KURYR_IPV6" == "False" ]; then + subnet_params+="--ip-version 4 " + else + # NOTE(dulek): K8s API won't accept subnets bigger than 20 bits. + # And 20 will totally be fine for us. + subnet_params+="--ip-version 6 --prefix-length 108 " + fi subnet_params+="--no-dhcp --gateway none " subnet_params+="--subnet-pool $subnetpool_id " diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 18ea69f48..eaa2d0332 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -280,7 +280,15 @@ function configure_neutron_defaults { # If a subnetpool is not passed, we get the one created in devstack's # Neutron module - subnetpool_id=${KURYR_NEUTRON_DEFAULT_SUBNETPOOL_ID:-${SUBNETPOOL_V4_ID}} + KURYR_IPV6=$(trueorfalse False KURYR_IPV6) + if [ "$KURYR_IPV6" == "False" ]; then + export KURYR_ETHERTYPE=IPv4 + subnetpool_id=${KURYR_NEUTRON_DEFAULT_SUBNETPOOL_ID:-${SUBNETPOOL_V4_ID}} + else + export KURYR_ETHERTYPE=IPv6 + subnetpool_id=${KURYR_NEUTRON_DEFAULT_SUBNETPOOL_ID:-${SUBNETPOOL_V6_ID}} + fi + router=${KURYR_NEUTRON_DEFAULT_ROUTER:-$Q_ROUTER_NAME} if [ "$router" != "$Q_ROUTER_NAME" ]; then openstack --os-cloud devstack-admin --os-region "$REGION_NAME" \ @@ -330,14 +338,14 @@ function configure_neutron_defaults { openstack --os-cloud devstack-admin --os-region "$REGION_NAME" \ security group rule create --project "$project_id" \ --description "k8s service subnet allowed" \ - --remote-ip "$service_cidr" --ethertype IPv4 --protocol tcp \ + --remote-ip "$service_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol tcp \ "$service_pod_access_sg_id" # Since Octavia supports also UDP load balancing, we need to allow # also udp traffic openstack --os-cloud devstack-admin --os-region "$REGION_NAME" \ security group rule create --project "$project_id" \ --description "k8s service subnet UDP allowed" \ - --remote-ip "$service_cidr" --ethertype IPv4 --protocol udp \ + --remote-ip "$service_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol udp \ "$service_pod_access_sg_id" if [[ "$KURYR_K8S_OCTAVIA_MEMBER_MODE" == "L3" ]]; then @@ -365,14 +373,14 @@ function configure_neutron_defaults { 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 IPv4 --protocol tcp \ + --remote-ip "$pod_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol tcp \ "$octavia_pod_access_sg_id" # Since Octavia supports also UDP load balancing, we need to allow # also udp 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 IPv4 --protocol udp \ + --remote-ip "$pod_cidr" --ethertype "$KURYR_ETHERTYPE" --protocol udp \ "$octavia_pod_access_sg_id" if [ -n "$sg_ids" ]; then sg_ids+=",${octavia_pod_access_sg_id}" @@ -399,7 +407,7 @@ function configure_neutron_defaults { openstack --os-cloud devstack-admin --os-region "$REGION_NAME" \ security group rule create --project "$project_id" \ --description "allow all ingress traffic" \ - --ethertype IPv4 --ingress --protocol any \ + --ethertype "$KURYR_ETHERTYPE" --ingress --protocol any \ "$allow_all_sg_id" if [ -n "$sg_ids" ]; then sg_ids+=",${allow_all_sg_id}" @@ -894,7 +902,7 @@ function configure_overcloud_vm_k8s_svc_sg { awk '{if ($2=="default") print $1}') openstack --os-cloud devstack-admin --os-region "$REGION_NAME" \ security group rule create --project "$project_id" \ - --dst-port "$dst_port" "$security_group" + --dst-port "$dst_port" --ethertype "$KURYR_ETHERTYPE" "$security_group" openstack port set "$KURYR_OVERCLOUD_VM_PORT" --security-group service_pod_access } @@ -933,6 +941,9 @@ function update_tempest_conf_file { if [[ "$KURYR_CONFIGMAP_MODIFIABLE" == "True" ]]; then iniset $TEMPEST_CONFIG kuryr_kubernetes configmap_modifiable True fi + if [[ "$KURYR_IPV6" == "True" ]]; then + iniset $TEMPEST_CONFIG kuryr_kubernetes ipv6 True + fi iniset $TEMPEST_CONFIG kuryr_kubernetes validate_crd True } diff --git a/devstack/settings b/devstack/settings index 2b0506e49..7f88946e2 100644 --- a/devstack/settings +++ b/devstack/settings @@ -102,3 +102,5 @@ KURYR_CONTAINERS_USE_LOWER_CONSTRAINTS=${KURYR_CONTAINERS_USE_LOWER_CONSTRAINTS: # Kuryr overcloud VM port's name KURYR_OVERCLOUD_VM_PORT=${KURYR_OVERCLOUD_VM_PORT:-port0} + +KURYR_IPV6=${KURYR_IPV6:-False} diff --git a/kuryr_kubernetes/clients.py b/kuryr_kubernetes/clients.py index 53153ae4a..6178d87fc 100644 --- a/kuryr_kubernetes/clients.py +++ b/kuryr_kubernetes/clients.py @@ -14,6 +14,7 @@ # under the License. from functools import partial +import ipaddress import os from kuryr.lib import utils @@ -80,6 +81,9 @@ def setup_kubernetes_client(): # K8s Pods. host = os.environ['KUBERNETES_SERVICE_HOST'] port = os.environ['KUBERNETES_SERVICE_PORT_HTTPS'] + addr = ipaddress.ip_address(host) + if addr.version == 6: + host = '[%s]' % host api_root = "https://%s:%s" % (host, port) _clients[_KUBERNETES_CLIENT] = k8s_client.K8sClient(api_root)