Add openSUSE driver support to Magnum

Change-Id: I3eb83867cca1f4d47b84d31d75d9f8f333af372b
Closes-bug: #1600197
This commit is contained in:
Michal Jura 2016-08-02 14:52:47 +02:00
parent a72817c77e
commit b5d05fc955
19 changed files with 2021 additions and 0 deletions

View File

@ -0,0 +1,19 @@
# Magnum openSUSE K8s driver
This is openSUSE Kubernetes driver for Magnum, which allow to deploy Kubernetes cluster on openSUSE.
## Installation
### 1. Install the openSUSE K8s driver in Magnum
- To install the driver, from this directory run:
`python ./setup.py install`
### 2. Enable driver in magnum.conf
enabled_definitions = ...,magnum_vm_opensuse_k8s
### 2. Restart Magnum
Both Magnum services has to restarted `magnum-api` and `magnum-conductor`

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python
# Copyright (c) 2015 Rackspace Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import setuptools
setuptools.setup(
name="k8s_opensuse_v1",
version="1.0",
packages=['k8s_opensuse_v1'],
package_data={
'k8s_opensuse_v1': ['templates/*', 'templates/fragments/*']
},
author="Michal Jura",
author_email="mjura@suse.com",
description="Magnum openSUSE Kubernetes driver",
license="Apache",
keywords="magnum opensuse driver",
entry_points={
'magnum.template_definitions': [
'k8s_opensuse_v1 = k8s_opensuse_v1:JeOSK8sTemplateDefinition'
]
}
)

View File

@ -0,0 +1,150 @@
# 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_private')
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 JeOSK8sTemplateDefinition(K8sTemplateDefinition):
"""Kubernetes template for openSUSE/SLES JeOS VM."""
provides = [
{'server_type': 'vm',
'os': 'opensuse',
'coe': 'kubernetes'},
]
def __init__(self):
super(JeOSK8sTemplateDefinition, self).__init__()
self.add_parameter('docker_volume_size',
baymodel_attr='docker_volume_size')
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
return super(JeOSK8sTemplateDefinition,
self).get_params(context, baymodel, bay,
extra_params=extra_params,
**kwargs)
@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 or OpenSUSE 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: openSUSELeap42.1-jeos-k8s
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,58 @@
#!/bin/sh
. /etc/sysconfig/heat-params
echo "stopping docker"
systemctl stop docker
ip link del docker0
if [ "$NETWORK_DRIVER" == "flannel" ]; then
FLANNEL_ENV=/run/flannel/subnet.env
attempts=60
while [[ ! -f $FLANNEL_ENV && $attempts != 0 ]]; do
echo "waiting for file $FLANNEL_ENV"
sleep 1
let attempts--
done
source $FLANNEL_ENV
if ! [ "\$FLANNEL_SUBNET" ] && [ "\$FLANNEL_MTU" ] ; then
echo "ERROR: missing required environment variables." >&2
exit 1
fi
sed -i '
/^DOCKER_OPTS=/ s/=.*/="--storage-driver=btrfs"/
/^DOCKER_NETWORK_OPTIONS=/ s|=.*|="--bip='"$FLANNEL_SUBNET"' --mtu='"$FLANNEL_MTU"'"|
' /etc/sysconfig/docker
fi
DOCKER_DEV=/dev/disk/by-id/virtio-${DOCKER_VOLUME:0:20}
attempts=60
while [[ ! -b $DOCKER_DEV && $attempts != 0 ]]; do
echo "waiting for disk $DOCKER_DEV"
sleep 0.5
udevadm trigger
let attempts--
done
if ! [ -b $DOCKER_DEV ]; then
echo "ERROR: device $DOCKER_DEV does not exist" >&2
exit 1
fi
mkfs.btrfs $DOCKER_DEV
mount $DOCKER_DEV /var/lib/docker
# make sure we pick up any modified unit files
systemctl daemon-reload
echo "activating docker service"
systemctl enable docker
echo "starting docker service"
systemctl --no-block start docker

View File

@ -0,0 +1,21 @@
#!/bin/sh
. /etc/sysconfig/heat-params
myip="$KUBE_NODE_IP"
sed -i '
/ETCD_NAME=/c ETCD_NAME="'$myip'"
/ETCD_DATA_DIR=/c ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
/ETCD_LISTEN_CLIENT_URLS=/c ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
/ETCD_LISTEN_PEER_URLS=/c ETCD_LISTEN_PEER_URLS="http://'$myip':2380"
/ETCD_ADVERTISE_CLIENT_URLS=/c ETCD_ADVERTISE_CLIENT_URLS="http://'$myip':2379"
/ETCD_INITIAL_ADVERTISE_PEER_URLS=/c ETCD_INITIAL_ADVERTISE_PEER_URLS="http://'$myip':2380"
/ETCD_DISCOVERY=/c ETCD_DISCOVERY="'$ETCD_DISCOVERY_URL'"
' /etc/sysconfig/etcd
echo "activating etcd service"
systemctl enable etcd
echo "starting etcd service"
systemctl --no-block start etcd

