Update the AWS config.

pull/6/head
Brendan Burns 2014-11-06 14:27:15 -08:00
parent 1ff79fdeb0
commit 62bd634c07
15 changed files with 369 additions and 482 deletions

View File

@ -14,12 +14,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
ZONE=eu-west-1
MASTER_SIZE=t2.small
MINION_SIZE=t2.small
# TODO: this isn't quite piped into all the right places...
ZONE=us-west-2
MASTER_SIZE=t2.micro
MINION_SIZE=t2.micro
NUM_MINIONS=4
IMAGE=ami-0307d674
# This is the ubuntu 14.04 image for us-west-2 + ebs
# See here: http://cloud-images.ubuntu.com/locator/ec2/ for other images
# This will need to be updated from time to time as amis are deprecated
IMAGE=ami-55d69e65
INSTANCE_PREFIX=kubernetes
AWS_SSH_KEY=$HOME/.ssh/kube_aws_rsa
@ -29,3 +33,5 @@ MINION_TAG="${INSTANCE_PREFIX}-minion"
MINION_NAMES=($(eval echo ip-172-20-0-1{0..$(($NUM_MINIONS-1))}.$ZONE.compute.internal))
MINION_IP_RANGES=($(eval echo "10.244.{1..${NUM_MINIONS}}.0/24"))
MINION_SCOPES=""
POLL_SLEEP_INTERVAL=3
PORTAL_NET="10.0.0.0/16"

View File

@ -1,36 +0,0 @@
#!/bin/bash
# Copyright 2014 Google 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.
# Bring up a Kubernetes cluster.
#
# If the full release name (s3://<bucket>/<release>) is passed in then we take
# that directly. If not then we assume we are doing development stuff and take
# the defaults in the release config.
# exit on any error
set -e
source $(dirname $0)/../kube-env.sh
source $(dirname $0)/../$KUBERNETES_PROVIDER/util.sh
echo "Starting cluster using provider: $KUBERNETES_PROVIDER"
verify-prereqs
kube-up
source $(dirname $0)/validate-cluster.sh
echo "Done"

View File

@ -14,17 +14,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Tear down a Kubernetes cluster.
# Create the overlay files for the salt tree. We create these in a separate
# place so that we can blow away the rest of the salt configs on a kube-push and
# re-apply these.
# exit on any error
set -e
mkdir -p /srv/salt-overlay/pillar
cat <<EOF >/srv/salt-overlay/pillar/cluster-params.sls
node_instance_prefix: $NODE_INSTANCE_PREFIX
portal_net: $PORTAL_NET
use-fluentd-es: $FLUENTD_ELASTICSEARCH
use-fluentd-gcp: $FLUENTD_GCP
EOF
source $(dirname $0)/../kube-env.sh
source $(dirname $0)/../$KUBERNETES_PROVIDER/util.sh
echo "Bringing down cluster using provider: $KUBERNETES_PROVIDER"
verify-prereqs
kube-down
echo "Done"
mkdir -p /srv/salt-overlay/salt/nginx
echo $MASTER_HTPASSWD > /srv/salt-overlay/salt/nginx/htpasswd

View File

@ -20,13 +20,15 @@
# the release tar to download and unpack. It is meant to be pushed to the
# master and run.
echo "Downloading release ($MASTER_RELEASE_TAR)"
wget $MASTER_RELEASE_TAR
echo "Downloading binary release tar ($SERVER_BINARY_TAR_URL)"
wget "$SERVER_BINARY_TAR_URL" .
echo "Downloading binary release tar ($SALT_TAR_URL)"
wget "$SALT_TAR_URL" .
echo "Unpacking release"
rm -rf master-release || false
tar xzf master-release.tgz
echo "Unpacking Salt tree"
rm -rf kubernetes
tar xzf "${SALT_TAR_URL##*/}"
echo "Running release install script"
master-release/src/scripts/master-release-install.sh
sudo kubernetes/saltbase/install.sh "${SERVER_BINARY_TAR_URL##*/}"

View File

@ -25,6 +25,14 @@ grains:
cloud: aws
EOF
cat <<EOF > /etc/aws.conf
{
"Global": {
"Region": "${AWS_ZONE}"
}
}
EOF
# Auto accept all keys from minions that try to join
mkdir -p /etc/salt/master.d
cat <<EOF >/etc/salt/master.d/auto-accept.conf
@ -35,12 +43,9 @@ cat <<EOF >/etc/salt/master.d/reactor.conf
# React to new minions starting by running highstate on them.
reactor:
- 'salt/minion/*/start':
- /srv/reactor/start.sls
- /srv/reactor/highstate-new.sls
EOF
mkdir -p /srv/salt/nginx
echo $MASTER_HTPASSWD > /srv/salt/nginx/htpasswd
# Install Salt
#
# We specify -X to avoid a race condition that can cause minion failure to
@ -50,5 +55,3 @@ echo $MASTER_HTPASSWD > /srv/salt/nginx/htpasswd
set +x
curl -L --connect-timeout 20 --retry 6 --retry-delay 10 http://bootstrap.saltstack.com | sh -s -- -M -X
set -x
echo $MASTER_HTPASSWD > /srv/salt/nginx/htpasswd

View File

@ -22,32 +22,12 @@ source $(dirname ${BASH_SOURCE})/${KUBE_CONFIG_FILE-"config-default.sh"}
AWS_CMD="aws --output json ec2"
# Find the release to use. If passed in, go with that and validate. If not use
# the release/config.sh version assuming a dev workflow.
function find-release() {
if [ -n "$1" ]; then
RELEASE_NORMALIZED=$1
else
local RELEASE_CONFIG_SCRIPT=$(dirname $0)/../../release/aws/config.sh
if [ -f $(dirname $0)/../../release/aws/config.sh ]; then
. $RELEASE_CONFIG_SCRIPT
normalize_release
fi
fi
# Do one final check that we have a good release
if ! aws s3 ls $RELEASE_NORMALIZED/$RELEASE_TAR_FILE | grep $RELEASE_TAR_FILE > /dev/null; then
echo "Could not find release tar. If developing, make sure you have run src/release/release.sh to create a release."
exit 1
fi
echo "Release: ${RELEASE_NORMALIZED}"
}
function json_val {
python -c 'import json,sys;obj=json.load(sys.stdin);print obj'$1''
}
# TODO (ayurchuk) Refactor the get_* functions to use filters
# TODO (bburns) Parameterize this for multiple cluster per project
function get_instance_ids {
python -c 'import json,sys; lst = [str(instance["InstanceId"]) for reservation in json.load(sys.stdin)["Reservations"] for instance in reservation["Instances"] for tag in instance["Tags"] if tag["Value"].startswith("kubernetes-minion") or tag["Value"].startswith("kubernetes-master")]; print " ".join(lst)'
}
@ -82,10 +62,10 @@ function get_instance_public_ip {
function detect-master () {
KUBE_MASTER=${MASTER_NAME}
if [ -z "$KUBE_MASTER_IP" ]; then
if [[ -z "${KUBE_MASTER_IP-}" ]]; then
KUBE_MASTER_IP=$($AWS_CMD describe-instances | get_instance_public_ip $MASTER_NAME)
fi
if [ -z "$KUBE_MASTER_IP" ]; then
if [[ -z "${KUBE_MASTER_IP-}" ]]; then
echo "Could not detect Kubernetes master node. Make sure you've launched a cluster with 'kube-up.sh'"
exit 1
fi
@ -105,26 +85,6 @@ function detect-minions () {
fi
}
function get-password {
file=${HOME}/.kubernetes_auth
if [ -e ${file} ]; then
user=$(cat $file | python -c 'import json,sys;print json.load(sys.stdin)["User"]')
passwd=$(cat $file | python -c 'import json,sys;print json.load(sys.stdin)["Password"]')
return
fi
user=admin
passwd=$(python -c 'import string,random; print "".join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(16))')
# Store password for reuse.
cat << EOF > ~/.kubernetes_auth
{
"User": "$user",
"Password": "$passwd"
}
EOF
chmod 0600 ~/.kubernetes_auth
}
# Verify prereqs
function verify-prereqs {
if [ "$(which aws)" == "" ]; then
@ -133,51 +93,163 @@ function verify-prereqs {
fi
}
function kube-up {
# Find the release to use. Generally it will be passed when doing a 'prod'
# install and will default to the release/config.sh version when doing a
# developer up.
find-release $1
# Build up start up script for master
# Create a temp dir that'll be deleted at the end of this bash session.
#
# Vars set:
# KUBE_TEMP
function ensure-temp-dir {
if [[ -z ${KUBE_TEMP-} ]]; then
KUBE_TEMP=$(mktemp -d -t kubernetes.XXXXXX)
trap "rm -rf ${KUBE_TEMP}" EXIT
trap 'rm -rf "${KUBE_TEMP}"' EXIT
fi
}
get-password
echo "Using password: $user:$passwd"
python $(dirname $0)/../../third_party/htpasswd/htpasswd.py -b -c ${KUBE_TEMP}/htpasswd $user $passwd
HTPASSWD=$(cat ${KUBE_TEMP}/htpasswd)
# Verify and find the various tar files that we are going to use on the server.
#
# Vars set:
# SERVER_BINARY_TAR
# SALT_TAR
function find-release-tars {
SERVER_BINARY_TAR="${KUBE_ROOT}/server/kubernetes-server-linux-amd64.tar.gz"
if [[ ! -f "$SERVER_BINARY_TAR" ]]; then
SERVER_BINARY_TAR="${KUBE_ROOT}/_output/release-tars/kubernetes-server-linux-amd64.tar.gz"
fi
if [[ ! -f "$SERVER_BINARY_TAR" ]]; then
echo "!!! Cannot find kubernetes-server-linux-amd64.tar.gz"
exit 1
fi
if [ ! -f $AWS_SSH_KEY ]; then
ssh-keygen -f $AWS_SSH_KEY -N ''
fi
SALT_TAR="${KUBE_ROOT}/server/kubernetes-salt.tar.gz"
if [[ ! -f "$SALT_TAR" ]]; then
SALT_TAR="${KUBE_ROOT}/_output/release-tars/kubernetes-salt.tar.gz"
fi
if [[ ! -f "$SALT_TAR" ]]; then
echo "!!! Cannot find kubernetes-salt.tar.gz"
exit 1
fi
}
# Take the local tar files and upload them to S3. They will then be
# downloaded by the master as part of the start up script for the master.
#
# Assumed vars:
# SERVER_BINARY_TAR
# SALT_TAR
# Vars set:
# SERVER_BINARY_TAR_URL
# SALT_TAR_URL
function upload-server-tars() {
SERVER_BINARY_TAR_URL=
SALT_TAR_URL=
local project_hash
local key = $(aws configure get aws_access_key_id)
if which md5 > /dev/null 2>&1; then
project_hash = $(md5 -q -s "${USER} ${key}")
else
project_hash = $(echo -n "${USER} ${key}" | md5sum)
fi
local -r staging_bucket="kubernetes-staging-${project_hash}"
echo "Uploading to Amazon S3"
if ! aws s3 ls "s3://${staging_bucket}" > /dev/null 2>&1 ; then
echo "Creating ${staging_bucket}"
aws s3 mb "s3://${staging_bucket}"
fi
aws s3api put-bucket-acl --bucket $staging_bucket --acl public-read
local -r staging_path="${staging_bucket}/devel"
echo "+++ Staging server tars to S3 Storage: ${staging_path}"
SERVER_BINARY_TAR_URL="${staging_path}/${SERVER_BINARY_TAR##*/}"
aws s3 cp "${SERVER_BINARY_TAR}" "s3://${SERVER_BINARY_TAR_URL}"
aws s3api put-object-acl --bucket ${staging_bucket} --key "devel/${SERVER_BINARY_TAR##*/}" --grant-read 'uri="http://acs.amazonaws.com/groups/global/AllUsers"'
SALT_TAR_URL="${staging_path}/${SALT_TAR##*/}"
aws s3 cp "${SALT_TAR}" "s3://${SALT_TAR_URL}"
aws s3api put-object-acl --bucket ${staging_bucket} --key "devel/${SALT_TAR##*/}" --grant-read 'uri="http://acs.amazonaws.com/groups/global/AllUsers"'
}
# Ensure that we have a password created for validating to the master. Will
# read from $HOME/.kubernetres_auth if available.
#
# Vars set:
# KUBE_USER
# KUBE_PASSWORD
function get-password {
local file="$HOME/.kubernetes_auth"
if [[ -r "$file" ]]; then
KUBE_USER=$(cat "$file" | python -c 'import json,sys;print json.load(sys.stdin)["User"]')
KUBE_PASSWORD=$(cat "$file" | python -c 'import json,sys;print json.load(sys.stdin)["Password"]')
return
fi
KUBE_USER=admin
KUBE_PASSWORD=$(python -c 'import string,random; print "".join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(16))')
# Remove this code, since in all use cases I can see, we are overwriting this
# at cluster creation time.
cat << EOF > "$file"
{
"User": "$KUBE_USER",
"Password": "$KUBE_PASSWORD"
}
EOF
chmod 0600 "$file"
}
function kube-up {
find-release-tars
upload-server-tars
ensure-temp-dir
get-password
python "${KUBE_ROOT}/third_party/htpasswd/htpasswd.py" \
-b -c "${KUBE_TEMP}/htpasswd" "$KUBE_USER" "$KUBE_PASSWORD"
local htpasswd
htpasswd=$(cat "${KUBE_TEMP}/htpasswd")
if [ ! -f $AWS_SSH_KEY ]; then
ssh-keygen -f $AWS_SSH_KEY -N ''
fi
$AWS_CMD import-key-pair --key-name kubernetes --public-key-material file://$AWS_SSH_KEY.pub > /dev/null 2>&1 || true
VPC_ID=$($AWS_CMD create-vpc --cidr-block 172.20.0.0/16 | json_val '["Vpc"]["VpcId"]')
$AWS_CMD modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-support '{"Value": true}' > /dev/null
$AWS_CMD modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames '{"Value": true}' > /dev/null
$AWS_CMD create-tags --resources $VPC_ID --tags Key=Name,Value=kubernetes-vpc > /dev/null
SUBNET_ID=$($AWS_CMD create-subnet --cidr-block 172.20.0.0/24 --vpc-id $VPC_ID | json_val '["Subnet"]["SubnetId"]')
IGW_ID=$($AWS_CMD create-internet-gateway | json_val '["InternetGateway"]["InternetGatewayId"]')
$AWS_CMD attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID > /dev/null
ROUTE_TABLE_ID=$($AWS_CMD describe-route-tables --filters Name=vpc-id,Values=$VPC_ID | json_val '["RouteTables"][0]["RouteTableId"]')
$AWS_CMD associate-route-table --route-table-id $ROUTE_TABLE_ID --subnet-id $SUBNET_ID > /dev/null
$AWS_CMD describe-route-tables --filters Name=vpc-id,Values=$VPC_ID > /dev/null
$AWS_CMD create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID > /dev/null
SEC_GROUP_ID=$($AWS_CMD create-security-group --group-name kubernetes-sec-group --description kubernetes-sec-group --vpc-id $VPC_ID | json_val '["GroupId"]')
$AWS_CMD authorize-security-group-ingress --group-id $SEC_GROUP_ID --protocol -1 --port all --cidr 0.0.0.0/0 > /dev/null
$AWS_CMD import-key-pair --key-name kubernetes --public-key-material file://$AWS_SSH_KEY.pub > /dev/null 2>&1 || true
VPC_ID=$($AWS_CMD create-vpc --cidr-block 172.20.0.0/16 | json_val '["Vpc"]["VpcId"]')
$AWS_CMD modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-support '{"Value": true}' > /dev/null
$AWS_CMD modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames '{"Value": true}' > /dev/null
$AWS_CMD create-tags --resources $VPC_ID --tags Key=Name,Value=kubernetes-vpc > /dev/null
SUBNET_ID=$($AWS_CMD create-subnet --cidr-block 172.20.0.0/24 --vpc-id $VPC_ID | json_val '["Subnet"]["SubnetId"]')
IGW_ID=$($AWS_CMD create-internet-gateway | json_val '["InternetGateway"]["InternetGatewayId"]')
$AWS_CMD attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID > /dev/null
ROUTE_TABLE_ID=$($AWS_CMD describe-route-tables --filters Name=vpc-id,Values=$VPC_ID | json_val '["RouteTables"][0]["RouteTableId"]')
$AWS_CMD associate-route-table --route-table-id $ROUTE_TABLE_ID --subnet-id $SUBNET_ID > /dev/null
$AWS_CMD describe-route-tables --filters Name=vpc-id,Values=$VPC_ID > /dev/null
$AWS_CMD create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID > /dev/null
SEC_GROUP_ID=$($AWS_CMD create-security-group --group-name kubernetes-sec-group --description kubernetes-sec-group --vpc-id $VPC_ID | json_val '["GroupId"]')
$AWS_CMD authorize-security-group-ingress --group-id $SEC_GROUP_ID --protocol -1 --port all --cidr 0.0.0.0/0 > /dev/null
(
echo "#!/bin/bash"
echo "MASTER_NAME=${MASTER_NAME}"
echo "MASTER_RELEASE_TAR=${RELEASE_FULL_HTTP_PATH}/master-release.tgz"
echo "MASTER_HTPASSWD='${HTPASSWD}'"
grep -v "^#" $(dirname $0)/templates/download-release.sh
grep -v "^#" $(dirname $0)/templates/salt-master.sh
) > ${KUBE_TEMP}/master-start.sh
(
# We pipe this to the ami as a startup script in the user-data field. Requires a compatible ami
echo "#! /bin/bash"
echo "mkdir -p /var/cache/kubernetes-install"
echo "cd /var/cache/kubernetes-install"
echo "readonly MASTER_NAME='${MASTER_NAME}'"
echo "readonly NODE_INSTANCE_PREFIX='${INSTANCE_PREFIX}-minion'"
echo "readonly SERVER_BINARY_TAR_URL='https://s3-${ZONE}.amazonaws.com/${SERVER_BINARY_TAR_URL}'"
echo "readonly SALT_TAR_URL='https://s3-${ZONE}.amazonaws.com/${SALT_TAR_URL}'"
echo "readonly AWS_ZONE='${ZONE}'"
echo "readonly MASTER_HTPASSWD='${htpasswd}'"
echo "readonly PORTAL_NET='${PORTAL_NET}'"
echo "readonly FLUENTD_ELASTICSEARCH='${FLUENTD_ELASTICSEARCH:-false}'"
echo "readonly FLUENTD_GCP='false'"
grep -v "^#" "${KUBE_ROOT}/cluster/aws/templates/create-dynamic-salt-files.sh"
grep -v "^#" "${KUBE_ROOT}/cluster/aws/templates/download-release.sh"
grep -v "^#" "${KUBE_ROOT}/cluster/aws/templates/salt-master.sh"
) > "${KUBE_TEMP}/master-start.sh"
master_id=$($AWS_CMD run-instances \
master_id=$($AWS_CMD run-instances \
--image-id $IMAGE \
--instance-type $MASTER_SIZE \
--subnet-id $SUBNET_ID \
@ -186,102 +258,151 @@ function kube-up {
--security-group-ids $SEC_GROUP_ID \
--associate-public-ip-address \
--user-data file://${KUBE_TEMP}/master-start.sh | json_val '["Instances"][0]["InstanceId"]')
sleep 3
$AWS_CMD create-tags --resources $master_id --tags Key=Name,Value=$MASTER_NAME > /dev/null
sleep 3
$AWS_CMD create-tags --resources $master_id --tags Key=Role,Value=$MASTER_TAG > /dev/null
$AWS_CMD create-tags --resources $master_id --tags Key=Name,Value=$MASTER_NAME > /dev/null
$AWS_CMD create-tags --resources $master_id --tags Key=Role,Value=$MASTER_TAG > /dev/null
for (( i=0; i<${#MINION_NAMES[@]}; i++)); do
for (( i=0; i<${#MINION_NAMES[@]}; i++)); do
(
# We pipe this to the ami as a startup script in the user-data field. Requires a compatible ami
echo "#! /bin/bash"
echo "MASTER_NAME=${MASTER_NAME}"
echo "MINION_IP_RANGE=${MINION_IP_RANGES[$i]}"
grep -v "^#" $(dirname $0)/templates/salt-minion.sh
) > ${KUBE_TEMP}/minion-start-${i}.sh
minion_id=$($AWS_CMD run-instances \
--image-id $IMAGE \
--instance-type $MINION_SIZE \
--subnet-id $SUBNET_ID \
--private-ip-address 172.20.0.1${i} \
--key-name kubernetes \
--security-group-ids $SEC_GROUP_ID \
--associate-public-ip-address \
--user-data file://${KUBE_TEMP}/minion-start-${i}.sh | json_val '["Instances"][0]["InstanceId"]')
echo "MASTER_NAME='${MASTER_NAME}'"
echo "MINION_IP_RANGE='${MINION_IP_RANGES[$i]}'"
grep -v "^#" "${KUBE_ROOT}/cluster/aws/templates/salt-minion.sh"
) > "${KUBE_TEMP}/minion-start-${i}.sh"
minion_id=$($AWS_CMD run-instances \
--image-id $IMAGE \
--instance-type $MINION_SIZE \
--subnet-id $SUBNET_ID \
--private-ip-address 172.20.0.1${i} \
--key-name kubernetes \
--security-group-ids $SEC_GROUP_ID \
--associate-public-ip-address \
--user-data file://${KUBE_TEMP}/minion-start-${i}.sh | json_val '["Instances"][0]["InstanceId"]')
sleep 3
n=0
until [ $n -ge 5 ]; do
$AWS_CMD create-tags --resources $minion_id --tags Key=Name,Value=${MINION_NAMES[$i]} > /dev/null && break
n=$[$n+1]
sleep 15
done
$AWS_CMD create-tags --resources $minion_id --tags Key=Name,Value=${MINION_NAMES[$i]} > /dev/null
$AWS_CMD create-tags --resources $minion_id --tags Key=Role,Value=$MINION_TAG > /dev/null
$AWS_CMD modify-instance-attribute --instance-id $minion_id --source-dest-check '{"Value": false}' > /dev/null
# We are not able to add a route to the instance until that instance is in "running" state.
# This is quite an ugly solution to this problem. In Bash 4 we could use assoc. arrays to do this for
# all instances at once but we can't be sure we are running Bash 4.
while true; do
instance_state=$($AWS_CMD describe-instances --instance-ids $minion_id | expect_instance_states running)
if [[ "$instance_state" == "" ]]; then
echo "Minion ${MINION_NAMES[$i]} running"
$AWS_CMD create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block "10.244.$i.0/24" --instance-id $minion_id > /dev/null
break
else
echo "Waiting for minion ${MINION_NAMES[$i]} to spawn"
echo "Sleeping for 3 seconds..."
sleep 3
fi
done
sleep 3
n=0
until [ $n -ge 5 ]; do
$AWS_CMD create-tags --resources $minion_id --tags Key=Role,Value=$MINION_TAG > /dev/null && break
n=$[$n+1]
sleep 15
done
sleep 3
$AWS_CMD modify-instance-attribute --instance-id $minion_id --source-dest-check '{"Value": false}' > /dev/null
FAIL=0
for job in `jobs -p`
do
wait $job || let "FAIL+=1"
# We are not able to add a route to the instance until that instance is in "running" state.
# This is quite an ugly solution to this problem. In Bash 4 we could use assoc. arrays to do this for
# all instances at once but we can't be sure we are running Bash 4.
while true; do
instance_state=$($AWS_CMD describe-instances --instance-ids $minion_id | expect_instance_states running)
if [[ "$instance_state" == "" ]]; then
echo "Minion ${MINION_NAMES[$i]} running"
sleep 10
$AWS_CMD create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block ${MINION_IP_RANGES[$i]} --instance-id $minion_id > /dev/null
break
else
echo "Waiting for minion ${MINION_NAMES[$i]} to spawn"
echo "Sleeping for 3 seconds..."
sleep 3
fi
done
if (( $FAIL != 0 )); then
echo "${FAIL} commands failed. Exiting."
exit 2
done
FAIL=0
for job in `jobs -p`; do
wait $job || let "FAIL+=1"
done
if (( $FAIL != 0 )); then
echo "${FAIL} commands failed. Exiting."
exit 2
fi
detect-master > /dev/null
detect-minions > /dev/null
# Wait 3 minutes for cluster to come up. We hit it with a "highstate" after that to
# make sure that everything is well configured.
echo "Waiting for cluster to settle"
local i
for (( i=0; i < 6*3; i++)); do
printf "."
sleep 10
done
echo "Re-running salt highstate"
ssh -oStrictHostKeyChecking=no -i ~/.ssh/kube_aws_rsa ubuntu@${KUBE_MASTER_IP} sudo salt '*' state.highstate > /dev/null
echo "Waiting for cluster initialization."
echo
echo " This will continually check to see if the API for kubernetes is reachable."
echo " This might loop forever if there was some uncaught error during start"
echo " up."
echo
until $(curl --insecure --user ${KUBE_USER}:${KUBE_PASSWORD} --max-time 5 \
--fail --output /dev/null --silent https://${KUBE_MASTER_IP}/api/v1beta1/pods); do
printf "."
sleep 2
done
echo "Kubernetes cluster created."
echo "Sanity checking cluster..."
sleep 5
# Don't bail on errors, we want to be able to print some info.
set +e
# Basic sanity checking
for i in ${KUBE_MINION_IP_ADDRESSES[@]}; do
# Make sure docker is installed
ssh -oStrictHostKeyChecking=no ubuntu@$i -i ~/.ssh/kube_aws_rsa which docker > /dev/null 2>&1
if [ "$?" != "0" ]; then
echo "Docker failed to install on $i. Your cluster is unlikely to work correctly."
echo "Please run ./cluster/aws/kube-down.sh and re-create the cluster. (sorry!)"
exit 1
fi
done
echo
echo "Kubernetes cluster is running. Access the master at:"
echo
echo " https://${KUBE_USER}:${KUBE_PASSWORD}@${KUBE_MASTER_IP}"
echo
detect-master > /dev/null
detect-minions > /dev/null
local kube_cert=".kubecfg.crt"
local kube_key=".kubecfg.key"
local ca_cert=".kubernetes.ca.crt"
echo "Waiting for cluster initialization."
echo
echo " This will continually check to see if the API for kubernetes is reachable."
echo " This might loop forever if there was some uncaught error during start"
echo " up."
echo
# TODO: generate ADMIN (and KUBELET) tokens and put those in the master's
# config file. Distribute the same way the htpasswd is done.
(
umask 077
ssh -oStrictHostKeyChecking=no -i ~/.ssh/kube_aws_rsa ubuntu@${KUBE_MASTER_IP} sudo cat /usr/share/nginx/kubecfg.crt >"${HOME}/${kube_cert}" 2>/dev/null
ssh -oStrictHostKeyChecking=no -i ~/.ssh/kube_aws_rsa ubuntu@${KUBE_MASTER_IP} sudo cat /usr/share/nginx/kubecfg.key >"${HOME}/${kube_key}" 2>/dev/null
ssh -oStrictHostKeyChecking=no -i ~/.ssh/kube_aws_rsa ubuntu@${KUBE_MASTER_IP} sudo cat /usr/share/nginx/ca.crt >"${HOME}/${ca_cert}" 2>/dev/null
until $(curl --insecure --user ${user}:${passwd} --max-time 5 \
--fail --output /dev/null --silent https://${KUBE_MASTER_IP}/api/v1beta1/pods); do
printf "."
sleep 2
done
cat << EOF > ~/.kubernetes_auth
{
"User": "$KUBE_USER",
"Password": "$KUBE_PASSWORD",
"CAFile": "$HOME/$ca_cert",
"CertFile": "$HOME/$kube_cert",
"KeyFile": "$HOME/$kube_key"
}
EOF
echo "Kubernetes cluster created."
echo "Sanity checking cluster..."
sleep 5
# Don't bail on errors, we want to be able to print some info.
set +e
# Basic sanity checking
for i in ${KUBE_MINION_IP_ADDRESSES[@]}; do
# Make sure docker is installed
ssh -oStrictHostKeyChecking=no ubuntu@$i -i ~/.ssh/kube_aws_rsa which docker > /dev/null 2>&1
if [ "$?" != "0" ]; then
echo "Docker failed to install on $i. Your cluster is unlikely to work correctly."
echo "Please run ./cluster/aws/kube-down.sh and re-create the cluster. (sorry!)"
exit 1
fi
done
echo
echo "Kubernetes cluster is running. Access the master at:"
echo
echo " https://${user}:${passwd}@${KUBE_MASTER_IP}"
echo
echo "Security note: The server above uses a self signed certificate. This is"
echo " subject to \"Man in the middle\" type attacks."
chmod 0600 ~/.kubernetes_auth "${HOME}/${kube_cert}" \
"${HOME}/${kube_key}" "${HOME}/${ca_cert}"
)
}
function kube-down {

View File

@ -1,47 +0,0 @@
#!/bin/bash
# Copyright 2014 Google 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.
# exit on any error
set -e
source $(dirname $0)/../kube-env.sh
source $(dirname $0)/../$KUBERNETES_PROVIDER/util.sh
get-password
detect-master > /dev/null
detect-minions > /dev/null
MINIONS_FILE=/tmp/minions
$(dirname $0)/../kubecfg.sh -template '{{range.Items}}{{.ID}}:{{end}}' list minions > ${MINIONS_FILE}
for (( i=0; i<${#MINION_NAMES[@]}; i++)); do
# Grep returns an exit status of 1 when line is not found, so we need the : to always return a 0 exit status
count=$(grep -c ${MINION_NAMES[i]} ${MINIONS_FILE}) || :
if [ "$count" == "0" ]; then
echo "Failed to find ${MINION_NAMES[i]}, cluster is probably broken."
exit 1
fi
# Make sure the kubelet is healthy
if [ "$(curl --insecure --user ${user}:${passwd} https://${KUBE_MASTER_IP}/proxy/minion/${MINION_NAMES[$i]}/healthz)" != "ok" ]; then
echo "Kubelet failed to install on ${MINION_NAMES[$i]}. Your cluster is unlikely to work correctly."
echo "Please run ./cluster/kube-down.sh and re-create the cluster. (sorry!)"
exit 1
else
echo "Kubelet is successfully installed on ${MINION_NAMES[$i]}"
fi
done
echo "Cluster validation succeeded"

View File

@ -21,6 +21,12 @@
{% set cloud_provider = "-cloud_provider=gce" %}
{% set machines = "-machines=" + ','.join(salt['mine.get']('roles:kubernetes-pool', 'network.ip_addrs', expr_form='grain').keys()) %}
{% endif %}
{% if grains.cloud == 'aws' %}
# TODO: turn on AWS as a cloud provider. Need to figure out AWS role-based auth.
{% set cloud_provider = "" %}
{% set minion_regexp = "" %}
{% set machines = "-machines " + ','.join(salt['mine.get']('roles:kubernetes-pool', 'network.ip_addrs', expr_form='grain').keys()) %}
{% endif %}
{% if grains.cloud == 'azure' %}
MACHINES="{{ salt['mine.get']('roles:kubernetes-pool', 'grains.items', expr_form='grain').values()|join(',', attribute='hostnamef') }}"
{% set machines = "-machines=$MACHINES" %}

View File

@ -14,6 +14,9 @@ nginx:
{% if grains.cloud == 'gce' %}
{% set cert_ip='_use_gce_external_ip_' %}
{% endif %}
{% if grains.cloud == 'aws' %}
{% set cert_ip='_use_aws_external_ip_' %}
{% endif %}
{% if grains.cloud == 'vagrant' %}
{% set cert_ip=grains.fqdn_ip4 %}
{% endif %}

View File

@ -23,7 +23,11 @@ cert_ip=$1
# TODO: Add support for discovery on other providers?
if [ "$cert_ip" == "_use_gce_external_ip_" ]; then
cert_ip=$(curl -s -H Metadata-Flavor:Google http://metadata.google.internal./computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip)
fi
fi
if [ "$cert_ip" == "_use_aws_external_ip_" ]; then
cert_ip=$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4)
fi
tmpdir=$(mktemp -d --tmpdir kubernetes_cacert.XXXXXX)
trap 'rm -rf "${tmpdir}"' EXIT

View File

@ -2,6 +2,7 @@
The example below creates an elastic Kubernetes cluster with 3 worker nodes and a master.
<<<<<<< HEAD
## Highlights
* Cluster bootstrapping using [cloud-config](https://coreos.com/docs/cluster-management/setup/cloudinit-cloud-config)
@ -34,13 +35,28 @@ aws cloudformation describe-stack-events --stack-name kubernetes
```
> Record the Kubernetes Master IP address
=======
1. You need an AWS account. Visit [http://aws.amazon.com](http://aws.amazon.com) to get started
2. Install and configure [AWS Command Line Interface](http://aws.amazon.com/cli)
### Run from a binary release
>>>>>>> Update the AWS config.
1. Download the [binary release](https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/getting-started-guides/binary_release.md)
2. Unpack the archive and ```cd kubernetes```
3. Turn up the cluster:
```
<<<<<<< HEAD
aws cloudformation describe-stacks --stack-name kubernetes
=======
export KUBERNETES_PROVIDER=aws
cluster/kube-up.sh
>>>>>>> Update the AWS config.
```
[Skip to kubecfg client configuration](#configure-the-kubecfg-ssh-tunnel)
<<<<<<< HEAD
### Manually
The following commands use the CoreOS 490.0.0 alpha AMI `ami-e18dc5d1` from the `us-west-2` region. For a list of different regions and corresponding AMI IDs see the [CoreOS EC2 cloud provider documentation](https://coreos.com/docs/running-coreos/cloud-providers/ec2/#choosing-a-channel).
@ -97,8 +113,15 @@ aws ec2 describe-instances --instance-id <instance-id>
Edit `node.yaml` and replace all instances of `<master-private-ip>` with the **private** IP address of the master node.
### Launch 3 worker nodes
=======
### Running examples
Take a look at [next steps](https://github.com/GoogleCloudPlatform/kubernetes#where-to-go-next)
>>>>>>> Update the AWS config.
### Tearing down the cluster
```
<<<<<<< HEAD
aws ec2 run-instances --count 3 --image-id ami-e18dc5d1 --key-name <keypair> \
--region us-west-2 --security-groups kubernetes --instance-type m3.medium \
--user-data file://node.yaml
@ -201,3 +224,11 @@ Visit the public IP address in your browser to view the running pod.
```
kubecfg delete pods/hello
```
=======
cd kubernetes
cluster/kube-down.sh
```
### Cloud Formation
There is a contributed example from [CoreOS](http://www.coreos.com) using Cloud Formation.
>>>>>>> Update the AWS config.

View File

@ -1,26 +0,0 @@
#!/bin/bash
# Copyright 2014 Google 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.
# This script will build a dev release and bring up a new cluster with that
# release.
SCRIPT_DIR=$(CDPATH="" cd $(dirname $0); pwd)
# First build a release
$SCRIPT_DIR/../../release/aws/release.sh
# Now bring a new cluster up with that release.
$SCRIPT_DIR/../../cluster/aws/kube-up.sh

View File

@ -1,69 +0,0 @@
# Copyright 2014 Google 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.
if which md5 > /dev/null 2>&1; then
MD5_FUNC=md5
else
MD5_FUNC=md5sum
fi
function json_val () {
python -c 'import json,sys;obj=json.load(sys.stdin);print obj'$1''
}
INSTANCE_PREFIX=kubernetes
AWS_HASH=$(aws --output json iam list-access-keys | json_val '["AccessKeyMetadata"][0]["AccessKeyId"]' | $MD5_FUNC)
AWS_HASH=${AWS_HASH:0:5}
RELEASE_BUCKET=${RELEASE_BUCKET-s3://kubernetes-releases-$AWS_HASH/}
RELEASE_PREFIX=${RELEASE_PREFIX-devel/$USER/}
RELEASE_NAME=${RELEASE_NAME-r$(date -u +%Y%m%d-%H%M%S)}
# This is a 'soft link' to the release in question. It is a single line file to
# the full GS path for a release.
RELEASE_TAG=${RELEASE_TAG-testing}
RELEASE_TAR_FILE=master-release.tgz
RELEASE_FULL_PATH=$RELEASE_BUCKET$RELEASE_PREFIX$RELEASE_NAME
RELEASE_FULL_TAG_PATH=$RELEASE_BUCKET$RELEASE_PREFIX$RELEASE_TAG
# Takes a release path ($1 if passed, otherwise $RELEASE_FULL_TAG_PATH) and
# computes the normalized release path. Results are stored in
# $RELEASE_NORMALIZED. Returns 0 if a valid release can be found.
function normalize_release() {
RELEASE_NORMALIZED=${1-$RELEASE_FULL_TAG_PATH}
# First test to see if there is a valid release at this path.
if aws s3 ls $RELEASE_NORMALIZED/$RELEASE_TAR_FILE | grep $RELEASE_TAR_FILE > /dev/null; then
return 0
fi
# Check if this is a simple file. If so, read it and use the result as the
# new RELEASE_NORMALIZED.
if aws s3 ls $RELEASE_NORMALIZED | grep $RELEASE_TAG > /dev/null; then
RELEASE_NORMALIZED=$(aws s3 cp $RELEASE_NORMALIZED >(cat) > /dev/null)
normalize_release $RELEASE_NORMALIZED
RELEASE_FULL_HTTP_PATH=${RELEASE_NORMALIZED/s3:\/\//https:\/\/s3-$ZONE.amazonaws.com/}
return
fi
return 1
}
# Sets a tag ($1) to a release ($2)
function set_tag() {
TMPFILE=$(mktemp -t release_tag 2>/dev/null || mktemp -t release_tag.XXXX)
echo $2 > $TMPFILE
aws s3 cp $TMPFILE $1 > /dev/null
}

View File

@ -1,46 +0,0 @@
# Copyright 2014 Google 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.
# Prerequisites
# TODO (ayurchuk): Perhaps install cloud SDK automagically if we can't find it?
# Exit on any error
set -e
echo "Auto installer for launching Kubernetes"
echo "Release: $RELEASE_PREFIX$RELEASE_NAME"
# Make sure that prerequisites are installed.
if [ "$(which aws)" == "" ]; then
echo "Can't find aws in PATH, please fix and retry."
exit 1
fi
# TODO(jbeda): Provide a way to install this in to someplace beyond a temp dir
# so that users have access to local tools.
TMPDIR=$(mktemp -d /tmp/installer.kubernetes.XXXXXX)
cd $TMPDIR
echo "Downloading support files"
aws s3 cp $RELEASE_FULL_PATH/launch-kubernetes.tgz .
tar xzf launch-kubernetes.tgz
./src/scripts/kube-up.sh $RELEASE_FULL_PATH
cd /
# clean up
# rm -rf $TMPDIR

View File

@ -1,65 +0,0 @@
#!/bin/bash
# Copyright 2014 Google 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.
# This script will build and release Kubernetes.
#
# The main parameters to this script come from the config.sh file. This is set
# up by default for development releases. Feel free to edit it or override some
# of the variables there.
# exit on any error
set -e
SCRIPT_DIR=$(CDPATH="" cd $(dirname $0); pwd)
source $SCRIPT_DIR/config.sh
$SCRIPT_DIR/../build-release.sh $INSTANCE_PREFIX
echo "Building launch script"
# Create the local install script. These are the tools to install the local
# tools and launch a new cluster.
LOCAL_RELEASE_DIR=$SCRIPT_DIR/../../_output/release/local-release
mkdir -p $LOCAL_RELEASE_DIR/src/scripts
cp -r $SCRIPT_DIR/../../cluster/templates $LOCAL_RELEASE_DIR/src/templates
cp -r $SCRIPT_DIR/../../cluster/*.sh $LOCAL_RELEASE_DIR/src/scripts
tar cz -C $LOCAL_RELEASE_DIR -f $SCRIPT_DIR/../../_output/release/launch-kubernetes.tgz .
echo "#!/bin/bash" >> $SCRIPT_DIR/../../_output/release/launch-kubernetes.sh
echo "RELEASE_TAG=$RELEASE_TAG" >> $SCRIPT_DIR/../../_output/release/launch-kubernetes.sh
echo "RELEASE_PREFIX=$RELEASE_PREFIX" >> $SCRIPT_DIR/../../_output/release/launch-kubernetes.sh
echo "RELEASE_NAME=$RELEASE_NAME" >> $SCRIPT_DIR/../../_output/release/launch-kubernetes.sh
echo "RELEASE_FULL_PATH=$RELEASE_FULL_PATH" >> $SCRIPT_DIR/../../_output/release/launch-kubernetes.sh
cat $SCRIPT_DIR/launch-kubernetes-base.sh >> $SCRIPT_DIR/../../_output/release/launch-kubernetes.sh
chmod a+x $SCRIPT_DIR/../../_output/release/launch-kubernetes.sh
echo "Uploading to Amazon S3"
if ! aws s3 ls $RELEASE_BUCKET > /dev/null 2>&1 ; then
echo "Creating $RELEASE_BUCKET"
aws s3 mb $RELEASE_BUCKET > /dev/null
fi
aws s3api put-bucket-acl --bucket kubernetes-releases-$AWS_HASH --acl public-read
for x in master-release.tgz launch-kubernetes.tgz launch-kubernetes.sh; do
aws s3 cp $SCRIPT_DIR/../../_output/release/$x $RELEASE_FULL_PATH/$x > /dev/null
aws s3api put-object-acl --bucket kubernetes-releases-$AWS_HASH --key $RELEASE_PREFIX$RELEASE_NAME/$x --acl public-read
done
set_tag $RELEASE_FULL_TAG_PATH $RELEASE_FULL_PATH
echo "Release pushed ($RELEASE_PREFIX$RELEASE_NAME)."