Skip to content

MTO Preparation Guide#

This document provides a detailed walk through of the preparation steps required for MTO installation.

Cluster Requirements#

An AKS cluster with the following components:

  • An Ingress controller
  • Valid certificates for MTO Gateway, MTO Console, and MTO Keycloak

DNS entries configured for MTO Gateway, MTO Console, and MTO Keycloak

A user with cluster administrator privileges.

Local Setup Requirements#

The installation machine must have:

  • Helm installed
  • kubectl installed

Once these preparations are complete, you can proceed with the installation section.

Optional: Creating and Configuring an AKS Cluster#

If you already have an AKS cluster that meets the Cluster Requirements you can skip this section and proceed directly to the Installation Guide.

However, if you don’t have an existing cluster, follow this step-by-step guide to create and configure one properly for MTO installation.

Configure Admin Group#

Execute the following snippet in your terminal with appropriate values. This snippet will configure the Azure CLI. See Register a Microsoft Entra app and create a service principal for more details about access keys

az login --service-principal --username "<SERVICE_PRINCIPAL_APP_ID>" --password "<SERVICE_PRINCIPAL_PASSWORD>" --tenant "<SERVICE_PRINCIPAL_TENANT_ID>"

Create a group called mto-admins:

az ad group create --display-name mto-admins --mail-nickname mto-admins

Fetch the service principal user id

SP_USER_ID=$(az ad sp show --id "$(az account show --query user.name -o tsv)" --query id -o tsv)

Add user to mto-admins group

az ad group member add --group mto-admins --member-id "$SP_USER_ID"

Fetch the admin group id by executing the following command. This value will be used when creating AKS cluster

ADMIN_GROUP_ID=$(az ad group show --group mto-admins --query id -o tsv)

Create AKS Cluster#

Create a resource group using following command

az group create --name "<RESOURCE_GROUP_NAME>" --location westus2

Create AKS cluster

az aks create --resource-group "<RESOURCE_GROUP_NAME>" --name "<CLUSTER_NAME>" \
              --node-count 1 --vm-set-type VirtualMachineScaleSets \
              --enable-cluster-autoscaler --min-count 1 --max-count 3 \
              --enable-aad --aad-admin-group-object-ids "<ADMIN_GROUP_ID>" \
              --generate-ssh-keys

Run the following command to install Azure AKS CLI to install kubectl and other dependencies if they are not installed

az aks install-cli

Set the kubernetes context to the specified cluster.

# Update the current context
az aks get-credentials --resource-group "<RESOURCE_GROUP_NAME>" --name "<CLUSTER_NAME>" --admin

Install Ingress Controller#

To install nginx Ingress Controller, run the following command:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml

Install Certmanager#

To install Cert-Manager, execute the following command:

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.1/cert-manager.yaml

Create Let's Encrypt Access Key Secret#

To configure Let's Encrypt with AWS, create the Kubernetes Secret using the following command:

kubectl create secret generic letsencrypt-production-key \
  --namespace cert-manager \
  --from-literal=aws_secret_access_key=<AWS_SECRET_ACCESS_KEY>

Replace with your actual AWS secret key.

Create ClusterIssuer for Let's Encrypt#

To enable automatic SSL certificate issuance using Let’s Encrypt, you need to create a ClusterIssuer resource in Kubernetes. This issuer will use Route 53 DNS-01 challenge to validate domain ownership and issue certificates.

  1. Create a YAML file named letsencrypt-clusterissuer.yaml for the ClusterIssuer with the following content. Replace the placeholders with your actual values:

    • <AWS_ACCESS_KEY_ID>: Your AWS Access Key ID.
    • <REGION>: The AWS region where your Route 53 hosted zone is located (e.g., us-east-1).
    • <BASE_DOMAIN>: Your base domain (e.g., example.com).
    • <EMAIL>: Your email address for Let's Encrypt notifications.
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-production
    spec:
      acme:
        email: <EMAIL>  # Replace with your email address
        preferredChain: ISRG Root X1
        privateKeySecretRef:
          name: issuer-account-key
        server: 'https://acme-v02.api.letsencrypt.org/directory'
        solvers:
          - dns01:
              route53:
                accessKeyID: <AWS_ACCESS_KEY_ID>  # Replace with your AWS Access Key ID
                region: <REGION>  # Replace with your AWS region
                secretAccessKeySecretRef:
                  key: aws_secret_access_key
                  name: letsencrypt-production-key
            selector:
              dnsZones:
                - <BASE_DOMAIN>  # Replace with your base domain
    
  2. Apply the YAML file to your cluster:

    kubectl apply -f letsencrypt-clusterissuer.yaml
    
  3. Run the following command to ensure the ClusterIssuer is ready:

    kubectl get clusterissuer letsencrypt-production
    

