Skip to content
On this page

Mappia on Azure

This guide will walk you through installing Mappia from scratch onto Azure.

Prerequisites

Setup

This Terraform module needs two things to start its installation:

Azure Resource group

Create a Resource Group and grab its name.

bash
RESOURCE_GROUP="demoResourceGroup"
az group create --name $RESOURCE_GROUP --location eastus2

Service principal

The service principal is an Azure identity created for use with applications, hosted services, and automated tools to access Azure resources. The following command will create a service principal with the necessary permissions on the Resource Group:

bash
SERVICE_PRINCIPAL_NAME="myServicePrincipalName"
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
SERVICE_PRINCIPAL=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME \
                         --role owner \
                         --scopes /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP)

The service principal that we just created expires in exactly 1 year from creation. Please remember to rotate the client secret before that time!

Resource Providers

For security reasons Azure limits what kinds of resources you can create by default. As a result, you will also need to set your subscription up with certain resource provider registrations.

bash
az provider register --namespace Microsoft.KeyVault --wait
az provider register --namespace Microsoft.ContainerService --wait
az provider register --namespace Microsoft.ContainerRegistry --wait
az provider register --namespace Microsoft.Network --wait
az provider register --namespace Microsoft.Compute --wait
az provider register --namespace Microsoft.Insights --wait
az provider register --namespace Microsoft.Storage --wait

Using terraform

To use this terraform module set the variables safely in the environment and then create the main.tf file:

bash
mkdir -p my-terraform-project
touch \
  my-terraform-project/main.tf \
  my-terraform-project/variables.tf \
  my-terraform-project/outputs.tf

In your main.tf, add the following content:

hcl
module "my-terraform-project" {
<<<<<<< Updated upstream
  source  = "graycore/mappia-azure/graycore"
  version = "0.3.8-alpha.2" # x-release-please-version
=======
  source  = "graycoreio/mappia-azure/graycore"
  version = "0.3.8-alpha.2" # x-release-please-version
>>>>>>> Stashed changes

  resource_group_name = "demoResourceGroup"
  location            = "eastus2"
  sp_id               = var.mappia_sp_id
  sp_object_id        = var.mappia_sp_object_id
  sp_secret           = var.mappia_sp_password
  subscription_id     = var.mappia_subscription_id
  sp_tenant_id        = var.mappia_sp_tenant_id
  helm_user           = var.mappia_helm_user
  helm_pwd            = var.mappia_helm_pwd
}

Next, let's add a few outputs to the outputs.tf that we will likely want to access once we finish creating our resources.

hcl
output "acr_admin_pwd" {
  value = module.my-terraform-project.acr_admin_pwd
  sensitive = true
}

output "acr_admin_user" {
  value = module.my-terraform-project.acr_admin_user
  sensitive = true
}

output "acr_name" {
  value = module.my-terraform-project.acr_name
}

output "ip_address" {
  value = module.my-terraform-project.ip_address
}

output "full_qualified_domain_name" {
  value = module.my-terraform-project.full_qualified_domain_name
}

output "aks_name" {
  value = module.my-terraform-project.aks_name
}

output "kube_config_raw" {
  value     = module.my-terraform-project.kube_config_raw
  sensitive = true
}

Now, let's set the appropriate variables for your terraform projects. You can set these via environment variables as below. You can also use a .tfvars file.

bash
export TF_VAR_mappia_sp_id="$(echo $SERVICE_PRINCIPAL | jq -r .appId)"
export TF_VAR_mappia_sp_tenant_id="$(echo $SERVICE_PRINCIPAL | jq -r .tenant)"
export TF_VAR_mappia_sp_password="$(echo $SERVICE_PRINCIPAL | jq -r .password)"
export TF_VAR_mappia_sp_object_id="$(az ad sp show --id $TF_VAR_mappia_sp_id --query id -o tsv)"
export TF_VAR_mappia_subscription_id="$(az account show --query id -o tsv)"

Also, add the helm variables:

bash
export TF_VAR_mappia_helm_user="YOUR_HELM_USER"
export TF_VAR_mappia_helm_pwd="YOUR_HELM_PWD"

Finally, let's add the following content to our variables.tf:

hcl
variable "mappia_sp_id" {
  type        = string
  description = "Service principal client Id"
}

variable "mappia_sp_object_id" {
  type        = string
  description = "Service principal object Id"
}

variable "mappia_sp_password" {
  type        = string
  description = "Service principal client secret"
}

variable "mappia_subscription_id" {
  type        = string
  description = "Azure subscription id"
}

variable "mappia_sp_tenant_id" {
  type        = string
  description = "Service principal tenant id"
}

variable "mappia_helm_user" {
  type        = string
  description = "Helm mappia user name provided by graycore"
}

variable "mappia_helm_pwd" {
  type        = string
  description = "Helm mappia password (token) provided by graycore"
}

Now, we can init within my-terraform-project

bash
cd my-terraform-project
terraform init

After initialization, we can now run terraform plan.

bash
terraform plan

You should take a moment to review the output to get a feeling for the resources terraform is creating under the hood.

