Allow k8s cluster without Floating IP

This patch adds an environment file and a couple of template resources
to allow the Floating IP resources to be conditionally enabled/disabled.

Change-Id: I95025d39443165e8463a81f8f75e78f5aa3809a1
Partially-Implements: blueprint bay-with-no-floating-ips
This commit is contained in:
OTSUKA, Yuanying 2016-08-05 14:22:35 +09:00
parent 778f144fd4
commit 2cc25abe49
10 changed files with 221 additions and 15 deletions

View File

@ -0,0 +1,13 @@
# Environment file to disable FloatingIP in a Kubernetes cluster by mapping
# FloatingIP-related resource types to OS::Heat::None
resource_registry:
"Magnum::FloatingIPAddressSwitcher": "../fragments/floating_ip_address_switcher_private.yaml"
# with_master_lb.yaml
"Magnum::Optional::Neutron::Pool::FloatingIP": "OS::Heat::None"
# kubemaster.yaml
"Magnum::Optional::KubeMaster::Neutron::FloatingIP": "OS::Heat::None"
# kubeminion.yaml
"Magnum::Optional::KubeMinion::Neutron::FloatingIP": "OS::Heat::None"

View File

@ -0,0 +1,10 @@
# Environment file to disable FloatingIP in a Kubernetes cluster by mapping
# FloatingIP-related resource types to OS::Neutron::FloatingIP
resource_registry:
"Magnum::FloatingIPAddressSwitcher": "../fragments/floating_ip_address_switcher_public.yaml"
# kubemaster.yaml
"Magnum::Optional::KubeMaster::Neutron::FloatingIP": "OS::Neutron::FloatingIP"
# kubeminion.yaml
"Magnum::Optional::KubeMinion::Neutron::FloatingIP": "OS::Neutron::FloatingIP"

View File

@ -0,0 +1,21 @@
heat_template_version: 2014-10-16
description: >
This is a template resource that accepts public and private IPs.
It connects private ip address to its outputs, essentially acting as
one state of a multiplexer.
parameters:
public_ip:
type: string
default: ""
private_ip:
type: string
default: ""
outputs:
ip_address:
value: {get_param: private_ip}

View File

@ -0,0 +1,21 @@
heat_template_version: 2014-10-16
description: >
This is a template resource that accepts public and private IPs.
It connects public ip address to its outputs, essentially acting as
one state of a multiplexer.
parameters:
public_ip:
type: string
default: ""
private_ip:
type: string
default: ""
outputs:
ip_address:
value: {get_param: public_ip}

View File

@ -15,6 +15,7 @@
from neutronclient.common import exceptions as n_exception
from neutronclient.neutron import v2_0 as neutronV20
import os
from oslo_log import log as logging
from magnum.common import exception
from magnum.drivers.common import template_def
@ -24,6 +25,8 @@ CONF = cfg.CONF
KUBE_SECURE_PORT = '6443'
KUBE_INSECURE_PORT = '8080'
LOG = logging.getLogger(__name__)
class K8sApiAddressOutputMapping(template_def.OutputMapping):
@ -49,6 +52,34 @@ class K8sApiAddressOutputMapping(template_def.OutputMapping):
setattr(bay, self.bay_attr, value)
class ServerAddressOutputMapping(template_def.OutputMapping):
public_ip_output_key = None
private_ip_output_key = None
def __init__(self, dummy_arg, bay_attr=None):
self.bay_attr = bay_attr
self.heat_output = self.public_ip_output_key
def set_output(self, stack, baymodel, bay):
if not baymodel.floating_ip_enabled:
self.heat_output = self.private_ip_output_key
LOG.debug("Using heat_output: %s", self.heat_output)
super(ServerAddressOutputMapping,
self).set_output(stack, baymodel, bay)
class MasterAddressOutputMapping(ServerAddressOutputMapping):
public_ip_output_key = 'kube_masters'
private_ip_output_key = 'kube_masters_private'
class NodeAddressOutputMapping(ServerAddressOutputMapping):
public_ip_output_key = 'kube_minions'
private_ip_output_key = 'kube_minions_private'
class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
"""Base Kubernetes template."""
@ -84,11 +115,13 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
self.add_output('kube_minions_private',
bay_attr=None)
self.add_output('kube_minions',
bay_attr='node_addresses')
bay_attr='node_addresses',
mapping_type=NodeAddressOutputMapping)
self.add_output('kube_masters_private',
bay_attr=None)
self.add_output('kube_masters',
bay_attr='master_addresses')
bay_attr='master_addresses',
mapping_type=MasterAddressOutputMapping)
def get_params(self, context, baymodel, bay, **kwargs):
extra_params = kwargs.pop('extra_params', {})
@ -152,10 +185,21 @@ class AtomicK8sTemplateDefinition(K8sTemplateDefinition):
**kwargs)
def get_env_files(self, baymodel):
env_files = []
if baymodel.master_lb_enabled:
return ['../../common/templates/environments/with_master_lb.yaml']
env_files.append(
'../../common/templates/environments/with_master_lb.yaml')
else:
return ['../../common/templates/environments/no_master_lb.yaml']
env_files.append(
'../../common/templates/environments/no_master_lb.yaml')
if baymodel.floating_ip_enabled:
env_files.append(
'../../common/templates/environments/enable_floating_ip.yaml')
else:
env_files.append(
'../../common/templates/environments/disable_floating_ip.yaml')
return env_files
@property
def template_path(self):

