Microsoft Azure¶
In Juju, Microsoft Azure is a machine cloud and works as described below.
Note
This reference assumes basic familiarity with Juju. If you are new to Juju, start with the Tutorial, then use this page together with the generic materials it links to and/or consult the example workflows.
Requirements¶
Juju needs the Azure API permissions listed below to create and manage the Azure resources used during cloud registration and bootstrap:
Microsoft.Compute/skus(read).Microsoft.Resources/subscriptions/resourceGroups(read, write, delete).Microsoft.Resources/deployments/*(write, read, delete, cancel, validate).Microsoft.Network/networkSecurityGroups(write, read, delete, join).Microsoft.Network/virtualNetworks/*(write, read, delete).Microsoft.Compute/virtualMachineScaleSets/*(write, read, delete, start, deallocate, restart, powerOff).Microsoft.Network/virtualNetworks/subnets/*(read, write, delete, join).Microsoft.Compute/availabilitySets(write, read, delete).Microsoft.Network/publicIPAddresses(write, read, delete, join) – optional for public-facing services.Microsoft.Network/networkInterfaces(write, read, delete, join).Microsoft.Compute/virtualMachines(write, read, delete, start, powerOff, restart, deallocate).Microsoft.Compute/disks(write, read, delete).
Concepts¶
The following table shows how Azure’s native abstractions map to Juju concepts:
Azure |
Juju |
|---|---|
model (roughly) |
|
Process or container within a VM |
|
Collection of VMs running the same workload |
|
Network space (roughly) |
The cloud¶
See also: Cloud, Juju | Manage clouds, Terraform Provider for Juju | Manage clouds
As for all machine clouds, the cloud is registered in Juju via a cloud definition, stored in clouds.yaml on the client (on Linux: ~/.local/share/juju/clouds.yaml) and following this schema:
clouds:
<cloud-name>: # Predefined name
type: azure
auth-types:
- <auth-type> # See Authentication types below
regions:
<region-name>: # e.g. eastus
endpoint: <endpoint> # Region-specific Azure API endpoint
config: # Optional: model config defaults
<config-key>: <value> # See Configuration keys below
Credentials¶
See also: Credential, Juju | Manage credentials, Terraform Provider for Juju | Manage credentials
As for all machine clouds, credentials are stored in credentials.yaml on the client and follow this schema:
credentials:
azure # Predefined cloud name for Azure
<credential-name>: # User-defined credential name
auth-type: <auth-type> # managed-identity | interactive | service-principal-secret (see Authentication types)
<attribute>: <value> # Auth-type-specific attributes (see below)
Authentication types¶
Microsoft Azure supports the following authentication types:
managed-identity¶
Requirements:
Juju 3.6+
Managed identity created in Azure.
Same subscription for managed identity and Juju resources.
Credential addition must occur from Azure Cloud Shell or Azure-hosted jump host (for cloud metadata endpoint access).
Behavior: Controller uses managed identity for Azure API operations without storing credential secrets.
interactive¶
Browser-based OAuth flow. If using unconfined juju snap with Azure CLI logged in, subscription ID can be auto-filled.
Note: Optional fields application-name and role-definition-name must have unique values if specified.
Version note: Starting with Juju 3.6, can be combined with managed identity via instance-role constraint during bootstrap.
service-principal-secret¶
Requires application ID, subscription ID, and client secret.
Version note: Starting with Juju 3.6, can be combined with managed identity via instance-role constraint during bootstrap.
Known issues¶
Credentials occasionally stop working over time. Refresh using credential update or re-add credential.
Controllers¶
See also: Controller, Juju | Manage controllers, Terraform Provider for Juju | Manage controllers
Bootstrap behavior¶
Creates controller and initial model on Azure.
Resources created at bootstrap¶
The controller runs on an Azure VM provisioned using the same mechanisms as workload machines – see Resources created per machine for the full per-machine resource model. Controller-specific differences are noted below.
Compute
Resource group: Contains all resources for the model. Auto-generated name or user-specified via
resource-group-nameconfig.Controller virtual machine: Ubuntu LTS. Size configurable via
instance-typeconstraint.
Networking
Virtual network: Named
juju-internal-networkwith192.168.0.0/16address space. User-configurable vianetworkconfig.Subnets:
Controller subnet (
192.168.16.0/20) for controller machines.Internal subnet (
192.168.0.0/20) for application machines.
Network security group: Named
juju-internal-nsg. Rules: SSH (port 22) to all machines, Juju API (port 17070) to controller subnet.
Models¶
See also: Model, Juju | Manage models, Terraform Provider for Juju | Manage models
Configuration keys¶
Microsoft Azure supports the following cloud-specific model configuration keys:
Networking
load-balancer-sku-name: Mirrors the LoadBalancerSkuName type in the Azure SDK. Type:string. Default:"Standard". Mandatory.
resource-group-name: If set, use the specified resource group for all model resources instead of creating one based on the model UUID. Type:string. Default: none. Immutable.
network: If set, use the specified virtual network for all model machines instead of creating one. Type:string. Default: none. Immutable.
Machines¶
See also: Machine, Juju | Manage machines, Terraform Provider for Juju | Manage machines
Constraints¶
Microsoft Azure supports the following constraints:
Note
The constraints instance-type and [arch, cores, mem] are mutually exclusive.
Compute
arch. Valid values:
amd64.instance-role. Juju 3.6+. Valid values:
autoor managed identity name in format<resource-group>/<identity-name>or<subscription>/<resource-group>/<identity-name>.instance-type. See Azure VM sizes documentation.
Networking
Storage
root-disk. Minimum 30 GiB.
root-disk-source. Specifies storage pool for root disk. Enables encryption configuration.
Placement directives¶
Microsoft Azure supports the following placement directives:
Resources created per machine¶
Applies to all machines, including controller machines. Controller-specific defaults are documented in Resources created at bootstrap.
Compute
Virtual machine: Type configurable via
instance-typeconstraint.
Networking
Network interface: Connected to appropriate subnet (controller or internal) with dynamically-allocated private IP address.
Public IP address: Static IPv4 address created by default. Disable via
allocate-public-ipconstraint.
Storage
OS disk: 30 GiB minimum,
StandardSSD_LRStype by default. Size and type configurable viaroot-diskandroot-disk-sourceconstraints.Additional storage: Created when requested via storage specifications.
Resource tags: All resources tagged with juju-model (model UUID), juju-controller (controller UUID), juju-machine-name (machine identifier).
Networking behavior¶
Spaces: Azure supports multiple network devices. Supplying multiple space constraints or endpoint bindings will provision machines with NICs in subnets representing the union of specified spaces.
IP addressing: Private IPs allocated dynamically via DHCP. Public IPs use static allocation.
Subnet placement: Controller machines →
192.168.16.0/20; application machines →192.168.0.0/20.NSG rules: SSH (port 22) accessible on all machines. Juju API (port 17070) accessible on controller subnet only.
Storage behavior¶
See also: azure for the Azure storage provider configuration options.
OS disk:
StandardSSD_LRSby default, minimum 30 GiB. Configurable viaroot-diskandroot-disk-sourceconstraints.Additional disks: Created via storage constraints using the configured storage pool.
Storage¶
See also: Storage, Juju | Manage storage
Storage providers¶
In addition to generic storage providers, Microsoft Azure provides the following cloud-specific storage providers:
azure¶
Type: Azure Managed Disks
Configuration options:
account-type: Disk type.Standard_LRS: Standard HDD (associated with poolazure)Premium_LRS: Premium SSD (associated with poolazure-premium)
See more: Azure Managed Disks Overview
Appendix: Example workflows¶
Authenticate with managed identity (recommended)¶
Requirements:
Juju 3.6+.
A managed identity. See more: Appendix: How to create a managed identity
The managed identity and the Juju resources must be created on the same subscription.
The
add-credentialsteps must be run from either the Azure Cloud Shell or a jump host running in Azure in order to allow the cloud metadata endpoint to be reached.
Run
juju add-credential azure; choosemanaged-identity; supply the requested information (themanaged-identity-pathmust be of the form<resourcegroup>/<identityname>).Bootstrap as usual.
Tip
With this workflow where you provide the managed identity during add-credential you avoid the need for either your Juju client or your Juju controller to store your credential secrets. Relatedly, the user running add-credential / bootstrap doesn’t need to have any credential secrets supplied to them.
Authenticate with service principal secret and managed identity¶
Requirements:
Juju 3.6+.
A managed identity. See more: Appendix: How to create a managed identity
Add a service-principal-secret:
interactive= “service-principal-via-browser” (recommended):If you have the
azureCLI and you are logged in and you want to use the currently logged in user: Run/snap/juju/current/bin/juju add-credential azure; chooseinteractive, then leave the subscription ID field empty – Juju will fill this in for you.Otherwise: Run
juju add-credential azure, chooseinteractive, then provide the subscription ID – Juju will open up a browser and you’ll be prompted to log in to Azure.
service-principal-secret: Runjuju add-credential azure, then chooseservice-principal-secretand supply all the requested information.
During bootstrap, provide the managed identity to the controller by using the
instance-roleconstraint.
Tip
With this workflow where you provide the managed identity during bootstrap you avoid the need for your Juju controller to store your credential secrets. Relatedly, the user running / bootstrap doesn’t need to have any credential secrets supplied to them.
Authenticate with service principal secret only (dispreferred)¶
Add a service-principal-secret:
interactive= “service-principal-via-browser” (recommended):If you have the
azureCLI and you are logged in and you want to use the currently logged in user: Run/snap/juju/current/bin/juju add-credential azure; chooseinteractive, then leave the subscription ID field empty – Juju will fill this in for you.Otherwise: Run
juju add-credential azure, chooseinteractive, then provide the subscription ID – Juju will open up a browser and you’ll be prompted to log in to Azure.
service-principal-secret: Runjuju add-credential azure, then chooseservice-principal-secretand supply all the requested information.
Bootstrap as usual.
Appendix: How to create a managed identity¶
Caution
This is just an example. For more information please see the upstream cloud documentation. See more: Microsoft Azure | Managed identities .
To create a managed identity for Juju to use, you will need to use the Azure CLI and be logged in to your account. This is a set up step that can be done ahead of time by an administrator.
The 4 values below need to be filled in according to your requirements.
$ export group=someresourcegroup
$ export location=someregion
$ export role=myrolename
$ export identityname=myidentity
$ export subscription=mysubscription_id
The role definition and role assignment can be scoped to either the subscription or a particular resource group. If scoped to a resource group, this group needs to be provided to Juju when bootstrapping so that the controller resources are also created in that group.
For a subscription scoped managed identity:
$ az group create --name "${group}" --location "${location}"
$ az identity create --resource-group "${group}" --name "${identityname}"
$ mid=$(az identity show --resource-group "${group}" --name "${identityname}" --query principalId --output tsv)
$ az role definition create --role-definition "{
\"Name\": \"${role}\",
\"Description\": \"Role definition for a Juju controller\",
\"Actions\": [
\"Microsoft.Compute/*\",
\"Microsoft.KeyVault/*\",
\"Microsoft.Network/*\",
\"Microsoft.Resources/*\",
\"Microsoft.Storage/*\",
\"Microsoft.ManagedIdentity/userAssignedIdentities/*\"
],
\"AssignableScopes\": [
\"/subscriptions/${subscription}\"
]
}"
$ az role assignment create --assignee-object-id "${mid}" --assignee-principal-type "ServicePrincipal" --role "${role}" --scope "/subscriptions/${subscription}"
A resource scoped managed identity is similar except:
the role definition assignable scopes becomes
\"AssignableScopes\": [
\"/subscriptions/${subscription}/resourcegroups/${group}\"
]
the role assignment scope becomes
--scope "/subscriptions/${subscription}/resourcegroups/${group}"