Bay driver: k8s Fedora Atomic

Change-Id: I1fae89e902ef73fe18ef78733a18e3690b67f312
Paritially-Implements: blueprint bay-drivers
This commit is contained in:
Vijendar Komalla 2016-07-06 16:36:20 -05:00
parent 3d8c397c07
commit a5ae8b37aa
52 changed files with 2076 additions and 85 deletions

View File

@ -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')

View File

@ -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."""

View File

@ -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'),

View 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')

View 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.

View 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/

View File

@ -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`

View File

@ -0,0 +1 @@
package-installs

View File

@ -0,0 +1,4 @@
kubernetes:
etcd:
flannel:
docker-io:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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//'`

View File

@ -0,0 +1,8 @@
#cloud-boothook
#!/bin/sh
setenforce 0
sed -i '
/^SELINUX=/ s/=.*/=permissive/
' /etc/selinux/config

View File

@ -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

View File

@ -0,0 +1,5 @@
#!/bin/sh
echo "starting etcd"
systemctl enable etcd
systemctl --no-block start etcd

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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}"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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:

View 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'

View File

@ -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()

View File

@ -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