View File

@ -0,0 +1,74 @@
#!/bin/sh
. /etc/sysconfig/heat-params
if [ "$NETWORK_DRIVER" == "flannel" ]; then
exit 0
fi
FLANNEL_ETCD="http://127.0.0.1:2379"
FLANNEL_JSON=/etc/sysconfig/flannel-network.json
FLANNELD_CONFIG=/etc/sysconfig/flanneld
FLANNEL_NETWORK_CIDR="$FLANNEL_NETWORK_CIDR"
FLANNEL_NETWORK_SUBNETLEN="$FLANNEL_NETWORK_SUBNETLEN"
FLANNEL_USE_VXLAN="$FLANNEL_USE_VXLAN"
sed -i '
/^FLANNEL_ETCD=/ s/=.*/="http:\/\/127.0.0.1:2379"/
/^#FLANNEL_OPTIONS=/ s//FLANNEL_OPTIONS="-iface eth0 --ip-masq"/
' /etc/sysconfig/flanneld
cat >> /etc/sysconfig/flanneld <<EOF
# etcd config key. This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_KEY="/flannel/network"
EOF
. /etc/sysconfig/flanneld
if [ "$FLANNEL_USE_VXLAN" == "true" ]; then
use_vxlan=1
fi
# Generate a flannel configuration that we will
# store into etcd using curl.
cat > $FLANNEL_JSON <<EOF
{
"Network": "$FLANNEL_NETWORK_CIDR",
"Subnetlen": $FLANNEL_NETWORK_SUBNETLEN
EOF
if [ "$use_vxlan" = 1 ]; then
cat >> $FLANNEL_JSON <<EOF
,
"Backend": {
"Type": "vxlan"
}
EOF
fi
cat >> $FLANNEL_JSON <<EOF
}
EOF
#echo "creating flanneld config in etcd"
#etcdctl --endpoints $FLANNEL_ETCD --no-sync set ${FLANNEL_ETCD_KEY}/config < ${FLANNEL_JSON}
# 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$FLANNEL_ETCD_KEY/config \
-X PUT \
--data-urlencode value@$FLANNEL_JSON
echo "activating flanneld service"
systemctl enable flanneld
echo "starting flanneld service"
systemctl --no-block start flanneld

View File

@ -0,0 +1,25 @@
#!/bin/sh
. /etc/sysconfig/heat-params
if [ "$NETWORK_DRIVER" != "flannel" ]; then
exit 0
fi
sed -i '
/^FLANNEL_ETCD_ENDPOINTS=/ s|=.*|="http://'"$ETCD_SERVER_IP"':2379"|
/^#FLANNEL_OPTIONS=/ s//FLANNEL_OPTIONS="-iface eth0 --ip-masq"/
' /etc/sysconfig/flanneld
cat >> /etc/sysconfig/flanneld <<EOF
# etcd config key. This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_KEY="/flannel/network"
EOF
echo "activating flanneld service"
systemctl enable flanneld
echo "starting flanneld service"
systemctl --no-block start flanneld

View File

@ -0,0 +1,55 @@
#!/bin/sh
. /etc/sysconfig/heat-params
echo "configuring kubernetes (master)"
KUBE_API_ARGS="--runtime_config=api/all=true"
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0 --insecure-port=$KUBE_API_PORT"
sed -i '
/^KUBE_ALLOW_PRIV=/ s/=.*/="--allow_privileged='"$KUBE_ALLOW_PRIV"'"/
' /etc/kubernetes/config
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 >> /etc/kubernetes/apiserver <<EOF
#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/kubernetes_openstack_config --cloud_provider=openstack"
EOF
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\/kubernetes_openstack_config --cloud_provider=openstack"/
' /etc/kubernetes/controller-manager
# Generate a the configuration for Kubernetes services to talk to OpenStack Neutron
cat > /etc/sysconfig/kubernetes_openstack_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
for service in kube-apiserver kube-scheduler kube-controller-manager; do
echo "activating $service service"
systemctl enable $service
echo "starting $service services"
systemctl --no-block start $service
done

View File

