You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
8.3 KiB

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