View File

@ -399,7 +399,7 @@ resources:
# LBaaS pool depending on whether LBaaS is enabled for the bay.
#
api_address_switch:
api_address_lb_switch:
type: Magnum::ApiGatewaySwitcher
properties:
pool_public_ip: {get_attr: [api_pool_floating, floating_ip_address]}
@ -407,12 +407,24 @@ resources:
master_public_ip: {get_attr: [kube_masters, resource.0.kube_master_external_ip]}
master_private_ip: {get_attr: [kube_masters, resource.0.kube_master_ip]}
etcd_address_switch:
etcd_address_lb_switch:
type: Magnum::ApiGatewaySwitcher
properties:
pool_private_ip: {get_attr: [etcd_pool, vip, address]}
master_private_ip: {get_attr: [kube_masters, resource.0.kube_master_ip]}
######################################################################
#
# resources that expose the IPs of either floating ip or a given
# fixed ip depending on whether FloatingIP is enabled for the bay.
#
api_address_floating_switch:
type: Magnum::FloatingIPAddressSwitcher
properties:
public_ip: {get_attr: [api_address_lb_switch, public_ip]}
private_ip: {get_attr: [api_address_lb_switch, private_ip]}
######################################################################
#
# kubernetes masters. This is a resource group that will create
@ -490,8 +502,8 @@ resources:
fixed_subnet: {get_resource: fixed_subnet}
network_driver: {get_param: network_driver}
flannel_network_cidr: {get_param: flannel_network_cidr}
kube_master_ip: {get_attr: [api_address_switch, private_ip]}
etcd_server_ip: {get_attr: [etcd_address_switch, private_ip]}
kube_master_ip: {get_attr: [api_address_lb_switch, private_ip]}
etcd_server_ip: {get_attr: [etcd_address_lb_switch, private_ip]}
external_network: {get_param: external_network}
kube_allow_priv: {get_param: kube_allow_priv}
docker_volume_size: {get_param: docker_volume_size}
@ -533,7 +545,7 @@ outputs:
str_replace:
template: api_ip_address
params:
api_ip_address: {get_attr: [api_address_switch, public_ip]}
api_ip_address: {get_attr: [api_address_floating_switch, ip_address]}
description: >
This is the API endpoint of the Kubernetes cluster. Use this to access
the Kubernetes API.

View File

@ -414,7 +414,7 @@ resources:
replacement_policy: AUTO
kube_master_floating:
type: OS::Neutron::FloatingIP
type: Magnum::Optional::KubeMaster::Neutron::FloatingIP
properties:
floating_network: {get_param: external_network}
port_id: {get_resource: kube_master_eth0}

View File

@ -398,7 +398,7 @@ resources:
replacement_policy: AUTO
kube_minion_floating:
type: OS::Neutron::FloatingIP
type: Magnum::Optional::KubeMinion::Neutron::FloatingIP
properties:
floating_network: {get_param: external_network}
port_id: {get_resource: kube_minion_eth0}

View File