@ -0,0 +1,50 @@
#!/bin/sh
. /etc/sysconfig/heat-params
echo "configuring kubernetes (minion)"
myip=$(ip addr show eth0 |
awk '$1 == "inet" {print $2}' |
cut -f1 -d/)
ETCD_SERVER_IP=${ETCD_SERVER_IP:-$KUBE_MASTER_IP}
if [ "$TLS_DISABLED" == "True" ]; then
KUBE_PROTOCOL="http"
KUBE_CONFIG=""
else
KUBE_PROTOCOL="https"
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
sed -i '
/^KUBELET_ADDRESS=/ s/=.*/="--address=0.0.0.0"/
/^KUBELET_HOSTNAME=/ s/=.*/="--hostname-override='"$myip"'"/
/^KUBELET_API_SERVER=/ s|=.*|="--api_servers='"$KUBE_MASTER_URI"'"|
/^KUBELET_ARGS=/ s|=.*|='"$KUBE_CONFIG"'|
' /etc/kubernetes/kubelet
sed -i '
/^KUBE_PROXY_ARGS=/ s|=.*|='"$KUBE_CONFIG"'|
' /etc/kubernetes/proxy
cat >> /etc/environment <<EOF
KUBERNETES_MASTER=$KUBE_MASTER_URI
EOF
for service in kubelet kube-proxy; do
echo "activating $service service"
systemctl enable $service
echo "starting $service service"
systemctl --no-block start $service
done

View File

@ -0,0 +1,9 @@
#cloud-config
system_info:
default_user:
name: kubernetes
lock_passwd: true
gecos: Kubernetes Interactive User
groups: [wheel, systemd-journal]
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
shell: /bin/bash

View File

@ -0,0 +1,25 @@
#cloud-config
merge_how: dict(recurse_array)+list(append)
write_files:
- path: /etc/sysconfig/heat-params
owner: "root:root"
permissions: "0644"
content: |
KUBE_NODE_PUBLIC_IP="$KUBE_NODE_PUBLIC_IP"
KUBE_NODE_IP="$KUBE_NODE_IP"
KUBE_API_PORT="$KUBE_API_PORT"
KUBE_ALLOW_PRIV="$KUBE_ALLOW_PRIV"
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"
AUTH_URL="$AUTH_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"

View File

@ -0,0 +1,32 @@
#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"
NETWORK_DRIVER="$NETWORK_DRIVER"
REGISTRY_ENABLED="$REGISTRY_ENABLED"
REGISTRY_PORT="$REGISTRY_PORT"
REGISTRY_AUTH_URL="$REGISTRY_AUTH_URL"
REGISTRY_REGION="$REGISTRY_REGION"
REGISTRY_USERNAME="$REGISTRY_USERNAME"
REGISTRY_PASSWORD="$REGISTRY_PASSWORD"
REGISTRY_DOMAIN="$REGISTRY_DOMAIN"
REGISTRY_TRUST_ID="$REGISTRY_TRUST_ID"
REGISTRY_CONTAINER="$REGISTRY_CONTAINER"
REGISTRY_INSECURE="$REGISTRY_INSECURE"
REGISTRY_CHUNKSIZE="$REGISTRY_CHUNKSIZE"
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"

View File