Create Wildcard DNS Record#

To ensure proper routing for applications, you need to create a wildcard DNS record that points to the nginx Ingress Controller’s external IP. Follow these steps:

  1. Retrieve the Ingress Controller's External IP Run the following command to get the external IP of the nginx Ingress Controller:

    kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath="{.status.loadBalancer.ingress[0].ip}"
    

    If the hostname is not available, wait for a few minutes and re-run the command.

  2. Retrieve Hosted Zone and Load Balancer IDs Run the following commands to retrieve the Route 53 Hosted Zone ID and Load Balancer Hosted Zone ID:

    # Retrieve Hosted Zone ID
    HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name --dns-name <BASE_DOMAIN> --query "HostedZones[0].Id" --output text | cut -d '/' -f3)
    
    # Retrieve Hosted Zone Load Balancer ID
    HOSTED_ZONE_LB_ID=$(aws elbv2 describe-load-balancers --query "LoadBalancers[0].CanonicalHostedZoneId" --output text)
    
  3. Create a JSON File for the DNS Update Create a file named change-batch.json and update the placeholders:

    • <FULL_SUBDOMAIN> – Your subdomain (e.g., apps.example.com)
    • <HOSTED_ZONE_LB_ID> – Hosted Zone Load Balancer ID from Step 2
    • <EXTERNAL_IP> – External IP retrieved in Step 1
    {
      "Comment": "Update wildcard DNS record to point to AKS Ingress Controller",
      "Changes": [
        {
          "Action": "UPSERT",
          "ResourceRecordSet": {
            "Name": "*.<FULL_SUBDOMAIN>",
            "Type": "A",
            "TTL": 300,
            "ResourceRecords": [
              {
                "Value": "<EXTERNAL_IP>"
              }
            ]
          }
        }
      ]
    }
    
  4. Update the DNS Record in Route 53 by using the following command

    aws route53 change-resource-record-sets --hosted-zone-id $HOSTED_ZONE_ID --change-batch file://change-batch.json
    
  5. Verify DNS Configuration Check if the DNS record has been propagated correctly:

    nslookup <YOUR_DOMAIN>
    

    Once the record is updated, traffic will be properly routed to the nginx Ingress Controller.

Create Wildcard Certificate#

A wildcard certificate allows all applications under a given subdomain to use a single SSL certificate. MTO will use this certificate to secure the MTO Console, MTO Gateway, and MTO Keycloak.

  1. Apply the Wildcard Certificate Configuration

    Create a file named wildcard-certificate.yaml and replace the placeholders with the appropriate values:

    • <CERTIFICATE_NAME> - Name of the certificate to be generated.
    • <FULL_SUBDOMAIN> - DNS subdomain for which the wildcard certificate will be issued.
    • <NAMESPACE> - Namespace where the certificate and secret will be created. If MTO is installed in a different namespace, manually copy the generated secret.
    • <CERTIFICATE_SECRET_NAME> - Name of the secret that will store the generated certificate. This secret will be used in MTO’s configuration to enable SSL for MTO components.
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: <CERTIFICATE_NAME>
      namespace: <NAMESPACE>
    spec:
      secretName: <CERTIFICATE_SECRET_NAME>
      issuerRef:
        name: letsencrypt-production
        kind: ClusterIssuer
      commonName: "*.<FULL_SUBDOMAIN>"
      dnsNames:
      - "*.<FULL_SUBDOMAIN>"
    
  2. Apply the certificate configuration using the following command:

    kubectl apply -f wildcard-certificate.yaml
    
  3. Verify Certificate Creation

    After applying the configuration, check if the certificate has been issued successfully:

    kubectl wait --for=condition=Ready certificate/<CERTIFICATE_NAME> -n <NAMESPACE> --timeout=300s
    

What's Next?#

All the required components have been installed and configured. Now MTO can be installed on the EKS Cluster. See AKS MTO Installation Guide