Bay driver: k8s Fedora Atomic
Change-Id: I1fae89e902ef73fe18ef78733a18e3690b67f312 Paritially-Implements: blueprint bay-drivers
This commit is contained in:
parent
3d8c397c07
commit
a5ae8b37aa
@ -31,7 +31,6 @@ from magnum.conductor.handlers import conductor_listener
|
||||
from magnum.conductor.handlers import docker_conductor
|
||||
from magnum.conductor.handlers import indirection_api
|
||||
from magnum.conductor.handlers import k8s_conductor
|
||||
from magnum.i18n import _LE
|
||||
from magnum.i18n import _LI
|
||||
from magnum import version
|
||||
|
||||
@ -59,15 +58,6 @@ def main():
|
||||
ca_conductor.Handler(),
|
||||
]
|
||||
|
||||
if (not os.path.isfile(cfg.CONF.bay.k8s_atomic_template_path)
|
||||
and not os.path.isfile(cfg.CONF.bay.k8s_coreos_template_path)):
|
||||
LOG.error(_LE("The Heat template can not be found for either k8s "
|
||||
"atomic %(atomic_template)s or coreos "
|
||||
"%(coreos_template)s. Install template first if you "
|
||||
"want to create bay.") %
|
||||
{'atomic_template': cfg.CONF.bay.k8s_atomic_template_path,
|
||||
'coreos_template': cfg.CONF.bay.k8s_coreos_template_path})
|
||||
|
||||
server = rpc_service.Service.create(cfg.CONF.conductor.topic,
|
||||
conductor_id, endpoints,
|
||||
binary='magnum-conductor')
|
||||
|
@ -25,13 +25,6 @@ KUBE_SECURE_PORT = '6443'
|
||||
KUBE_INSECURE_PORT = '8080'
|
||||
|
||||
template_def_opts = [
|
||||
cfg.StrOpt('k8s_atomic_template_path',
|
||||
default=paths.basedir_def('templates/kubernetes/'
|
||||
'kubecluster.yaml'),
|
||||
deprecated_name='template_path',
|
||||
deprecated_group='bay_heat',
|
||||
help=_(
|
||||
'Location of template to build a k8s cluster on atomic.')),
|
||||
cfg.StrOpt('k8s_coreos_template_path',
|
||||
default=paths.basedir_def('templates/kubernetes/'
|
||||
'kubecluster-coreos.yaml'),
|
||||
@ -163,40 +156,6 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
|
||||
return ['environments/no_master_lb.yaml']
|
||||
|
||||
|
||||
class AtomicK8sTemplateDefinition(K8sTemplateDefinition):
|
||||
"""Kubernetes template for a Fedora Atomic VM."""
|
||||
|
||||
provides = [
|
||||
{'server_type': 'vm',
|
||||
'os': 'fedora-atomic',
|
||||
'coe': 'kubernetes'},
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
super(AtomicK8sTemplateDefinition, self).__init__()
|
||||
self.add_parameter('docker_volume_size',
|
||||
baymodel_attr='docker_volume_size')
|
||||
self.add_parameter('docker_storage_driver',
|
||||
baymodel_attr='docker_storage_driver')
|
||||
|
||||
def get_params(self, context, baymodel, bay, **kwargs):
|
||||
extra_params = kwargs.pop('extra_params', {})
|
||||
|
||||
extra_params['username'] = context.user_name
|
||||
extra_params['tenant_name'] = context.tenant
|
||||
osc = self.get_osc(context)
|
||||
extra_params['region_name'] = osc.cinder_region_name()
|
||||
|
||||
return super(AtomicK8sTemplateDefinition,
|
||||
self).get_params(context, baymodel, bay,
|
||||
extra_params=extra_params,
|
||||
**kwargs)
|
||||
|
||||
@property
|
||||
def template_path(self):
|
||||
return cfg.CONF.bay.k8s_atomic_template_path
|
||||
|
||||
|
||||
class CoreOSK8sTemplateDefinition(K8sTemplateDefinition):
|
||||
"""Kubernetes template for CoreOS VM."""
|
||||
|
||||
|
@ -33,13 +33,6 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
template_def_opts = [
|
||||
cfg.StrOpt('k8s_atomic_template_path',
|
||||
default=paths.basedir_def('templates/kubernetes/'
|
||||
'kubecluster.yaml'),
|
||||
deprecated_name='template_path',
|
||||
deprecated_group='bay_heat',
|
||||
help=_(
|
||||
'Location of template to build a k8s cluster on atomic.')),
|
||||
cfg.StrOpt('k8s_coreos_template_path',
|
||||
default=paths.basedir_def('templates/kubernetes/'
|
||||
'kubecluster-coreos.yaml'),
|
||||
|
0
magnum/drivers/k8s_fedora_atomic_v1/__init__.py
Normal file
0
magnum/drivers/k8s_fedora_atomic_v1/__init__.py
Normal file
160
magnum/drivers/k8s_fedora_atomic_v1/template_def.py
Normal file
160
magnum/drivers/k8s_fedora_atomic_v1/template_def.py
Normal file
@ -0,0 +1,160 @@
|
||||
# Copyright 2016 Rackspace Inc. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import os
|
||||
|
||||
from magnum.drivers.common import template_def
|
||||
from oslo_config import cfg
|
||||
|
||||
CONF = cfg.CONF
|
||||
KUBE_SECURE_PORT = '6443'
|
||||
KUBE_INSECURE_PORT = '8080'
|
||||
|
||||
|
||||
class K8sApiAddressOutputMapping(template_def.OutputMapping):
|
||||
|
||||
def set_output(self, stack, baymodel, bay):
|
||||
if self.bay_attr is None:
|
||||
return
|
||||
|
||||
output_value = self.get_output_value(stack)
|
||||
if output_value is not None:
|
||||
# TODO(yuanying): port number is hardcoded, this will be fix
|
||||
protocol = 'https'
|
||||
port = KUBE_SECURE_PORT
|
||||
if baymodel.tls_disabled:
|
||||
protocol = 'http'
|
||||
port = KUBE_INSECURE_PORT
|
||||
|
||||
params = {
|
||||
'protocol': protocol,
|
||||
'address': output_value,
|
||||
'port': port,
|
||||
}
|
||||
value = "%(protocol)s://%(address)s:%(port)s" % params
|
||||
setattr(bay, self.bay_attr, value)
|
||||
|
||||
|
||||
class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
|
||||
"""Base Kubernetes template."""
|
||||
|
||||
def __init__(self):
|
||||
super(K8sTemplateDefinition, self).__init__()
|
||||
self.add_parameter('master_flavor',
|
||||
baymodel_attr='master_flavor_id')
|
||||
self.add_parameter('minion_flavor',
|
||||
baymodel_attr='flavor_id')
|
||||
self.add_parameter('number_of_minions',
|
||||
bay_attr='node_count')
|
||||
self.add_parameter('external_network',
|
||||
baymodel_attr='external_network_id',
|
||||
required=True)
|
||||
self.add_parameter('network_driver',
|
||||
baymodel_attr='network_driver')
|
||||
self.add_parameter('volume_driver',
|
||||
baymodel_attr='volume_driver')
|
||||
self.add_parameter('tls_disabled',
|
||||
baymodel_attr='tls_disabled',
|
||||
required=True)
|
||||
self.add_parameter('registry_enabled',
|
||||
baymodel_attr='registry_enabled')
|
||||
self.add_parameter('bay_uuid',
|
||||
bay_attr='uuid',
|
||||
param_type=str)
|
||||
self.add_parameter('insecure_registry_url',
|
||||
baymodel_attr='insecure_registry')
|
||||
|
||||
self.add_output('api_address',
|
||||
bay_attr='api_address',
|
||||
mapping_type=K8sApiAddressOutputMapping)
|
||||
self.add_output('kube_minions_private',
|
||||
bay_attr=None)
|
||||
self.add_output('kube_minions',
|
||||
bay_attr='node_addresses')
|
||||
self.add_output('kube_masters_private',
|
||||
bay_attr=None)
|
||||
self.add_output('kube_masters',
|
||||
bay_attr='master_addresses')
|
||||
|
||||
def get_params(self, context, baymodel, bay, **kwargs):
|
||||
extra_params = kwargs.pop('extra_params', {})
|
||||
scale_mgr = kwargs.pop('scale_manager', None)
|
||||
if scale_mgr:
|
||||
hosts = self.get_output('kube_minions')
|
||||
extra_params['minions_to_remove'] = (
|
||||
scale_mgr.get_removal_nodes(hosts))
|
||||
|
||||
extra_params['discovery_url'] = self.get_discovery_url(bay)
|
||||
osc = self.get_osc(context)
|
||||
extra_params['magnum_url'] = osc.magnum_url()
|
||||
|
||||
if baymodel.tls_disabled:
|
||||
extra_params['loadbalancing_protocol'] = 'HTTP'
|
||||
extra_params['kubernetes_port'] = 8080
|
||||
|
||||
label_list = ['flannel_network_cidr', 'flannel_backend',
|
||||
'flannel_network_subnetlen']
|
||||
for label in label_list:
|
||||
extra_params[label] = baymodel.labels.get(label)
|
||||
|
||||
if baymodel.registry_enabled:
|
||||
extra_params['swift_region'] = CONF.docker_registry.swift_region
|
||||
extra_params['registry_container'] = (
|
||||
CONF.docker_registry.swift_registry_container)
|
||||
|
||||
return super(K8sTemplateDefinition,
|
||||
self).get_params(context, baymodel, bay,
|
||||
extra_params=extra_params,
|
||||
**kwargs)
|
||||
|
||||
|
||||
class AtomicK8sTemplateDefinition(K8sTemplateDefinition):
|
||||
"""Kubernetes template for a Fedora Atomic VM."""
|
||||
|
||||
provides = [
|
||||
{'server_type': 'vm',
|
||||
'os': 'fedora-atomic',
|
||||
'coe': 'kubernetes'},
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
super(AtomicK8sTemplateDefinition, self).__init__()
|
||||
self.add_parameter('docker_volume_size',
|
||||
baymodel_attr='docker_volume_size')
|
||||
self.add_parameter('docker_storage_driver',
|
||||
baymodel_attr='docker_storage_driver')
|
||||
|
||||
def get_params(self, context, baymodel, bay, **kwargs):
|
||||
extra_params = kwargs.pop('extra_params', {})
|
||||
|
||||
extra_params['username'] = context.user_name
|
||||
extra_params['tenant_name'] = context.tenant
|
||||
osc = self.get_osc(context)
|
||||
extra_params['region_name'] = osc.cinder_region_name()
|
||||
|
||||
return super(AtomicK8sTemplateDefinition,
|
||||
self).get_params(context, baymodel, bay,
|
||||
extra_params=extra_params,
|
||||
**kwargs)
|
||||
|
||||
def get_env_files(self, baymodel):
|
||||
if baymodel.master_lb_enabled:
|
||||
return ['environments/with_master_lb.yaml']
|
||||
else:
|
||||
return ['environments/no_master_lb.yaml']
|
||||
|
||||
@property
|
||||
def template_path(self):
|
||||
return os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
||||
'templates/kubecluster.yaml')
|
202
magnum/drivers/k8s_fedora_atomic_v1/templates/COPYING
Normal file
202
magnum/drivers/k8s_fedora_atomic_v1/templates/COPYING
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
143
magnum/drivers/k8s_fedora_atomic_v1/templates/README.md
Normal file
143
magnum/drivers/k8s_fedora_atomic_v1/templates/README.md
Normal file
@ -0,0 +1,143 @@
|
||||
A Kubernetes cluster with Heat
|
||||
==============================
|
||||
|
||||
These [Heat][] templates will deploy a [Kubernetes][] cluster that
|
||||
supports automatic scaling based on CPU load.
|
||||
|
||||
[heat]: https://wiki.openstack.org/wiki/Heat
|
||||
[kubernetes]: https://github.com/GoogleCloudPlatform/kubernetes
|
||||
|
||||
The cluster uses [Flannel][] to provide an overlay network connecting
|
||||
pods deployed on different minions.
|
||||
|
||||
[flannel]: https://github.com/coreos/flannel
|
||||
|
||||
## Requirements
|
||||
|
||||
### OpenStack
|
||||
|
||||
These templates will work with the Kilo version of Heat. They *may*
|
||||
work with Juno as well as soon as [#1402894][] is resolved.
|
||||
|
||||
[#1402894]: https://bugs.launchpad.net/heat/+bug/1402894
|
||||
|
||||
### Guest image
|
||||
|
||||
These templates will work with either CentOS Atomic Host or Fedora 21
|
||||
Atomic.
|
||||
|
||||
You can enable docker registry v2 by setting the "registry_enabled"
|
||||
parameter to "true".
|
||||
|
||||
## Creating the stack
|
||||
|
||||
Creating an environment file `local.yaml` with parameters specific to
|
||||
your environment:
|
||||
|
||||
parameters:
|
||||
ssh_key_name: testkey
|
||||
external_network: public
|
||||
dns_nameserver: 192.168.200.1
|
||||
server_image: centos-7-atomic-20150101
|
||||
registry_enabled: true
|
||||
registry_username: username
|
||||
registry_password: password
|
||||
registry_domain: domain
|
||||
registry_trust_id: trust_id
|
||||
registry_auth_url: auth_url
|
||||
registry_region: region
|
||||
registry_container: container
|
||||
|
||||
And then create the stack, referencing that environment file:
|
||||
|
||||
heat stack-create -f kubecluster.yaml -e local.yaml my-kube-cluster
|
||||
|
||||
You must provide values for:
|
||||
|
||||
- `ssh_key_name`
|
||||
- `server_image`
|
||||
|
||||
If you enable docker registry v2, you must provide values for:
|
||||
|
||||
- `registry_username`
|
||||
- `registry_password`
|
||||
- `registry_domain`
|
||||
- `registry_trust_id`
|
||||
- `registry_auth_url`
|
||||
- `registry_region`
|
||||
- `registry_container
|
||||
|
||||
## Interacting with Kubernetes
|
||||
|
||||
You can get the ip address of the Kubernetes master using the `heat
|
||||
output-show` command:
|
||||
|
||||
$ heat output-show my-kube-cluster kube_masters
|
||||
"192.168.200.86"
|
||||
|
||||
You can ssh into that server as the `minion` user:
|
||||
|
||||
$ ssh minion@192.168.200.86
|
||||
|
||||
And once logged in you can run `kubectl`, etc:
|
||||
|
||||
$ kubectl get minions
|
||||
NAME LABELS STATUS
|
||||
10.0.0.4 <none> Ready
|
||||
|
||||
You can log into your minions using the `minion` user as well. You
|
||||
can get a list of minion addresses by running:
|
||||
|
||||
$ heat output-show my-kube-cluster kube_minions
|
||||
[
|
||||
"192.168.200.182"
|
||||
]
|
||||
|
||||
You can get the docker registry v2 address:
|
||||
$ heat output-show my-kube-cluster registry_address
|
||||
localhost:5000
|
||||
|
||||
## Testing
|
||||
|
||||
The templates install an example Pod and Service description into
|
||||
`/etc/kubernetes/examples`. You can deploy this with the following
|
||||
commands:
|
||||
|
||||
$ kubectl create -f /etc/kubernetes/examples/web.service
|
||||
$ kubectl create -f /etc/kubernetes/examples/web.pod
|
||||
|
||||
This will deploy a minimal webserver and a service. You can use
|
||||
`kubectl get pods` and `kubectl get services` to see the results of
|
||||
these commands.
|
||||
|
||||
## License
|
||||
|
||||
Copyright 2014 Lars Kellogg-Stedman <lars@redhat.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use these files 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.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please submit bugs and pull requests via the [GitHub repository][] at
|
||||
https://github.com/larsks/heat-kubernetes/.
|
||||
|
||||
When submitting pull requests:
|
||||
|
||||
- Please ensure that each pull request contains a single commit and
|
||||
contains only related changes. Put unrelated changes in multiple
|
||||
pull requests.
|
||||
|
||||
- Please avoid conflating new features with
|
||||
stylistic/formatting/cleanup changes.
|
||||
|
||||
[github repository]: https://github.com/larsks/heat-kubernetes/
|
@ -0,0 +1,29 @@
|
||||
Kubernetes elements
|
||||
===================
|
||||
|
||||
This directory contains `[diskimage-builder](https://github.com/openstack/diskimage-builder)`
|
||||
elements to build an image which contains kubernetes required to use kubecluster-fedora-ironic.yaml.
|
||||
|
||||
An example fedora based image and uploaded to glance with the following:
|
||||
|
||||
git clone https://git.openstack.org/openstack/magnum
|
||||
git clone https://git.openstack.org/openstack/diskimage-builder.git
|
||||
git clone https://git.openstack.org/openstack/tripleo-image-elements.git
|
||||
git clone https://git.openstack.org/openstack/heat-templates.git
|
||||
git clone https://git.openstack.org/openstack/dib-utils.git
|
||||
export PATH="${PWD}/dib-utils/bin:$PATH"
|
||||
export ELEMENTS_PATH=tripleo-image-elements/elements:heat-templates/hot/software-config/elements
|
||||
export ELEMENTS_PATH=${ELEMENTS_PATH}:magnum/etc/magnum/templates/kubernetes/elements
|
||||
export DIB_RELEASE=21
|
||||
diskimage-builder/bin/disk-image-create baremetal \
|
||||
fedora selinux-permissive \
|
||||
os-collect-config \
|
||||
os-refresh-config \
|
||||
os-apply-config \
|
||||
heat-config-script \
|
||||
kubernetes \
|
||||
-o fedora-21-kubernetes.qcow2
|
||||
|
||||
KERNEL_ID=`glance image-create --name fedora-k8s-kernel --visibility public --disk-format=aki --container-format=aki --file=fedora-21-kubernetes.vmlinuz | grep id | tr -d '| ' | cut --bytes=3-57`
|
||||
RAMDISK_ID=`glance image-create --name fedora-k8s-ramdisk --visibility public --disk-format=ari --container-format=ari --file=fedora-21-kubernetes.initrd | grep id | tr -d '| ' | cut --bytes=3-57`
|
||||
BASE_ID=`glance image-create --name fedora-k8s --visibility public --disk-format=qcow2 --container-format=bare --property kernel_id=$KERNEL_ID --property ramdisk_id=$RAMDISK_ID --file=fedora-21-kubernetes.qcow2 | grep -v kernel | grep -v ramdisk | grep id | tr -d '| ' | cut --bytes=3-57`
|
@ -0,0 +1 @@
|
||||
package-installs
|
@ -0,0 +1,4 @@
|
||||
kubernetes:
|
||||
etcd:
|
||||
flannel:
|
||||
docker-io:
|
@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
DOCKER_PROXY_CONF=/etc/systemd/system/docker.service.d/proxy.conf
|
||||
BASH_RC=/etc/bashrc
|
||||
|
||||
mkdir -p /etc/systemd/system/docker.service.d
|
||||
|
||||
if [ -n "$HTTP_PROXY" ]; then
|
||||
cat <<EOF | sed "s/^ *//" > $DOCKER_PROXY_CONF
|
||||
[Service]
|
||||
Environment=HTTP_PROXY=$HTTP_PROXY
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl --no-block restart docker.service
|
||||
|
||||
if [ -f "$BASH_RC" ]; then
|
||||
echo "declare -x http_proxy=$HTTP_PROXY" >> $BASH_RC
|
||||
else
|
||||
echo "File $BASH_RC does not exist, not setting http_proxy"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$HTTPS_PROXY" ]; then
|
||||
if [ -f "$BASH_RC" ]; then
|
||||
echo "declare -x https_proxy=$HTTPS_PROXY" >> $BASH_RC
|
||||
else
|
||||
echo "File $BASH_RC does not exist, not setting https_proxy"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$NO_PROXY" ]; then
|
||||
if [ -f "$BASH_RC" ]; then
|
||||
echo "declare -x no_proxy=$NO_PROXY" >> $BASH_RC
|
||||
else
|
||||
echo "File $BASH_RC does not exist, not setting no_proxy"
|
||||
fi
|
||||
fi
|
@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
if [ "$REGISTRY_ENABLED" = "False" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cat > /etc/sysconfig/registry-config.yml << EOF
|
||||
version: 0.1
|
||||
log:
|
||||
fields:
|
||||
service: registry
|
||||
storage:
|
||||
cache:
|
||||
layerinfo: inmemory
|
||||
swift:
|
||||
authurl: "$AUTH_URL"
|
||||
region: "$SWIFT_REGION"
|
||||
username: "$TRUSTEE_USERNAME"
|
||||
password: "$TRUSTEE_PASSWORD"
|
||||
domainid: "$TRUSTEE_DOMAIN_ID"
|
||||
trustid: "$TRUST_ID"
|
||||
container: "$REGISTRY_CONTAINER"
|
||||
insecureskipverify: $REGISTRY_INSECURE
|
||||
chunksize: $REGISTRY_CHUNKSIZE
|
||||
http:
|
||||
addr: :5000
|
||||
EOF
|
||||
|
||||
cat > /etc/systemd/system/registry.service << EOF
|
||||
[Unit]
|
||||
Description=Docker registry v2
|
||||
Requires=docker.service
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/usr/bin/docker run -d -p $REGISTRY_PORT:5000 --restart=always --name registry -v /etc/sysconfig/registry-config.yml:/etc/docker/registry/config.yml registry:2
|
||||
ExecStop=/usr/bin/docker rm -f registry
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
attempts=60
|
||||
while [ ${attempts} -gt 0 ]; do
|
||||
device_name=$(ls /dev/disk/by-id | grep ${DOCKER_VOLUME:0:20}$)
|
||||
if [ -n "${device_name}" ]; then
|
||||
break
|
||||
fi
|
||||
echo "waiting for disk device"
|
||||
sleep 0.5
|
||||
udevadm trigger
|
||||
let attempts--
|
||||
done
|
||||
|
||||
if [ -z "${device_name}" ]; then
|
||||
echo "ERROR: disk device does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
device_path=/dev/disk/by-id/${device_name}
|
||||
|
||||
$configure_docker_storage_driver
|
||||
|
||||
if [ "$DOCKER_STORAGE_DRIVER" = "overlay" ]; then
|
||||
if [ $(echo -e "$(uname -r)\n3.18" | sort -V | head -1) \
|
||||
= $(uname -r) ]; then
|
||||
ERROR_MESSAGE="OverlayFS requires at least Linux kernel 3.18. Bay node kernel version: $(uname -r)"
|
||||
echo "ERROR: ${ERROR_MESSAGE}" >&2
|
||||
sh -c "${WAIT_CURL} --data-binary '{\"status\": \"FAILURE\", \"reason\": \"${ERROR_MESSAGE}\"}'"
|
||||
else
|
||||
configure_overlay
|
||||
fi
|
||||
else
|
||||
configure_devicemapper
|
||||
fi
|
@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
myip="$KUBE_NODE_IP"
|
||||
|
||||
cat > /etc/etcd/etcd.conf <<EOF
|
||||
ETCD_NAME="$myip"
|
||||
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
|
||||
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
|
||||
ETCD_LISTEN_PEER_URLS="http://$myip:2380"
|
||||
|
||||
ETCD_ADVERTISE_CLIENT_URLS="http://$myip:2379"
|
||||
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://$myip:2380"
|
||||
ETCD_DISCOVERY="$ETCD_DISCOVERY_URL"
|
||||
EOF
|
||||
|
||||
if [ -n "$HTTP_PROXY" ]; then
|
||||
echo "ETCD_DISCOVERY_PROXY=$HTTP_PROXY" >> /etc/etcd/etcd.conf
|
||||
fi
|
@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
. /etc/sysconfig/flanneld
|
||||
|
||||
FLANNEL_JSON=/etc/sysconfig/flannel-network.json
|
||||
|
||||
# Generate a flannel configuration that we will
|
||||
# store into etcd using curl.
|
||||
cat > $FLANNEL_JSON <<EOF
|
||||
{
|
||||
"Network": "$FLANNEL_NETWORK_CIDR",
|
||||
"Subnetlen": $FLANNEL_NETWORK_SUBNETLEN,
|
||||
"Backend": {
|
||||
"Type": "$FLANNEL_BACKEND"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# wait for etcd to become active (we will need it to push the flanneld config)
|
||||
while ! curl -sf -o /dev/null $FLANNEL_ETCD/v2/keys/; do
|
||||
echo "waiting for etcd"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# put the flannel config in etcd
|
||||
echo "creating flanneld config in etcd"
|
||||
curl -sf -L $FLANNEL_ETCD/v2/keys/coreos.com/network/config \
|
||||
-X PUT \
|
||||
--data-urlencode value@/etc/sysconfig/flannel-network.json
|
@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
echo "configuring kubernetes (master)"
|
||||
sed -i '
|
||||
/^ETCD_LISTEN_CLIENT_URLS=/ s/=.*/="http:\/\/0.0.0.0:2379"/
|
||||
' /etc/etcd/etcd.conf
|
||||
|
||||
sed -i '
|
||||
/^KUBE_ALLOW_PRIV=/ s/=.*/="--allow_privileged='"$KUBE_ALLOW_PRIV"'"/
|
||||
' /etc/kubernetes/config
|
||||
|
||||
KUBE_API_ARGS="--runtime_config=api/all=true"
|
||||
if [ "$TLS_DISABLED" == "True" ]; then
|
||||
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0 --insecure-port=$KUBE_API_PORT"
|
||||
else
|
||||
KUBE_API_ADDRESS="--bind_address=0.0.0.0 --secure-port=$KUBE_API_PORT"
|
||||
# insecure port is used internaly
|
||||
KUBE_API_ADDRESS="$KUBE_API_ADDRESS --insecure-port=8080"
|
||||
KUBE_API_ARGS="$KUBE_API_ARGS --tls_cert_file=/srv/kubernetes/server.crt"
|
||||
KUBE_API_ARGS="$KUBE_API_ARGS --tls_private_key_file=/srv/kubernetes/server.key"
|
||||
KUBE_API_ARGS="$KUBE_API_ARGS --client_ca_file=/srv/kubernetes/ca.crt"
|
||||
fi
|
||||
|
||||
sed -i '
|
||||
/^KUBE_API_ADDRESS=/ s/=.*/='"${KUBE_API_ADDRESS}"'/
|
||||
/^KUBE_SERVICE_ADDRESSES=/ s|=.*|="--service-cluster-ip-range='"$PORTAL_NETWORK_CIDR"'"|
|
||||
/^KUBE_API_ARGS=/ s/KUBE_API_ARGS.//
|
||||
/^KUBE_ETCD_SERVERS=/ s/=.*/="--etcd_servers=http:\/\/127.0.0.1:2379"/
|
||||
/^KUBE_ADMISSION_CONTROL=/ s/=.*/=""/
|
||||
' /etc/kubernetes/apiserver
|
||||
cat << _EOC_ >> /etc/kubernetes/apiserver
|
||||
#Uncomment the following line to disable Load Balancer feature
|
||||
KUBE_API_ARGS="$KUBE_API_ARGS"
|
||||
#Uncomment the following line to enable Load Balancer feature
|
||||
#KUBE_API_ARGS="$KUBE_API_ARGS --cloud_config=/etc/sysconfig/kube_openstack_config --cloud_provider=openstack"
|
||||
_EOC_
|
||||
|
||||
sed -i '
|
||||
/^KUBELET_ADDRESSES=/ s/=.*/="--machines='""'"/
|
||||
/^KUBE_CONTROLLER_MANAGER_ARGS=/ s/KUBE_CONTROLLER_MANAGER_ARGS.*/#Uncomment the following line to enable Kubernetes Load Balancer feature \n#KUBE_CONTROLLER_MANAGER_ARGS="--cloud_config=\/etc\/sysconfig\/kube_openstack_config --cloud_provider=openstack"/
|
||||
' /etc/kubernetes/controller-manager
|
||||
|
||||
KUBELET_ARGS="--register-node=true --register-schedulable=false --config=/etc/kubernetes/manifests --hostname-override=$KUBE_NODE_IP"
|
||||
|
||||
if [ -n "${INSECURE_REGISTRY_URL}" ]; then
|
||||
KUBELET_ARGS="${KUBELET_ARGS} --pod-infra-container-image=${INSECURE_REGISTRY_URL}/google_containers/pause\:0.8.0"
|
||||
echo "INSECURE_REGISTRY='--insecure-registry ${INSECURE_REGISTRY_URL}'" >> /etc/sysconfig/docker
|
||||
fi
|
||||
|
||||
sed -i '
|
||||
/^KUBELET_ADDRESS=/ s/=.*/="--address=0.0.0.0"/
|
||||
/^KUBELET_HOSTNAME=/ s/=.*/=""/
|
||||
/^KUBELET_ARGS=/ s|=.*|='"$KUBELET_ARGS"'|
|
||||
' /etc/kubernetes/kubelet
|
@ -0,0 +1,85 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
echo "configuring kubernetes (minion)"
|
||||
|
||||
ETCD_SERVER_IP=${ETCD_SERVER_IP:-$KUBE_MASTER_IP}
|
||||
KUBE_PROTOCOL="https"
|
||||
KUBE_CONFIG=""
|
||||
if [ "$TLS_DISABLED" = "True" ]; then
|
||||
KUBE_PROTOCOL="http"
|
||||
else
|
||||
KUBE_CONFIG="--kubeconfig=/srv/kubernetes/kubeconfig.yaml"
|
||||
fi
|
||||
KUBE_MASTER_URI="$KUBE_PROTOCOL://$KUBE_MASTER_IP:$KUBE_API_PORT"
|
||||
|
||||
sed -i '
|
||||
/^KUBE_ALLOW_PRIV=/ s/=.*/="--allow_privileged='"$KUBE_ALLOW_PRIV"'"/
|
||||
/^KUBE_ETCD_SERVERS=/ s|=.*|="--etcd_servers=http://'"$ETCD_SERVER_IP"':2379"|
|
||||
/^KUBE_MASTER=/ s|=.*|="--master='"$KUBE_MASTER_URI"'"|
|
||||
' /etc/kubernetes/config
|
||||
|
||||
KUBELET_ARGS="--config=/etc/kubernetes/manifests --cadvisor-port=4194 --hostname-override=$KUBE_NODE_IP ${KUBE_CONFIG}"
|
||||
|
||||
if [ -n "${INSECURE_REGISTRY_URL}" ]; then
|
||||
KUBELET_ARGS="${KUBELET_ARGS} --pod-infra-container-image=${INSECURE_REGISTRY_URL}/google_containers/pause\:0.8.0"
|
||||
echo "INSECURE_REGISTRY='--insecure-registry ${INSECURE_REGISTRY_URL}'" >> /etc/sysconfig/docker
|
||||
fi
|
||||
|
||||
sed -i '
|
||||
/^KUBELET_ADDRESS=/ s/=.*/="--address=0.0.0.0"/
|
||||
/^KUBELET_HOSTNAME=/ s/=.*/=""/
|
||||
/^KUBELET_API_SERVER=/ s|=.*|="--api_servers='"$KUBE_MASTER_URI"'"|
|
||||
/^KUBELET_ARGS=/ s|=.*|='"${KUBELET_ARGS}"'|
|
||||
' /etc/kubernetes/kubelet
|
||||
|
||||
sed -i '
|
||||
/^KUBE_PROXY_ARGS=/ s|=.*|='"$KUBE_CONFIG"'|
|
||||
' /etc/kubernetes/proxy
|
||||
|
||||
if [ "$NETWORK_DRIVER" = "flannel" ]; then
|
||||
sed -i '
|
||||
/^FLANNEL_ETCD=/ s|=.*|="http://'"$ETCD_SERVER_IP"':2379"|
|
||||
' /etc/sysconfig/flanneld
|
||||
|
||||
# Make sure etcd has a flannel configuration
|
||||
. /etc/sysconfig/flanneld
|
||||
until curl -sf "$FLANNEL_ETCD/v2/keys${FLANNEL_ETCD_KEY}/config?quorum=false&recursive=false&sorted=false"
|
||||
do
|
||||
echo "Waiting for flannel configuration in etcd..."
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$VOLUME_DRIVER" = "cinder" ]; then
|
||||
CLOUD_CONFIG=/etc/kubernetes/kube_openstack_config
|
||||
KUBERNETES=/etc/kubernetes
|
||||
if [ ! -d ${KUBERNETES} -o ! -f ${CLOUD_CONFIG} ]; then
|
||||
sudo mkdir -p $KUBERNETES
|
||||
fi
|
||||
AUTH_URL=$(echo "$AUTH_URL" | tr -s "v3" "v2")
|
||||
cat > $CLOUD_CONFIG <<EOF
|
||||
[Global]
|
||||
auth-url=$AUTH_URL
|
||||
username=$USERNAME
|
||||
password=$PASSWORD
|
||||
region=$REGION_NAME
|
||||
tenant-name=$TENANT_NAME
|
||||
EOF
|
||||
|
||||
cat << _EOC_ >> /etc/kubernetes/kubelet
|
||||
#KUBELET_ARGS="$KUBELET_ARGS --cloud-provider=openstack --cloud-config=/etc/kubernetes/kube_openstack_config"
|
||||
_EOC_
|
||||
|
||||
if [ ! -f /usr/bin/udevadm ]; then
|
||||
sudo ln -s /sbin/udevadm /usr/bin/udevadm
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
cat >> /etc/environment <<EOF
|
||||
KUBERNETES_MASTER=$KUBE_MASTER_URI
|
||||
EOF
|
||||
|
||||
hostname `hostname | sed 's/.novalocal//'`
|
@ -0,0 +1,8 @@
|
||||
#cloud-boothook
|
||||
#!/bin/sh
|
||||
|
||||
setenforce 0
|
||||
|
||||
sed -i '
|
||||
/^SELINUX=/ s/=.*/=permissive/
|
||||
' /etc/selinux/config
|
@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
if [ "$REGISTRY_ENABLED" = "False" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "starting docker registry ..."
|
||||
systemctl daemon-reload
|
||||
systemctl enable registry
|
||||
systemctl --no-block start registry
|
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "starting etcd"
|
||||
systemctl enable etcd
|
||||
systemctl --no-block start etcd
|
@ -0,0 +1,150 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
if [ -n "${INSECURE_REGISTRY_URL}" ]; then
|
||||
PODMASTER_IMAGE="${INSECURE_REGISTRY_URL}/google_containers/podmaster:1.1"
|
||||
HYPERKUBE_IMAGE="${INSECURE_REGISTRY_URL}/google_containers/hyperkube:${KUBE_VERSION}"
|
||||
else
|
||||
PODMASTER_IMAGE="gcr.io/google_containers/podmaster:1.1"
|
||||
HYPERKUBE_IMAGE="gcr.io/google_containers/hyperkube:${KUBE_VERSION}"
|
||||
fi
|
||||
|
||||
|
||||
init_templates () {
|
||||
local TEMPLATE=/etc/kubernetes/manifests/kube-podmaster.yaml
|
||||
[ -f ${TEMPLATE} ] || {
|
||||
echo "TEMPLATE: $TEMPLATE"
|
||||
mkdir -p $(dirname ${TEMPLATE})
|
||||
cat << EOF > ${TEMPLATE}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: kube-podmaster
|
||||
namespace: kube-system
|
||||
spec:
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: scheduler-elector
|
||||
image: ${PODMASTER_IMAGE}
|
||||
command:
|
||||
- /podmaster
|
||||
- --etcd-servers=http://127.0.0.1:2379
|
||||
- --key=scheduler
|
||||
- --source-file=/src/manifests/kube-scheduler.yaml
|
||||
- --dest-file=/dst/manifests/kube-scheduler.yaml
|
||||
volumeMounts:
|
||||
- mountPath: /src/manifests
|
||||
name: manifest-src
|
||||
readOnly: true
|
||||
- mountPath: /dst/manifests
|
||||
name: manifest-dst
|
||||
- name: controller-manager-elector
|
||||
image: ${PODMASTER_IMAGE}
|
||||
command:
|
||||
- /podmaster
|
||||
- --etcd-servers=http://127.0.0.1:2379
|
||||
- --key=controller
|
||||
- --source-file=/src/manifests/kube-controller-manager.yaml
|
||||
- --dest-file=/dst/manifests/kube-controller-manager.yaml
|
||||
terminationMessagePath: /dev/termination-log
|
||||
volumeMounts:
|
||||
- mountPath: /src/manifests
|
||||
name: manifest-src
|
||||
readOnly: true
|
||||
- mountPath: /dst/manifests
|
||||
name: manifest-dst
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /srv/kubernetes/manifests
|
||||
name: manifest-src
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/manifests
|
||||
name: manifest-dst
|
||||
EOF
|
||||
}
|
||||
|
||||
local SERVICE_ACCOUNT_PRIVATE_KEY_FILE=/etc/kubernetes/ssl/server.key
|
||||
local ROOT_CA_FILE=/etc/kubernetes/ssl/ca.crt
|
||||
|
||||
if [ "${TLS_DISABLED}" = "True" ]; then
|
||||
SERVICE_ACCOUNT_PRIVATE_KEY_FILE=
|
||||
ROOT_CA_FILE=
|
||||
fi
|
||||
|
||||
local TEMPLATE=/srv/kubernetes/manifests/kube-controller-manager.yaml
|
||||
[ -f ${TEMPLATE} ] || {
|
||||
echo "TEMPLATE: $TEMPLATE"
|
||||
mkdir -p $(dirname ${TEMPLATE})
|
||||
cat << EOF > ${TEMPLATE}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: kube-controller-manager
|
||||
namespace: kube-system
|
||||
spec:
|
||||
containers:
|
||||
- name: kube-controller-manager
|
||||
image: ${HYPERKUBE_IMAGE}
|
||||
command:
|
||||
- /hyperkube
|
||||
- controller-manager
|
||||
- --master=http://127.0.0.1:8080
|
||||
- --service-account-private-key-file=${SERVICE_ACCOUNT_PRIVATE_KEY_FILE}
|
||||
- --root-ca-file=${ROOT_CA_FILE}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
host: 127.0.0.1
|
||||
path: /healthz
|
||||
port: 10252
|
||||
initialDelaySeconds: 15
|
||||
timeoutSeconds: 1
|
||||
volumeMounts:
|
||||
- mountPath: /etc/kubernetes/ssl
|
||||
name: ssl-certs-kubernetes
|
||||
readOnly: true
|
||||
- mountPath: /etc/ssl/certs
|
||||
name: ssl-certs-host
|
||||
readOnly: true
|
||||
hostNetwork: true
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /srv/kubernetes
|
||||
name: ssl-certs-kubernetes
|
||||
- hostPath:
|
||||
path: /etc/ssl/certs
|
||||
name: ssl-certs-host
|
||||
EOF
|
||||
}
|
||||
|
||||
local TEMPLATE=/srv/kubernetes/manifests/kube-scheduler.yaml
|
||||
[ -f ${TEMPLATE} ] || {
|
||||
echo "TEMPLATE: $TEMPLATE"
|
||||
mkdir -p $(dirname ${TEMPLATE})
|
||||
cat << EOF > ${TEMPLATE}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: kube-scheduler
|
||||
namespace: kube-system
|
||||
spec:
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: kube-scheduler
|
||||
image: ${HYPERKUBE_IMAGE}
|
||||
command:
|
||||
- /hyperkube
|
||||
- scheduler
|
||||
- --master=http://127.0.0.1:8080
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
host: 127.0.0.1
|
||||
path: /healthz
|
||||
port: 10251
|
||||
initialDelaySeconds: 15
|
||||
timeoutSeconds: 1
|
||||
EOF
|
||||
}
|
||||
}
|
||||
|
||||
init_templates
|
@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
if [ -n "${INSECURE_REGISTRY_URL}" ]; then
|
||||
HYPERKUBE_IMAGE="${INSECURE_REGISTRY_URL}/google_containers/hyperkube:${KUBE_VERSION}"
|
||||
else
|
||||
HYPERKUBE_IMAGE="gcr.io/google_containers/hyperkube:${KUBE_VERSION}"
|
||||
fi
|
||||
|
||||
init_templates () {
|
||||
local TEMPLATE=/etc/kubernetes/manifests/kube-proxy.yaml
|
||||
[ -f ${TEMPLATE} ] || {
|
||||
echo "TEMPLATE: $TEMPLATE"
|
||||
mkdir -p $(dirname ${TEMPLATE})
|
||||
cat << EOF > ${TEMPLATE}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: kube-proxy
|
||||
namespace: kube-system
|
||||
spec:
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: kube-proxy
|
||||
image: ${HYPERKUBE_IMAGE}
|
||||
command:
|
||||
- /hyperkube
|
||||
- proxy
|
||||
- --master=http://127.0.0.1:8080
|
||||
- --logtostderr=true
|
||||
- --v=0
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /etc/ssl/certs
|
||||
name: ssl-certs-host
|
||||
readOnly: true
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /etc/ssl/certs
|
||||
name: ssl-certs-host
|
||||
EOF
|
||||
}
|
||||
}
|
||||
|
||||
init_templates
|
@ -0,0 +1,62 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
if [ -n "${INSECURE_REGISTRY_URL}" ]; then
|
||||
HYPERKUBE_IMAGE="${INSECURE_REGISTRY_URL}/google_containers/hyperkube:${KUBE_VERSION}"
|
||||
else
|
||||
HYPERKUBE_IMAGE="gcr.io/google_containers/hyperkube:${KUBE_VERSION}"
|
||||
fi
|
||||
|
||||
init_templates () {
|
||||
local KUBE_PROTOCOL="https"
|
||||
local KUBE_CONFIG="/srv/kubernetes/kubeconfig.yaml"
|
||||
if [ "${TLS_DISABLED}" = "True" ]; then
|
||||
KUBE_PROTOCOL="http"
|
||||
KUBE_CONFIG=
|
||||
fi
|
||||
|
||||
local MASTER="${KUBE_PROTOCOL}://${KUBE_MASTER_IP}:${KUBE_API_PORT}"
|
||||
local TEMPLATE=/etc/kubernetes/manifests/kube-proxy.yaml
|
||||
[ -f ${TEMPLATE} ] || {
|
||||
echo "TEMPLATE: $TEMPLATE"
|
||||
mkdir -p $(dirname ${TEMPLATE})
|
||||
cat << EOF > ${TEMPLATE}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: kube-proxy
|
||||
namespace: kube-system
|
||||
spec:
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: kube-proxy
|
||||
image: ${HYPERKUBE_IMAGE}
|
||||
command:
|
||||
- /hyperkube
|
||||
- proxy
|
||||
- --master=${MASTER}
|
||||
- --kubeconfig=${KUBE_CONFIG}
|
||||
- --logtostderr=true
|
||||
- --v=0
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /etc/ssl/certs
|
||||
name: ssl-certs-host
|
||||
readOnly: true
|
||||
- mountPath: /srv/kubernetes
|
||||
name: "srv-kube"
|
||||
readOnly: true
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /etc/ssl/certs
|
||||
name: ssl-certs-host
|
||||
- hostPath:
|
||||
path: "/srv/kubernetes"
|
||||
name: "srv-kube"
|
||||
EOF
|
||||
}
|
||||
}
|
||||
|
||||
init_templates
|
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
# make sure we pick up any modified unit files
|
||||
systemctl daemon-reload
|
||||
|
||||
echo "starting services"
|
||||
for service in etcd docker kube-apiserver kubelet; do
|
||||
echo "activating service $service"
|
||||
systemctl enable $service
|
||||
systemctl --no-block start $service
|
||||
done
|
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
# docker is already enabled and possibly running on centos atomic host
|
||||
# so we need to stop it first and delete the docker0 bridge (which will
|
||||
# be re-created using the flannel-provided subnet).
|
||||
echo "stopping docker"
|
||||
systemctl stop docker
|
||||
ip link del docker0
|
||||
|
||||
# make sure we pick up any modified unit files
|
||||
systemctl daemon-reload
|
||||
|
||||
for service in docker kubelet; do
|
||||
echo "activating service $service"
|
||||
systemctl enable $service
|
||||
systemctl --no-block start $service
|
||||
done
|
@ -0,0 +1,117 @@
|
||||
#cloud-config
|
||||
merge_how: dict(recurse_array)+list(append)
|
||||
write_files:
|
||||
- path: /etc/kubernetes/examples/replication-controller.yaml
|
||||
owner: "root:root"
|
||||
permissions: "0644"
|
||||
content: |
|
||||
apiVersion: v1
|
||||
kind: ReplicationController
|
||||
metadata:
|
||||
name: nginx-controller
|
||||
spec:
|
||||
replicas: 2
|
||||
# selector identifies the set of pods that this
|
||||
# replication controller is responsible for managing
|
||||
selector:
|
||||
name: nginx
|
||||
# template defines the 'cookie cutter' used for creating
|
||||
# new pods when necessary
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
# Important: these labels need to match the selector above
|
||||
# The api server enforces this constraint.
|
||||
name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
|
||||
- path: /etc/kubernetes/examples/pod-nginx-with-label.yaml
|
||||
owner: "root:root"
|
||||
permissions: "0644"
|
||||
content: |
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: nginx
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
|
||||
- path: /etc/kubernetes/examples/service.yaml
|
||||
owner: "root:root"
|
||||
permissions: "0644"
|
||||
content: |
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-service
|
||||
spec:
|
||||
ports:
|
||||
- port: 8000 # the port that this service should serve on
|
||||
# the container on each pod to connect to, can be a name
|
||||
# (e.g. 'www') or a number (e.g. 80)
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
# just like the selector in the replication controller,
|
||||
# but this time it identifies the set of pods to load balance
|
||||
# traffic to.
|
||||
selector:
|
||||
app: nginx
|
||||
|
||||
- path: /etc/kubernetes/examples/README.md
|
||||
owner: "root:root"
|
||||
permissions: "0644"
|
||||
content: |
|
||||
Kubernetes 101 (http://kubernetes.io/v1.0/docs/user-guide/walkthrough/README.html)
|
||||
==================================================================================
|
||||
|
||||
List all nodes:
|
||||
|
||||
kubectl get nodes
|
||||
|
||||
Replication Controllers:
|
||||
|
||||
kubectl create -f /etc/kubernetes/examples/replication-controller.yaml
|
||||
kubectl get rc
|
||||
kubectl delete rc nginx-controller
|
||||
|
||||
Pods:
|
||||
|
||||
kubectl create -f /etc/kubernetes/examples/pod-nginx-with-label.yaml
|
||||
kubectl get pods
|
||||
curl http://$(kubectl get pod nginx -o=template -t={{.status.podIP}})
|
||||
|
||||
Services:
|
||||
|
||||
kubectl create -f /etc/kubernetes/examples/service.yaml
|
||||
kubectl get services
|
||||
|
||||
export SERVICE_IP=$(kubectl get service nginx-service -o=template -t={{.spec.clusterIP}})
|
||||
export SERVICE_PORT=$(kubectl get service nginx-service -o=template '-t={{(index .spec.ports 0).port}}')
|
||||
curl http://${SERVICE_IP}:${SERVICE_PORT}
|
||||
|
||||
kubectl delete service nginx-service
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
kubectl get events
|
||||
|
||||
kubectl describe rc nginx-controller
|
||||
|
||||
kubectl describe pod nginx
|
||||
|
||||
kubectl describe service nginx-service
|
||||
|
||||
kubectl exec nginx env
|
||||
|
||||
kubectl exec -ti nginx -- bash
|
@ -0,0 +1,66 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this service required because docker will start only after cloud init was finished
|
||||
# due service dependencies at Fedora Atomic (docker <- docker-storage-setup <- cloud-final)
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
KUBE_SYSTEM_JSON=/srv/kubernetes/kube-system-namespace.json
|
||||
[ -f ${KUBE_SYSTEM_JSON} ] || {
|
||||
echo "Writing File: $KUBE_SYSTEM_JSON"
|
||||
mkdir -p $(dirname ${KUBE_SYSTEM_JSON})
|
||||
cat << EOF > ${KUBE_SYSTEM_JSON}
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Namespace",
|
||||
"metadata": {
|
||||
"name": "kube-system"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
KUBE_SYSTEM_BIN=/usr/local/bin/kube-system-namespace
|
||||
[ -f ${KUBE_SYSTEM_BIN} ] || {
|
||||
echo "Writing File: $KUBE_SYSTEM_BIN"
|
||||
mkdir -p $(dirname ${KUBE_SYSTEM_BIN})
|
||||
cat << EOF > ${KUBE_SYSTEM_BIN}
|
||||
#!/bin/sh
|
||||
until curl -sf "http://127.0.0.1:8080/healthz"
|
||||
do
|
||||
echo "Waiting for Kubernetes API..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
/usr/bin/kubectl create -f /srv/kubernetes/kube-system-namespace.json
|
||||
EOF
|
||||
}
|
||||
|
||||
KUBE_SYSTEM_SERVICE=/etc/systemd/system/kube-system-namespace.service
|
||||
[ -f ${KUBE_SYSTEM_SERVICE} ] || {
|
||||
echo "Writing File: $KUBE_SYSTEM_SERVICE"
|
||||
mkdir -p $(dirname ${KUBE_SYSTEM_SERVICE})
|
||||
cat << EOF > ${KUBE_SYSTEM_SERVICE}
|
||||
[Unit]
|
||||
After=kubelet.service
|
||||
Requires=kubelet.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
Environment=HOME=/root
|
||||
EnvironmentFile=-/etc/kubernetes/config
|
||||
ExecStart=${KUBE_SYSTEM_BIN}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
}
|
||||
|
||||
chown root:root ${KUBE_SYSTEM_BIN}
|
||||
chmod 0755 ${KUBE_SYSTEM_BIN}
|
||||
|
||||
chown root:root ${KUBE_SYSTEM_SERVICE}
|
||||
chmod 0644 ${KUBE_SYSTEM_SERVICE}
|
||||
|
||||
systemctl enable kube-system-namespace
|
||||
systemctl start --no-block kube-system-namespace
|
@ -0,0 +1,121 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this service is required because docker will start only after cloud init was finished
|
||||
# due to the service dependencies in Fedora Atomic (docker <- docker-storage-setup <- cloud-final)
|
||||
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
if [ -n "${INSECURE_REGISTRY_URL}" ]; then
|
||||
KUBEUI_IMAGE="${INSECURE_REGISTRY_URL}/google_containers/kube-ui:v4"
|
||||
else
|
||||
KUBEUI_IMAGE="gcr.io/google_containers/kube-ui:v4"
|
||||
fi
|
||||
|
||||
KUBE_UI_RC=/srv/kubernetes/manifests/kube-ui-rc.yaml
|
||||
|
||||
[ -f ${KUBE_UI_RC} ] || {
|
||||
echo "Writing File: $KUBE_UI_RC"
|
||||
mkdir -p $(dirname ${KUBE_UI_RC})
|
||||
cat << EOF > ${KUBE_UI_RC}
|
||||
apiVersion: v1
|
||||
kind: ReplicationController
|
||||
metadata:
|
||||
name: kube-ui-v4
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: kube-ui
|
||||
version: v4
|
||||
kubernetes.io/cluster-service: "true"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
k8s-app: kube-ui
|
||||
version: v4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kube-ui
|
||||
version: v4
|
||||
kubernetes.io/cluster-service: "true"
|
||||
spec:
|
||||
containers:
|
||||
- name: kube-ui
|
||||
image: ${KUBEUI_IMAGE}
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 50Mi
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
EOF
|
||||
}
|
||||
|
||||
KUBE_UI_SVC=/srv/kubernetes/manifests/kube-ui-svc.yaml
|
||||
[ -f ${KUBE_UI_SVC} ] || {
|
||||
echo "Writing File: $KUBE_UI_SVC"
|
||||
mkdir -p $(dirname ${KUBE_UI_SVC})
|
||||
cat << EOF > ${KUBE_UI_SVC}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kube-ui
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: kube-ui
|
||||
kubernetes.io/cluster-service: "true"
|
||||
kubernetes.io/name: "KubeUI"
|
||||
spec:
|
||||
selector:
|
||||
k8s-app: kube-ui
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
EOF
|
||||
}
|
||||
|
||||
KUBE_UI_BIN=/usr/local/bin/kube-ui
|
||||
[ -f ${KUBE_UI_BIN} ] || {
|
||||
echo "Writing File: $KUBE_UI_BIN"
|
||||
mkdir -p $(dirname ${KUBE_UI_BIN})
|
||||
cat << EOF > ${KUBE_UI_BIN}
|
||||
#!/bin/sh
|
||||
until curl -sf "http://127.0.0.1:8080/healthz"
|
||||
do
|
||||
echo "Waiting for Kubernetes API..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
/usr/bin/kubectl create -f /srv/kubernetes/manifests/kube-ui-rc.yaml --namespace=kube-system
|
||||
/usr/bin/kubectl create -f /srv/kubernetes/manifests/kube-ui-svc.yaml --namespace=kube-system
|
||||
EOF
|
||||
}
|
||||
|
||||
KUBE_UI_SERVICE=/etc/systemd/system/kube-ui.service
|
||||
[ -f ${KUBE_UI_SERVICE} ] || {
|
||||
echo "Writing File: $KUBE_UI_SERVICE"
|
||||
mkdir -p $(dirname ${KUBE_UI_SERVICE})
|
||||
cat << EOF > ${KUBE_UI_SERVICE}
|
||||
[Unit]
|
||||
After=kube-system-namespace
|
||||
Requires=kubelet.service
|
||||
Requires=kube-system-namespace.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
EnvironmentFile=-/etc/kubernetes/config
|
||||
ExecStart=${KUBE_UI_BIN}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
}
|
||||
|
||||
chown root:root ${KUBE_UI_BIN}
|
||||
chmod 0755 ${KUBE_UI_BIN}
|
||||
|
||||
chown root:root ${KUBE_UI_SERVICE}
|
||||
chmod 0644 ${KUBE_UI_SERVICE}
|
||||
|
||||
systemctl enable kube-ui
|
||||
systemctl start --no-block kube-ui
|
@ -0,0 +1,9 @@
|
||||
#cloud-config
|
||||
system_info:
|
||||
default_user:
|
||||
name: minion
|
||||
lock_passwd: true
|
||||
gecos: Kubernetes Interactive User
|
||||
groups: [wheel, adm, systemd-journal]
|
||||
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
|
||||
shell: /bin/bash
|
@ -0,0 +1,115 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
if [ "$TLS_DISABLED" == "True" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cert_dir=/srv/kubernetes
|
||||
cert_conf_dir=${cert_dir}/conf
|
||||
|
||||
mkdir -p "$cert_dir"
|
||||
mkdir -p "$cert_conf_dir"
|
||||
|
||||
CA_CERT=$cert_dir/ca.crt
|
||||
CLIENT_CERT=$cert_dir/client.crt
|
||||
CLIENT_CSR=$cert_dir/client.csr
|
||||
CLIENT_KEY=$cert_dir/client.key
|
||||
|
||||
#Get a token by user credentials and trust
|
||||
auth_json=$(cat << EOF
|
||||
{
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": [
|
||||
"password"
|
||||
],
|
||||
"password": {
|
||||
"user": {
|
||||
"id": "$TRUSTEE_USER_ID",
|
||||
"password": "$TRUSTEE_PASSWORD"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": {
|
||||
"OS-TRUST:trust": {
|
||||
"id": "$TRUST_ID"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
#trust is introduced in Keystone v3 version
|
||||
AUTH_URL=${AUTH_URL/v2.0/v3}
|
||||
USER_TOKEN=`curl -s -i -X POST -H "Content-Type: application/json" -d "$auth_json" \
|
||||
$AUTH_URL/auth/tokens | grep X-Subject-Token | awk '{print $2}'`
|
||||
|
||||
# Get CA certificate for this bay
|
||||
curl -X GET \
|
||||
-H "X-Auth-Token: $USER_TOKEN" \
|
||||
$MAGNUM_URL/certificates/$BAY_UUID | python -c 'import sys, json; print json.load(sys.stdin)["pem"]' > $CA_CERT
|
||||
|
||||
# Create config for client's csr
|
||||
cat > ${cert_conf_dir}/client.conf <<EOF
|
||||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = req_ext
|
||||
prompt = no
|
||||
[req_distinguished_name]
|
||||
CN = kubernetes.invalid
|
||||
[req_ext]
|
||||
keyUsage=critical,digitalSignature,keyEncipherment
|
||||
extendedKeyUsage=clientAuth
|
||||
subjectAltName=dirName:kubelet,dirName:kubeproxy
|
||||
[kubelet]
|
||||
CN=kubelet
|
||||
[kubeproxy]
|
||||
CN=kube-proxy
|
||||
EOF
|
||||
|
||||
# Generate client's private key and csr
|
||||
openssl genrsa -out "${CLIENT_KEY}" 4096
|
||||
chmod 400 "${CLIENT_KEY}"
|
||||
openssl req -new -days 1000 \
|
||||
-key "${CLIENT_KEY}" \
|
||||
-out "${CLIENT_CSR}" \
|
||||
-reqexts req_ext \
|
||||
-config "${cert_conf_dir}/client.conf"
|
||||
|
||||
# Send csr to Magnum to have it signed
|
||||
csr_req=$(python -c "import json; fp = open('${CLIENT_CSR}'); print json.dumps({'bay_uuid': '$BAY_UUID', 'csr': fp.read()}); fp.close()")
|
||||
curl -X POST \
|
||||
-H "X-Auth-Token: $USER_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$csr_req" \
|
||||
$MAGNUM_URL/certificates | python -c 'import sys, json; print json.load(sys.stdin)["pem"]' > ${CLIENT_CERT}
|
||||
|
||||
chmod 500 "${cert_dir}"
|
||||
chown -R kube:kube "${cert_dir}"
|
||||
|
||||
sed -i '
|
||||
s|CA_CERT|'"$CA_CERT"'|
|
||||
s|CLIENT_CERT|'"$CLIENT_CERT"'|
|
||||
s|CLIENT_KEY|'"$CLIENT_KEY"'|
|
||||
' /srv/kubernetes/kubeconfig.yaml
|
@ -0,0 +1,111 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
if [ "$TLS_DISABLED" == "True" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cert_ip=$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4)
|
||||
sans="IP:${cert_ip},IP:${KUBE_API_PUBLIC_ADDRESS},IP:${KUBE_API_PRIVATE_ADDRESS},IP:127.0.0.1"
|
||||
MASTER_HOSTNAME=${MASTER_HOSTNAME:-}
|
||||
if [[ -n "${MASTER_HOSTNAME}" ]]; then
|
||||
sans="${sans},DNS:${MASTER_HOSTNAME}"
|
||||
fi
|
||||
|
||||
cert_dir=/srv/kubernetes
|
||||
cert_conf_dir=${cert_dir}/conf
|
||||
|
||||
mkdir -p "$cert_dir"
|
||||
mkdir -p "$cert_conf_dir"
|
||||
|
||||
CA_CERT=$cert_dir/ca.crt
|
||||
SERVER_CERT=$cert_dir/server.crt
|
||||
SERVER_CSR=$cert_dir/server.csr
|
||||
SERVER_KEY=$cert_dir/server.key
|
||||
|
||||
#Get a token by user credentials and trust
|
||||
auth_json=$(cat << EOF
|
||||
{
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": [
|
||||
"password"
|
||||
],
|
||||
"password": {
|
||||
"user": {
|
||||
"id": "$TRUSTEE_USER_ID",
|
||||
"password": "$TRUSTEE_PASSWORD"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": {
|
||||
"OS-TRUST:trust": {
|
||||
"id": "$TRUST_ID"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
#trust is introduced in Keystone v3 version
|
||||
AUTH_URL=${AUTH_URL/v2.0/v3}
|
||||
USER_TOKEN=`curl -s -i -X POST -H "Content-Type: application/json" -d "$auth_json" \
|
||||
$AUTH_URL/auth/tokens | grep X-Subject-Token | awk '{print $2}'`
|
||||
|
||||
# Get CA certificate for this bay
|
||||
curl -X GET \
|
||||
-H "X-Auth-Token: $USER_TOKEN" \
|
||||
$MAGNUM_URL/certificates/$BAY_UUID | python -c 'import sys, json; print json.load(sys.stdin)["pem"]' > ${CA_CERT}
|
||||
|
||||
# Create config for server's csr
|
||||
cat > ${cert_conf_dir}/server.conf <<EOF
|
||||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = req_ext
|
||||
prompt = no
|
||||
[req_distinguished_name]
|
||||
CN = kubernetes.invalid
|
||||
[req_ext]
|
||||
subjectAltName = ${sans}
|
||||
extendedKeyUsage = clientAuth,serverAuth
|
||||
EOF
|
||||
|
||||
# Generate server's private key and csr
|
||||
openssl genrsa -out "${SERVER_KEY}" 4096
|
||||
chmod 400 "${SERVER_KEY}"
|
||||
openssl req -new -days 1000 \
|
||||
-key "${SERVER_KEY}" \
|
||||
-out "${SERVER_CSR}" \
|
||||
-reqexts req_ext \
|
||||
-config "${cert_conf_dir}/server.conf"
|
||||
|
||||
# Send csr to Magnum to have it signed
|
||||
csr_req=$(python -c "import json; fp = open('${SERVER_CSR}'); print json.dumps({'bay_uuid': '$BAY_UUID', 'csr': fp.read()}); fp.close()")
|
||||
curl -X POST \
|
||||
-H "X-Auth-Token: $USER_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$csr_req" \
|
||||
$MAGNUM_URL/certificates | python -c 'import sys, json; print json.load(sys.stdin)["pem"]' > ${SERVER_CERT}
|
||||
|
||||
chmod 500 "${cert_dir}"
|
||||
chown -R kube:kube "${cert_dir}"
|
@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
if [ "$NETWORK_DRIVER" != "flannel" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
. /etc/sysconfig/flanneld
|
||||
|
||||
FLANNEL_CONFIG_BIN=/usr/local/bin/flannel-config
|
||||
FLANNEL_CONFIG_SERVICE=/etc/systemd/system/flannel-config.service
|
||||
FLANNEL_JSON=/etc/sysconfig/flannel-network.json
|
||||
|
||||
echo "creating $FLANNEL_CONFIG_BIN"
|
||||
cat > $FLANNEL_CONFIG_BIN <<EOF
|
||||
#!/bin/sh
|
||||
|
||||
if ! [ -f "$FLANNEL_JSON" ]; then
|
||||
echo "ERROR: missing network configuration file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ "$FLANNEL_ETCD" ] && [ "$FLANNEL_ETCD_KEY" ]; then
|
||||
echo "ERROR: missing required configuration" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "creating flanneld config in etcd"
|
||||
while ! curl -sf -L $FLANNEL_ETCD/v2/keys${FLANNEL_ETCD_KEY}/config \
|
||||
-X PUT --data-urlencode value@${FLANNEL_JSON}; do
|
||||
echo "waiting for etcd"
|
||||
sleep 1
|
||||
done
|
||||
EOF
|
||||
|
||||
cat > $FLANNEL_CONFIG_SERVICE <<EOF
|
||||
[Unit]
|
||||
After=etcd.service
|
||||
Requires=etcd.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
EnvironmentFile=/etc/sysconfig/flanneld
|
||||
ExecStart=$FLANNEL_CONFIG_BIN
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
chown root:root $FLANNEL_CONFIG_BIN
|
||||
chmod 0755 $FLANNEL_CONFIG_BIN
|
||||
|
||||
chown root:root $FLANNEL_CONFIG_SERVICE
|
||||
chmod 0644 $FLANNEL_CONFIG_SERVICE
|
||||
|
||||
systemctl enable flannel-config
|
||||
systemctl start --no-block flannel-config
|
@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
if [ "$NETWORK_DRIVER" != "flannel" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
FLANNEL_DOCKER_BRIDGE_BIN=/usr/local/bin/flannel-docker-bridge
|
||||
FLANNEL_DOCKER_BRIDGE_SERVICE=/etc/systemd/system/flannel-docker-bridge.service
|
||||
DOCKER_FLANNEL_CONF=/etc/systemd/system/docker.service.d/flannel.conf
|
||||
FLANNEL_DOCKER_BRIDGE_CONF=/etc/systemd/system/flanneld.service.d/flannel-docker-bridge.conf
|
||||
|
||||
mkdir -p /etc/systemd/system/docker.service.d
|
||||
mkdir -p /etc/systemd/system/flanneld.service.d
|
||||
|
||||
cat >> $FLANNEL_DOCKER_BRIDGE_BIN <<EOF1
|
||||
#!/bin/sh
|
||||
|
||||
if ! [ "\$FLANNEL_SUBNET" ] && [ "\$FLANNEL_MTU" ] ; then
|
||||
echo "ERROR: missing required environment variables." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p /run/flannel/
|
||||
cat > /run/flannel/docker <<EOF2
|
||||
DOCKER_NETWORK_OPTIONS="--bip=\$FLANNEL_SUBNET --mtu=\$FLANNEL_MTU"
|
||||
EOF2
|
||||
EOF1
|
||||
|
||||
chown root:root $FLANNEL_DOCKER_BRIDGE_BIN
|
||||
chmod 0755 $FLANNEL_DOCKER_BRIDGE_BIN
|
||||
|
||||
cat >> $FLANNEL_DOCKER_BRIDGE_SERVICE <<EOF
|
||||
[Unit]
|
||||
After=flanneld.service
|
||||
Before=docker.service
|
||||
Requires=flanneld.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
EnvironmentFile=/run/flannel/subnet.env
|
||||
ExecStart=/usr/local/bin/flannel-docker-bridge
|
||||
|
||||
[Install]
|
||||
WantedBy=docker.service
|
||||
EOF
|
||||
|
||||
chown root:root $FLANNEL_DOCKER_BRIDGE_SERVICE
|
||||
chmod 0644 $FLANNEL_DOCKER_BRIDGE_SERVICE
|
||||
|
||||
cat >> $DOCKER_FLANNEL_CONF <<EOF
|
||||
[Unit]
|
||||
Requires=flannel-docker-bridge.service
|
||||
After=flannel-docker-bridge.service
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=/run/flannel/docker
|
||||
EOF
|
||||
|
||||
chown root:root $DOCKER_FLANNEL_CONF
|
||||
chmod 0644 $DOCKER_FLANNEL_CONF
|
||||
|
||||
cat >> $FLANNEL_DOCKER_BRIDGE_CONF <<EOF
|
||||
[Unit]
|
||||
Requires=flannel-docker-bridge.service
|
||||
Before=flannel-docker-bridge.service
|
||||
|
||||
[Install]
|
||||
Also=flannel-docker-bridge.service
|
||||
EOF
|
||||
|
||||
chown root:root $FLANNEL_DOCKER_BRIDGE_CONF
|
||||
chmod 0644 $FLANNEL_DOCKER_BRIDGE_CONF
|
||||
|
||||
echo "activating service flanneld"
|
||||
systemctl enable flanneld
|
||||
systemctl --no-block start flanneld
|
@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
WC_NOTIFY_BIN=/usr/local/bin/wc-notify
|
||||
WC_NOTIFY_SERVICE=/etc/systemd/system/wc-notify.service
|
||||
|
||||
cat > $WC_NOTIFY_BIN <<EOF
|
||||
#!/bin/bash -v
|
||||
until curl -sf "http://127.0.0.1:8080/healthz"; do
|
||||
echo "Waiting for Kubernetes API..."
|
||||
sleep 5
|
||||
done
|
||||
$WAIT_CURL --data-binary '{"status": "SUCCESS"}'
|
||||
EOF
|
||||
|
||||
cat > $WC_NOTIFY_SERVICE <<EOF
|
||||
[Unit]
|
||||
Description=Notify Heat
|
||||
After=docker.service etcd.service
|
||||
Requires=docker.service etcd.service
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=$WC_NOTIFY_BIN
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
chown root:root $WC_NOTIFY_BIN
|
||||
chmod 0755 $WC_NOTIFY_BIN
|
||||
|
||||
chown root:root $WC_NOTIFY_SERVICE
|
||||
chmod 0644 $WC_NOTIFY_SERVICE
|
||||
|
||||
systemctl enable wc-notify
|
||||
systemctl start --no-block wc-notify
|
@ -0,0 +1,37 @@
|
||||
#cloud-config
|
||||
merge_how: dict(recurse_array)+list(append)
|
||||
write_files:
|
||||
- path: /etc/sysconfig/heat-params
|
||||
owner: "root:root"
|
||||
permissions: "0644"
|
||||
content: |
|
||||
KUBE_API_PUBLIC_ADDRESS="$KUBE_API_PUBLIC_ADDRESS"
|
||||
KUBE_API_PRIVATE_ADDRESS="$KUBE_API_PRIVATE_ADDRESS"
|
||||
KUBE_API_PORT="$KUBE_API_PORT"
|
||||
KUBE_NODE_IP="$KUBE_NODE_IP"
|
||||
KUBE_ALLOW_PRIV="$KUBE_ALLOW_PRIV"
|
||||
DOCKER_VOLUME="$DOCKER_VOLUME"
|
||||
DOCKER_STORAGE_DRIVER="$DOCKER_STORAGE_DRIVER"
|
||||
NETWORK_DRIVER="$NETWORK_DRIVER"
|
||||
FLANNEL_NETWORK_CIDR="$FLANNEL_NETWORK_CIDR"
|
||||
FLANNEL_NETWORK_SUBNETLEN="$FLANNEL_NETWORK_SUBNETLEN"
|
||||
FLANNEL_BACKEND="$FLANNEL_BACKEND"
|
||||
PORTAL_NETWORK_CIDR="$PORTAL_NETWORK_CIDR"
|
||||
ETCD_DISCOVERY_URL="$ETCD_DISCOVERY_URL"
|
||||
USERNAME="$USERNAME"
|
||||
PASSWORD="$PASSWORD"
|
||||
TENANT_NAME="$TENANT_NAME"
|
||||
CLUSTER_SUBNET="$CLUSTER_SUBNET"
|
||||
TLS_DISABLED="$TLS_DISABLED"
|
||||
BAY_UUID="$BAY_UUID"
|
||||
MAGNUM_URL="$MAGNUM_URL"
|
||||
HTTP_PROXY="$HTTP_PROXY"
|
||||
HTTPS_PROXY="$HTTPS_PROXY"
|
||||
NO_PROXY="$NO_PROXY"
|
||||
WAIT_CURL="$WAIT_CURL"
|
||||
KUBE_VERSION="$KUBE_VERSION"
|
||||
TRUSTEE_USER_ID="$TRUSTEE_USER_ID"
|
||||
TRUSTEE_PASSWORD="$TRUSTEE_PASSWORD"
|
||||
TRUST_ID="$TRUST_ID"
|
||||
AUTH_URL="$AUTH_URL"
|
||||
INSECURE_REGISTRY_URL="$INSECURE_REGISTRY_URL"
|
@ -0,0 +1,42 @@
|
||||
#cloud-config
|
||||
merge_how: dict(recurse_array)+list(append)
|
||||
write_files:
|
||||
- path: /etc/sysconfig/heat-params
|
||||
owner: "root:root"
|
||||
permissions: "0644"
|
||||
content: |
|
||||
KUBE_ALLOW_PRIV="$KUBE_ALLOW_PRIV"
|
||||
KUBE_MASTER_IP="$KUBE_MASTER_IP"
|
||||
KUBE_API_PORT="$KUBE_API_PORT"
|
||||
KUBE_NODE_IP="$KUBE_NODE_IP"
|
||||
ETCD_SERVER_IP="$ETCD_SERVER_IP"
|
||||
DOCKER_VOLUME="$DOCKER_VOLUME"
|
||||
DOCKER_STORAGE_DRIVER="$DOCKER_STORAGE_DRIVER"
|
||||
NETWORK_DRIVER="$NETWORK_DRIVER"
|
||||
REGISTRY_ENABLED="$REGISTRY_ENABLED"
|
||||
REGISTRY_PORT="$REGISTRY_PORT"
|
||||
SWIFT_REGION="$SWIFT_REGION"
|
||||
REGISTRY_CONTAINER="$REGISTRY_CONTAINER"
|
||||
REGISTRY_INSECURE="$REGISTRY_INSECURE"
|
||||
REGISTRY_CHUNKSIZE="$REGISTRY_CHUNKSIZE"
|
||||
TLS_DISABLED="$TLS_DISABLED"
|
||||
BAY_UUID="$BAY_UUID"
|
||||
MAGNUM_URL="$MAGNUM_URL"
|
||||
AUTH_URL="$AUTH_URL"
|
||||
USERNAME="$USERNAME"
|
||||
PASSWORD="$PASSWORD"
|
||||
VOLUME_DRIVER="$VOLUME_DRIVER"
|
||||
REGION_NAME="$REGION_NAME"
|
||||
TENANT_NAME="$TENANT_NAME"
|
||||
HTTP_PROXY="$HTTP_PROXY"
|
||||
HTTPS_PROXY="$HTTPS_PROXY"
|
||||
NO_PROXY="$NO_PROXY"
|
||||
WAIT_CURL="$WAIT_CURL"
|
||||
KUBE_VERSION="$KUBE_VERSION"
|
||||
TRUSTEE_USER_ID="$TRUSTEE_USER_ID"
|
||||
TRUSTEE_USERNAME="$TRUSTEE_USERNAME"
|
||||
TRUSTEE_PASSWORD="$TRUSTEE_PASSWORD"
|
||||
TRUSTEE_DOMAIN_ID="$TRUSTEE_DOMAIN_ID"
|
||||
TRUST_ID="$TRUST_ID"
|
||||
AUTH_URL="$AUTH_URL"
|
||||
INSECURE_REGISTRY_URL="$INSECURE_REGISTRY_URL"
|
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
KUBE_OS_CLOUD_CONFIG=/etc/sysconfig/kube_openstack_config
|
||||
|
||||
# kubernetes backend only support keystone v2 at this point
|
||||
AUTH_URL=$(echo "$AUTH_URL" | tr -s "v3" "v2")
|
||||
|
||||
# Generate a the configuration for Kubernetes services
|
||||
# to talk to OpenStack Neutron
|
||||
cat > $KUBE_OS_CLOUD_CONFIG <<EOF
|
||||
[Global]
|
||||
auth-url=$AUTH_URL
|
||||
Username=$USERNAME
|
||||
Password=$PASSWORD
|
||||
tenant-name=$TENANT_NAME
|
||||
[LoadBalancer]
|
||||
subnet-id=$CLUSTER_SUBNET
|
||||
create-monitor=yes
|
||||
monitor-delay=1m
|
||||
monitor-timeout=30s
|
||||
monitor-max-retries=3
|
||||
EOF
|
@ -0,0 +1,24 @@
|
||||
#cloud-config
|
||||
merge_how: dict(recurse_array)+list(append)
|
||||
write_files:
|
||||
- path: /srv/kubernetes/kubeconfig.yaml
|
||||
owner: "root:root"
|
||||
permissions: "0644"
|
||||
content: |
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
users:
|
||||
- name: kubeclient
|
||||
user:
|
||||
client-certificate: CLIENT_CERT
|
||||
client-key: CLIENT_KEY
|
||||
clusters:
|
||||
- name: kubernetes
|
||||
cluster:
|
||||
certificate-authority: CA_CERT
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kubernetes
|
||||
user: kubeclient
|
||||
name: service-account-context
|
||||
current-context: service-account-context
|
@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/sysconfig/heat-params
|
||||
|
||||
if [ "$NETWORK_DRIVER" != "flannel" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
. /etc/sysconfig/flanneld
|
||||
|
||||
FLANNEL_JSON=/etc/sysconfig/flannel-network.json
|
||||
FLANNELD_CONFIG=/etc/sysconfig/flanneld
|
||||
|
||||
sed -i '
|
||||
/^FLANNEL_ETCD=/ s/=.*/="http:\/\/127.0.0.1:2379"/
|
||||
' /etc/sysconfig/flanneld
|
||||
|
||||
# Generate a flannel configuration that we will
|
||||
# store into etcd using curl.
|
||||
cat > $FLANNEL_JSON <<EOF
|
||||
{
|
||||
"Network": "$FLANNEL_NETWORK_CIDR",
|
||||
"Subnetlen": $FLANNEL_NETWORK_SUBNETLEN,
|
||||
"Backend": {
|
||||
"Type": "$FLANNEL_BACKEND"
|
||||
}
|
||||
}
|
||||
EOF
|
@ -268,7 +268,7 @@ resources:
|
||||
config:
|
||||
str_replace:
|
||||
params:
|
||||
$configure_docker_storage_driver: {get_file: ../common/fragments/configure_docker_storage_driver_atomic.sh}
|
||||
$configure_docker_storage_driver: {get_file: ../../common/fragments/configure_docker_storage_driver_atomic.sh}
|
||||
template: {get_file: fragments/configure-docker-storage.sh}
|
||||
|
||||
configure_etcd:
|
@ -275,7 +275,7 @@ resources:
|
||||
config:
|
||||
str_replace:
|
||||
params:
|
||||
$configure_docker_storage_driver: {get_file: ../common/fragments/configure_docker_storage_driver_atomic.sh}
|
||||
$configure_docker_storage_driver: {get_file: ../../common/fragments/configure_docker_storage_driver_atomic.sh}
|
||||
template: {get_file: fragments/configure-docker-storage.sh}
|
||||
|
||||
configure_docker_registry:
|
16
magnum/drivers/k8s_fedora_atomic_v1/version.py
Normal file
16
magnum/drivers/k8s_fedora_atomic_v1/version.py
Normal file
@ -0,0 +1,16 @@
|
||||
# Copyright 2016 - Rackspace Hosting
|
||||
#
|
||||
# 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.
|
||||
|
||||
version = '1.0.0'
|
||||
driver = 'k8s_fedora_atomic'
|
@ -18,6 +18,7 @@ from oslo_config import cfg
|
||||
from magnum.common import exception
|
||||
from magnum.conductor import template_definition as tdef
|
||||
from magnum.drivers.common import template_def as cmn_tdef
|
||||
from magnum.drivers.k8s_fedora_atomic_v1 import template_def as k8sa_tdef
|
||||
from magnum.drivers.mesos_ubuntu_v1 import template_def as mesos_tdef
|
||||
from magnum.drivers.swarm_fedora_atomic_v1 import template_def as swarm_tdef
|
||||
from magnum.tests import base
|
||||
@ -48,7 +49,7 @@ class TemplateDefinitionTestCase(base.TestCase):
|
||||
vm_coreos_k8s = defs[('vm', 'coreos', 'kubernetes')]
|
||||
|
||||
self.assertEqual(1, len(vm_atomic_k8s))
|
||||
self.assertEqual(tdef.AtomicK8sTemplateDefinition,
|
||||
self.assertEqual(k8sa_tdef.AtomicK8sTemplateDefinition,
|
||||
vm_atomic_k8s['magnum_vm_atomic_k8s'])
|
||||
self.assertEqual(1, len(vm_coreos_k8s))
|
||||
self.assertEqual(tdef.CoreOSK8sTemplateDefinition,
|
||||
@ -61,7 +62,7 @@ class TemplateDefinitionTestCase(base.TestCase):
|
||||
'kubernetes')
|
||||
|
||||
self.assertIsInstance(definition,
|
||||
tdef.AtomicK8sTemplateDefinition)
|
||||
k8sa_tdef.AtomicK8sTemplateDefinition)
|
||||
|
||||
def test_get_vm_coreos_kubernetes_definition(self):
|
||||
definition = cmn_tdef.TemplateDefinition.get_template_definition(
|
||||
@ -168,7 +169,7 @@ class TemplateDefinitionTestCase(base.TestCase):
|
||||
class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
|
||||
@mock.patch('magnum.common.clients.OpenStackClients')
|
||||
@mock.patch('magnum.conductor.template_definition'
|
||||
@mock.patch('magnum.drivers.k8s_fedora_atomic_v1.template_def'
|
||||
'.AtomicK8sTemplateDefinition.get_discovery_url')
|
||||
@mock.patch('magnum.drivers.common.template_def.BaseTemplateDefinition'
|
||||
'.get_params')
|
||||
@ -202,7 +203,7 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
flannel_subnet = mock_baymodel.labels.get('flannel_network_subnetlen')
|
||||
flannel_backend = mock_baymodel.labels.get('flannel_backend')
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
|
||||
k8s_def.get_params(mock_context, mock_baymodel, mock_bay,
|
||||
scale_manager=mock_scale_manager)
|
||||
@ -221,8 +222,8 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
mock_bay, **expected_kwargs)
|
||||
|
||||
@mock.patch('magnum.common.clients.OpenStackClients')
|
||||
@mock.patch('magnum.conductor.template_definition'
|
||||
'.AtomicK8sTemplateDefinition.get_discovery_url')
|
||||
@mock.patch('magnum.drivers.common.template_def'
|
||||
'.BaseTemplateDefinition.get_discovery_url')
|
||||
@mock.patch('magnum.drivers.common.template_def.BaseTemplateDefinition'
|
||||
'.get_params')
|
||||
@mock.patch('magnum.drivers.common.template_def.TemplateDefinition'
|
||||
@ -255,7 +256,7 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
flannel_subnet = mock_baymodel.labels.get('flannel_network_subnetlen')
|
||||
flannel_backend = mock_baymodel.labels.get('flannel_backend')
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
|
||||
k8s_def.get_params(mock_context, mock_baymodel, mock_bay,
|
||||
scale_manager=mock_scale_manager)
|
||||
@ -283,14 +284,14 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
mock_resp.text = expected_result
|
||||
mock_get.return_value = mock_resp
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def.validate_discovery_url('http://etcd/test', 1)
|
||||
|
||||
@mock.patch('requests.get')
|
||||
def test_k8s_validate_discovery_url_fail(self, mock_get):
|
||||
mock_get.side_effect = req_exceptions.RequestException()
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
self.assertRaises(exception.GetClusterSizeFailed,
|
||||
k8s_def.validate_discovery_url,
|
||||
'http://etcd/test', 1)
|
||||
@ -301,7 +302,7 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
mock_resp.text = str('{"action":"get"}')
|
||||
mock_get.return_value = mock_resp
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
self.assertRaises(exception.InvalidBayDiscoveryURL,
|
||||
k8s_def.validate_discovery_url,
|
||||
'http://etcd/test', 1)
|
||||
@ -314,7 +315,7 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
mock_resp.text = expected_result
|
||||
mock_get.return_value = mock_resp
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
self.assertRaises(exception.InvalidClusterSize,
|
||||
k8s_def.validate_discovery_url,
|
||||
'http://etcd/test', 5)
|
||||
@ -332,7 +333,7 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
mock_bay.master_count = 10
|
||||
mock_bay.discovery_url = None
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
discovery_url = k8s_def.get_discovery_url(mock_bay)
|
||||
|
||||
mock_get.assert_called_once_with('http://etcd/test?size=10')
|
||||
@ -349,13 +350,13 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
mock_bay.master_count = 10
|
||||
mock_bay.discovery_url = None
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
|
||||
self.assertRaises(exception.GetDiscoveryUrlFailed,
|
||||
k8s_def.get_discovery_url, mock_bay)
|
||||
|
||||
def test_k8s_get_heat_param(self):
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
|
||||
heat_param = k8s_def.get_heat_param(bay_attr='node_count')
|
||||
self.assertEqual('number_of_minions', heat_param)
|
||||
@ -369,9 +370,10 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
|
||||
fake_bay = mock.MagicMock()
|
||||
fake_bay.discovery_url = None
|
||||
|
||||
self.assertRaises(exception.InvalidDiscoveryURL,
|
||||
tdef.AtomicK8sTemplateDefinition().get_discovery_url,
|
||||
fake_bay)
|
||||
self.assertRaises(
|
||||
exception.InvalidDiscoveryURL,
|
||||
k8sa_tdef.AtomicK8sTemplateDefinition().get_discovery_url,
|
||||
fake_bay)
|
||||
|
||||
def _test_update_outputs_api_address(self, coe, params, tls=True):
|
||||
|
||||
@ -538,14 +540,14 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
|
||||
mock_resp.text = expected_result
|
||||
mock_get.return_value = mock_resp
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def.validate_discovery_url('http://etcd/test', 1)
|
||||
|
||||
@mock.patch('requests.get')
|
||||
def test_swarm_validate_discovery_url_fail(self, mock_get):
|
||||
mock_get.side_effect = req_exceptions.RequestException()
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
self.assertRaises(exception.GetClusterSizeFailed,
|
||||
k8s_def.validate_discovery_url,
|
||||
'http://etcd/test', 1)
|
||||
@ -556,7 +558,7 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
|
||||
mock_resp.text = str('{"action":"get"}')
|
||||
mock_get.return_value = mock_resp
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
self.assertRaises(exception.InvalidBayDiscoveryURL,
|
||||
k8s_def.validate_discovery_url,
|
||||
'http://etcd/test', 1)
|
||||
@ -569,7 +571,7 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
|
||||
mock_resp.text = expected_result
|
||||
mock_get.return_value = mock_resp
|
||||
|
||||
k8s_def = tdef.AtomicK8sTemplateDefinition()
|
||||
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
|
||||
self.assertRaises(exception.InvalidClusterSize,
|
||||
k8s_def.validate_discovery_url,
|
||||
'http://etcd/test', 5)
|
||||
@ -602,9 +604,10 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
|
||||
fake_bay = mock.MagicMock()
|
||||
fake_bay.discovery_url = None
|
||||
|
||||
self.assertRaises(exception.InvalidDiscoveryURL,
|
||||
tdef.AtomicK8sTemplateDefinition().get_discovery_url,
|
||||
fake_bay)
|
||||
self.assertRaises(
|
||||
exception.InvalidDiscoveryURL,
|
||||
k8sa_tdef.AtomicK8sTemplateDefinition().get_discovery_url,
|
||||
fake_bay)
|
||||
|
||||
def test_swarm_get_heat_param(self):
|
||||
swarm_def = swarm_tdef.AtomicSwarmTemplateDefinition()
|
||||
|
@ -56,7 +56,7 @@ oslo.config.opts.defaults =
|
||||
magnum = magnum.common.config:set_cors_middleware_defaults
|
||||
|
||||
magnum.template_definitions =
|
||||
magnum_vm_atomic_k8s = magnum.conductor.template_definition:AtomicK8sTemplateDefinition
|
||||
magnum_vm_atomic_k8s = magnum.drivers.k8s_fedora_atomic_v1.template_def:AtomicK8sTemplateDefinition
|
||||
magnum_vm_coreos_k8s = magnum.conductor.template_definition:CoreOSK8sTemplateDefinition
|
||||
magnum_vm_atomic_swarm = magnum.drivers.swarm_fedora_atomic_v1.template_def:AtomicSwarmTemplateDefinition
|
||||
magnum_vm_ubuntu_mesos = magnum.drivers.mesos_ubuntu_v1.template_def:UbuntuMesosTemplateDefinition
|
||||
|
Loading…
Reference in New Issue
Block a user