This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Azure Deployment

This document describes the deployment of the required Atolio services into your Azure subscription. It is intended to be followed in linear order, skipping any steps not relevant to the particular deployment.

    Architecture

    arch-azure

    Deployment Prerequisites

    Before getting started, Atolio needs to have done the following on your behalf:

    1. Add your Deployment Engineer as a collaborator to the Atolio terraform-lumen GitHub repository, which contains the Terraform used to grant Atolio support access to your Azure subscription
    2. Add your Deployment Engineer as a collaborator to the Atolio GitHub repository (lumen-infra), which contains:
      • Deployment documentation
      • Terraform for the Atolio stack infrastructure
      • Configuration files for Atolio services
      • Maintenance scripts
    3. Provide image pull credentials for the Atolio Client Container Registry (for pulling Atolio container images)

    The following deployment prerequisites will help streamline your deployment process.

    Determine Azure Subscription

    You can choose to deploy Atolio into a new or an existing Azure subscription. We recommend a dedicated subscription, as this keeps your Atolio deployment and its permissions separate from your other resources. Atolio will deploy into a new Azure Resource Group (RG), with another RG created automatically by Azure Kubernetes Service (AKS) for the cluster. When the subscription is available, share the subscription ID and your Azure tenant ID with your Atolio support team.

    We recommend:

    • Ensuring that Service Quotas within your Azure subscription allow for a minimum of 64 vCPU under the Total Regional vCPUs quota. See Hardware Requirements for the full list of recommended quotas.
    • Raising any other organizational Azure policies / restrictions (e.g. networking, containers, storage account key access) with your Atolio support team ahead of the deployment call.

    Determine Deployment Model

    We offer both Atolio managed and customer managed deployment models for you to choose from. Please review the comparison and requirements for each approach on our Deployment Model Overview page and inform your Atolio support team which method you’d like to use for your deployment.

    Grant Atolio Support Access

    Atolio’s deployment support team needs scoped access to your Azure subscription in order to deploy and support the Atolio stack. This access is granted with Azure Lighthouse, using a standalone Terraform configuration in the terraform-lumen repository. Atolio engineers sign in as themselves, in Atolio’s own tenant, from a restricted support machine; no application registration, service principal, or client secret is created in your tenant, and you can review or remove the delegation at any time.

    Run this step before the deployment call, regardless of whether you have chosen the Atolio managed or customer managed deployment model. It must be run by someone who can assign roles in the subscription (e.g. Owner, or User Access Administrator and Contributor).

    1. Clone the terraform-lumen repository:

      git clone git@github.com:atolio/terraform-lumen.git
      
    2. Sign in to your Azure tenant and select the subscription Atolio will deploy into:

      az login --tenant your-tenant-id
      az account set --subscription your-subscription-id
      
    3. Create a terraform.tfvars file in the support-only directory describing your subscription and deployment:

      cd terraform-lumen/examples/azure/support-only
      
      deployment_name = "acmecorp"
      customer_name   = "Acme Corp"
      region          = "westus3"
      

      Use the same deployment_name you intend to use for the rest of the deployment (the --name passed to create-infra.sh). Typically this is your company name, with an optional suffix if you’re specifying an environment (e.g. acmecorp or acmecorp-qa). Use the Azure region you intend to deploy Atolio into for region.

    4. Apply the configuration. Terraform picks up terraform.tfvars automatically, and deploys into the subscription selected above:

      terraform init
      terraform apply
      

      Terraform will display everything it creates in the plan output before you approve the apply.

    5. Provide the resulting outputs to your Atolio support team:

      terraform output
      
      atolio_support_subscription_id                   = "your-subscription-id"
      atolio_support_lighthouse_definition_id          = "/subscriptions/your-subscription-id/providers/Microsoft.ManagedServices/registrationDefinitions/..."
      atolio_support_contributor_role_id               = "00000000-0000-0000-0000-000000000000"
      atolio_support_user_access_administrator_role_id = "00000000-0000-0000-0000-000000000000"
      atolio_support_role_assigner_identity_id         = "/subscriptions/your-subscription-id/resourceGroups/acmecorp-atolio-support/providers/Microsoft.ManagedIdentity/userAssignedIdentities/acmecorp-atolio-role-assigner"
      atolio_support_subscription_tags                 = { ... }
      atolio_support_customer_deployment_name          = "acmecorp"
      atolio_support_customer_deployment_region        = "westus3"
      

      The deployment name and region are the values Atolio will use when deploying the stack with create-infra.sh.

    What Atolio Is Granted

    Azure Lighthouse only accepts Azure built-in roles, so the delegation is made up of the following:

    • Contributor on the subscription, for day-to-day deployment and support operations.
    • User Access Administrator, restricted to assigning only Contributor, Reader, Network Contributor, AcrPull and DNS Zone Contributor, and only to managed identities in your subscription. The deployment uses this to give its AKS, ingress and workload identities the roles they need. It cannot be used to grant Owner, to grant anything broader than Contributor, or to grant access to users or groups.

    Azure Lighthouse cannot delegate roles that grant access to data (roles with DataActions), but Atolio’s services need Storage Blob Data Contributor and Storage Blob Data Reader on their storage containers. The configuration therefore also creates a managed identity, {deployment-name}-atolio-role-assigner, in a new {deployment-name}-atolio-support resource group. It holds Role Based Access Control Administrator on the subscription with a condition that only allows it to assign or remove those two Storage Blob Data roles, and only to managed identities. During the deployment it creates the per-container storage role assignments for Atolio’s services.

    The configuration also tags the subscription with atolio:* tags (customer, deployment and so on) so Atolio can identify it.

    Reviewing or Removing Access

    The delegation is listed in the Azure portal under Service providers → Delegations. To remove Atolio’s access, run terraform destroy from the same support-only directory, or remove the delegation from the portal.

    Determine Atolio DNS Name

    Before the deployment call, you may want to decide on your desired Atolio web address. An Azure DNS Zone will be created in the Azure subscription used for hosting the Atolio stack (e.g. search.example.com.): this will be the DNS name (without the trailing dot) for the Atolio web application (e.g. https://search.example.com).

    This DNS zone allows the deployment control plane (i.e. the External DNS controller) to add records to link host names (e.g. search.example.com, feed.search.example.com and relay.search.example.com) to the Ingress controller used for the deployment. If your DNS is managed in Cloudflare instead, records can be managed there; let your Atolio support team know.

    For the remainder of this document, we will use https://search.example.com in the examples, but it is expected for you to replace with your own DNS name.

    Determine Cloud Networking Options

    By default, Atolio’s Terraform code will create a VNet in your Azure subscription. However, you may choose to use an existing VNet and subnets within your Azure subscription. In this case, set create_vnet to false in the config.hcl file during the deployment, and configure all three VNet IDs. See this example from config.hcl:

    # Uncomment these lines and update the values in case you want to deploy in a
    # pre-existing VNet (by default a new VNet will be created). All three IDs are
    # required when create_vnet is false.
    # create_vnet            = false
    # vnet_id                = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Network/virtualNetworks/{vnetName}"
    # vnet_private_subnet_id = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Network/virtualNetworks/{vnetName}/subnets/{privateSubnetName}"
    # vnet_public_subnet_id  = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Network/virtualNetworks/{vnetName}/subnets/{publicSubnetName}"
    

    Optionally, when create_vnet is not set to false you can customize the default VNet and subnet CIDR blocks if you have specific requirements. See this example from config.hcl:

    # Uncomment these lines and update the values to customize the CIDR blocks of the
    # VNet and subnets created automatically (ignored when create_vnet = false)
    # vnet_cidr                 = "10.42.0.0/20"
    # vnet_private_subnet_block = "10.42.0.0/22" # AKS pod subnet
    # vnet_public_subnet_block  = "10.42.4.0/24" # Application Gateway subnet
    

    AKS uses Azure CNI, so every pod takes an IP address from the pod subnet; keep it at least a /22.

    If custom networking configuration will be necessary be sure to provide these details to the engineer performing the deployment.

    Setup Authentication

    Atolio supports single sign-on (SSO) authentication through Okta, Microsoft Entra ID, and Google using the OpenID Connect (OIDC) protocol.

    Refer to Configuring Authentication for more details on the steps to complete in your desired SSO provider in order to obtain the necessary OIDC configuration values.

    If using Microsoft Entra ID, the OIDC client ID and client secret will be the respective values created and saved during Azure AD - Create New App Registration.

    Setup Local Environment

    Finally, if an engineer from your team will be performing the deployment, ensure they have the following utilities installed:

    Note: If you are running on Windows, you may also need to install the Windows Subsystem for Linux.

    Provide Deployment Engineer with Configuration

    At this point if you’re proceeding with an Atolio managed deployment you’ll need to provide the information from these prerequisite steps to your Atolio deployment support team. Otherwise please ensure the information is provided to the engineer from your organization who will be performing the deployment with Atolio’s support.

    To recap, provide these details:

    If you’re opting to have Atolio manage the deployment you can disregard the remainder of this documentation as these steps will be performed by your Atolio deployment engineer. Otherwise be sure to share this documentation with the engineer from your organization that will be performing the deployment so they can familiarize themselves with the steps required.

    Create Cloud Infrastructure

    Note: Atolio requires an Azure region with 3 availability zones. You can check which regions include support for multiple availability zones here.

    The Terraform configuration requires an Azure storage account to store state. A script is available to automate the whole process (including running Terraform). Before running the script, create a config.hcl file based on the provided config.hcl.template:

    cd deploy/terraform/azure
    cp ./config.hcl.template config.hcl
    

    Atolio Domain Name and Image Pull Secrets

    Update the copied file with appropriate values. At a minimum, it should look something like this:

    # Domain name for Atolio stack (same as hosted zone name without trailing ".")
    lumen_domain_name = "search.example.com"
    
    # The registry from which to pull container images for services
    container_registry  = "atolioimages.azurecr.io"
    image_pull_username = "provided-by-atolio"
    image_pull_password = "provided-by-atolio"
    

    Your Atolio support team will share the appropriate values for the image_pull_username and image_pull_password values.

    (Optional) Lite Mode

    For proofs of concept, demos and development environments, Atolio can run on 2 AKS node pools instead of the 6 used in production: one for Lumen and embedding services, and one for Vespa and Tika. Each defaults to a single Standard_D8ps_v6 (8 vCPU, 32 GB) node, with an optional GPU embedder. Lite mode is meant for small-to-moderate document volumes where high availability isn’t needed, and it doesn’t replace the production layout at scale.

    To enable it, set lite_mode = true in config.hcl. The LITE MODE section of config.hcl.template lists the optional sizing settings.

    Application Helm Value Options

    Next copy the Helm template and update the values as directed.

    cp ./templates/values-lumen-admin.yaml values-lumen.yaml
    cp ./templates/values-vespa-admin.yaml values-vespa.yaml
    
    # Default values for lumen.
    # This is a YAML-formatted file.
    # Declare variables to be passed into your templates (provided by admin user).
    
    # JWT secret key for API call (signature) verification (at least 256 bits / 32 chars)
    # Can be generated by running `openssl rand -base64 32` in your terminal
    jwtSecretKey: "add-your-jwt-secret-key-here"
    
    # Secret salts for generating Vespa document IDs
    # Can be generated by running `openssl rand -base64 32` in your terminal
    secretSalts: "add-your-secret-salts-here"
    
    # Secret salt keying log redaction, so redacted log values cannot be recovered
    # by hashing candidates. Generate with `openssl rand -base64 32`
    logRedactionSalt: "add-your-log-redaction-salt-here"
    
    # See also scripts/config-oidc.sh helper script to obtain some of the values below
    oidc:
      provider: "add-your-provider-here"
      endpoint: "add-your-endpoint-here"
      clientId: "add-your-id-here"
      clientSecret: "add-your-secret-here"
    
    # Use the Atolio provided image pull secrets for accessing Atolio container images
    imagePullSecret:
      create: true
    
    # If running behind a reverse proxy, this should be set to the URL the end user will
    # use to access the product.
    reverseProxyUrl: ""
    
    # The ACME Cluster Issuer for LetsEncrypt requires an email address to be provided
    # for certificate notifications. This is required for LetsEncrypt certificates to work properly.
    letsencrypt:
      email: "letsencrypt@example.com"
      dns01:
        azureDNS:
          environment: AzurePublicCloud
    

    For the jwtSecretKey, secretSalts and logRedactionSalt values any 256 bit (32 character) string can be used. These values are used to sign JWT tokens used by the web application and atolioctl tool, salt document IDs in Atolio’s database, and key the redaction of sensitive strings in logs. They should be well guarded secrets that are unique to the deployment.

    Without logRedactionSalt the redacted fields in logs are replaced with a placeholder rather than a hash, because an unsalted hash of a low entropy value such as an email address can be reversed by hashing candidate values.

    If your users will be accessing the web interface via a reverse proxy (e.g. such as StrongDM), then be sure to set the reverseProxyUrl field to reflect the URL they will actually enter into their browser to access Atolio, which will be different to the hostname defined in lumen_domain_name. Leave this field empty if not using a reverse proxy.

    The ACME Cluster Issuer for LetsEncrypt requires an email address to be provided for certificate notifications. If the default @example.com email address is used, then the Cluster Issuer will fail to register for certificate management so be sure to provide a valid email address.

    Deployment with create-infra.sh Script

    Once you have all variables configured, sign in to Azure and select the subscription to deploy into. From the deploy/terraform/azure directory:

    az account set --subscription your-subscription-id
    ./scripts/create-infra.sh --name=acmecorp
    

    This will create the infrastructure in the westus3 Azure region. If you want to deploy in another region (e.g. eastus) an additional parameter can be provided:

    ./scripts/create-infra.sh --name=acmecorp --region=eastus
    

    The --name argument is used to define a deployment name for collecting resources into an Azure Resource Group containing the Kubernetes cluster, networking, storage, etc. It must match the deployment_name used when granting Atolio support access. Typically this is set to your company name with an optional suffix if specifying environment (e.g. acmecorp or acmecorp-qa).

    The script automates the following steps (parameterized based on the provided deployment name):

    1. Create a resource group, and an Azure storage account to store Terraform state
    2. Create a terraform.tfvars file for Terraform based on the config.hcl file
    3. Run terraform init
    4. Run terraform apply (using input variables in generated terraform.tfvars)

    Before making any changes, the script shows the subscription, tenant and account it will deploy with, and whether it is running through Azure Lighthouse, and asks for confirmation.

    Deploying Directly or Through Azure Lighthouse

    The same script is used whether the deployment is run by your own team or by Atolio, and it detects which applies from the current az sign-in:

    • Customer managed: an engineer signed in to your own tenant, with Owner (or User Access Administrator and Contributor) on the subscription, runs the script. All role assignments are made directly.
    • Atolio managed: an Atolio engineer signed in to Atolio’s tenant runs the script through the Azure Lighthouse delegation. Role assignments for Atolio’s services are made within the limits of the delegation, and the Storage Blob Data role assignments are made by the role assigner identity created when granting Atolio support access.

    The first run records the subscription, your tenant and, for an Atolio managed deployment, Atolio’s tenant in settings.sh. Later runs of create-infra.sh and destroy-infra.sh stop if the current sign-in doesn’t match, so a deployment can’t accidentally be pointed at a different subscription or switched between the two models. To make such a change intentionally, pass --force.

    Post-Deployment Steps

    With the infrastructure created, you’ll want to update your local kubeconfig with a context for the Atolio cluster (this is also output via Terraform as update_kubeconfig_command):

    az aks get-credentials --name lumen-{deployment-name} --resource-group lumen-{deployment-name}
    

    Delegate Responsibility for Atolio Subdomain

    The parent domain (e.g. example.com) needs to delegate traffic to the new Atolio subdomain (search.example.com). This is achieved by adding an NS record to the parent domain with the 4 name servers copied from the new subdomain.

    These nameservers can be retrieved post-creation with terraform output:

    terraform output --json name_servers | jq -r '.[]'
    

    Deployment Verification

    At this point you should be able to interact with the Kubernetes cluster and see Atolio pods deployed, e.g.

    kubectl get po -n atolio-svc
    

    Note, Atolio specific services run on the following namespaces:

    • atolio-svc (Application Services)
    • atolio-db (Database)
    • atolio-ctl (Control Plane)

    When you have validated that the infrastructure is available, the next step is to configure sources.