See also: Model
Contents:
- Add a model
- View all the models available on a controller
- Switch to a different model
- View the status of a model
- View details about a model
- Configure a model
- Manage constraints for a model
- Restrict commands on a model
- Compare and export the contents of a model to a bundle
- Upgrade a model
- Migrate a workload model to another controller
- Destroy a model
Add a model
If you have multiple credentials: Be careful which one you use for the new model. Any machines subsequently on the model will be associated with this credential. As such, make sure you’re not spending resources for the wrong cloud account!
To add a model to the current controller using the default credential and switch to this model, run the add-model
command followed by the name of the model. For example:
juju add-model mymodel
You can also pass various options to choose a different controller or credential, specify a configuration, designate a different model owner
, not switch to the newly create model, add it to a particular cloud (for multi-cloud controllers), etc.
See more:
juju add-model
To add a model on the controller specified in the juju
provider definition, in your Terraform plan create a resource of the juju_model
type, specifying, at the very least, a name. For example:
resource "juju_model" "testmodel" {
name = "machinetest"
}
In the case of a multi-cloud controller, you can specify which cloud you want the model to be associated with by defining a cloud
block. To specify a model configuration, include a config
block.
See more:
juju_model
(resource)
To add a model, on a connected controller, call the add_model
function. For example, below we’re adding a model called test-model
on the controller
:
await controller.add_model("test-model")
See more:
Controller.add_model()
,juju_model
(module),juju_controller
(module)
View all the models available on a controller
To get a list of all the models in the current controller, use the models
command:
juju models
The current model will be denoted with an asterisk.
Expand to see a sample output
Controller: localhost-localhost
Model Cloud/Region Type Status Machines Units Access Last connection
controller localhost/localhost lxd available 1 1 admin 1 minute ago
prod* localhost/localhost lxd available 0 - admin never connected
test localhost/localhost lxd available 0 - admin 2 minutes ago
By passing various options you can filter by controller, get a time stamp, output to a specific format, etc.
See more:
juju models
The terraform juju
client does not support this. Please use the juju
client.
To view all the models available on a controller, call the Controller.list_models()
function:
await controller.list_models()
See more:
Controller.list_models()
,
Switch to a different model
Identify the current model. To identify the current model, run the switch
command with no arguments:
juju switch
This will show the current controller, user, and model in a <controller>:<user>/<model>
format.
Expand to see a sample output
localhost-localhost:admin/test
You can also identify the current model by running juju models
– your current model is the model with an asterisk!
Switch to a different model. To change from the current model to a different model, use the switch
command followed by the target model name in a <controller>:<user>/<model>
format:
juju switch <controller>:<admin>/<model>
The command also allows you to specify the target controller in an abbreviated form by omitting one or more of the components.
See more:
juju switch
For important operations we recommend you specify the model in the unambiguous form shown above.
The terraform juju
client does not support this. Please use the juju
client.
In python-libjuju
, switching to a different model means simply connecting to the model you want to work with, which is done by calling connect
on the Model object:
from juju.model import Model
model = Model()
await model.connect() # will connect to the "current" model
await model.connect(model_name="test-model") # will connect to the model named "test-model"
Note that if the model
object is already connected to a model, then that connection will be closed before making the new connection.
See more:
Model.connect()
View the status of a model
To see the status of a model and everything inside of it, run the status
command:
juju status
Expand to see a sample output
Model Controller Cloud/Region Version SLA Timestamp
test localhost-localhost localhost/localhost 3.1.0 unsupported 16:07:52+01:00
Model "admin/test" is empty.
By passing various options you can also specify a model, see the output in color formatting or with additional sections for relations or storage, watch the status for a given duration, etc.
See more:
juju status
The terraform juju
client does not support this. Please use the juju
client.
View details about a model
To view detailed information about a specific model, use the show-model
command followed by the model name. For example:
juju show-model test
Expand to see a sample output for an empty model called 'test'
test:
name: admin/test
short-name: test
model-uuid: 3850c8cc-0cd0-4d53-8a6d-591b63024141
model-type: iaas
controller-uuid: f06afa86-3461-42bb-86ed-6c2f5d7b0ac7
controller-name: localhost-localhost
is-controller: false
owner: admin
cloud: localhost
region: localhost
type: lxd
life: alive
status:
current: available
since: 5 hours ago
users:
admin:
display-name: admin
access: admin
last-connection: 2 minutes ago
sla: unsupported
agent-version: 3.1.0
credential:
name: localhost
owner: admin
cloud: localhost
validity-check: valid
supported-features:
- name: juju
description: the version of Juju used by the model
version: 3.1.0
By passing options you can also specify a format, an output file, etc.
See more:
juju show-model
The terraform juju
client does not support this. Please use the juju
client.
Configure a model
See also: Model configuration, List of model configuration keys
See related: How to configure a controller
The procedure for how to configure a model differs slightly depending on whether you are interested in the configuration of a specific model or rather of all the models on a controller.
A specific model
Set values. You can set the configuration for a model both while you are creating the model and later.
- To set it for the
controller
model during control creation, use thebootstrap
command with the--config
option followed by the desired configuration, for example:
juju bootstrap --config image-stream=daily localhost lxd-daily
- To set it for any other (workload) model while creating it, use the
add-model
command with the--config
flag followed by the desired configuration:
juju add-model mymodel --config image-stream=daily
- To set it for any model – whether
controller
or otherwise – after the model has already been created, use themodel-config
command followed by the desired configuration. For example, below we set the default space binding for all the applications on the model to ‘myspace’:
juju model-config default-space=myspace
Juju does not currently check that the provided key is a valid setting, so make sure you spell it correctly.
In all cases, the configuration can be passed in the form of a space-separated list of key-value pairs or in the form of a YAML configuration file, and you can also use it to overwrite (e.g., with a null value) or to reset existing values, among other things.
If you’re trying to pass multiple configurations using the --config
flag, make sure to repeat the flag for every configuration.
See more:
juju bootstrap --config ...
,juju add-model ... --config
,juju model-config
Get values. You can get the configuration of a model at any time by running the model-config
command without any argument, as below:
juju model-config
By using various flags of this command you can also target a specific model or key, choose a different output format, etc.
See more:
juju model-config
All the models on a controller
Set values. You can set the default configuration values for all the models on a controller either during controller creation or after.
- To set model configuration defaults during controller creation, use the
bootstrap
command with the--model-defaults
flag followed by the desired configuration(s), for example, as below. This will affect thecontroller
model and any subsequent (workload) model during controller creation.
For the controller
model you can override --model-defaults
through --config
. See more: How to configure a controller.
juju bootstrap microk8s uk8s \
--model-defaults logging-config="<root>=WARNING; unit=DEBUG" \
--model-defaults update-status-hook-interval="60m"
By passing various flags you can also target a specific cloud or cloud region, pass the configuration(s) in the form of a yaml file, reset keys, etc.
See more:
juju bootstrap --model-defaults ...
- To set model configuration defaults after controller creation, use the
model-defaults
command followed by the desired configuration. This willl affect any models created from that point onwards.
juju model-defaults ftp-proxy=10.0.0.1:8000
These defaults can be overridden, on a per-model basis, during the invocation of the add-model
command (option --config
) as well as by resetting specific options to their original defaults through the use of the model-config
command (option --reset
).
See more:
juju model-defaults
Get values. At any point, you can get the default configuration values for all the models on a controller by running the model-defaults
command, as below:
juju model-defaults
Just as before, by using various flags you can filter by a specific cloud or cloud region, or see the value for a specific key, etc.
See more:
juju model-defaults
With the terraform juju
client you can only set configuration values, only for a specific model, and only a workload model; for anything else, please use the juju
client.
To configure a specific workload model, in your Terraform plan, in the model’s resource definition, specify a config
block, listing all the key=value pairs you want to set. For example:
resource "juju_model" "this" {
name = "development"
cloud {
name = "aws"
region = "eu-west-1"
}
config = {
logging-config = "<root>=INFO"
development = true
no-proxy = "jujucharms.com"
update-status-hook-interval = "5m"
}
}
See more:
juju_model
(resource)
Manage constraints for a model
See also: Constraint
Set values. You can set constraints for the controller
model during controller creation or to regular models at any other point.
To set constraints for just the controller
application in the controller
model only: Use the bootstrap
command with the --bootstrap-constraints
flag. See more: How to manage constraints for a controller.
- To apply a constraint to the entire
controller
model during controller creation, run thebootstrap
command with the--constraints
option. Below we use it to ensure that every machine has 4GiB memory.
juju bootstrap --constraints mem=4G aws
See more:
juju bootstrap --constraints
- To set constraints for a regular model, run the
set-model-constraints
command followed by the desired key-value pair, as in the example below. This will affect all new resources provisioned for the model.
juju set-model-constraints mem=4G
Pro tip: To reset a constraint key to its default value, run the command with the value part empty (e.g., juju set-model-constraints mem=
).
See more:
juju set-model-constraints
Get values. To get constraint values for the current model, run the model-constraints
command, as below:
juju model-constraints
By using various flags, you can specify a model (e.g., -m controller
, to view constraints for the controller model), an output file, etc.
See more:
juju model-constraints
With the terraform juju
provider you can only set constraints – to view them, please use the juju
client.
To set constraints for a model, in your Terraform, in the model’s resource definition, specify the constraints
attribute (value is a quotes-enclosed space-separated list of key=value pairs). For example:
resource "juju_model" "this" {
name = "development"
cloud {
name = "aws"
region = "eu-west-1"
}
constraints = "cores=4 mem=16G"
}
See more:
juju_model
(resource)
Restrict commands on a model
Disable commands. To disable commands for the current model, run the disable-command
followed by the name of the command group that you want to restrict and, optionally, a message. For example, the code below disables the ability to destroy the model and its controller:
juju disable-command destroy-model ""Check with SA before destruction.""
See more:
juju disable-command
View a list of the disabled commands. To see which command groups have been disabled for a model, run the disabled-commands
command:
juju disabled-commands
See more:
juju disabled-commands
Enable commands. To lift command restrictions, run enable-command
followed by the command group that you want to enable. For example, the code below re-allows people to destroy the model and its controller.
juju enable-command destroy-model
See more:
juju enable-command
The terraform juju
client does not support this. Please use the juju
client.
Compare and export the contents of a model to a bundle
Compare. To compare the contents of the current model with a bundle and report any differences, run the diff-bundle
command:
juju diff-bundle <bundle>
Expand to see an example
Consider, for example, a model for which the status
command yields the output below:
Model Controller Cloud/Region Version SLA Timestamp
docs lxd localhost/localhost 2.5.0 unsupported 05:22:22Z
App Version Status Scale Charm Store Rev OS Notes
haproxy unknown 1 haproxy jujucharms 46 ubuntu
mariadb 10.1.37 active 1 mariadb jujucharms 7 ubuntu
mediawiki 1.19.14 active 1 mediawiki jujucharms 19 ubuntu
Unit Workload Agent Machine Public address Ports Message
haproxy/0* unknown idle 2 10.86.33.28 80/tcp
mariadb/0* active idle 1 10.86.33.192 ready
mediawiki/0* active idle 0 10.86.33.19 80/tcp Ready
Machine State DNS Inst id Series AZ Message
0 started 10.86.33.19 juju-dbf96b-0 trusty Running
1 started 10.86.33.192 juju-dbf96b-1 trusty Running
2 started 10.86.33.28 juju-dbf96b-2 bionic Running
Relation provider Requirer Interface Type Message
haproxy:peer haproxy:peer haproxy-peer peer
mariadb:cluster mariadb:cluster mysql-ha peer
mariadb:db mediawiki:db mysql regular
mediawiki:website haproxy:reverseproxy http regular
Now say we have a bundle file bundle.yaml
with these contents:
applications:
mediawiki:
charm: "mediawiki"
num_units: 1
options:
name: Central library
mysql:
charm: "mysql"
num_units: 1
options:
"binlog-format": MIXED
"block-size": 5
"dataset-size": "512M"
flavor: distro
"ha-bindiface": eth0
"ha-mcastport": 5411
"max-connections": -1
"preferred-storage-engine": InnoDB
"query-cache-size": -1
"query-cache-type": "OFF"
"rbd-name": mysql1
"tuning-level": safest
vip_cidr: 24
vip_iface: eth0
relations:
- - "mediawiki:db"
- "mysql:db"
Comparison of the currently active model with the bundle can be achieved in this way:
juju diff-bundle bundle.yaml
This produces an output of:
applications:
haproxy:
missing: bundle
mariadb:
missing: bundle
mediawiki:
charm:
bundle: mediawiki-5
model: mediawiki-19
series:
bundle: ""
model: trusty
options:
name:
bundle: Central library
model: null
mysql:
missing: model
machines:
"0":
missing: bundle
"1":
missing: bundle
"2":
missing: bundle
relations:
bundle-additions:
- - mediawiki:db
- mysql:db
model-additions:
- - haproxy:reverseproxy
- mediawiki:website
- - mariadb:db
- mediawiki:db
This informs us of the differences in terms of applications, machines, and relations. For instance, compared to the model, the bundle is missing applications haproxy
and mariadb
, whereas the model is missing mysql
. Both model and bundle utilise the ‘mediawiki’ application but they differ in terms of configuration. There are also differences being reported in the machines
and relations
sections.
Let’s now focus on the machines
section and explore some other features of the diff-bundle
command.
We can extend the bundle by including a bundle overlay. Consider an overlay bundle file changes.yaml
with these machine related contents:
applications:
mediawiki:
to: 2
mysql:
to: 3
machines:
"2":
series: trusty
constraints: arch=amd64 cores=1
"3":
series: trusty
constraints: arch=amd64 cores=1
Here, by means of the --overlay
option, we can add this extra information to the comparison, effectively inflating the configuration of the bundle:
juju diff-bundle bundle.yaml --overlay changes.yaml
This changes the machines
section of the output to:
machines:
"0":
missing: bundle
"1":
missing: bundle
"2":
series:
bundle: trusty
model: bionic
"3":
missing: model
The initial comparison displayed a lack of all three machines in the bundle. By adding machines 2
and 3
in the overlay, the output now shows machines 0
and 1
as missing in the bundle, machine 2
differs in configuration, and machine 3
is missing in the model.
As with the deploy
command, there is the ability to map machines in the bundle to those in the model. Below, the addition of --map-machines=2=0,3=1
makes, for the sake of the comparison, bundle machines 2
and 3
become model machines 0
and 1
, respectively:
juju diff-bundle bundle.yaml --overlay changes.yaml --map-machines=2=0,3=1
The machines
section now becomes:
machines:
"2":
missing: bundle
The bundle shows as only missing machine 2
now, which makes sense.
The target bundle can also reside on Charmhub. In that case you would simply reference the bundle name, such as wiki-simple
:
juju diff-bundle wiki-simple
See more:
juju diff-bundle
Export. To export the contents of the current model to a bundle file (a file of the form <bundle name>.yaml
), run the export-bundle
command with the --filename
flag followed by the file path. For example:
juju export-bundle --filename mybundle.yaml
The command also has flags that allow you to select a different model, include charm configuration default values in the exported bundle, etc.
Example
Suppose you have a model that looks like this:
$ juju status
Model Controller Cloud/Region Version SLA Timestamp
welcome-k8s microk8s microk8s/localhost 3.1.6 unsupported 09:09:56+01:00
App Version Status Scale Charm Channel Rev Address Exposed Message
example-k8s active 1 example-k8s 1 10.152.183.43 no
microsample-vm active 1 microsample-vm 0 10.152.183.230 no
Unit Workload Agent Address Ports Message
example-k8s/0* active idle 10.1.64.174
microsample-vm/0* active idle 10.1.64.169
Running juju export-bundle
will print this:
$ juju export-bundle
bundle: kubernetes
applications:
example-k8s:
charm: local:example-k8s-1
scale: 1
constraints: arch=amd64
microsample-vm:
charm: local:microsample-vm-0
scale: 1
constraints: arch=amd64
See more:
juju export-bundle
, SDK | How to manage bundles
The terraform juju
client does not support this. Please use the juju
client.
Upgrade a model
See more: Upgrading things
A model upgrade affects the version of Juju (Juju machine and unit agents) on all the Juju machines in the model.
First, prepare for the upgrade:
- Ensure the controller has already been upgraded. See more: How to upgrade a controller
- Ensure the models that are to be upgraded are in good working order (
juju status
).
Then, perform the upgrade. How you upgrade a model depends on whether you’d be crossing patch versions (e.g., v.2.9.25
→ v.2.9.26
) or rather minor (e.g., v.2.7
→ v.2.8
) or major versions (v.2
→ v.3
).
- To upgrade the current model across patch versions, use the
upgrade-model
command:
juju upgrade-model
By using various flags, you can specify an agent stream, agent version, etc., or you can even perform a dry run, to simulate what would happen if you upgraded.
This procedure can also be used to upgrade a controller model.
See more:
juju upgrade-model
- To upgrade a model’s minor or major version, use model migration. First, bootstrap a controller of your target version, migrate your model to that controller, and then do
upgrade-model
on the new controller.
This procedure cannot be used to upgrade a controller model.
See more: How to migrate a workload model to another controller,
When you’re done, verify that the model has been succesful by running the status
command. If the output looks wrong, you will have to do some investigation.
Error: some agents have not upgraded to the current model version <version>
When the running agent software that is more than 1 patch point behind the targeted upgrade version the upgrade process will abort.
One very common reason for “agent version skew” is that during a previous upgrade the agent could not be contacted and, therefore, was not upgraded along with the rest of the agents.
To overcome this situation you may force the upgrade by ignoring the agent version check:
juju upgrade-model --ignore-agent-versions
Unit agent has not restarted after upgrade
It may occur that an agent does not restart upon upgrade. One thing that may help is the inspection and modification of its agent.conf
file. Comparing it with its file before upgrading can be very useful.
Installing a different or modified configuration file will require a restart of the daemon. For example, for a machine with an ID of ‘2’:
juju ssh 2 'ls -lh /etc/systemd/system/juju*'
This will return something similar to:
-rwxr-xr-x 1 root root 326 Jun 29 19:02 /etc/systemd/system/jujud-machine-2-exec-start.sh
-rw-r--r-- 1 root root 284 Jun 29 19:02 /etc/systemd/system/jujud-machine-2.service
Therefore, if the agent for machine ‘2’ is not coming up you can connect to the machine in this way:
juju ssh 2
Then modify or restore the agent file (/var/lib/juju/agents/machine-2/agent.conf
), and while still connected to the machine, restart the agent:
sudo systemctl restart jujud-machine-2
The terraform juju
client does not support this. Please use the juju
client.
Migrate a workload model to another controller
Model migration is the movement of a model from one controller to another. The same configuration of machines, units, and their relations will be replicated on the destination controller, while your applications continue uninterrupted. Migration is used to upgrade models across minor or major versions. Migration is also useful for load balancing: If a controller hosting multiple models reaches capacity, you can move the busiest models to a new controller, reducing load without affecting your applications.
A controller model cannot be migrated.
Prepare for migration.
- Verify that the source and destination controllers are both known to the Juju client (i.e., they show up in the
juju controllers
output) and located in the same cloud environment. - Verify that the version of Juju running on the destination controller is the same or newer than the version on the source controller.
- Verify that the destination controller does not have any model with the same name as the name of the model you want to migrate to it.
- Back up the source controller.
- If the destination controller is on a different region or VPC: Ensure that the destination controller has direct connectivity to the source controller.
- If the model is large: Configure the destination controller to throttle the reconnection rate for the agents running for each machine and unit in the model and increase the migration agent timeout time. For example:
juju controller-config agent-ratelimit-rate=50ms
juju controller-config agent-ratelimit-max=100
juju controller-config migration-agent-wait-time=30m
See more: List of controller configuration keys >
agent-ratelimit-rate
,agent-ratelimit-max
,migration-agent-wait-time
- If the model has multiple users: Ensure that all the users have been set up on the destination controller. The operation will be aborted, and an advisory message displayed, if this is not the case.
- If the model contains secrets: Set up the target controller to use the same secret bank end as the source controller. For example, for a backend called
myvault
, as below. This will ensure that any secrets are correctly migrated with the model.
$ juju switch sourcecontroller
$ juju show-secret-backend myvault
myvault:
backend: vault
config:
endpoint: http://10.0.0.77:8200
secrets: 0
status: active
id: 63c8ad37c906eb278540e942
$ juju switch targetcontroller
$ juju add-secret-backend --config /path/to/backendcfg.yaml --import-id 63c8ad37c906eb278540e942
Migrate the model. To migrate a model on the current controller to a destination controller, use the migrate
command followed by the name of the model and the name of the destination controller, as below:
juju migrate <model> <destination controller>
You can monitor progress from the output of the status
command run against the source model. You may want to use a command such as watch
to automatically refresh the status output, rather than manually running status each time:
watch --color -n 1 juju status --color
In the output, a ‘Notes’ column is appended to the model overview line at the top of the output. The migration will step through various states, from ‘starting’ to ‘successful’.
The ‘status’ section in the output from the show-model
command also includes details on the current or most recently run migration. It adds extra information too, such as the migration start time, and is a good place to start if you need to determine why a migration has failed.
This section will look similar to the following after starting a migration:
status:
current: available
since: 23 hours ago
migration: uploading model binaries into destination controller
migration-start: 21 seconds ago
Migration time depends on the complexity of the model, the resources it uses, and the capabilities of the backing cloud.
If failure occurs during the migration process, the model, in its original state, will be reverted to the original controller.
When the migration has completed successfully, the model will no longer reside on the source controller. It, and its applications, machines and units, will be running on the destination controller.
Inspect the migrated model with the status
command:
juju status -m <destination-controller>:<model>
Error: migration: 'aborted, removing model from target controller: model data transfer failed, failed to import model into target controller: granting admin permission to the owner: user "<user>" is permanently deleted'
This error occurs when the model owner does not exist on the target controller. The solution is to create a user with that name on the target controller.
Note: The underlying cause is because a model is tightly coupled with the user who has created it. Starting with Juju 4, it will be possible to identify models independently of the user.
Error:migration: 'aborted, removing model from target controller: model data transfer failed, failed to import model into target controller: credential "<credential>" not found (not found)'
This error occurs when the model owner does not own the credential associated with the model. The solution is to change the credential to a credential the user owns (via juju set-credential
).
Error: migration: 'aborted, removing model from target controller: machine sanity check failed, 1 error found'
This error occurs when the machines known by Juju differ from the ones the underlying cloud reports (e.g., a LXD cloud still sees a container that has been removed from Juju). The solution is to check the cloud and resolve the difference (i.e., continuing with the previous example, to delete the container from the LXD cloud as well).
See more:
juju migrate
To migrate a model to another controller, use the juju
client to perform the migration, then, in your Terraform plan, reconfigure the juju
provider to point to the destination controller (we recommend the method where you configure the provider using static credentials). You can verify your configuration changes by running terraform plan
and noticing no change: Terraform merely compares the plan to what it finds in your deployment – if model migration with juju
has been successful, it should detect no change.
See more: How to use the client
Destroy a model
See also: Removing things
To remove a model, along with any associated machines and applications, use the destroy-model
command followed by the name of the model:
juju destroy-model <model>
The command has a variety of flags that you can use to skip the confirmation, to rush through the destruction without waiting for each step to complete, to release or destroy any persistant storage on the model, etc., or even to force destroy the model, ignoring any errors (not recommended as it might leave behind unresolved issues).
See more:
juju destroy-model
To destroy a model, remove its resource definition from your Terraform plan.
See more:
juju_model
(resource)
To destroy a model, with a connected controller object, call the Controller.destroy_model()
function. For example:
await controller.destroy_model("test-model")
See more:
Controller.destroy_model()
Contributors: @aflynn, @awnns, @barrettj12, @cderici, @hmlanigan, @pedroleaoc, @pmatulis, @serdarvural80, @timclicks, @tmihoc