Juju 2.9 - new Azure features (disk encryption, BYO vnets, public IP constraint...)

The upcoming Juju 2.9 release brings some new Azure capabilities. These landed in the early release candidates and have had some successful field testing so it’s time to announce them to a wider audience.

In summary, the new features include:

  • bring your own resource group
  • bring your own virtual network
  • space aware / multi-NIC instances
  • constraint to allow instances to be provisioned without a public IP address
  • full disk encryption on instance volumes

BYO Resource Group

By default, Juju will create a new resource group for each model, to hold the artifacts for that model.
Sometimes, permissions will be such that the user does not have rights to create new resource groups, but they can use existing groups. Juju models can be configured to use such pre-existing resource groups using the resource-group model config, eg

juju add-model test --config resource-group=myresgroup

It’s also possible to bootstrap using an existing resource group for the controller model, eg

juju bootstrap azure --config resource-group=myresgroup --no-default-model

Note that the --no-default-model option is required to ensure Juju does not create an additional “default” model in a new resource group as would normally occur.

Note: When destroying a controller containing models with BYO resource groups, those resource groups will need to be cleaned up manually since there’s a limitation in how Juju tears down a controller, preventing those groups from being cleaned up up automatically.

BYO virtual network

It’s possible to use an existing virtual network when provisioning instances. Say there’s an existing resource group containing a virtual network

|- test-rg
  |- test-vn
    |- juju-controller-subnet
    |- subnet2

The network model config attribute can be used to specify this network be used instead of Juju creating a new one:

juju add-model --config network=test-rg/test-vn

Depending on spaces setup (see below), the machine can be provisioned with NICs on each subnet.

If the specified virtual network has a security group already, Juju will use that, otherwise it will create a new one called juju-internal-nsg.

Placement also works, eg to choose one of the subnets in the vnet:

juju deploy mysql --to subnet=subnet2

Note: For bootstrap, if space constraints are not used to specify a particular subnet, Juju will prefer a subnet called juju-controller-subnet to use for the controller’s primary NIC. If a so named subnet does not exist, Juju will choose one at random, or else error. A simple option for specifying a particular non-default subnet to use (if spaces are not set up) is to use placement:

juju bootstrap azure --config network=test-rg/test-vn --to subnet=subnet2

You must also ensure that the subnet has a security group which is configured to allow incoming traffic to the following ports:
- 22 (for bootstrap to use ssh to provision the instance)
- 17070 (to allow Juju clients and agents to connect to the controller API server)

Spaces support

The Azure provider now supports network spaces.

juju subnets will show the subnets Juju knows about for a given model.

Assuming the example from above, add a space in one of the subnets:

juju add-space foo

and now add a machine in that space:

juju add-machine --constraints="space=foo"

This will create a machine and use “subnet1” for the network
configuration of the primary NIC machine-X-primary. If no space is specified, Juju will default to using a subnet called juju-internal-network in the configured vnet.

You can create another space:

juju add-space bar

and create a machine in both spaces:

juju add-machine --constraints="spaces=foo,bar"

A machine gets created with 2 NICs, machine-X-primary and machine-X-interface-1.
Each NIC is bound to the subnet of each space.

If you do this instead (ie a space with multiple subnets):

juju add-space foobar
juju add-machine --constraints=“spaces=foobar”

Then the machine only gets one NIC and one of the subnets is chosen at random.

Public IP address constraint

A new constraint value is available: allocate-public-ip.
It defaults to true and specifies whether instances get a public IP address or not.
The constraint is supported across all relevant providers, not just Azure (AWS, GCE, Openstack etc).
juju add-machine --constraints="allocate-public-ip=false"

Full disk encryption

When provisioning an Azure instance, it is now possible to ask for root disk encryption using a disk encryption set and a key vault.

You can either use your own disk encryption set or have Juju create a key vault and disk encryption set. Right now, the key size and algorithm is not user configurable. It’s RSA and 4096 bits.

The provisioning is configured using a Juju storage pool.
The configurable parameters are:

- encrypted (must be true for Juju to act on it)
- disk-encryption-set-name (defaults to vault name prefix)
- vault-name-prefix
- vault-key-name (defaults to "disk-secret")
- vault-user-id

If just the disk encryption set name is configured, Juju will use that existing disk encryption set and not create any additional resources. It can reside in a different resource group by specifying resgroup_name/DES_name

If a vault name prefix is also configured, Juju will create a vault called vault_name_prefix-resource_group_name. Vault names need to be unique across a subscription.

If vault-user-id is configured, that user will be given full access to manage the vault and keys created by Juju.

To add an instance with disk encryption, first create a storage pool and then use the root-disk-source constraint when adding the Juju machine, eg

juju create-storage-pool byo azure encrypted=true disk-encryption-set-name="mydisksecrets"
juju add-machine --constraints="root-disk-source=byo"


juju create-storage-pool des azure encrypted=true vault-name-prefix=mysecrets vault-user-id=27f86c31-bca0-4a37-b233-0e5030107696
juju add-machine --constraints="root-disk-source=des"


If you want the controller to also use disk encryption, the storage pool will need to be created at bootstrap time, eg

juju bootstrap azure \
  --no-default-model \
  --storage-pool name=foo \
  --storage-pool type=azure \
  --storage-pool encrypted=true \
  --storage-pool vault-name-prefix=secret \

The same arg handling as is used for --config is used here; either a YAML file or multiple cmd args can be used with --storage-pool.