From 7684278f8bc436020c9eecf0b88cba717004c02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mil=C3=A1n=20Figueredo?= Date: Tue, 9 Jul 2019 17:49:53 +0200 Subject: [PATCH 1/5] Fixed --docker-password parameter handling and a typo in --docker-username at usage() --- k8s/helm/deploy-all.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/k8s/helm/deploy-all.sh b/k8s/helm/deploy-all.sh index 705b172f5..cea7289e1 100755 --- a/k8s/helm/deploy-all.sh +++ b/k8s/helm/deploy-all.sh @@ -37,7 +37,7 @@ Parameters: This is useful for production environments where infrastructure is hosted outside the Kubernetes cluster. -t | --tag The tag used for the newly created docker images. Default: newly created, date-based timestamp, with 1-minute resolution. - -u | --docker-user + -u | --docker-username The Docker username used to logon to the custom registry, supplied using the -r parameter. --use-local-k8s Deploy to a locally installed Kubernetes (default: false). @@ -86,7 +86,7 @@ while [[ $# -gt 0 ]]; do -n | --app-name ) app_name="$2"; shift 2;; -p | --docker-password ) - docker_password="$2"; shift;; + docker_password="$2"; shift 2;; -r | --registry ) container_registry="$2"; shift 2;; --skip-clean ) From 00bf2470ce64fd43235e99247a33b6791f92410a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mil=C3=A1n=20Figueredo?= Date: Wed, 10 Jul 2019 07:35:44 +0200 Subject: [PATCH 2/5] Several improvement and fixes: image_tag check for linux- prefix, login procedure for custom registry, --docker-username normalization and --dns aks option documented at usage() --- k8s/helm/deploy-all.sh | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/k8s/helm/deploy-all.sh b/k8s/helm/deploy-all.sh index cea7289e1..f5e932fe9 100755 --- a/k8s/helm/deploy-all.sh +++ b/k8s/helm/deploy-all.sh @@ -14,8 +14,9 @@ Parameters: The resource group for the AKS cluster. Required when the registry (using the -r parameter) is set to "aks". -b | --build-solution Force a solution build before deployment (default: false). - -d | --dns - Specifies the external DNS/ IP address of the Kubernetes cluster. + -d | --dns | --dns aks + Specifies the external DNS/ IP address of the Kubernetes cluster. + If 'aks' is set as value, the DNS value is retrieved from the AKS. --aks-name and --aks-rg are needed. When --use-local-k8s is specified the external DNS is automatically set to localhost. -h | --help Displays this help text and exits the script. @@ -37,7 +38,7 @@ Parameters: This is useful for production environments where infrastructure is hosted outside the Kubernetes cluster. -t | --tag The tag used for the newly created docker images. Default: newly created, date-based timestamp, with 1-minute resolution. - -u | --docker-username + -u | --docker-user The Docker username used to logon to the custom registry, supplied using the -r parameter. --use-local-k8s Deploy to a locally installed Kubernetes (default: false). @@ -124,6 +125,19 @@ if [[ $build_images ]]; then docker rmi $(docker images -qf "dangling=true") fi +use_custom_registry='' + +if [[ -n $container_registry ]]; then + echo "################ Log into custom registry $container_registry ##################" + use_custom_registry='yes' + if [[ -z $docker_username ]] || [[ -z $docker_password ]]; then + echo "Error: Must use -u (--docker-username) AND -p (--docker-password) if specifying custom registry" + exit 1 + fi + docker login -u $docker_username -p $docker_password $container_registry +fi + + if [[ $push_images ]]; then echo "#################### Pushing images to the container registry ####################" services=(basket.api catalog.api identity.api ordering.api marketing.api payment.api locations.api webmvc webspa webstatus) @@ -131,6 +145,9 @@ if [[ $push_images ]]; then for service in "${services[@]}" do echo "Pushing image for service $service..." + if [[ -z "$(docker image ls -q --filter=reference=eshop/$service:$image_tag)" ]]; then + image_tag=linux-$image_tag + fi docker tag "eshop/$service:$image_tag" "$container_registry/$service:$image_tag" docker push "$container_registry/$service:$image_tag" done @@ -173,16 +190,6 @@ if [[ $clean ]]; then echo "Previous releases deleted" fi -use_custom_registry='' - -if [[ -n $container_registry ]]; then - use_custom_registry='yes' - if [[ -z $docker_user ]] || [[ -z $docker_password ]]; then - echo "Error: Must use -u (--docker-username) AND -p (--docker-password) if specifying custom registry" - exit 1 - fi -fi - echo "#################### Begin $app_name installation using Helm ####################" infras=(sql-data nosql-data rabbitmq keystore-data basket-data) 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) From d026eb44a4aa5b2b4325dee6cedf7b4de95148df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mil=C3=A1n=20Figueredo?= Date: Wed, 10 Jul 2019 13:29:25 +0200 Subject: [PATCH 3/5] Restored --docker-username reference in usage() lost in the last commit --- k8s/helm/deploy-all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/helm/deploy-all.sh b/k8s/helm/deploy-all.sh index f5e932fe9..d64a13fb0 100755 --- a/k8s/helm/deploy-all.sh +++ b/k8s/helm/deploy-all.sh @@ -38,7 +38,7 @@ Parameters: This is useful for production environments where infrastructure is hosted outside the Kubernetes cluster. -t | --tag The tag used for the newly created docker images. Default: newly created, date-based timestamp, with 1-minute resolution. - -u | --docker-user + -u | --docker-username The Docker username used to logon to the custom registry, supplied using the -r parameter. --use-local-k8s Deploy to a locally installed Kubernetes (default: false). From 93c86fc33eeee4104fa773ea62107d415340efbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mil=C3=A1n=20Figueredo?= Date: Thu, 11 Jul 2019 18:30:34 +0200 Subject: [PATCH 4/5] Default namespace, fixed AKS DNS and Ingress Several fixes in this commit: * Added 'namespace' argument, default to 'eshop'. * Every Helm command (`helm install` and `helm ls` used with `helm delete`) will honor the namespace parameter. This way this script is no longer destructive with the Kubernetes cluster. Usage() has been updated accordingly. * Custom registry image push didn't honor `--docker-username` and `--docker-password`. A `docker login` has been added to fix the situation. * AKS DNS discovery was not working properly due to case sensitivity with the JMESPath to the HTTPApplicationRouteZoneName. A small two-entries array with iterative loop has been added ton ensure either way the AKS http routing DNS retrieval is successful. * Helm charts were enabled to use Kubernetes Ingress, but the `Ingress.spec.rules.host[]` was not honored with the `$dns` variable. This has been fixed in the `helm install` commands and now the script deploys the Ingress as expected. --- k8s/helm/deploy-all.sh | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/k8s/helm/deploy-all.sh b/k8s/helm/deploy-all.sh index d64a13fb0..602d1ea0d 100755 --- a/k8s/helm/deploy-all.sh +++ b/k8s/helm/deploy-all.sh @@ -42,17 +42,18 @@ Parameters: The Docker username used to logon to the custom registry, supplied using the -r parameter. --use-local-k8s Deploy to a locally installed Kubernetes (default: false). + --namespace + Specifies the namespace name to deploy the app. If it doesn't exists it will be created (default: eshop). It is assumed that the Kubernetes cluster has been granted access to the container registry. If using AKS and ACR see link for more info: https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-aks WARNING! THE SCRIPT WILL COMPLETELY DESTROY ALL DEPLOYMENTS AND SERVICES VISIBLE -FROM THE CURRENT CONFIGURATION CONTEXT. -It is recommended that you create a separate namespace and confguration context -for the $app_name application, to isolate it from other applications on the cluster. +FROM THE CURRENT CONFIGURATION CONTEXT AND NAMESPACE. +It is recommended that you check your selected namespace, 'eshop' by default, is already in use. +Every deployment and service done in the namespace will be deleted. For more information see https://kubernetes.io/docs/tasks/administer-cluster/namespaces/ -You can use namespace.yaml file (in the same directory) to create the namespace. END } @@ -71,6 +72,7 @@ image_tag=$(date '+%Y%m%d%H%M') push_images='yes' skip_infrastructure='' use_local_k8s='' +namespace='eshop' while [[ $# -gt 0 ]]; do case "$1" in @@ -104,6 +106,8 @@ while [[ $# -gt 0 ]]; do docker_username="$2"; shift 2;; --use-local-k8s ) use_local_k8s='yes'; shift ;; + --namespace ) + namespace="$2"; shift 2;; *) echo "Unknown option $1" usage; exit 2 ;; @@ -169,13 +173,19 @@ if [[ $dns == "aks" ]]; then exit 1 fi - echo "Getting DNS of AKS of AKS $aks_name (in resource group $aks_rg)" - dns="$(az aks show -n $aks_name -g $aks_rg --query addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName)" - if [[ -z dns ]]; then + echo "Getting AKS cluster $aks_name AKS (in resource group $aks_rg)" + # JMESPath queries are case sensitive and httpapplicationrouting can be lowercase sometimes + jmespath_dnsqueries=(addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName \ + addonProfiles.httpapplicationrouting.config.HTTPApplicationRoutingZoneName) + for q in "${jmespath_dnsqueries[@]}" + do + dns="$(az aks show -n $aks_name -g $aks_rg --query $q -o tsv)" + if [[ -n $dns ]]; then break; fi + done + if [[ -z $dns ]]; then 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." exit 1 fi - $dns=${dns//[\"]/""} echo "DNS base found is $dns. Will use $aks_name.$dns for the app!" fi @@ -186,8 +196,12 @@ fi if [[ $clean ]]; then echo "Cleaning previous helm releases..." - helm delete --purge $(helm ls -q) - echo "Previous releases deleted" + if [[ -z $(helm ls -q --namespace $namespace) ]]; then + echo "No previous releases found" + else + helm delete --purge $(helm ls -q --namespace $namespace) + echo "Previous releases deleted" + fi fi echo "#################### Begin $app_name installation using Helm ####################" @@ -198,7 +212,7 @@ if [[ !$skip_infrastructure ]]; then for infra in "${infras[@]}" do echo "Installing infrastructure: $infra" - 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 + helm install --namespace $namespace --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 done fi @@ -206,9 +220,9 @@ for chart in "${charts[@]}" do echo "Installing: $chart" if [[ $use_custom_registry ]]; then - 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 + helm install --namespace $namespace --set ingress.hosts[0]=$dns --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 elif [[ $chart != "eshop-common" ]]; then # eshop-common is ignored when no secret must be deployed - 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 + helm install --namespace $namespace --set ingress.hosts[0]=$dns --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 fi done From 186b2eb534fff1eb02b1e6d3e6b140b77f908cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mil=C3=A1n=20Figueredo?= Date: Fri, 12 Jul 2019 11:34:51 +0200 Subject: [PATCH 5/5] Aligned with PowerShell version deploy-all.ps1 --- k8s/helm/deploy-all.sh | 53 ++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/k8s/helm/deploy-all.sh b/k8s/helm/deploy-all.sh index 602d1ea0d..6f6d868aa 100755 --- a/k8s/helm/deploy-all.sh +++ b/k8s/helm/deploy-all.sh @@ -20,30 +20,29 @@ Parameters: When --use-local-k8s is specified the external DNS is automatically set to localhost. -h | --help Displays this help text and exits the script. + --image-build + Build images (default is to not build all images). + --image-push + Upload images to the container registry (default is not pushing to the custom registry) -n | --app-name Specifies the name of the application (default: eshop). + --namespace + Specifies the namespace name to deploy the app. If it doesn't exists it will be created (default: eshop). -p | --docker-password The Docker password used to logon to the custom registry, supplied using the -r parameter. -r | --registry Specifies the container registry to use (required), e.g. myregistry.azurecr.io. --skip-clean Do not clean the Kubernetes cluster (default is to clean the cluster). - --skip-image-build - Do not build images (default is to build all images). - --skip-image-push - Do not upload images to the container registry (just run the Kubernetes deployment portion). - Default is to push the images to the container registry. --skip-infrastructure Do not deploy infrastructure resources (like sql-data, no-sql or redis). This is useful for production environments where infrastructure is hosted outside the Kubernetes cluster. -t | --tag - The tag used for the newly created docker images. Default: newly created, date-based timestamp, with 1-minute resolution. + The tag used for the newly created docker images. Default: latest. -u | --docker-username The Docker username used to logon to the custom registry, supplied using the -r parameter. --use-local-k8s Deploy to a locally installed Kubernetes (default: false). - --namespace - Specifies the namespace name to deploy the app. If it doesn't exists it will be created (default: eshop). It is assumed that the Kubernetes cluster has been granted access to the container registry. If using AKS and ACR see link for more info: @@ -61,15 +60,15 @@ END app_name='eshop' aks_name='' aks_rg='' -build_images='yes' +build_images='' clean='yes' build_solution='' container_registry='' docker_password='' docker_username='' dns='' -image_tag=$(date '+%Y%m%d%H%M') -push_images='yes' +image_tag='latest' +push_images='' skip_infrastructure='' use_local_k8s='' namespace='eshop' @@ -94,10 +93,10 @@ while [[ $# -gt 0 ]]; do container_registry="$2"; shift 2;; --skip-clean ) clean=''; shift ;; - --skip-image-build ) - build_images=''; shift ;; - --skip-image-push ) - push_images=''; shift ;; + --image-build ) + build_images='yes'; shift ;; + --image-push ) + push_images='yes'; shift ;; --skip-infrastructure ) skip_infrastructure='yes'; shift ;; -t | --tag ) @@ -141,17 +140,17 @@ if [[ -n $container_registry ]]; then docker login -u $docker_username -p $docker_password $container_registry fi - if [[ $push_images ]]; then echo "#################### Pushing images to the container registry ####################" services=(basket.api catalog.api identity.api ordering.api marketing.api payment.api locations.api webmvc webspa webstatus) + if [[ -z "$(docker image ls -q --filter=reference=eshop/$service:$image_tag)" ]]; then + image_tag=linux-$image_tag + fi + for service in "${services[@]}" do echo "Pushing image for service $service..." - if [[ -z "$(docker image ls -q --filter=reference=eshop/$service:$image_tag)" ]]; then - image_tag=linux-$image_tag - fi docker tag "eshop/$service:$image_tag" "$container_registry/$service:$image_tag" docker push "$container_registry/$service:$image_tag" done @@ -175,8 +174,10 @@ if [[ $dns == "aks" ]]; then echo "Getting AKS cluster $aks_name AKS (in resource group $aks_rg)" # JMESPath queries are case sensitive and httpapplicationrouting can be lowercase sometimes - jmespath_dnsqueries=(addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName \ - addonProfiles.httpapplicationrouting.config.HTTPApplicationRoutingZoneName) + jmespath_dnsqueries=(\ + addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName \ + addonProfiles.httpapplicationrouting.config.HTTPApplicationRoutingZoneName \ + ) for q in "${jmespath_dnsqueries[@]}" do dns="$(az aks show -n $aks_name -g $aks_rg --query $q -o tsv)" @@ -187,6 +188,7 @@ if [[ $dns == "aks" ]]; then exit 1 fi echo "DNS base found is $dns. Will use $aks_name.$dns for the app!" + dns="$aks_name.$dns" fi # Initialization & check commands @@ -199,8 +201,9 @@ if [[ $clean ]]; then if [[ -z $(helm ls -q --namespace $namespace) ]]; then echo "No previous releases found" else - helm delete --purge $(helm ls -q --namespace $namespace) + helm delete --purge $(helm ls -q --namespace $namespace) echo "Previous releases deleted" + waitsecs=10; while [ $waitsecs -gt 0 ]; do echo -ne "$waitsecs\033[0K\r"; sleep 1; : $((waitsecs--)); done fi fi @@ -212,7 +215,7 @@ if [[ !$skip_infrastructure ]]; then for infra in "${infras[@]}" do echo "Installing infrastructure: $infra" - helm install --namespace $namespace --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 + helm install --namespace $namespace --set "ingress.hosts={$dns}" --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 done fi @@ -220,9 +223,9 @@ for chart in "${charts[@]}" do echo "Installing: $chart" if [[ $use_custom_registry ]]; then - helm install --namespace $namespace --set ingress.hosts[0]=$dns --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 + helm install --namespace $namespace --set "ingress.hosts={$dns}" --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 elif [[ $chart != "eshop-common" ]]; then # eshop-common is ignored when no secret must be deployed - helm install --namespace $namespace --set ingress.hosts[0]=$dns --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 + helm install --namespace $namespace --set "ingress.hosts={$dns}" --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 fi done