@ -0,0 +1,513 @@
heat_template_version: 2013-05-23
description: >
This template will boot a Kubernetes cluster with one or more
minions (as specified by the number_of_minions parameter, which
defaults to 1).
parameters:
ssh_key_name:
type: string
description: name of ssh key to be provisioned on our server
external_network:
type: string
description: uuid/name of a network to use for floating ip addresses
default: public
server_image:
type: string
description: glance image used to boot the server
master_flavor:
type: string
default: m1.small
description: flavor to use when booting the server
minion_flavor:
type: string
default: m1.small
description: flavor to use when booting the server
dns_nameserver:
type: string
description: address of a dns nameserver reachable in your environment
default: 8.8.8.8
number_of_masters:
type: number
description: how many kubernetes masters to spawn
default: 1
number_of_minions:
type: number
description: how many kubernetes minions to spawn
default: 1
fixed_network_cidr:
type: string
description: network range for fixed ip network
default: 10.0.0.0/24
portal_network_cidr:
type: string
description: >
address range used by kubernetes for service portals
default: 10.254.0.0/16
network_driver:
type: string
description: network driver to use for instantiating container networks
default: flannel
flannel_network_cidr:
type: string
description: network range for flannel overlay network
default: 10.100.0.0/16
flannel_network_subnetlen:
type: string
description: size of subnet assigned to each minion
default: 24
flannel_backend:
type: string
description: >
specify the backend for flannel, default udp backend
default: "udp"
constraints:
- allowed_values: ["udp", "vxlan", "host-gw"]
kube_allow_priv:
type: string
description: >
whether or not kubernetes should permit privileged containers.
default: "true"
constraints:
- allowed_values: ["true", "false"]
docker_volume_size:
type: number
description: >
size of a cinder volume to allocate to docker for container/image
storage
default: 25
wait_condition_timeout:
type: number
description: >
timeout for the Wait Conditions
default: 600
minions_to_remove:
type: comma_delimited_list
description: >
List of minions to be removed when doing an update. Individual minion may
be referenced several ways: (1) The resource name (e.g. ['1', '3']),
(2) The private IP address ['10.0.0.4', '10.0.0.6']. Note: the list should
be empty when doing an create.
default: []
discovery_url:
type: string
description: >
Discovery URL used for bootstrapping the etcd cluster.
registry_enabled:
type: boolean
description: >
Indicates whether the docker registry is enabled.
default: false
registry_port:
type: number
description: port of registry service
default: 5000
registry_username:
type: string
description: username used by docker registry
default: "username"
registry_password:
type: string
description: password used by docker registry
default: "password"
hidden: true
registry_domain:
type: string
description: domain used by docker registry
default: "domain"
registry_trust_id:
type: string
description: trust_id used by docker registry
default: "trust_id"
hidden: true
registry_auth_url:
type: string
description: auth_url for keystone
default: "auth_url"
registry_region:
type: string
description: region of swift service
default: "region"
registry_container:
type: string
description: >
name of swift container which docker registry stores images in
default: "container"
registry_insecure:
type: boolean
description: >
indicates whether to skip TLS verification between registry and backend storage
default: true
registry_chunksize:
type: number
description: >
size fo the data segments for the swift dynamic large objects
default: 5242880
auth_url:
type: string
description: >
url for kubernetes to authenticate before sending request to neutron
must be v2 since kubernetes backend only suppor v2 at this point
username:
type: string
description: >
user account
password:
type: string
description: >
user password, not set in current implementation, only used to
fill in for Kubernetes config file
default:
ChangeMe
tenant_name:
type: string
description: >
tenant name
loadbalancing_protocol:
type: string
description: >
The protocol which is used for load balancing. If you want to change
tls_disabled option to 'True', please change this to "HTTP".
default: TCP
constraints:
- allowed_values: ["TCP", "HTTP"]
tls_disabled:
type: boolean
description: whether or not to disable TLS
default: False
kubernetes_port:
type: number
description: >
The port which are used by kube-apiserver to provide Kubernetes
service.
default: 6443
bay_uuid:
type: string
description: identifier for the bay this template is generating
magnum_url:
type: string
description: endpoint to retrieve TLS certs from
trustee_domain_id:
type: string
description: domain id of the trustee
default: ""
trustee_user_id:
type: string
description: user id of the trustee
default: ""
trustee_username:
type: string
description: username of the trustee
default: ""
trustee_password:
type: string
description: password of the trustee
default: ""
hidden: true
trust_id:
type: string
description: id of the trust which is used by the trustee
default: ""
hidden: true
resources:
######################################################################
#
# network resources. allocate a network and router for our server.
# Important: the Load Balancer feature in Kubernetes requires that
# the name for the fixed_network must be "private" for the
# address lookup in Kubernetes to work properly
#
fixed_network:
type: OS::Neutron::Net
properties:
name: private
fixed_subnet:
type: OS::Neutron::Subnet
properties:
cidr: {get_param: fixed_network_cidr}
network: {get_resource: fixed_network}
dns_nameservers:
- {get_param: dns_nameserver}
extrouter:
type: OS::Neutron::Router
properties:
external_gateway_info:
network: {get_param: external_network}
extrouter_inside:
type: OS::Neutron::RouterInterface
properties:
router_id: {get_resource: extrouter}
subnet: {get_resource: fixed_subnet}
######################################################################
#
# security groups. we need to permit network traffic of various
# sorts.
#
secgroup_base:
type: OS::Neutron::SecurityGroup
properties:
rules:
- protocol: icmp
- protocol: tcp
port_range_min: 22
port_range_max: 22
secgroup_kube_master:
type: OS::Neutron::SecurityGroup
properties:
rules:
- protocol: tcp
port_range_min: 7080
port_range_max: 7080
- protocol: tcp
port_range_min: 8080
port_range_max: 8080
- protocol: tcp
port_range_min: 2379
port_range_max: 2379
- protocol: tcp
port_range_min: 2380
port_range_max: 2380
- protocol: tcp
port_range_min: 6443
port_range_max: 6443
secgroup_kube_minion:
type: OS::Neutron::SecurityGroup
properties:
rules:
- protocol: icmp
- protocol: tcp
- protocol: udp
######################################################################
#
# load balancers.
#
api_monitor:
type: OS::Neutron::HealthMonitor
properties:
type: TCP
delay: 5
max_retries: 5
timeout: 5
api_pool:
type: OS::Neutron::Pool
properties:
protocol: {get_param: loadbalancing_protocol}
monitors: [{get_resource: api_monitor}]
subnet: {get_resource: fixed_subnet}
lb_method: ROUND_ROBIN
vip:
protocol_port: {get_param: kubernetes_port}
api_pool_floating:
type: OS::Neutron::FloatingIP
depends_on:
- extrouter_inside
properties:
floating_network: {get_param: external_network}
port_id: {get_attr: [api_pool, vip, port_id]}
etcd_monitor:
type: OS::Neutron::HealthMonitor
properties:
type: TCP
delay: 5
max_retries: 5
timeout: 5
etcd_pool:
type: OS::Neutron::Pool
properties:
protocol: HTTP
monitors: [{get_resource: etcd_monitor}]
subnet: {get_resource: fixed_subnet}
lb_method: ROUND_ROBIN
vip:
protocol_port: 2379
######################################################################
#
# kubernetes masters. This is a resource group that will create
# <number_of_masters> masters.
#
kube_masters:
type: OS::Heat::ResourceGroup
depends_on:
- extrouter_inside
properties:
count: {get_param: number_of_masters}
resource_def:
type: kubemaster.yaml
properties:
api_public_address: {get_attr: [api_pool_floating, floating_ip_address]}
api_private_address: {get_attr: [api_pool, vip, address]}
ssh_key_name: {get_param: ssh_key_name}
server_image: {get_param: server_image}
master_flavor: {get_param: master_flavor}
external_network: {get_param: external_network}
kube_allow_priv: {get_param: kube_allow_priv}
wait_condition_timeout: {get_param: wait_condition_timeout}
network_driver: {get_param: network_driver}
flannel_backend: {get_param: flannel_backend}
flannel_network_cidr: {get_param: flannel_network_cidr}
flannel_network_subnetlen: {get_param: flannel_network_subnetlen}
portal_network_cidr: {get_param: portal_network_cidr}
discovery_url: {get_param: discovery_url}
bay_uuid: {get_param: bay_uuid}
magnum_url: {get_param: magnum_url}
fixed_network: {get_resource: fixed_network}
fixed_subnet: {get_resource: fixed_subnet}
api_pool_id: {get_resource: api_pool}
etcd_pool_id: {get_resource: etcd_pool}
auth_url: {get_param: auth_url}
username: {get_param: username}
password: {get_param: password}
tenant_name: {get_param: tenant_name}
kubernetes_port: {get_param: kubernetes_port}
tls_disabled: {get_param: tls_disabled}
secgroup_base_id: {get_resource: secgroup_base}
secgroup_kube_master_id: {get_resource: secgroup_kube_master}
######################################################################
#
# kubernetes minions. This is an resource group that will initially
# create <number_of_minions> minions, and needs to be manually scaled.
#
kube_minions:
type: OS::Heat::ResourceGroup
depends_on:
- extrouter_inside
- kube_masters
properties:
count: {get_param: number_of_minions}
removal_policies: [{resource_list: {get_param: minions_to_remove}}]
resource_def:
type: kubeminion.yaml
properties:
ssh_key_name: {get_param: ssh_key_name}
server_image: {get_param: server_image}
minion_flavor: {get_param: minion_flavor}
fixed_network: {get_resource: fixed_network}
fixed_subnet: {get_resource: fixed_subnet}
network_driver: {get_param: network_driver}
kube_master_ip: {get_attr: [api_pool, vip, address]}
etcd_server_ip: {get_attr: [etcd_pool, vip, address]}
external_network: {get_param: external_network}
kube_allow_priv: {get_param: kube_allow_priv}
docker_volume_size: {get_param: docker_volume_size}
wait_condition_timeout: {get_param: wait_condition_timeout}
registry_enabled: {get_param: registry_enabled}
registry_port: {get_param: registry_port}
registry_username: {get_param: registry_username}
registry_password: {get_param: registry_password}
registry_domain: {get_param: registry_domain}
registry_trust_id: {get_param: registry_trust_id}
registry_auth_url: {get_param: registry_auth_url}
registry_region: {get_param: registry_region}
registry_container: {get_param: registry_container}
registry_insecure: {get_param: registry_insecure}
registry_chunksize: {get_param: registry_chunksize}
bay_uuid: {get_param: bay_uuid}
magnum_url: {get_param: magnum_url}
kubernetes_port: {get_param: kubernetes_port}
tls_disabled: {get_param: tls_disabled}
secgroup_kube_minion_id: {get_resource: secgroup_kube_minion}
kube_minion_id: 'kube_minion_%index%'
outputs:
api_address:
value:
str_replace:
template: api_ip_address
params:
api_ip_address: {get_attr: [api_pool_floating, floating_ip_address]}
description: >
This is the API endpoint of the Kubernetes server. Use this to access
the Kubernetes API from outside the cluster.
registry_address:
value:
str_replace:
template: localhost:port
params:
port: {get_param: registry_port}
description:
This is the url of docker registry server where you can store docker
images.
kube_masters:
value: {get_attr: [kube_masters, kube_master_external_ip]}
description: >
This is a list of "public" ip addresses of all Kubernetes master servers.
Use these addresses to log in to the Kubernetes masters via ssh.
kube_minions:
value: {get_attr: [kube_minions, kube_minion_ip]}
description: >
This is a list of the "private" addresses of all the Kubernetes minions.
kube_minions_external:
value: {get_attr: [kube_minions, kube_minion_external_ip]}
description: >
This is a list of the "public" addresses of all the Kubernetes minions. Use
these addresses to, e.g., log into the minions.

