From ea0978f4f2e83e3adc9d5b9754140c2c8b73d4f1 Mon Sep 17 00:00:00 2001 From: Charles Butler Date: Thu, 5 Mar 2015 16:46:11 -0500 Subject: [PATCH] Adds JUJU to the Kubernetes Provider listing This feature adds Juju provisioning to the kube-up script. It currently parses out the pre-requisits on debian/ubuntu based systems and installs them if they are missing. From there we followed the integration path that was found in the libvirt-coreos path, implementing the methods found in the boilerplate and calling juju service calls. There are a few "arbitrary sleeps" in the code to allow the cloud provider to settle and properly deploy. These are work-around cases from the script executing faster than juju was able to communicate from the state server to subsequent nodes. I left comments inline at these points. To exercise this: export KUBERNETES_PROVIDER=juju cluster/kube-up.sh It will spin up a ref arch with 1 Kubernetes Master, 2 minions, and run the cluster validation checks against the deployment. Bridging the gap between the juju specific bits and the upstream recommended guides for getting started with Juju. To note, if you do not have a "current environment" set in Juju, it will spin up the quickstart integration wizard in interactive mode, allowing you to configure juju, and add the proper provider/use it. Otherwise it assumes you're in the provider you wish to use, and will deploy there. --- cluster/juju/prereqs/ubuntu-juju.sh | 46 ++++++++++++++ cluster/juju/util.sh | 93 +++++++++++++++++++++++++++++ cluster/kube-env.sh | 2 +- cluster/validate-cluster.sh | 6 +- 4 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 cluster/juju/prereqs/ubuntu-juju.sh create mode 100755 cluster/juju/util.sh diff --git a/cluster/juju/prereqs/ubuntu-juju.sh b/cluster/juju/prereqs/ubuntu-juju.sh new file mode 100644 index 0000000000..bd266d8b1a --- /dev/null +++ b/cluster/juju/prereqs/ubuntu-juju.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# Copyright 2014 Canonical LTD. 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. + +# If you find any bugs within this script - please file bugs against the +# Kubernetes Juju Charms project - located here: https://github.com/whitmo/bundle-kubernetes + +function check_for_ppa(){ + grep -s ^ /etc/apt/sources.list /etc/apt/sources.list.d/* | grep juju +} + +function package_status(){ + local pkgstatus=`dpkg-query -W --showformat='${Status}\n' $1|grep "install ok installed"` + if [ "" == "$pkgstatus" ]; then + echo "Missing package $1" + sudo apt-get --force-yes --yes install $1 + fi + +} + +function gather_installation_reqs(){ + + ppa_installed=$(check_for_ppa) || ppa_installed='' + if [[ -z "$ppa_installed" ]]; then + echo "... Detected missing dependencies.. running" + echo "... add-apt-repository ppa:juju/stable" + sudo add-apt-repository ppa:juju/stable + sudo apt-get update + fi + + package_status 'juju' + package_status 'juju-quickstart' +} + diff --git a/cluster/juju/util.sh b/cluster/juju/util.sh new file mode 100755 index 0000000000..a65341eb19 --- /dev/null +++ b/cluster/juju/util.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# Copyright 2014 Canonical LTD. 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. + +# If you find any bugs within this script - please file bugs against the +# Kubernetes Juju Charms project - located here: https://github.com/whitmo/bundle-kubernetes + + +source $KUBE_ROOT/cluster/juju/prereqs/ubuntu-juju.sh +kube_bundle_url='https://raw.githubusercontent.com/whitmo/bundle-kubernetes/master/bundles.yaml' +function verify-prereqs() { + gather_installation_reqs +} + +function get-password() { + echo "TODO: Assign username/password security" +} + +function kube-up() { + # If something were to happen that I'm not accounting for, do not + # punish the user by making them tear things down. In a perfect world + # quickstart should handle this situation, so be nice in the meantime + local JUJUSTATUS=$(juju status kubernetes-master --format=oneline) + if [[ -z "$JUJUSTATUS" ]]; then + if [[ -d "~/.juju/current-env" ]]; then + juju quickstart -i -e $kube_jujuenv --no-browser -i $kube_bundle_url + # sleeping because of juju bug # + sleep 120 + else + juju quickstart --no-browser $kube_bundle_url + # sleeping because of juju bug # + sleep 120 + fi + fi + sleep-status +} + + +function detect-master() { + foo=$(juju status --format=oneline kubernetes-master | cut -d' ' -f3) + export KUBE_MASTER_IP=`echo -n $foo` + export KUBE_MASTER=$KUBE_MASTER_IP:8080 + export KUBERNETES_MASTER=$KUBE_MASTER + + } + +function detect-minions(){ + KUBE_MINION_IP_ADDRESSES=($(juju run --service kubernetes "unit-get private-address" --format=yaml | grep Stdout | cut -d "'" -f 2)) + NUM_MINIONS=${#KUBE_MINION_IP_ADDRESSES[@]} + MINION_NAMES=$KUBE_MINION_IP_ADDRESSES +} + +function setup-logging-firewall(){ + echo "TODO: setup logging and firewall rules" +} + +function teardown-logging-firewall(){ + echo "TODO: teardown logging and firewall rules" +} + + +function sleep-status(){ + local i=0 + local maxtime=900 + local JUJUSTATUS=$(juju status kubernetes-master --format=oneline) + echo "Waiting up to 15 minutes to allow the cluster to come online... wait for it..." + + while [[ $i < $maxtime ]] && [[ $JUJUSTATUS != *"started"* ]]; do + sleep 30 + i+=30 + JUJUSTATUS=$(juju status kubernetes-master --format=oneline) + done + + # sleep because we cannot get the status back of where the minions are in the deploy phase + # thanks to a generic "started" state and our service not actually coming online until the + # minions have recieved the binary from the master distribution hub during relations + echo "Sleeping an additional minute to allow the cluster to settle" + sleep 60 + +} + diff --git a/cluster/kube-env.sh b/cluster/kube-env.sh index 89be7dc848..2d3aef9b0c 100644 --- a/cluster/kube-env.sh +++ b/cluster/kube-env.sh @@ -18,7 +18,7 @@ # You can override the default provider by exporting the KUBERNETES_PROVIDER # variable in your bashrc # -# The valid values: 'gce', 'gke', 'aws', 'azure', 'vagrant', 'vsphere', 'libvirt-coreos' +# The valid values: 'gce', 'gke', 'aws', 'azure', 'vagrant', 'vsphere', 'libvirt-coreos', 'juju' KUBERNETES_PROVIDER=${KUBERNETES_PROVIDER:-gce} diff --git a/cluster/validate-cluster.sh b/cluster/validate-cluster.sh index 4f845f0554..3bb9fe3b7f 100755 --- a/cluster/validate-cluster.sh +++ b/cluster/validate-cluster.sh @@ -55,7 +55,7 @@ echo "Found ${found} nodes." cat -n "${MINIONS_FILE}" # On vSphere, use minion IPs as their names -if [[ "${KUBERNETES_PROVIDER}" == "vsphere" ]] || [[ "${KUBERNETES_PROVIDER}" == "vagrant" ]] || [[ "${KUBERNETES_PROVIDER}" == "libvirt-coreos" ]]; then +if [[ "${KUBERNETES_PROVIDER}" == "vsphere" ]] || [[ "${KUBERNETES_PROVIDER}" == "vagrant" ]] || [[ "${KUBERNETES_PROVIDER}" == "libvirt-coreos" ]] || [[ "${KUBERNETES_PROVIDER}" == "juju" ]] ; then MINION_NAMES=("${KUBE_MINION_IP_ADDRESSES[@]}") fi @@ -69,7 +69,7 @@ for (( i=0; i<${#MINION_NAMES[@]}; i++)); do fi name="${MINION_NAMES[$i]}" - if [ "$KUBERNETES_PROVIDER" != "vsphere" ] && [ "$KUBERNETES_PROVIDER" != "vagrant" ] && [ "$KUBERNETES_PROVIDER" != "libvirt-coreos" ]; then + if [ "$KUBERNETES_PROVIDER" != "vsphere" ] && [ "$KUBERNETES_PROVIDER" != "vagrant" ] && [ "$KUBERNETES_PROVIDER" != "libvirt-coreos" ] && [ "$KUBERNETES_PROVIDER" != "juju" ]; then # Grab fully qualified name name=$(grep "${MINION_NAMES[$i]}\." "${MINIONS_FILE}") fi @@ -79,7 +79,7 @@ for (( i=0; i<${#MINION_NAMES[@]}; i++)); do attempt=0 while true; do echo -n "Attempt $((attempt+1)) at checking Kubelet installation on node ${MINION_NAMES[$i]} ..." - if [ "$KUBERNETES_PROVIDER" != "libvirt-coreos" ]; then + if [ "$KUBERNETES_PROVIDER" != "libvirt-coreos" ] && [ "$KUBERNETES_PROVIDER" != "juju" ]; then curl_output=$(curl -s --insecure --user "${KUBE_USER}:${KUBE_PASSWORD}" \ "https://${KUBE_MASTER_IP}/api/v1beta1/proxy/minions/${name}/healthz") else