From d18f0745e929ae80492c17c26559e7a68de6df17 Mon Sep 17 00:00:00 2001 From: garland Date: Wed, 3 Jul 2019 16:40:43 -0700 Subject: [PATCH] Adding kops.sh script to automate kops creation --- clusters/aws/kops/kops.sh | 379 ++++++++++++++++++++++++++++++++++++++ docs/README.md | 4 +- 2 files changed, 381 insertions(+), 2 deletions(-) create mode 100755 clusters/aws/kops/kops.sh diff --git a/clusters/aws/kops/kops.sh b/clusters/aws/kops/kops.sh new file mode 100755 index 000000000..5357085a6 --- /dev/null +++ b/clusters/aws/kops/kops.sh @@ -0,0 +1,379 @@ +#!/bin/bash -e + +# create_kops - A script to create a Kops Kubernetes cluster + +########################################## +##### Constants +########################################## + +TIME_NOW=$(date +"%x %r %Z") +KOPS_VERSION="1.11." + +########################################## +##### Functions +########################################## + +usage() +{ + echo "usage: create_kops [[[-n kops_name ] ] | [-h]]" +} + +check_kops_version() +{ + command=$(kops version) + + if [[ "${command}" == *"${KOPS_VERSION}"* ]]; then + echo "[INFO] Kops version: ${command}" + else + echo "[ERROR] Kops version expected: ${KOPS_VERSION}" + echo "Got: ${command}" + exit 1 + fi +} + +create() +{ + # Checks + VALUES_FILE_PATH="./clusters/${kops_name}/values.yaml" + TEMPLATE_FILE_PATH="./template/cluster.yml" + + if [ ! -f ${VALUES_FILE_PATH} ]; then + echo "File does not exist: ${VALUES_FILE_PATH}" + exit 1 + fi + + if [ ! -f ${TEMPLATE_FILE_PATH} ]; then + echo "File does not exist: ${TEMPLATE_FILE_PATH}" + exit 1 + fi + + kops_state_store=s3://$(cat ${VALUES_FILE_PATH} | grep "s3BucketName: " | awk '{print $2}' | tr -d '[:space:]') + export KOPS_STATE_STORE=${kops_state_store} + echo "[INFO] Setting KOPS_STATE_STORE: ${kops_state_store}" + + if [ "${dry_run}" == "false" ]; then + echo "[INFO] Not a dry run" + echo "[INFO] Templating out" + kops toolbox template --template ${TEMPLATE_FILE_PATH} --values ${VALUES_FILE_PATH} > ./kops-templated-${kops_name}.yaml + cat kops-templated-${kops_name}.yaml + + echo "[INFO] Creating the cluster" + kops create -f ./kops-templated-${kops_name}.yaml + + dns_zone=$(cat ${VALUES_FILE_PATH} | grep "dnsZone: " | awk '{print $2}' | tr -d '[:space:]') + cluster_name=$(cat ${VALUES_FILE_PATH} | grep "kopsName: " | awk '{print $2}' | tr -d '[:space:]').${dns_zone} + + ssh-keygen -t rsa -b 4096 -C "kops@kops.com" -f ./ssh-keys/id_rsa_kops_script -q -N "" + + echo "[INFO] Setting to generic ssh pub key" + kops create secret --name ${cluster_name} sshpublickey admin -i ./ssh-keys/id_rsa_kops_script.pub + + echo "[INFO] Applying cluster to AWS" + kops --name ${cluster_name} update cluster --yes + + echo "[INFO] Get instance groups" + kops --name ${cluster_name} get ig + + else + echo "[INFO] Dry run" + kops toolbox template --template ${TEMPLATE_FILE_PATH} --values ${VALUES_FILE_PATH} + fi + + echo "Finished" + +} + +read() +{ + # Checks + VALUES_FILE_PATH="./clusters/${kops_name}/values.yaml" + TEMPLATE_FILE_PATH="./template/cluster.yml" + + if [ ! -f ${VALUES_FILE_PATH} ]; then + echo "File does not exist: ${VALUES_FILE_PATH}" + exit 1 + fi + + if [ ! -f ${TEMPLATE_FILE_PATH} ]; then + echo "File does not exist: ${TEMPLATE_FILE_PATH}" + exit 1 + fi + + kops_state_store=s3://$(cat ${VALUES_FILE_PATH} | grep "s3BucketName: " | awk '{print $2}' | tr -d '[:space:]') + export KOPS_STATE_STORE=${kops_state_store} + echo "[INFO] Setting KOPS_STATE_STORE: ${kops_state_store}" + + dns_zone=$(cat ${VALUES_FILE_PATH} | grep "dnsZone: " | awk '{print $2}' | tr -d '[:space:]') + cluster_name=$(cat ${VALUES_FILE_PATH} | grep "kopsName: " | awk '{print $2}' | tr -d '[:space:]').${dns_zone} + + echo "[INFO] Get clusters" + kops --name ${cluster_name} get clusters + + echo "[INFO] Get instance groups" + kops --name ${cluster_name} get ig +} + +template() +{ + # Checks + VALUES_FILE_PATH="./clusters/${kops_name}/values.yaml" + TEMPLATE_FILE_PATH="./template/cluster.yml" + + if [ ! -f ${VALUES_FILE_PATH} ]; then + echo "File does not exist: ${VALUES_FILE_PATH}" + exit 1 + fi + + if [ ! -f ${TEMPLATE_FILE_PATH} ]; then + echo "File does not exist: ${TEMPLATE_FILE_PATH}" + exit 1 + fi + + kops_state_store=s3://$(cat ${VALUES_FILE_PATH} | grep "s3BucketName: " | awk '{print $2}' | tr -d '[:space:]') + export KOPS_STATE_STORE=${kops_state_store} + echo "[INFO] Setting KOPS_STATE_STORE: ${kops_state_store}" + + echo "[INFO] Dry run" + kops toolbox template --template ${TEMPLATE_FILE_PATH} --values ${VALUES_FILE_PATH} + + echo "Finished" +} + +update() +{ + # cluster_name=$(kops get clusters | grep "^${kops_name}\." | awk '{print $1}') + # echo "[INFO] Updating cluster named: ${cluster_name}" + + # Checks + VALUES_FILE_PATH="./clusters/${kops_name}/values.yaml" + TEMPLATE_FILE_PATH="./template/cluster.yml" + + if [ ! -f ${VALUES_FILE_PATH} ]; then + echo "File does not exist: ${VALUES_FILE_PATH}" + exit 1 + fi + + if [ ! -f ${TEMPLATE_FILE_PATH} ]; then + echo "File does not exist: ${TEMPLATE_FILE_PATH}" + exit 1 + fi + + kops_state_store=s3://$(cat ${VALUES_FILE_PATH} | grep "s3BucketName: " | awk '{print $2}' | tr -d '[:space:]') + export KOPS_STATE_STORE=${kops_state_store} + echo "[INFO] Setting KOPS_STATE_STORE: ${kops_state_store}" + + if [ "${dry_run}" == "false" ]; then + echo "[INFO] Not a dry run" + echo "[INFO] Templating out" + kops toolbox template --template ${TEMPLATE_FILE_PATH} --values ${VALUES_FILE_PATH} > ./kops-templated-${kops_name}.yaml + cat kops-templated-${kops_name}.yaml + + dns_zone=$(cat ${VALUES_FILE_PATH} | grep "dnsZone: " | awk '{print $2}' | tr -d '[:space:]') + cluster_name=$(cat ${VALUES_FILE_PATH} | grep "kopsName: " | awk '{print $2}' | tr -d '[:space:]').${dns_zone} + echo "[INFO] Updating cluster named: ${cluster_name}" + + echo "[INFO] Updating the cluster" + #--force is required so that any resources (ie new instance groups) are created; + # without this flag the call fails with a resource DNE error + kops --name ${cluster_name} replace -f ./kops-templated-${kops_name}.yaml --force + + echo "[INFO] Applying cluster to AWS" + kops --name ${cluster_name} update cluster --yes + + echo "[INFO] Cluster instance groups:" + kops --name ${cluster_name} get ig + + else + echo "[INFO] Dry run" + echo "[INFO] Templating out" + kops toolbox template --template ${TEMPLATE_FILE_PATH} --values ${VALUES_FILE_PATH} > ./kops-templated-${kops_name}.yaml + cat kops-templated-${kops_name}.yaml + + dns_zone=$(cat ${VALUES_FILE_PATH} | grep "dnsZone: " | awk '{print $2}' | tr -d '[:space:]') + cluster_name=$(cat ${VALUES_FILE_PATH} | grep "kopsName: " | awk '{print $2}' | tr -d '[:space:]').${dns_zone} + echo "[INFO] Updating cluster named: ${cluster_name}" + + echo "[INFO] Updating the cluster" + #--force is required so that any resources (ie new instance groups) are created; + # without this flag the call fails with a resource DNE error + kops --name ${cluster_name} replace -f ./kops-templated-${kops_name}.yaml --force + + echo "[INFO] Applying cluster to AWS" + kops --name ${cluster_name} update cluster + + echo "[INFO] Cluster instance groups:" + kops --name ${cluster_name} get ig + fi + + echo "Finished" +} + +rolling_update() +{ + # Checks + VALUES_FILE_PATH="./clusters/${kops_name}/values.yaml" + TEMPLATE_FILE_PATH="./template/cluster.yml" + + if [ ! -f ${VALUES_FILE_PATH} ]; then + echo "File does not exist: ${VALUES_FILE_PATH}" + exit 1 + fi + + if [ ! -f ${TEMPLATE_FILE_PATH} ]; then + echo "File does not exist: ${TEMPLATE_FILE_PATH}" + exit 1 + fi + + kops_state_store=s3://$(cat ${VALUES_FILE_PATH} | grep "s3BucketName: " | awk '{print $2}' | tr -d '[:space:]') + export KOPS_STATE_STORE=${kops_state_store} + echo "[INFO] Setting KOPS_STATE_STORE: ${kops_state_store}" + + USE_CLOUD_ONLY_FLAG="" + if [ "${cloudonly}" == "true" ]; then + echo "[INFO] Using --cloudonly flag. This will not drain the nodes first. It will simply terminate the nodes." + USE_CLOUD_ONLY_FLAG="--cloudonly" + fi + + if [ "${dry_run}" == "false" ]; then + echo "[INFO] Not a dry run" + + dns_zone=$(cat ${VALUES_FILE_PATH} | grep "dnsZone: " | awk '{print $2}' | tr -d '[:space:]') + cluster_name=$(cat ${VALUES_FILE_PATH} | grep "kopsName: " | awk '{print $2}' | tr -d '[:space:]').${dns_zone} + echo "[INFO] Rolling cluster named: ${cluster_name}" + + kops --name ${cluster_name} rolling-update cluster --yes ${USE_CLOUD_ONLY_FLAG} + + echo "[INFO] rolling-update cluster:" + kops --name ${cluster_name} rolling-update cluster ${USE_CLOUD_ONLY_FLAG} + + else + echo "[INFO] Dry run" + + dns_zone=$(cat ${VALUES_FILE_PATH} | grep "dnsZone: " | awk '{print $2}' | tr -d '[:space:]') + cluster_name=$(cat ${VALUES_FILE_PATH} | grep "kopsName: " | awk '{print $2}' | tr -d '[:space:]').${dns_zone} + echo "[INFO] Rolling cluster named: ${cluster_name}" + + kops --name ${cluster_name} rolling-update cluster ${USE_CLOUD_ONLY_FLAG} + + echo "[INFO] rolling-update cluster:" + kops --name ${cluster_name} rolling-update cluster ${USE_CLOUD_ONLY_FLAG} + fi + + echo "Finished" +} + +delete() +{ + # Checks + VALUES_FILE_PATH="./clusters/${kops_name}/values.yaml" + TEMPLATE_FILE_PATH="./template/cluster.yml" + + if [ ! -f ${VALUES_FILE_PATH} ]; then + echo "File does not exist: ${VALUES_FILE_PATH}" + exit 1 + fi + + if [ ! -f ${TEMPLATE_FILE_PATH} ]; then + echo "File does not exist: ${TEMPLATE_FILE_PATH}" + exit 1 + fi + + kops_state_store=s3://$(cat ${VALUES_FILE_PATH} | grep "s3BucketName: " | awk '{print $2}' | tr -d '[:space:]') + export KOPS_STATE_STORE=${kops_state_store} + echo "[INFO] Setting KOPS_STATE_STORE: ${kops_state_store}" + + dns_zone=$(cat ${VALUES_FILE_PATH} | grep "dnsZone: " | awk '{print $2}' | tr -d '[:space:]') + cluster_name=$(cat ${VALUES_FILE_PATH} | grep "kopsName: " | awk '{print $2}' | tr -d '[:space:]').${dns_zone} + echo "[INFO] Deleting cluster named: ${cluster_name}" + + if [ "${dry_run}" == "false" ]; then + echo "[INFO] Not a dry run" + + kops --name ${cluster_name} delete cluster --yes + + else + echo "[INFO] Dry run" + kops --name ${cluster_name} delete cluster + fi +} + + +########################################## +##### Main +########################################## + +kops_name="none" +dry_run="true" +create="false" +read="false" +update="false" +delete="false" +rolling_update="false" +cloudonly="false" + +while [ "$1" != "" ]; do + case $1 in + -n | --name ) shift + kops_name=$1 + ;; + -d | --dry-run ) shift + dry_run=$1 + ;; + -c | --create ) shift + create=true + ;; + -r | --read ) shift + read=true + ;; + -u | --update ) shift + update=true + ;; + -ru | --rolling-update ) shift + rolling_update=true + ;; + -co | --cloudonly ) shift + cloudonly=true + ;; + -t | --template ) shift + template=true + ;; + -x | --delete ) shift + delete=true + ;; + -h | --help ) usage + exit + ;; + * ) usage + exit 1 + esac + shift +done + +echo "[INFO] dry_run = ${dry_run}" +echo "[INFO] kops_name = $kops_name" + +check_kops_version + +if [ "${create}" == "true" ]; then + create $kops_name +fi + +if [ "${read}" == "true" ]; then + read $kops_name +fi + +if [ "${update}" == "true" ]; then + update $kops_name +fi + +if [ "${rolling_update}" == "true" ]; then + rolling_update $kops_name +fi + +if [ "${template}" == "true" ]; then + template $kops_name +fi + +if [ "${delete}" == "true" ]; then + delete $kops_name +fi diff --git a/docs/README.md b/docs/README.md index 5b0afcd4e..9f414f8f8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -212,14 +212,14 @@ the file `./clusters/dev-example/values.yaml` in the `s3BucketName` values field Run this command to create the S3 bucket ``` aws s3api create-bucket \ - --bucket kubernetes-ops-2345-kops-state-store \ + --bucket ${KOPS_STATE_STORE} \ --region us-east-1 \ --versioning-configuration Status=Enabled ``` Enable versioning on the bucket: ``` -aws s3api put-bucket-versioning --bucket kubernetes-ops-2345-kops-state-store --versioning-configuration Status=Enabled +aws s3api put-bucket-versioning --bucket ${KOPS_STATE_STORE} --versioning-configuration Status=Enabled ``` Now, export out your AWS keys to the local shell: