N1 Get started on Kubernetes

Juju is an Open Source Charmed Operator Framework. It helps you move from configuration management to application management and has two main components:

  • Charmed Operator Lifecycle Manager (OLM) - a hybrid-cloud application management and orchestration system that helps you from Day 0 to Day 2. Deploy, configure, scale, integrate, maintain and manage Kubernetes native, container-native and VM-native applications – and the relations between them.

    • Charmed Operators, packaged as “Charms”, are software that encapsulate a single application and all the code and know-how it takes to operate it on Kubernetes or machines.
  • Charmed Operator SDK - a guide to help you build Charmed Operators for use with the Charmed OLM.

Kubernetes – also known as K8s – provides a flexible architecture for Cloud Native applications at scale. The Juju Charmed OLM manages multi-container workloads on K8s. This guide takes you through the registration steps necessary to connect the two systems.

You don’t need to have previous knowledge of Juju or Charmed Operators to follow this guide.

This page covers the following topics:

Useful tools to manage Juju and Kubernetes
A. Install Juju CLI Allows you to configure and manage other Juju components.
B. Install Kubectl CLI Allows you to run commands against Kubernetes clusters.
C. Gain access to a Kubernetes cluster If you don’t have a cluster, we will go through the process of creating one.
Connecting Juju to your Kubernetes cluster
Register your cluster with Juju
1. Register the cluster with Juju Make your cluster known to Juju.
2. Create a Juju controller Bootstrap the Juju controller to your cluster
Deploy workloads
Deploy and integrate applications
3. Add a model Create a model to wrap your infrastructure.
4. Deploy workloads Deploy applications using universal operators from charmhub.io
5. Relate your applications Use juju relate to integrate your applications.


I. Installing Juju

Juju is a single binary executable that is published and supported on multiple operating systems and CPU architectures.

OS Method
Linux snap install --classic juju
macOS brew install juju
Windows Download the signed Juju installer, md5, signature

Alternative installations:
You can find instructions on installing development releases or building from the source in the Juju installation page.

II. Installing Kubectl

Kubectl is a command-line tool that allows you to run commands against Kubernetes clusters. If you have access to a cluster, you might already have it installed. If not, you can follow these instructions to download and install the binary.

III. Gaining access to a Kubernetes cluster

Juju supports a variety of Kubernetes distributions running on your laptop, private infrastructure, or public cloud. You can connect Juju to your existing K8s cluster or get one based on the recommendations below. If you are new to Kubernetes, we recommend following this guide with MicroK8s.

Use Case Recommended Action
Local development, testing and experimentation Install MicroK8s
Multi-node testing/production on a private cloud Install Charmed Kubernetes
Multi-node testing/production on the public cloud Install Charmed Kubernetes with the relevant integrator charm
Use a hosted Kubernetes distribution Enable the service via the provider

We also have guides for creating clusters on the following Kubernetes distributions:

If your distribution is not listed above, you are still able to use Juju on any cluster to which you have sufficient access privileges, recorded in a kubeconfig entry.

Connecting Juju to your Kubernetes cluster

1. Register the cluster with Juju

Juju will look for the kube configuration files to find the cloud definition.

You can see what clouds Juju has found by running:
bash juju clouds

If for any reason that can’t be done automatically, you can manually point Juju to the cluster’s configuration file.

Manually exposing the cluster's configuration file

Copy the cluster’s configuration file from the master node to your local machine and save it as $HOME/.kube/config, then run

juju add-k8s

If Juju can see your cluster (juju clouds), move on to 2. Create a Juju controller.

Some clouds will require extra steps configure the cluster to work with Juju:

a. When running MicroK8s

The cluster is registered with Juju automatically, but we have to enable the storage and dns addons.

microk8s enable storage dns

Then move on to 2. Create a Juju controller.

b. When you’re already able to interact with your cluster via kubectl

Juju will automatically look in the standard kube configuration file.

Then move on to 2. Create a Juju controller.

c. When you have used Juju to deploy Charmed Kubernetes
mkdir ~/.kube
juju scp kubernetes-master/0:/home/ubuntu/config ~/.kube/config
juju add-k8s

Then move on to 2. Create a Juju controller.

2. Create a Juju controller

The Juju controller is a central software agent that oversees applications managed with Juju. It is created via the juju bootstrap command.

juju bootstrap <cloud-name> <controller-name>

Cloud name is microk8s or <cloud-name> specified previously.

Config file:
The command above assumes that the config file is located at $HOME/.kube/config (or it has been loaded manually) and you can communicate to your cluster via kubectl.

To check that you have configured kubectl correctly, execute the command:
kubectl get nodes

Then move on to 3. Add a model.

Deploy workloads

3. Add a model

Before deploying applications with universal operators, Juju users create a “model”. In the Kubernetes context, models are namespaces.

A model is a canvas on a particular cloud/k8s-cluster. The model is used to group applications that are being operated together for a common purpose on a common substrate. The model will capture the applications, their integration, configuration, and resource allocation.

Since each model is on a single substrate, and the service as a whole may span multiple clouds/k8s-clusters, it may require several models to provide the canvases for all the different applications in the service.

The model is a workspace for inter-related applications. It is an abstraction over applications, machines hosting them and other components such as persistent storage.

To add a model, use the juju add-model command:

juju add-model <cloud-name>

Inside the cluster, adding a Juju model creates a Kubernetes namespace with the same name. The namespace hosts all of the pods and other resources, except global resources.

4. Deploy workloads

The fundamental purpose of Juju is to deploy and manage software applications in a way that is easy and repeatable. All this is done with the help of universal operators , which are bits of code that contain all the necessary intelligence to do these things. Universal operators can exist online (in the Charm Store) or on your local filesystem (previously downloaded from the store or written locally).

As an example, we will deploy Mattermost, an open-source, self-hostable online chat service using PostgreSQL as its database.

Typically, applications are deployed using the online universal operators. This ensures that you get the latest version of the charm. Deploying in this way is straightforward:

Deploy Mattermost:

juju deploy mattermost

When deployed, this outputs:

Located charm "mattermost" in charm-store, revision 20

Deploying "mattermost" from charm-store charm "mattermost", revision 20 in channel stable

You can observe the deployment status with the following command:

watch -c juju status --format short --color

Then deploy the PostgreSQL Charm:

juju deploy postgresql-k8s

When deployed, this outputs:

Located charm "postgresql-k8s" in charm-store, revision 9

Deploying "postgresql" from charm-store charm "postgresql-k8s", revision 9 in channel stable

At this point, both applications are deployed in the model located in the Kubernetes cluster, but they don’t know about each other. Next we will relate apps.

5. Relate Applications


Most applications rely on other applications to function correctly. For example, typically web apps require a database to connect to. Relations avoid the need for manual intervention when the charm’s environment changes. The charm will be notified of new changes, re-configure and restart the application automatically.

Relations are a Juju abstraction that enables applications to inter-operate. They are a communication channel between universal operators.

A certain charm knows that it requires, say, a database and, correspondingly, a database charm knows that it is capable of satisfying another charm’s requirements. The act of joining such mutually-dependent universal operators causes code (hooks) to run in each charm in such a way that both universal operators can effectively talk to one another. When universal operators have joined logically in this manner they are said to have formed a relation.

Create relation

Creating a relation is straightforward. The add-relation command is used to set up a relation between two applications:

juju relate mattermost postgresql:db

This will satisfy Mattermost’s database requirement where PostgreSQL provides the appropriate structures (e.g. tables) needed for Mattermost to run properly.

Ambiguous relations

If the universal operators in question are versatile enough, Juju may need to be supplied with more information as to how the universal operators should be joined.

In this example, we had to specify to which postresql endpoint we wanted to connect: postgresql:db That’s because postgresql has multiple endpoints for syslog, db and db_admin.

Again, watch the deployment status with the following command until both universal operators’ status is active.

watch -c juju status --format short --color

Which will return the following when the applications are related:

- mattermost/0: (agent:idle, workload:active) 8065/TCP

- postgresql/0: (agent:idle, workload:active) 5432/TCP

Your deployment is dynamic: If you need to scale, deploy other applications or move it around, Juju will adapt and maintain the relations active without the need of special configurations.

Access the application

To access the application locally, get the Pod name:

export APP_NAME=$(kubectl get pod -l app.kubernetes.io/name=mattermost -n my-model -o name)

And create a port-forward:

kubectl port-forward -n my-model $APP_NAME 8065

Open your browser and access the page http://localhost:8065. You should see the Mattermost home page.

Congratulations, you just deployed and integrated cloud-native applications in a Kubernetes cluster!

Next steps

This guide presents the core of Juju’s functionality - most applications will follow a similar workflow: bootstrap the controller in your cluster, add a model, deploy and relate applications. If you would like to see some examples of what you can do with Juju, our tutorials page has application specific guide. You can also try Juju on your own cloud or localhost

Notes from a proofread:

There’s a typo in this sentence fragment: “that it isthat is capable”

You say “Creating a relation is straightforward enough.” I’d leave out the “enough.” Creating a relation is straightforward, full stop. We’re justified in being confident there.

The flow about getting your kubernetes setup is a little bit fussy. I’d rather see an example with microk8s and/or a generic kubernetes, with callouts and links to examples on other substrates. As written, I suspect that all the options would be intimidating to someone new to kubernetes.

1 Like

I agree. The challenge here is that I need to be objective but also sell the idea that we are not limited to uK8s. I might have to be more clear about directing people towards “if you have no idea of what you are doing, follow the uK8s route”

four business decisions. (link updated too)

1 Like

I’d be inclined to replace this with some prose about bootstrapping to any cluster to which you have sufficient access privileges, recorded in a kube config entry.

I believe 2.9 should support bootstrapping to such clusters directly without having to run add-k8s, which could be reflected somehow in lieu of:

I’d make this a little snappier by dropping the “canvas” bit and just describing it as a logical grouping.

And user credentials.

1 Like


If your distribution is not listed above, you are still able to use Juju on any cluster to which you have sufficient access privileges, recorded in a kubeconfig entry.


Does it mean we can simply drop the add-k8s command?
What was the function of add-clusters?

The model is used to group applications, their integration, configuration, and resource allocation. Models allow you to easily interact with your deployment without having to think about how each individual component will react to a change.


  1. Here?
1 Like

The manual installation looks like a link but doesn’t work.

This section, particularly for manual installs needs more details. Juju requires storage, DNS (I beleive), and a way to ingress. For manual providers and particularly for something like an on-prem VM Ware these may not be in the ‘test cluster’ the individual sets up. I see Field engineers trip over this on a semi regular basis we shouldn’t leave this trap for new users who will fail to bootstrap and likely walk away.

For a Private CDK deployed cloud you won’t have meet these requirements and must add the CDK K8s to your existing controller.

I encourage you to deploy CDK and try walking through this guide. I tried it a few weeks ago and was unable to bootstrap. I believe at least one bug I ran into has now been fixed, but I have no confidence you can successfully bootstrap juju on top of CDK we need to tell people to add the cloud to their existing controller.

1 Like

I feel like this paragraph is hinting about the steps, but not actually defining the steps yet, and leads to a weird “we will tell you about something but we have to be careful not to tell you about it yet”.

Maybe we can drop the parenthetical, which shortens it a bit, and still gives us a preamble but by keeping it to not require the user to think about ‘future things’ that they don’t have a concrete understanding yet.

For things like Registering the cloud, is it worth pointing to other docs around this? For example for Charmed Kubernetes, we could reference: Basic operations | Ubuntu

For 1b with 2.9 you should be able to ‘juju bootstrap KUBENAME’ and juju should look in standard kube configuration files to find what cloud that defines (so you shouldn’t need to do add-k8s.).
If we do have most clusters that you have access to not need an ‘add-k8s’ step, I’m wondering if we should rethink making this as prominent, and instead focus on it as a ‘if you don’t have access, here is a guide for telling Juju about your kubernetes’, and then we can take it out of this doc.

1 Like

Suggested edits are good.

I think we need it for cases like AKS where we pass pass a resource group to the command, but from 2.9, if a cluster is in your kube config and the configured access is sufficient, bootstrapping directly to it as though it were already a registered cloud should work.

1 Like

As a follow up - it’s probably worth adding a section about the automatic kube-context thing that shows how to check the name of the available kube contexts, and show that in order to go straight to bootstrap without add-k8s you need to use the same name (i included something in the call for testing you could steal if required)


That’s a very good point, @chris.sanders.

Would be good enough to warn people of the requirements at this point?

I think the cloud specific guides cover most of the requirements but we definitely don’t have one specific for CDK. @achalkias do you have a guide for bootstrapping Juju on top of CDK that is more comprehensive than a installation landing page kind of thing? Something that would fit a manual rather than a “getting started” page.

Hmmm… Is that the only option at this point? Can’t we have a separate controller for CDK and Juju on top of the CDK?

  • You are right! I was trying to let people know they shouldn’t expect a very complex procedure, but it came across as a cheap trick to hook people’s attention.
  • Brilliant, that’s the guide I was looking for CDK!
  • I would prefer that. I would still leave the section for information about microk8s and and CDK.

What does the add-k8s function does in 2.9?

I might add a note to saying exactly that.

  • What do you mean by this?

From the AKS doc:

juju add-k8s --aks --resource-group <resource-group> --cluster-name <k8s-cluster> <cloud>

Do we have a guide on registering an existing CDK cluster with a second Juju? Or even, should we be also telling people that they can just use the original controller to deploy applications on top of CDK? I am thinking about item 1c

See the QA steps for this patch, which demonstrate:

  • Bootstrapping to AWS
  • Deploying charmed K8s
  • Adding the K8s cluster to the same controller
  • Deploying to the cluster.

Incidentally, this shows why we still need the add-k8s command - it is used here on an existing controller whereas it is only obviated for some bootstrap cases.

No you can’t bootstrap on top of CDK, additional operator charms are required before you can bootstrap. Add it to the existing controller, this is the way.

1 Like

Hi @chris.sanders, can you please add instructions for CDK on 1.c.? I

I’m happy to review it, but I can’t stop and write this right now I’m sorry.