|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# http://redsymbol.net/articles/unofficial-bash-strict-mode |
| 4 | +set -euo pipefail |
| 5 | + |
| 6 | +usage() |
| 7 | +{ |
| 8 | + cat <<END |
| 9 | +deploy.sh: deploys the $app_name application to a Kubernetes cluster using Helm. |
| 10 | +Parameters: |
| 11 | + --aks-name <AKS cluster name> |
| 12 | + The name of the AKS cluster. Required when the registry (using the -r parameter) is set to "aks". |
| 13 | + --aks-rg <AKS resource group> |
| 14 | + The resource group for the AKS cluster. Required when the registry (using the -r parameter) is set to "aks". |
| 15 | + -b | --build-solution |
| 16 | + Force a solution build before deployment (default: false). |
| 17 | + -d | --dns <dns or ip address> |
| 18 | + Specifies the external DNS/ IP address of the Kubernetes cluster. |
| 19 | + When --use-local-k8s is specified the external DNS is automatically set to localhost. |
| 20 | + -h | --help |
| 21 | + Displays this help text and exits the script. |
| 22 | + -n | --app-name <the name of the app> |
| 23 | + Specifies the name of the application (default: eshop). |
| 24 | + -p | --docker-password <docker password> |
| 25 | + The Docker password used to logon to the custom registry, supplied using the -r parameter. |
| 26 | + -r | --registry <container registry> |
| 27 | + Specifies the container registry to use (required), e.g. myregistry.azurecr.io. |
| 28 | + --skip-clean |
| 29 | + Do not clean the Kubernetes cluster (default is to clean the cluster). |
| 30 | + --skip-image-build |
| 31 | + Do not build images (default is to build all images). |
| 32 | + --skip-image-push |
| 33 | + Do not upload images to the container registry (just run the Kubernetes deployment portion). |
| 34 | + Default is to push the images to the container registry. |
| 35 | + --skip-infrastructure |
| 36 | + Do not deploy infrastructure resources (like sql-data, no-sql or redis). |
| 37 | + This is useful for production environments where infrastructure is hosted outside the Kubernetes cluster. |
| 38 | + -t | --tag <docker image tag> |
| 39 | + The tag used for the newly created docker images. Default: newly created, date-based timestamp, with 1-minute resolution. |
| 40 | + -u | --docker-user <docker username> |
| 41 | + The Docker username used to logon to the custom registry, supplied using the -r parameter. |
| 42 | + --use-local-k8s |
| 43 | + Deploy to a locally installed Kubernetes (default: false). |
| 44 | +
|
| 45 | +It is assumed that the Kubernetes cluster has been granted access to the container registry. |
| 46 | +If using AKS and ACR see link for more info: |
| 47 | +https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-aks |
| 48 | +
|
| 49 | +WARNING! THE SCRIPT WILL COMPLETELY DESTROY ALL DEPLOYMENTS AND SERVICES VISIBLE |
| 50 | +FROM THE CURRENT CONFIGURATION CONTEXT. |
| 51 | +It is recommended that you create a separate namespace and confguration context |
| 52 | +for the $app_name application, to isolate it from other applications on the cluster. |
| 53 | +For more information see https://kubernetes.io/docs/tasks/administer-cluster/namespaces/ |
| 54 | +You can use namespace.yaml file (in the same directory) to create the namespace. |
| 55 | +
|
| 56 | +END |
| 57 | +} |
| 58 | + |
| 59 | +app_name='eshop' |
| 60 | +aks_name='' |
| 61 | +aks_rg='' |
| 62 | +build_images='yes' |
| 63 | +clean='yes' |
| 64 | +build_solution='' |
| 65 | +container_registry='' |
| 66 | +docker_password='' |
| 67 | +docker_username='' |
| 68 | +dns='' |
| 69 | +image_tag=$(date '+%Y%m%d%H%M') |
| 70 | +push_images='yes' |
| 71 | +skip_infrastructure='' |
| 72 | +use_local_k8s='' |
| 73 | + |
| 74 | +while [[ $# -gt 0 ]]; do |
| 75 | + case "$1" in |
| 76 | + --aks-name ) |
| 77 | + aks_name="$2"; shift 2;; |
| 78 | + --aks-rg ) |
| 79 | + aks_rg="$2"; shift 2;; |
| 80 | + -b | --build-solution ) |
| 81 | + build_solution='yes'; shift ;; |
| 82 | + -d | --dns ) |
| 83 | + dns="$2"; shift 2;; |
| 84 | + -h | --help ) |
| 85 | + usage; exit 1 ;; |
| 86 | + -n | --app-name ) |
| 87 | + app_name="$2"; shift 2;; |
| 88 | + -p | --docker-password ) |
| 89 | + docker_password="$2"; shift;; |
| 90 | + -r | --registry ) |
| 91 | + container_registry="$2"; shift 2;; |
| 92 | + --skip-clean ) |
| 93 | + clean=''; shift ;; |
| 94 | + --skip-image-build ) |
| 95 | + build_images=''; shift ;; |
| 96 | + --skip-image-push ) |
| 97 | + push_images=''; shift ;; |
| 98 | + --skip-infrastructure ) |
| 99 | + skip_infrastructure='yes'; shift ;; |
| 100 | + -t | --tag ) |
| 101 | + image_tag="$2"; shift 2;; |
| 102 | + -u | --docker-username ) |
| 103 | + docker_username="$2"; shift 2;; |
| 104 | + --use-local-k8s ) |
| 105 | + use_local_k8s='yes'; shift ;; |
| 106 | + *) |
| 107 | + echo "Unknown option $1" |
| 108 | + usage; exit 2 ;; |
| 109 | + esac |
| 110 | +done |
| 111 | + |
| 112 | +if [[ $build_solution ]]; then |
| 113 | + echo "#################### Building $app_name solution ####################" |
| 114 | + dotnet publish -o obj/Docker/publish ../../eShopOnContainers-ServicesAndWebApps.sln |
| 115 | +fi |
| 116 | + |
| 117 | +export TAG=$image_tag |
| 118 | + |
| 119 | +if [[ $build_images ]]; then |
| 120 | + echo "#################### Building the $app_name Docker images ####################" |
| 121 | + docker-compose -p ../.. -f ../../docker-compose.yml build |
| 122 | + |
| 123 | + # Remove temporary images |
| 124 | + docker rmi $(docker images -qf "dangling=true") |
| 125 | +fi |
| 126 | + |
| 127 | +if [[ $push_images ]]; then |
| 128 | + echo "#################### Pushing images to the container registry ####################" |
| 129 | + services=(basket.api catalog.api identity.api ordering.api marketing.api payment.api locations.api webmvc webspa webstatus) |
| 130 | + |
| 131 | + for service in "${services[@]}" |
| 132 | + do |
| 133 | + echo "Pushing image for service $service..." |
| 134 | + docker tag "eshop/$service:$image_tag" "$container_registry/$service:$image_tag" |
| 135 | + docker push "$container_registry/$service:$image_tag" |
| 136 | + done |
| 137 | +fi |
| 138 | + |
| 139 | +ingress_values_file="ingress_values.yaml" |
| 140 | + |
| 141 | +if [[ $use_local_k8s ]]; then |
| 142 | + ingress_values_file="ingress_values_dockerk8s.yaml" |
| 143 | + dns="localhost" |
| 144 | +fi |
| 145 | + |
| 146 | +if [[ $dns == "aks" ]]; then |
| 147 | + echo "#################### Begin AKS discovery based on the --dns aks setting. ####################" |
| 148 | + if [[ -z $aks_name ]] || [[ -z $aks_rg ]]; then |
| 149 | + echo "Error: When using -dns aks, MUST set -aksName and -aksRg too." |
| 150 | + echo '' |
| 151 | + usage |
| 152 | + exit 1 |
| 153 | + fi |
| 154 | + |
| 155 | + echo "Getting DNS of AKS of AKS $aks_name (in resource group $aks_rg)" |
| 156 | + dns="$(az aks show -n $aks_name -g $aks_rg --query addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName)" |
| 157 | + if [[ -z dns ]]; then |
| 158 | + echo "Error: when getting DNS of AKS $aks_name (in resource group $aks_rg). Please ensure AKS has httpRouting enabled AND Azure CLI is logged in and is of version 2.0.37 or higher." |
| 159 | + exit 1 |
| 160 | + fi |
| 161 | + $dns=${dns//[\"]/""} |
| 162 | + echo "DNS base found is $dns. Will use $aks_name.$dns for the app!" |
| 163 | +fi |
| 164 | + |
| 165 | +# Initialization & check commands |
| 166 | +if [[ -z $dns ]]; then |
| 167 | + echo "No DNS specified. Ingress resources will be bound to public IP." |
| 168 | +fi |
| 169 | + |
| 170 | +if [[ $clean ]]; then |
| 171 | + echo "Cleaning previous helm releases..." |
| 172 | + helm delete --purge $(helm ls -q) |
| 173 | + echo "Previous releases deleted" |
| 174 | +fi |
| 175 | + |
| 176 | +use_custom_registry='' |
| 177 | + |
| 178 | +if [[ -n $container_registry ]]; then |
| 179 | + use_custom_registry='yes' |
| 180 | + if [[ -z $docker_user ]] || [[ -z $docker_password ]]; then |
| 181 | + echo "Error: Must use -u (--docker-username) AND -p (--docker-password) if specifying custom registry" |
| 182 | + exit 1 |
| 183 | + fi |
| 184 | +fi |
| 185 | + |
| 186 | +echo "#################### Begin $app_name installation using Helm ####################" |
| 187 | +infras=(sql-data nosql-data rabbitmq keystore-data basket-data) |
| 188 | +charts=(eshop-common apigwmm apigwms apigwwm apigwws basket-api catalog-api identity-api locations-api marketing-api mobileshoppingagg ordering-api ordering-backgroundtasks ordering-signalrhub payment-api webmvc webshoppingagg webspa webstatus webhooks-api webhooks-web) |
| 189 | + |
| 190 | +if [[ !$skip_infrastructure ]]; then |
| 191 | + for infra in "${infras[@]}" |
| 192 | + do |
| 193 | + echo "Installing infrastructure: $infra" |
| 194 | + helm install --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --name="$app_name-$infra" $infra |
| 195 | + done |
| 196 | +fi |
| 197 | + |
| 198 | +for chart in "${charts[@]}" |
| 199 | +do |
| 200 | + echo "Installing: $chart" |
| 201 | + if [[ $use_custom_registry ]]; then |
| 202 | + helm install --set inf.registry.server=$container_registry --set inf.registry.login=$docker_username --set inf.registry.pwd=$docker_password --set inf.registry.secretName=eshop-docker-scret --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always --name="$app_name-$chart" $chart |
| 203 | + elif [[ $chart != "eshop-common" ]]; then # eshop-common is ignored when no secret must be deployed |
| 204 | + helm install --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always --name="$app_name-$chart" $chart |
| 205 | + fi |
| 206 | +done |
| 207 | + |
| 208 | +echo "FINISHED: Helm charts installed." |
0 commit comments