From cbf6b6d765958527fdffcd42e799f2a8638ff931 Mon Sep 17 00:00:00 2001 From: Chris Proto Date: Wed, 22 May 2019 15:27:21 -0400 Subject: [PATCH] Adds a set of helpers for GKE setup and microservices installation --- .gitignore | 3 + _helpers/cleanup_microservices.sh | 38 +++++++++ _helpers/gke_boilerplate.sh | 113 +++++++++++++++++++++++++ _helpers/install_microservices.sh | 133 ++++++++++++++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100755 _helpers/cleanup_microservices.sh create mode 100755 _helpers/gke_boilerplate.sh create mode 100755 _helpers/install_microservices.sh diff --git a/.gitignore b/.gitignore index be86a53..3a6d4af 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ terraform.out *.profraw *tfstate* workstation.env +_helpers/hipsterservice.crt +_helpers/hipsterservice.csr +_helpers/hipsterservice.key diff --git a/_helpers/cleanup_microservices.sh b/_helpers/cleanup_microservices.sh new file mode 100755 index 0000000..81c707f --- /dev/null +++ b/_helpers/cleanup_microservices.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Copyright 2019 Google LLC +# +# 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. + +# Fail fast when a command fails or a variable is undefined +set -eu + +echo '' +echo 'Deleting installed Helm charts from this project...' + + +helm delete \ + --kube-context out-of-scope \ + --purge fluentd-custom-target-project || true + +helm delete \ + --kube-context out-of-scope \ + --purge out-of-scope-microservices || true + +helm delete \ + --kube-context in-scope \ + --purge fluentd-filter-dlp || true + +helm delete \ + --kube-context in-scope \ + --purge in-scope-microservices || true + diff --git a/_helpers/gke_boilerplate.sh b/_helpers/gke_boilerplate.sh new file mode 100755 index 0000000..453b094 --- /dev/null +++ b/_helpers/gke_boilerplate.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# Copyright 2019 Google LLC +# +# 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. + +# Fail fast when a command fails or a variable is undefined +set -eu + +# +# Default usage: +# `./_helpers/gke_boilerplate.sh` +# +# Use non-default in-scope/out-of-scope project names: +# `OUT_OF_SCOPE_SUFFIX=foo IN_SCOPE_SUFFIX=baz ./_helpers/gke_boilerplate.sh` +# +out_of_scope_suffix="${OUT_OF_SCOPE_SUFFIX:-out-of-scope}" +in_scope_suffix="${IN_SCOPE_SUFFIX:-in-scope}" +helper_dir="$(dirname "$(realpath "${BASH_SOURCE[0]}" )" )" + +echo '' +echo '+---------------------------------------------------------------+' +echo '| Fetching Cluster credentials and setting contexts for kubectl |' +echo '+---------------------------------------------------------------+' +echo '' +gcloud container clusters get-credentials out-of-scope --zone us-central1-a --project "${TF_VAR_project_prefix:?}-${out_of_scope_suffix}" +if ! kubectl config rename-context "$(kubectl config current-context)" out-of-scope +then + echo 'Error occurred while setting context. Check if there is already a context' + echo 'named "out-of-scope" and delete it with "kubectl config delete-context' + echo 'out-of-scope" before trying again' +fi +gcloud container clusters get-credentials in-scope --zone us-central1-a --project "${TF_VAR_project_prefix:?}-${in_scope_suffix}" +if ! kubectl config rename-context "$(kubectl config current-context)" in-scope +then + echo 'Error occurred while setting context. Check if there is already a context' + echo 'named "in-scope" and delete it with "kubectl config delete-context' + echo 'in-scope" before trying again' +fi + +echo '' +echo '+-------------------------------------------------------+' +echo '| Installing tiller service account on in-scope cluster |' +echo '+-------------------------------------------------------+' +echo '' +kubectl --context in-scope -n kube-system create sa tiller +kubectl --context in-scope \ + -n kube-system \ + create clusterrolebinding tiller \ + --clusterrole cluster-admin \ + --serviceaccount=kube-system:tiller +helm --kube-context in-scope init --history-max 200 --service-account tiller + +echo '' +echo '+-----------------------------------------------------------+' +echo '| Installing tiller service account on out-of-scope cluster |' +echo '+-----------------------------------------------------------+' +echo '' +kubectl --context out-of-scope -n kube-system create sa tiller +kubectl --context out-of-scope \ + -n kube-system \ + create clusterrolebinding tiller \ + --clusterrole cluster-admin \ + --serviceaccount=kube-system:tiller +helm --kube-context out-of-scope init --history-max 200 --service-account tiller + +echo '' +echo '+---------------------------------------------------------+' +echo '| Generating a TLS Secret for Encrypting Internal Traffic |' +echo '+---------------------------------------------------------+' + +# Execute in subshell so we don't mess up directory stack +if ! ( +cd "${helper_dir}" || exit +openssl genrsa -out hipsterservice.key 2048 +openssl req -new -key hipsterservice.key -out hipsterservice.csr \ + -subj "/CN=internal.hipsterstore.net" +openssl x509 -req -days 365 -in hipsterservice.csr -signkey hipsterservice.key \ + -out hipsterservice.crt + +if ! kubectl --context out-of-scope create secret tls tls-hipsterservice \ + --cert hipsterservice.crt --key hipsterservice.key || \ + ! kubectl --context in-scope create secret tls tls-hipsterservice \ + --cert hipsterservice.crt --key hipsterservice.key +then + exit 1 +fi +rm "hipsterservice.crt" +rm "hipsterservice.key" +rm "hipsterservice.csr" + +) +then + echo 'Error setting up TLS secret. Check the _helpers directory to see if the Certificate was generated correctly' + exit 1 +fi + +echo '' +echo '+---------+' +echo '| Success |' +echo '+---------+' +echo '' +echo 'kubectl contexts and tiller installed successfully. To continue run "_helpers/install_microservices.sh"' +echo '' diff --git a/_helpers/install_microservices.sh b/_helpers/install_microservices.sh new file mode 100755 index 0000000..7a1734a --- /dev/null +++ b/_helpers/install_microservices.sh @@ -0,0 +1,133 @@ +#!/bin/bash +# Copyright 2019 Google LLC +# +# 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. + +# Fail fast when a command fails or a variable is undefined +set -eu + +project_prefix="${TF_VAR_project_prefix:?}" +management_suffix="${MANAGEMENT_SUFFIX:-management}" + +helper_dir="$(dirname "$(realpath "${BASH_SOURCE[0]}" )" )" +helm_path="$(realpath "${helper_dir}/../helm/")" +domain_name="${DOMAIN_NAME:-}" + +echo '' +echo '+--------------------------+' +echo '| Installing Microservices |' +echo '+--------------------------+' +echo '' +echo "===================================================" +echo "Helm Path: ${helm_path:?}" +echo "Management Project: ${project_prefix:?}-${management_suffix}" +echo "Deidentification Template: ${DEIDENTIFY_TEMPLATE_NAME:?}" +echo "Fluentd Image Repo: ${FLUENTD_IMAGE_REMOTE_REPO:?}" +echo "Domain Name: ${domain_name}" +echo "===================================================" +echo "" +echo "Continuing in 10 seconds. Ctrl+C to cancel" +sleep 10 + +echo '' +echo '+---------------------+' +echo '| Out Of Scope Charts |' +echo '+---------------------+' +echo '' +echo '(this may take a few minutes)' +echo '' +echo 'Installing fluentd Daemonset...' +echo '' +helm install --wait \ + --kube-context out-of-scope \ + --name fluentd-custom-target-project \ + --namespace kube-system \ + --set project_id="${project_prefix}-${management_suffix}" \ + "${helm_path}/fluentd-custom-target-project" + +echo 'Installing Microservices...' +echo '' + +helm install --wait \ + --kube-context out-of-scope \ + --name out-of-scope-microservices \ + "${helm_path}/out-of-scope-microservices" + +echo '' +echo '+-----------------+' +echo '| In Scope Charts |' +echo '+-----------------+' +echo '' +echo '(this may take a few minutes)' +echo '' +echo 'Installing Fluentd Daemonset...' +echo '' + +helm install --wait \ + --kube-context in-scope \ + --name fluentd-filter-dlp \ + --namespace kube-system \ + --set project_id="${project-prefix}-${management_suffix}" \ + --set deidentify_template_name="${DEIDENTIFY_TEMPLATE_NAME:?}" \ + --set fluentd_image_remote_repo="${FLUENTD_IMAGE_REMOTE_REPO:?}" \ + "${helm_path}/fluentd-filter-dlp" + +echo 'Installing Microservices...' +echo '' + +# Setting `DOMAIN_NAME` environment variable will create a Managed Certificate +# resource. Don't set this variable if you can't manage your domain's DNS +# record. You will need to point the DNS record to your Ingress' external IP. +if [[ "${domain_name}" != "" ]] +then + helm install --wait \ + --kube-context in-scope \ + --name in-scope-microservices \ + --set nginx_listener_1_ip="$(kubectl --context out-of-scope get svc nginx-listener-1 -o jsonpath="{.status.loadBalancer.ingress[*].ip}")" \ + --set nginx_listener_2_ip="$(kubectl --context out-of-scope get svc nginx-listener-2 -o jsonpath="{.status.loadBalancer.ingress[*].ip}")" \ + --set domain_name="${domain_name}" \ + "${helm_path}/in-scope-microservices" +else + helm install --wait \ + --kube-context in-scope \ + --name in-scope-microservices \ + --set nginx_listener_1_ip="$(kubectl --context out-of-scope get svc nginx-listener-1 -o jsonpath="{.status.loadBalancer.ingress[*].ip}")" \ + --set nginx_listener_2_ip="$(kubectl --context out-of-scope get svc nginx-listener-2 -o jsonpath="{.status.loadBalancer.ingress[*].ip}")" \ + "${helm_path}/in-scope-microservices" +fi + +echo '' +echo 'All microservices are installed on your Kubernetes clusters' +echo -n 'Waiting for Loadbalancer to finish setting up...' + +until [[ "$(kubectl --context in-scope get ingress frontend-external-tls -o jsonpath="{.status.loadBalancer.ingress[*].ip}")" != "" ]] +do + sleep 1 + echo -n '.' +done +echo '.' +echo -n 'IP Address is attached. Waiting for service to become healthy...' + +ip="$(kubectl --context in-scope get ingress frontend-external-tls -o jsonpath="{.status.loadBalancer.ingress[*].ip}")" +until [[ "$(curl -s -k -o /dev/null -w '%{http_code}' "https://${ip}/")" == "200" ]] +do + sleep 5 + echo -n '.' +done + +echo '' +echo '+---------+' +echo '| Success |' +echo '+---------+' +echo "You can now visit https://${ip}/" +echo ''