Allow members to use the VIP address

The routing inside the amphora-haproxy namespace prohibited instances
added as members to a load balancer from using the VIP address.
This patch sets up a routing policy that allows this scenario to work
by clarifying that the VIP traffic only return out the VIP interface
routes and ignore the other attached networks.

Change-Id: If8c62f89dd8af7bb6936d455400fa0f8a0c26261
Story: 1715166
Task: 5375
This commit is contained in:
Michael Johnson 2017-09-07 18:38:25 -07:00
parent 2975e7a159
commit b935fa9068
5 changed files with 121 additions and 14 deletions

View File

@ -297,6 +297,7 @@ class RH(BaseOS):
ETH_X_VIP_CONF = 'rh_plug_vip_ethX.conf.j2'
ETH_X_ALIAS_VIP_CONF = 'rh_plug_vip_ethX_alias.conf.j2'
ROUTE_ETH_X_CONF = 'rh_route_ethX.conf.j2'
RULE_ETH_X_CONF = 'rh_rule_ethX.conf.j2'
@classmethod
def is_os_name(cls, os_name):
@ -321,6 +322,9 @@ class RH(BaseOS):
def get_static_routes_interface_file(self, interface):
return self.get_network_interface_file('route-' + interface)
def get_route_rules_interface_file(self, interface):
return self.get_network_interface_file('rule-' + interface)
def get_network_path(self):
return '/etc/sysconfig/network-scripts'
@ -373,18 +377,25 @@ class RH(BaseOS):
broadcast, netmask, gateway, mtu, vrrp_ip, vrrp_version,
render_host_routes, template_vip_alias)
if render_host_routes:
routes_interface_file_path = (
self.get_static_routes_interface_file(primary_interface))
template_routes = j2_env.get_template(self.ROUTE_ETH_X_CONF)
routes_interface_file_path = (
self.get_static_routes_interface_file(primary_interface))
template_routes = j2_env.get_template(self.ROUTE_ETH_X_CONF)
self.write_static_routes_interface_file(
routes_interface_file_path, primary_interface,
render_host_routes, template_routes)
self.write_static_routes_interface_file(
routes_interface_file_path, primary_interface,
render_host_routes, template_routes, gateway, vip)
route_rules_interface_file_path = (
self.get_route_rules_interface_file(primary_interface))
template_rules = j2_env.get_template(self.RULE_ETH_X_CONF)
self.write_static_routes_interface_file(
route_rules_interface_file_path, primary_interface,
render_host_routes, template_rules, gateway, vip)
def write_static_routes_interface_file(self, interface_file_path,
interface, host_routes,
template_routes):
template_routes, gateway, vip):
# write static routes interface file
mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
@ -400,6 +411,8 @@ class RH(BaseOS):
text = template_routes.render(
interface=interface,
host_routes=host_routes,
gateway=gateway,
vip=vip,
)
text_file.write(text)
@ -426,7 +439,7 @@ class RH(BaseOS):
self.write_static_routes_interface_file(
routes_interface_file_path, netns_interface,
host_routes, template_routes)
host_routes, template_routes, None, None)
def bring_interfaces_up(self, ip, primary_interface, secondary_interface):
if ip.version == 4:

View File

@ -40,3 +40,14 @@ iface {{ interface }}:0 inet{{ '6' if vip_ipv6 }} static
address {{ vip }}
broadcast {{ broadcast }}
netmask {{ netmask }}
# Add a source routing table to allow members to access the VIP
{%- if gateway %}
post-up /sbin/ip route add default via {{ gateway }} dev {{ interface }} onlink table 1
post-down /sbin/ip route del default via {{ gateway }} dev {{ interface }} onlink table 1
{%- endif %}
{%- for hr in host_routes %}
post-up /sbin/ip route add {{ hr.network }} via {{ hr.gw }} dev {{ interface }} onlink table 1
post-down /sbin/ip route del {{ hr.network }} via {{ hr.gw }} dev {{ interface }} onlink table 1
{%- endfor %}
post-up /sbin/ip rule add from {{ vip }}/32 table 1 priority 100
post-down /sbin/ip rule del from {{ vip }}/32 table 1 priority 100

View File

@ -17,4 +17,10 @@
{%- for hr in host_routes %}
{{ hr.network }} via {{ hr.gw }} dev {{ interface }}
{%- endfor %}
# Add a source routing table to allow members to access the VIP
{%- if gateway %}
default table 1 via {{ gateway }} dev {{ interface }}
{%- endif %}
{%- for hr in host_routes %}
{{ hr.network }} table 1 via {{ hr.gw }} dev {{ interface }}
{%- endfor %}

View File

@ -0,0 +1,17 @@
{#
# Copyright 2017 Rackspace, US Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#}
# Generated by Octavia agent
from {{ vip }} table 1

View File

@ -1662,7 +1662,25 @@ class TestServerTestCase(base.TestCase):
'iface {netns_int}:0 inet static\n'
'address 203.0.113.2\n'
'broadcast 203.0.113.255\n'
'netmask 255.255.255.0'.format(
'netmask 255.255.255.0\n'
'# Add a source routing table to allow members to '
'access the VIP\n'
'post-up /sbin/ip route add default via 203.0.113.1 '
'dev eth1 onlink table 1\n'
'post-down /sbin/ip route del default via 203.0.113.1 '
'dev eth1 onlink table 1\n'
'post-up /sbin/ip route add 203.0.114.0/24 '
'via 203.0.113.5 dev eth1 onlink table 1\n'
'post-down /sbin/ip route del 203.0.114.0/24 '
'via 203.0.113.5 dev eth1 onlink table 1\n'
'post-up /sbin/ip route add 203.0.115.0/24 '
'via 203.0.113.5 dev eth1 onlink table 1\n'
'post-down /sbin/ip route del 203.0.115.0/24 '
'via 203.0.113.5 dev eth1 onlink table 1\n'
'post-up /sbin/ip rule add from 203.0.113.2/32 table 1 '
'priority 100\n'
'post-down /sbin/ip rule del from 203.0.113.2/32 table 1 '
'priority 100'.format(
netns_int=consts.NETNS_PRIMARY_INTERFACE))
elif distro == consts.CENTOS:
handle.write.assert_any_call(
@ -1741,7 +1759,17 @@ class TestServerTestCase(base.TestCase):
'iface {netns_int}:0 inet static\n'
'address 203.0.113.2\n'
'broadcast 203.0.113.255\n'
'netmask 255.255.255.0'.format(
'netmask 255.255.255.0\n'
'# Add a source routing table to allow members to '
'access the VIP\n'
'post-up /sbin/ip route add default via 203.0.113.1 '
'dev eth1 onlink table 1\n'
'post-down /sbin/ip route del default via 203.0.113.1 '
'dev eth1 onlink table 1\n'
'post-up /sbin/ip rule add from 203.0.113.2/32 table 1 '
'priority 100\n'
'post-down /sbin/ip rule del from 203.0.113.2/32 table 1 '
'priority 100'.format(
netns_int=consts.NETNS_PRIMARY_INTERFACE))
elif distro == consts.CENTOS:
handle.write.assert_any_call(
@ -1946,7 +1974,27 @@ class TestServerTestCase(base.TestCase):
'iface {netns_int}:0 inet6 static\n'
'address 2001:0db8:0000:0000:0000:0000:0000:0002\n'
'broadcast 2001:0db8:ffff:ffff:ffff:ffff:ffff:ffff\n'
'netmask 32'.format(
'netmask 32\n'
'# Add a source routing table to allow members to access '
'the VIP\n'
'post-up /sbin/ip route add default via 2001:db8::1 '
'dev eth1 onlink table 1\n'
'post-down /sbin/ip route del default via 2001:db8::1 '
'dev eth1 onlink table 1\n'
'post-up /sbin/ip route add 2001:db9::/32 via 2001:db8::5 '
'dev eth1 onlink table 1\n'
'post-down /sbin/ip route del 2001:db9::/32 '
'via 2001:db8::5 dev eth1 onlink table 1\n'
'post-up /sbin/ip route add 2001:db9::/32 via 2001:db8::5 '
'dev eth1 onlink table 1\n'
'post-down /sbin/ip route del 2001:db9::/32 '
'via 2001:db8::5 dev eth1 onlink table 1\n'
'post-up /sbin/ip rule add from '
'2001:0db8:0000:0000:0000:0000:0000:0002/32 table 1 '
'priority 100\n'
'post-down /sbin/ip rule del from '
'2001:0db8:0000:0000:0000:0000:0000:0002/32 table 1 '
'priority 100'.format(
netns_int=consts.NETNS_PRIMARY_INTERFACE))
elif distro == consts.CENTOS:
handle.write.assert_any_call(
@ -2026,7 +2074,19 @@ class TestServerTestCase(base.TestCase):
'iface {netns_int}:0 inet6 static\n'
'address 2001:0db8:0000:0000:0000:0000:0000:0002\n'
'broadcast 2001:0db8:ffff:ffff:ffff:ffff:ffff:ffff\n'
'netmask 32'.format(
'netmask 32\n'
'# Add a source routing table to allow members to access '
'the VIP\n'
'post-up /sbin/ip route add default via 2001:db8::1 '
'dev eth1 onlink table 1\n'
'post-down /sbin/ip route del default via 2001:db8::1 '
'dev eth1 onlink table 1\n'
'post-up /sbin/ip rule add from '
'2001:0db8:0000:0000:0000:0000:0000:0002/32 table 1 '
'priority 100\n'
'post-down /sbin/ip rule del from '
'2001:0db8:0000:0000:0000:0000:0000:0002/32 table 1 '
'priority 100'.format(
netns_int=consts.NETNS_PRIMARY_INTERFACE))
elif distro == consts.CENTOS:
handle.write.assert_any_call(