View File

@ -0,0 +1,280 @@
heat_template_version: 2013-05-23
description: >
This is a nested stack that defines a single Kubernetes master, This stack is
included by an ResourceGroup resource in the parent template
(kubecluster.yaml).
parameters:
server_image:
type: string
description: glance image used to boot the server
master_flavor:
type: string
default: m1.small
description: flavor to use when booting the server
ssh_key_name:
type: string
description: name of ssh key to be provisioned on our server
default: lars
external_network:
type: string
description: uuid/name of a network to use for floating ip addresses
portal_network_cidr:
type: string
description: >
address range used by kubernetes for service portals
default: 10.254.0.0/16
kube_allow_priv:
type: string
description: >
whether or not kubernetes should permit privileged containers.
default: "false"
constraints:
- allowed_values: ["true", "false"]
flannel_network_cidr:
type: string
description: network range for flannel overlay network
default: 10.100.0.0/16
flannel_network_subnetlen:
type: string
description: size of subnet assigned to each master
default: 24
flannel_backend:
type: string
description: >
specify the backend for flannel, default udp backend
constraints:
- allowed_values: ["udp", "vxlan", "host-gw"]
discovery_url:
type: string
description: >
Discovery URL used for bootstrapping the etcd cluster.
tls_disabled:
type: boolean
description: whether or not to enable TLS
default: False
kubernetes_port:
type: number
description: >
The port which are used by kube-apiserver to provide Kubernetes
service.
default: 6443
bay_uuid:
type: string
description: identifier for the bay this template is generating
magnum_url:
type: string
description: endpoint to retrieve TLS certs from
# The following are all generated in the parent template.
api_public_address:
type: string
description: Public IP address of the Kubernetes master server.
api_private_address:
type: string
description: Private IP address of the Kubernetes master server.
fixed_network:
type: string
description: Network from which to allocate fixed addresses.
fixed_subnet:
type: string
description: Subnet from which to allocate fixed addresses.
network_driver:
type: string
description: network driver to use for instantiating container networks
wait_condition_timeout:
type: number
description : >
timeout for the Wait Conditions
secgroup_base_id:
type: string
description: ID of the security group for base.
secgroup_kube_master_id:
type: string
description: ID of the security group for kubernetes master.
api_pool_id:
type: string
description: ID of the load balancer pool of k8s API server.
etcd_pool_id:
type: string
description: ID of the load balancer pool of etcd server.
auth_url:
type: string
description: >
url for kubernetes to authenticate before sending request to neutron
username:
type: string
description: >
user account
password:
type: string
description: >
user password
tenant_name:
type: string
description: >
tenant name
resources:
master_wait_handle:
type: OS::Heat::WaitConditionHandle
master_wait_condition:
type: OS::Heat::WaitCondition
depends_on: kube_master
properties:
handle: {get_resource: master_wait_handle}
timeout: {get_param: wait_condition_timeout}
######################################################################
#
# software configs. these are components that are combined into
# a multipart MIME user-data archive.
#
write_heat_params:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config:
str_replace:
template: {get_file: fragments/write-heat-params-master.yaml}
params:
"$KUBE_NODE_PUBLIC_IP": {get_attr: [kube_master_floating, floating_ip_address]}
"$KUBE_NODE_IP": {get_attr: [kube_master_eth0, fixed_ips, 0, ip_address]}
"$KUBE_API_PORT": {get_param: kubernetes_port}
"$KUBE_ALLOW_PRIV": {get_param: kube_allow_priv}
"$NETWORK_DRIVER": {get_param: network_driver}
"$FLANNEL_NETWORK_CIDR": {get_param: flannel_network_cidr}
"$FLANNEL_NETWORK_SUBNETLEN": {get_param: flannel_network_subnetlen}
"$FLANNEL_BACKEND": {get_param: flannel_backend}
"$PORTAL_NETWORK_CIDR": {get_param: portal_network_cidr}
"$ETCD_DISCOVERY_URL": {get_param: discovery_url}
"$AUTH_URL": {get_param: auth_url}
"$USERNAME": {get_param: username}
"$PASSWORD": {get_param: password}
"$TENANT_NAME": {get_param: tenant_name}
"$CLUSTER_SUBNET": {get_param: fixed_subnet}
"$TLS_DISABLED": {get_param: tls_disabled}
"$BAY_UUID": {get_param: bay_uuid}
"$MAGNUM_URL": {get_param: magnum_url}
configure_etcd:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: {get_file: fragments/configure-etcd.sh}
configure_flanneld:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: {get_file: fragments/configure-flanneld-master.sh}
create_kubernetes_user:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: {get_file: fragments/create-kubernetes-user.yaml}
configure_kubernetes:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: {get_file: fragments/configure-kubernetes-master.sh}
master_wc_notify:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config:
str_replace:
template: |
#!/bin/bash -v
wc_notify --data-binary '{"status": "SUCCESS"}'
params:
wc_notify: {get_attr: [master_wait_handle, curl_cli]}
kube_master_init:
type: OS::Heat::MultipartMime
properties:
parts:
- config: {get_resource: write_heat_params}
- config: {get_resource: configure_etcd}
- config: {get_resource: configure_flanneld}
- config: {get_resource: create_kubernetes_user}
- config: {get_resource: configure_kubernetes}
- config: {get_resource: master_wc_notify}
######################################################################
#
# a single kubernetes master.
#
kube_master:
type: OS::Nova::Server
properties:
name: kube_master
image: {get_param: server_image}
flavor: {get_param: master_flavor}
key_name: {get_param: ssh_key_name}
user_data_format: RAW
user_data: {get_resource: kube_master_init}
config_drive: true
networks:
- port: {get_resource: kube_master_eth0}
kube_master_eth0:
type: OS::Neutron::Port
properties:
network: {get_param: fixed_network}
security_groups:
- {get_param: secgroup_base_id}
- {get_param: secgroup_kube_master_id}
fixed_ips:
- subnet: {get_param: fixed_subnet}
replacement_policy: AUTO
kube_master_floating:
type: OS::Neutron::FloatingIP
properties:
floating_network: {get_param: external_network}
port_id: {get_resource: kube_master_eth0}
api_pool_member:
type: OS::Neutron::PoolMember
properties:
pool_id: {get_param: api_pool_id}
address: {get_attr: [kube_master_eth0, fixed_ips, 0, ip_address]}
protocol_port: {get_param: kubernetes_port}
etcd_pool_member:
type: OS::Neutron::PoolMember
properties:
pool_id: {get_param: etcd_pool_id}
address: {get_attr: [kube_master_eth0, fixed_ips, 0, ip_address]}
protocol_port: 2379
outputs:
kube_master_ip:
value: {get_attr: [kube_master_eth0, fixed_ips, 0, ip_address]}
kube_master_external_ip:
value: {get_attr: [kube_master_floating, floating_ip_address]}