After you review (and are comfortable with) what we are about to create, you can run terraform apply.

bash
terraform apply

At this point, grab a cup of coffee. This will take about 10 minutes!

Once this has completed, you now have a working Mappia cluster on Azure. You can access the Kubernetes, by running the following commands:

bash
AKS_NAME=$(terraform output -raw aks_name)
az aks get-credentials --resource-group $RESOURCE_GROUP --name $AKS_NAME
kubectl get pods
helm get notes mappia

You will be able to get the URL of your Magento 2 store by:

terraform output full_qualified_domain_name

Known Isues

"The VM size of Standard_B2s is not allowed in your subscription in location 'westus2'."

This happens when the VM size you're trying to use is not available in the region you've selected.

To change the VM size, select one from Azure's list for your region and override the default_node_pool at your mappia module.

hcl
  default_node_pool =  {
    name              = "agentpool"
    max_count         = 5
    min_count         = 4
    vm_size           = "Standard_B2s"
    set_max_map_count = true
  }

"BadRequest: Failed to perform resource identity operation."

We're not sure of the root cause of this error when creating a new AKS, but setting the aks_name variable to another value can solve this issue

Terraform plan kubernetes error

Changing some configuration for AKS can lead to the terraform plan error Kubernetes cluster unreachable: invalid configuration: no configuration has been provided, try setting KUBERNETES_MASTER environment variable. This happens because terraform assumes the cluster configurations will change and it doesn't know its future credentials. In reality, most of the times this credentials will not change (they only do when recreating AKS).

As a temporary solution you can set the helm provider to use a local kube config that has the configurations you need. Open the .terraform/modules/mappia-azure/providers.tf and TEMPORARILY alter the helm provider's kubernetes block to look like this.

hcl
  kubernetes {
    config_path = "./mappia-aks-config"
  }

To fetch the mappia aks config run:

sh
terraform output -json kube_config_raw | jq -r > mappia-aks-config

Provider produced inconsistent result after apply

sh
Provider produced inconsistent result after apply

This is a somewhat rare error that can happen after quickly re-applying a Terraform installation shortly after a destroy.

Azure might take some time to actually delete its resources so its likely best to destroy and then wait a few minutes before attempting another application.

Could not download chart

sh
module.my-terraform-project.module.mappia.helm_release.mappia: Creating...

 Error: could not download chart: failed to download "oci://mappia.azurecr.io/helm/mappia"
 
   with module.my-terraform-project.module.mappia.helm_release.mappia,
   on .terraform/mappia/main.tf line 2, in resource "helm_release" "mappia":
    2: resource "helm_release" "mappia" {
 

This error message might be caused by incorrect access level permissions on your Mappia access token. Try reaching out to Mappia support to fix this. In the meantime you can set the helm_mappia_chart_version in your module declaration:

hcl
module "my-terraform-project" {
  source  = "graycoreio/mappia-azure/graycore"
  version = "0.3.8-alpha.2" # x-release-please-version

  helm_mappia_chart_version = "0.2.0"
}

Error on destroying the keyvault

On early versions of this module it is possible to see an error like this:

keyvault.VaultsClient#PurgeDeleted: Failure sending request: StatusCode=403 -- Original Error: Code="AuthorizationFailed" Message="The client '00000000-0000-0000-0000-00000000' with object id '00000000-0000-0000-0000-00000000' does not have authorization to perform action 'Microsoft.KeyVault/locations/deletedVaults/purge/action' over scope '/subscriptions/00000000-0000-0000-0000-00000000' or the scope is invalid. If access was recently granted, please refresh your credentials.

This happens because terraform is trying to purge the keyvault but the service principal it is using does not have authorization to do so. Your keyvault has been soft-deleted, so you can run terraform destroy again and it should delete the rest.

To prevent this error from happening you can either:

  • Update your terraform module version
  • Give the service principal subscription Contributor level or create a custom role with Microsoft.KeyVault/locations/deletedVaults/purge/action for it.

Could not acquire access token to parse claims

Planning failed. Terraform encountered an error while generating this plan.


│ Error: building account: could not acquire access token to parse claims: clientCredentialsToken: received HTTP status 401 with response: {"error":"invalid_client","error_description":"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'YOUR_APP_ID'.\r\nTrace ID: TRACE_NUMBER\r\nCorrelation ID: CORRELATION_NUMBER\r\nTimestamp: 2023-06-09 00:30:33Z","error_codes":[7000215],"timestamp":"2023-06-09 00:30:33Z","trace_id":"TRACE_NUMBER","correlation_id":"CORRELATION_NUMBER","error_uri":"https://login.microsoftonline.com/error?code=7000215"}

│   with module.my-terraform-module.provider["registry.terraform.io/hashicorp/azurerm"],
│   on graycore/mappia/packages/terraform/azure/providers.tf line 1, in provider "azurerm":
│    1: provider "azurerm" {

Sometimes, when attempting to apply a plan immediately after resetting your service principal's password, you will get the above error. Simply wait a few moments and try again.