@ -49,6 +49,7 @@ class TestBayConductorWithK8s(base.TestCase):
'registry_enabled': False,
'insecure_registry': '10.0.0.1:5000',
'master_lb_enabled': False,
'floating_ip_enabled': False,
}
self.bay_dict = {
'uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
@ -178,7 +179,8 @@ class TestBayConductorWithK8s(base.TestCase):
self.assertEqual(expected, definition)
self.assertEqual(
['../../common/templates/environments/no_master_lb.yaml'],
['../../common/templates/environments/no_master_lb.yaml',
'../../common/templates/environments/disable_floating_ip.yaml'],
env_files)
@patch('requests.get')
@ -246,7 +248,8 @@ class TestBayConductorWithK8s(base.TestCase):
self.assertEqual(expected, definition)
self.assertEqual(
['../../common/templates/environments/no_master_lb.yaml'],
['../../common/templates/environments/no_master_lb.yaml',
'../../common/templates/environments/disable_floating_ip.yaml'],
env_files)
@patch('requests.get')
@ -518,7 +521,8 @@ class TestBayConductorWithK8s(base.TestCase):
}
self.assertEqual(expected, definition)
self.assertEqual(
['../../common/templates/environments/no_master_lb.yaml'],
['../../common/templates/environments/no_master_lb.yaml',
'../../common/templates/environments/disable_floating_ip.yaml'],
env_files)
reqget.assert_called_once_with('http://etcd/test?size=1')

View File

@ -12,9 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import abc
import mock
from neutronclient.common import exceptions as n_exception
from oslo_config import cfg
import six
from magnum.common import exception
from magnum.drivers.common import template_def as cmn_tdef
@ -176,7 +178,56 @@ class TemplateDefinitionTestCase(base.TestCase):
definition.output_mappings)
class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
@six.add_metaclass(abc.ABCMeta)
class BaseTemplateDefinitionTestCase(base.TestCase):
@abc.abstractmethod
def get_definition(self):
"""Returns the template definition."""
pass
def _test_update_outputs_server_addrtess(
self,
floating_ip_enabled=True,
public_ip_output_key='kube_masters',
private_ip_output_key='kube_masters_private',
bay_attr='master_addresses',
):
definition = self.get_definition()
expected_address = expected_public_address = ['public']
expected_private_address = ['private']
if not floating_ip_enabled:
expected_address = expected_private_address
outputs = [
{"output_value": expected_public_address,
"description": "No description given",
"output_key": public_ip_output_key},
{"output_value": expected_private_address,
"description": "No description given",
"output_key": private_ip_output_key},
]
mock_stack = mock.MagicMock()
mock_stack.to_dict.return_value = {'outputs': outputs}
mock_bay = mock.MagicMock()
mock_baymodel = mock.MagicMock()
mock_baymodel.floating_ip_enabled = floating_ip_enabled
definition.update_outputs(mock_stack, mock_baymodel, mock_bay)
self.assertEqual(expected_address, getattr(mock_bay, bay_attr))
class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
def get_definition(self):
return cmn_tdef.TemplateDefinition.get_template_definition(
'vm',
'fedora-atomic',
'kubernetes',
)
@mock.patch('magnum.common.clients.OpenStackClients')
@mock.patch('magnum.drivers.k8s_fedora_atomic_v1.template_def'
@ -495,6 +546,36 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
}
self._test_update_outputs_none_api_address('swarm', params)
def test_update_outputs_master_address(self):
self._test_update_outputs_server_addrtess(
public_ip_output_key='kube_masters',
private_ip_output_key='kube_masters_private',
bay_attr='master_addresses',
)
def test_update_outputs_node_address(self):
self._test_update_outputs_server_addrtess(
public_ip_output_key='kube_minions',
private_ip_output_key='kube_minions_private',
bay_attr='node_addresses',
)
def test_update_outputs_master_address_fip_disabled(self):
self._test_update_outputs_server_addrtess(
floating_ip_enabled=False,
public_ip_output_key='kube_masters',
private_ip_output_key='kube_masters_private',
bay_attr='master_addresses',
)
def test_update_outputs_node_address_fip_disabled(self):
self._test_update_outputs_server_addrtess(
floating_ip_enabled=False,
public_ip_output_key='kube_minions',
private_ip_output_key='kube_minions_private',
bay_attr='node_addresses',
)
class FedoraK8sIronicTemplateDefinitionTestCase(base.TestCase):