How to manage applications
See also: Application
This document shows how to manage applications with Juju.
Contents:
- Deploy an application
- View details about an application
- Manage an application’s public availability over the network
- Trust an application with a credential
- Configure an application
- Manage machine constraints for an application
- Scale an application
- Change space bindings for an application
- Upgrade an application
- Remove an application
Deploy an application
To deploy an application from a charm on Charmhub / your local filesystem, use the deploy
command followed by the name of the charm / the path to the local directory of the charm that delivers the application and, optionally, a custom application name:
juju deploy <charm | <path/to/charm directory> <custom application name>
Example: Deploy MySQL from Charmhub using the `mysql` charm
juju deploy mysql
Example: Deploy an application from a local machine charm
juju deploy ./mini_ubuntu-20.04-amd64.charm
Example: Deploy an application from a local Kubernetes charm
To deploy an application from a local Kubernetes charm, you must also specify a resource.
juju deploy ./demo-api-charm_ubuntu-22.04-amd64.charm --resource \
demo-server-image=ghcr.io/beliaev-maksim/api_demo_server:0.0.9
Depending on the cloud substrate that your controller is running on, the above command will allocate a machine (physical, virtual, LXD container) or a Kubernetes pod and then proceed to deploy and configure the application.
Depending on your use case, you may alternatively opt to provision a set of machines in advance via the juju add-machine
command.
In this case, when running the above juju deploy
command, Juju will detect that the model contains machines with no applications assigned to them and automatically deploy the application to one of those machines instead of spinning up a new machine.
The command also allows you to add another argument to specify a custom name (alias) for your deployed application. You can also take advantage of the rich set of flags to specify a charm channel or revision, a machine base (e.g., , a machine constraint (e.g., availability zone), the number of application units you want (clusterised, a space binding, a placement directive (e.g., to depoy to a LXD container), a specific storage instance, a specific machine, etc., and even to trust the application with the current credential – in case the application requires access to the backing cloud in order to fulfil its purpose (e.g., storage-related tasks).
See more:
juju deploy
View details about an application
To view more information about a deployed application, run the show-application
command followed by the application name or alias:
juju show-application <application name or alias >
By specifying various flags you can also specify a model, or an output format or file.
See more:
juju show-application
Manage an application’s public availability over the network
See also: Control application network ingress
Expose an application. By default, once an application is deployed, it is only reachable by other applications in the same Juju model. However, if the particular deployment use case requires for the application to be reachable by Internet traffic (e.g. a web server, Wordpress installation etc.), Juju needs to tweak the backing cloud’s firewall rules to allow Internet traffic to reach the application. This is done with the juju expose
command.
After running a juju expose
command, any ports opened by the application’s charmed operator will become accessible by any public or private IP address.
Since Juju 2.9, operators can explicitly specify the list of CIDRs and/or spaces that should be able to access the ports opened by the application. See Controlling application expose settings via the Juju CLI to learn more about this feature.
Assuming the wordpress
application has been deployed (and a relation has been made to the deployed database mariadb
), the following command can be used to expose the application outside the Juju model:
juju expose wordpress
When running juju status
, its output will not only indicate whether an application is exposed or not, but also the public address that can be used to access each exposed application:
App Version Status Scale Charm Rev Exposed Message
mariadb 10.1.36 active 1 mariadb 7 no
wordpress active 1 wordpress 5 yes exposed
Unit Workload Agent Machine Public address Ports Message
mariadb/0* active idle 1 54.147.127.19 ready
wordpress/0* active idle 0 54.224.246.234 80/tcp
See more:
juju expose
Unexpose an application. The juju unexpose
command can be used to undo the firewall changes and once again only allow the application to be accessed by applications in the same Juju model:
juju unexpose wordpress
See more:
juju unexpose
Trust an application with a credential
Some applications may require access to the backing cloud in order to fulfil their purpose (e.g., storage-related tasks). In such cases, the remote credential associated with the current model would need to be shared with the application. When the Juju administrator allows this to occur the application is said to be trusted. An application can be trusted during deployment or after deployment.
Trust an application during deployment. To trust an application during deployment, run the deploy
command with the --trust
flag. E.g., below we trust
juju deploy --trust ...
See more:
juju deploy --trust
Trust an application after deployment. To trust an application after deployment, use the trust
command:
juju trust <application>
By specifying various flags, you can also use this command to remove trust from an application, or to give an application deployed on a Kubernetes model access to the full Kubernetes cluster, etc.
See more:
juju trust
Configure an application
See also: Application configuration
Most charms ship with a sensible default configuration out of the box. However, for some use cases, it may be desirable or necessary to override the default application configuration options at deployment time. Juju provides tools to help manage these options and respond to changes over the lifetime of the application. These options apply to the entire application, as opposed to only a specific unit or relation. The configuration can be done at deployment time or post-deployment.
- Discover application configuration options
- Configure an application during deployment
- Configure an application post deployment
Discover application configuration options
Each charm will have its own set of options and possible values. You can discover these in several ways:
- by running the
config
command - by viewing the charm on Charmhub
- by examining the
config.yaml
file in the charm itself
Configure an application during deployment
Configuration values can be set at deployment time using the following methods:
- by using a yaml-formatted file
- by passing options/values directly on the command line
- a combination of the above
All these methods use the --config
option.
For example, upon investigation we discover that the Mediawiki charm allows us to set values for the name
of the wiki and the skin
to use. We can put these inside a configuration file.
mediawiki:
name: Juju Wiki
skin: monobook
Assuming the file is called myconfig.yaml
, the application can be deployed and configured in this way:
juju deploy --config myconfig.yaml mediawiki
If the configuration file cannot be read or contains syntax errors or invalid options, an error message will be printed to this effect. However, the application will still be deployed.
To pass the options directly:
juju deploy --config name='Juju Wiki' --config skin='monobook'
A combination can also be used. If a duplication arises, the last-mentioned value gets used. For instance, below, the wiki will be assigned the name of ‘Juju Wiki’:
juju deploy --config name='Juju Wookie' --config myconfig.yaml
Configure an application post deployment
It is possible to set or change the configuration of an application which is already deployed.
Before you set any of these options, you may want to check what current options are already set. For example:
juju config mediawiki
Should return something like this:
application: mediawiki
charm: mediawiki
settings:
admins:
description: Admin users to create, user:pass
is_default: true
type: string
value: ""
debug:
description: turn on debugging features of mediawiki
is_default: true
type: boolean
value: false
logo:
description: URL to fetch logo from
is_default: true
type: string
value: ""
name:
description: The name, or Title of the Wiki
is_default: true
type: string
value: Please set name of wiki
server_address:
description: The server url to set "$wgServer". Useful for reverse proxies
is_default: true
type: string
value: ""
skin:
description: skin for the Wiki
is_default: true
type: string
value: vector
use_suffix:
description: If we should put '/mediawiki' suffix on the url
is_default: true
type: boolean
value: true
You can set the options in a very similar way. Simply add space-separated key=value pairs as arguments:
juju config mediawiki skin=monoblock name='Juju Wiki'
It is also possible to set options from a YAML file:
juju config mediawiki --file path/to/myconfig.yaml
Setting an option back to its default value is achieved with the --reset
option. Here, the argument is a comma-separated list of the option names in question:
juju config mediawiki --reset admins,name
Manage machine constraints for an application
See also: Constraint
Set values. You can set machine constraint values for an application during deployment or later.
- To set machine constraints for an application during deployment, run the
deploy
command with the--constraints
flag followed by the relevant key-value pair or a quotes-enclosed list of key-value pairs. For example, to deploy MySQL on a machine that has at least 6 GiB of memory and 2 CPUs:
juju deploy mysql --constraints "mem=6G cores=2"
Expand to see more examples
Assuming a LXD cloud, to deploy PostgreSQL with a specific amount of CPUs and memory, you can use a combination of the instance-type
and mem
constraints, as below – instance-type=c5.large
maps to 2 CPUs and 4 GiB, but mem
overrides the latter, such that the result is a machine with 2 CPUs and 3.5 GiB of memory.
juju deploy postgresql --constraints "instance-type=c5.large mem=3.5G"
To deploy Zookeeper to a new LXD container (on a new machine) limited to 5 GiB of memory and 2 CPUs, execute:
juju deploy zookeeper --constraints "mem=5G cores=2" --to lxd
To deploy two units of Redis across two AWS availability zones, run:
juju deploy redis -n 2 --constraints zones=us-east-1a,us-east-1d
See more:
juju deploy --constraints
If you want to use the image-id
constraint with juju deploy
:
You must also use the --base
flag of the command. The base specified via --base
will be used to determine the charm revision deployed on the machine created with the image-id
constraint.
See more:
juju deploy --base
- To set machine constraints for an application after deployment, run the
set-constraints
command followed by the desired ("-enclosed list of) key-value pair(s), as below. This will affect any future units you may add to the application.
juju set-constraints mariadb cores=2
Pro tip: To reset a constraint key to its default value, run the command with the value part empty (e.g., juju deploy apache2 --constraints mem=
).
See more:
juju set-constraints
Get values. To view an application’s current constraints, use the constraints
command:
juju constraints mariadb
See more:
juju constraints
Scale an application
The capability of a service to adjust its resource footprint to a level appropriate for fulfilling client demands placed upon it is known as scalability. Scaling vertically affects the resources of existing machines (memory, CPU, disk space) whereas scaling horizontally, in Juju, involves the number of application units available.
Units are not always synonymous with machines however. Multiple units can be placed onto a single machine (co-location) and still be considered horizontal scaling if sufficient resources are present on the machine.
This page will describe how rudimentary scaling works with Juju as well as mention some less common situations.
Scaling up
In the context of Juju, scaling up means increasing the number of application units and always involves the add-unit
command. The exception is for a Kubernetes-backed cloud where the scale-application
command is used.
Closely resembling scaling up is the addition of a machine devoid of a unit. This is accomplished via the add-machine
command:
juju add-machine
A machine provisioned via the add-machine
command that does not yet house an application unit will, by default, be used for any subsequent application deployment (via the deploy
command).
Scaling up behind a load balancer
In many cases simply adding more units will not make an application scale properly. A load balancer or proxy is often required.
Below is an example of deploying a load balanced MediaWiki application by placing the HAProxy application in front of it:
juju deploy mediawiki
juju deploy mysql
juju deploy haproxy
juju integrate mediawiki:db mysql
juju integrate mediawiki haproxy
juju expose haproxy
When a relation is made between MediaWiki and HAProxy, the latter will be configured to load balance requests to the MediaWiki application. This means that client requests should go to the HAProxy instance. To get the proxy’s IP address run the following:
juju status haproxy
You can now scale up the MediaWiki application behind the proxy as you see fit. To add five more units (with each running in its own machine):
juju add-unit -n 5 mediawiki
Scaling up within a Kubernetes model
To scale up while in a Kubernetes model the total number of desired units for the application is simply stated. Here we want a total of three units:
juju scale-application mediawiki 3
Scaling up using a charm with built-in scaling
Some charms have scaling built-in where scaling up really is as simple as adding more units.
An example of this is the WordPress charm:
juju deploy mysql
juju deploy wordpress
juju integrate mysql wordpress
juju expose wordpress
To scale up by adding an extra unit one can simply do:
juju add-unit wordpress
This will cause a new unit (and machine) to be spawned and configured to work alongside the existing one.
By default, add-unit
will add a single unit. To request multiple units the -n
option is needed. For example, to further scale up our current application by adding 100 units of MySQL one would run:
juju add-unit -n 100 mysql
Scaling up through co-location
Like the deploy
command, it is possible to co-locate multiple applications on a single machine. This is done via the --to
option.
For example, to add a unit of MySQL to the machine with an ID of ‘23’:
juju add-unit mysql --to 23
To add a unit of the same application to existing LXC container ‘3’ residing on host machine ‘24’:
juju add-unit mysql --to 24/lxc/3
Not all applications will happily co-exist (usually due to conflicting configuration files). It is therefore generally safer to place units on dedicated machines or containers.
Here we add a unit of MySQL to a new LXC container on host machine 25:
juju add-unit mysql --to lxc:25
Scaling up by specifying new constraints
It is possible to scale out an application by adding a unit with different hardware requirements (constraints) than those set with the initial deployment. The default behaviour is for new units to use the same, if any, constraints.
This is done by indirectly creating a machine with a constraint and then adding the unit to it. For example, to add a unit with 16 GiB of memory to the MySQL application if the initial deployment was only, say, 4 GiB:
juju add-machine --constraints mem=16G
juju machines
juju add-unit mysql --to 3
Above, it is presumed that juju machines
informed us that the new machine was assigned an ID of ‘3’.
Read the Using constraints page for details on constraints.
Scaling down
In the context of Juju, scaling down means decreasing the number of application units and always involves the remove-unit
command. The exception is for a Kubernetes-backed cloud where the scale-application
command is used.
Closely resembling scaling down is the direct removal of a machine. This is therefore also covered here and is accomplished via the remove-machine
command.
To scale down the MediaWiki application by removing a specific unit:
juju remove-unit mediawiki/1
Note that if this is the only unit running on the underlying machine, the machine will also be removed.
A machine cannot be manually removed if any of the following is true:
- it houses a unit
- it is being used as the only controller
- it is hosting Juju-managed containers (KVM guests or LXD containers)
For example, to remove a machine with ID of ‘6’:
juju remove-machine 6
For more information on removing applications and machines, see the Removing things page.
Scaling down within a Kubernetes model
To scale down while in a Kubernetes model the total number of desired units for the application is simply stated. Here we want a total of two units:
juju scale-application mediawiki 2
Charm Implementation
When developing charms using the Operator Framework, scaling is handled via relation events - specifically through peer relations. For more information see:
Change space bindings for an application
To change space bindings for a deployed application, run the bind
command followed by the name of the application followed by the name of a default space and/or key-value pairs consisting of specific application endpoints and the space you want to bind them to.
For example, to update the default binding for the application and automatically update all existing endpoint bindings that were referencing the old default, pass the name of the new default space:
juju bind <application> <new default space>
Or, to bind individual endpoints to a space, pass key-value pairs of specific application endpoints and the specific space you want to bind them to:
juju bind <application> endpoint-1=space-1 endpoint-2=space-2
Finally, to both update the default space and individual endpoints in one go, pass both:
juju bind <application> new-default endpoint-1=space-1
See more:
juju bind
Upgrade an application
See also: Upgrading things, Application, Juju SDK | Channel, Juju SDK | Upgrading a charm
To upgrade an application, you need to upgrade the channel of its deployed charm.
This always involves the refresh
command, but the exact way to use it differs a little bit depending on whether you are dealing with a Charmhub charm or rather a local charm.
Contents:
Upgrade a Charmhub charm
See also:
juju status
,juju info
,juju refresh
Run status
to find the current channel.
Run info
followed by the charm name to find out all the available channels.
Finally, run refresh
followed by the charm name and the channel
option to change the charm to the desired channel.
Upgrade a local charm
See also:
juju refresh
To upgrade a local charm, run the refresh
command followed by the name of the charm and the local path to the charm:
juju refresh juju-test --path ./path/to/juju-test
The command offers many other options, for example, the possibility to replace a charm completely with another charm by using the --switch
option followed by a different path (a process known as ‘crossgrading’). (Note: --path
and --switch
are mutually exclusive. Use --switch
if you want to replace your existing charm with a completely new charm.)
Remove an application
See also: Removing things reference
Contents:
Remove an application
An application can be removed with:
juju remove-application <application-name>
For example:
juju remove-application apache2
This will remove all of the application’s units. All associated machines will also be removed providing they are not hosting containers or another application’s units.
If persistent storage is in use by the application it will be detached and left in the model. However, the --destroy-storage
option can be used to instruct Juju to destroy the storage once detached.
Removing an application which has relations with another application will terminate that relation. This may adversely affect the other application. See section Removing relations below for how to selectively remove relations.
As a last resort, use the --force
option (in v.2.6.1
).
Remove a charm or a charm bundle
A charmed operator is the means by which an application is installed. There is therefore no method to remove a charm. Removal should be done at either the unit or application level.
A bundle is not a logical entity that can be removed. Once a bundle is deployed, applications can evolve in numerous ways that are not tracked and associated with the original bundle. For complex deployments, the recommendation is to deploy on a per-model basis so the removal of a complex deployment becomes equivalent to the removal of a model.
Remove an application offer
An application offer (for a cross model relation) is removed with:
juju remove-offer <offer url>
For example:
juju remove-offer hosted-mysql
The attempt will fail if a relation has already been made to the offer. To override this behaviour the --force
option is required, in which case the relation is also removed.
Note that if the offer does not reside in the current model then the full URL must be used:
juju remove-offer prod.model/hosted-mysql
Last updated a month ago.