View File

@ -0,0 +1,313 @@
heat_template_version: 2013-05-23
description: >
This is a nested stack that defines a single Kubernetes minion, This stack is
included by an AutoScalingGroup resource in the parent template
(kubecluster-jeos.yaml).
parameters:
server_image:
type: string
description: glance image used to boot the server
minion_flavor:
type: string
default: m1.small
description: flavor to use when booting the server
ssh_key_name:
type: string
description: name of ssh key to be provisioned on our server
default: lars
external_network:
type: string
description: uuid/name of a network to use for floating ip addresses
kube_allow_priv:
type: string
description: >
whether or not kubernetes should permit privileged containers.
default: "false"
constraints:
- allowed_values: ["true", "false"]
docker_volume_size:
type: number
description: >
size of a cinder volume to allocate to docker for container/image
storage
default: 25
tls_disabled:
type: boolean
description: whether or not to enable TLS
default: False
kubernetes_port:
type: number
description: >
The port which are used by kube-apiserver to provide Kubernetes
service.
default: 6443
bay_uuid:
type: string
description: identifier for the bay this template is generating
magnum_url:
type: string
description: endpoint to retrieve TLS certs from
# The following are all generated in the parent template.
kube_master_ip:
type: string
description: IP address of the Kubernetes master server.
etcd_server_ip:
type: string
description: IP address of the Etcd server.
fixed_network:
type: string
description: Network from which to allocate fixed addresses.
fixed_subnet:
type: string
description: Subnet from which to allocate fixed addresses.
network_driver:
type: string
description: network driver to use for instantiating container networks
wait_condition_timeout:
type: number
description : >
timeout for the Wait Conditions
registry_enabled:
type: boolean
description: >
Indicates whether the docker registry is enabled.
default: false
registry_port:
type: number
description: port of registry service
default: 5000
registry_username:
type: string
description: username used by docker registry
default: "username"
registry_password:
type: string
description: password used by docker registry
default: "password"
registry_domain:
type: string
description: domain used by docker registry
default: "domain"
registry_trust_id:
type: string
description: trust_id used by docker registry
default: "trust_id"
registry_auth_url:
type: string
description: auth_url for keystone
default: "auth_url"
registry_region:
type: string
description: region of swift service
default: "region"
registry_container:
type: string
description: >
name of swift container which docker registry stores images in
default: "container"
registry_insecure:
type: boolean
description: >
indicates whether to skip TLS verification between registry and backend storage
default: true
registry_chunksize:
type: number
description: >
size fo the data segments for the swift dynamic large objects
default: 5242880
secgroup_kube_minion_id:
type: string
description: ID of the security group for kubernetes minion.
kube_minion_id:
type: string
description: ID of for kubernetes minion.
resources:
minion_wait_handle:
type: OS::Heat::WaitConditionHandle
minion_wait_condition:
type: OS::Heat::WaitCondition
depends_on: kube-minion
properties:
handle: {get_resource: minion_wait_handle}
timeout: {get_param: wait_condition_timeout}
######################################################################
#
# software configs. these are components that are combined into
# a multipart MIME user-data archive.
#
write_heat_params:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config:
str_replace:
template: {get_file: fragments/write-heat-params.yaml}
params:
$KUBE_ALLOW_PRIV: {get_param: kube_allow_priv}
$KUBE_MASTER_IP: {get_param: kube_master_ip}
$KUBE_API_PORT: {get_param: kubernetes_port}
$ETCD_SERVER_IP: {get_param: etcd_server_ip}
$DOCKER_VOLUME: {get_resource: docker_volume}
$NETWORK_DRIVER: {get_param: network_driver}
$REGISTRY_ENABLED: {get_param: registry_enabled}
$REGISTRY_PORT: {get_param: registry_port}
$REGISTRY_AUTH_URL: {get_param: registry_auth_url}
$REGISTRY_REGION: {get_param: registry_region}
$REGISTRY_USERNAME: {get_param: registry_username}
$REGISTRY_PASSWORD: {get_param: registry_password}
$REGISTRY_DOMAIN: {get_param: registry_domain}
$REGISTRY_TRUST_ID: {get_param: registry_trust_id}
$REGISTRY_CONTAINER: {get_param: registry_container}
$REGISTRY_INSECURE: {get_param: registry_insecure}
$REGISTRY_CHUNKSIZE: {get_param: registry_chunksize}
$TLS_DISABLED: {get_param: tls_disabled}
$BAY_UUID: {get_param: bay_uuid}
$MAGNUM_URL: {get_param: magnum_url}
$NODE_FIXED_IP: {get_attr: [kube_minion_eth0, fixed_ips, 0, ip_address]}
configure_flanneld:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: {get_file: fragments/configure-flanneld-minion.sh}
configure_docker:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: {get_file: fragments/configure-docker.sh}
create_kubernetes_user:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: {get_file: fragments/create-kubernetes-user.yaml}
configure_kubernetes:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: {get_file: fragments/configure-kubernetes-minion.sh}
minion_wc_notify:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config:
str_replace:
template: |
#!/bin/bash -v
wc_notify --data-binary '{"status": "SUCCESS"}'
params:
wc_notify: {get_attr: [minion_wait_handle, curl_cli]}
kube_minion_init:
type: OS::Heat::MultipartMime
properties:
parts:
- config: {get_resource: write_heat_params}
- config: {get_resource: configure_flanneld}
- config: {get_resource: configure_docker}
- config: {get_resource: create_kubernetes_user}
- config: {get_resource: configure_kubernetes}
- config: {get_resource: minion_wc_notify}
######################################################################
#
# a single kubernetes minion.
# Important: the name for the heat resource kube-minion below must
# not contain "_" (underscore) because it will be used in the
# hostname. Because DNS domain name does not allow "_", the "_"
# will be converted to a "-" and this will make the hostname different
# from the Nova instance name. This in turn will break the load
# balancer feature in Kubernetes.
#
kube-minion:
type: OS::Nova::Server
properties:
name: {get_param: kube_minion_id}
image: {get_param: server_image}
flavor: {get_param: minion_flavor}
key_name: {get_param: ssh_key_name}
user_data_format: RAW
user_data: {get_resource: kube_minion_init}
networks:
- port: {get_resource: kube_minion_eth0}
kube_minion_eth0:
type: OS::Neutron::Port
properties:
network: {get_param: fixed_network}
security_groups:
- get_param: secgroup_kube_minion_id
fixed_ips:
- subnet: {get_param: fixed_subnet}
replacement_policy: AUTO
kube_minion_floating:
type: OS::Neutron::FloatingIP
properties:
floating_network: {get_param: external_network}
port_id: {get_resource: kube_minion_eth0}
######################################################################
#
# docker storage. This allocates a cinder volume and attaches it
# to the minion.
#
docker_volume:
type: OS::Cinder::Volume
properties:
size: {get_param: docker_volume_size}
docker_volume_attach:
type: OS::Cinder::VolumeAttachment
properties:
instance_uuid: {get_resource: kube-minion}
volume_id: {get_resource: docker_volume}
mountpoint: /dev/vdb
outputs:
kube_minion_ip:
value: {get_attr: [kube_minion_eth0, fixed_ips, 0, ip_address]}
kube_minion_external_ip:
value: {get_attr: [kube_minion_floating, floating_ip_address]}
OS::stack_id:
value: {get_attr: [kube_minion_eth0, fixed_ips, 0, ip_address]}

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