Mapping Juju concepts to Kubernetes

This document explains how Juju operates when managing a model within a “k8s cloud”, e.g. a Kubernetes cluster that is registered with Juju. It’s intended that readers are already familiar with Juju. It is split into multiple sections:


Why use Juju to drive Kubernetes?

What are some of the motivations for using Juju for Kubernetes deployments?

  • Using charms is simpler than other approaches. Charms have been a proven method for writing operators for a decade. Using charms means having reliable upgrades, automatic namespaces, streamlined storage management and other features.

  • Substrate independence. Other operator frameworks are tied to Kubernetes. Charms can be deployed to any substrate, allowing you to make use of the operator model for traditional infrastructure provisioning. Reuse knowledge that you’ve already gained.

  • Multi-cloud and hybrid-cloud aware. Juju allows you to deploy databases to bare metal, then applications to Kubernetes. Informed by relations, charms can automatically configure themselves.

Overview and Technical Internals

Juju is an instance of the operator model for software and configuration management. Charms are the most productive way to write operators.

Under Kubernetes, charms run within “operator pods”. They sit alongside your workloads and respond to messages and events propagated by the Juju controller.

Terminology refresher: Several terms have specialised meanings within a Juju context:

- A cloud is a deployment target. The term “compute cluster” matches closely, although the Juju term is more broad. This has historically been cloud provider, such as Microsoft Azure, AWS and Google Cloud Platform. Every Kubernetes cluster registered with Juju is a k8s cloud.

- A model is a dynamic set of applications, compute, storage volumes and network resources that interact as a logical service. Juju describes models in Kubernetes as a k8s model.

- An application is the software under management by a charm

- A charm is an instance of the operator model.

What deployments feel like

If you’ve used Juju before, k8s models will feel very similar. Your Juju experience at the command-line will translate very well to Kubernetes.

Under the hood, there are a few differences.

Within a (virtual) machine, Juju runs its agents alongside your application as operating system processes. This utilises the isolation afforded by the operating system.

Under Kubernetes, Juju deploys two workloads to the cluster that run concurrently. An operator pod is always deployed alongside your application’s pod(s).

Registering a Kubernetes cluster as a k8s cloud

K8s clouds are not added with juju add-cloud. Because of significantly different internal semantics, the bespoke command juju add-k8s is used.

Command Description
juju add-k8s Registers a Kubernetes cluster as a k8s cloud in Juju.

Using MicroK8s?: When installed locally, Juju will detect MicroK8s and add it as a k8s cloud automatically.

Credential management

Credentials on k8s clouds are managed with the same commands as other clouds.

Command Description
juju add-credential Registers a single credential with Juju.
juju autoload-credentials Scans your local system for stored credentials of known clouds and registers them with Juju.


Kubernetes can host a Juju controller. To create one, use the juju bootstrap command. One difference with k8s clouds is that there is no default model created by Juju after the bootstrapping process. Juju occupy Kubernetes namespaces and is unwilling to “invade” a namespace that may already exist.

Command Description
juju bootstrap Creates a Juju controller inside the k8s cloud
juju add-model Adds a model to the active k8s cloud

Already have a controller?: If you already have an active Juju controller, it can be used to manage multiple clouds. See for more details.


Deploying applications to k8s models is very similar to deploying to other models.

Command Description
juju add-k8s Registers a Kubernetes cluster as a k8s cloud in Juju.

Placement directives (juju deploy --to)

It’s impossible to target machines directly. By design, Kubernetes pods are ephemeral. In the Kubernetes world, Juju supports deploying to tags.

$ juju deploy mariadb-k8s \

It is also possible to use use tags as constraints:

$ juju deploy cs:~kelvin.liu/mariadb-k8s-x \


Kubernetes, as a container-centric technology, offers different storage primitives than cloud providers.

Juju will make a best effort approach to provision a default storage class.


This section describes how day-n operations differ between k8s clouds and other clouds.

Kubernetes clusters, and entities within them, are managed by kubectl. Entities are created by Juju, using the names provided by you.

Ad hoc commands

In the full-OS world, you may often find yourself using juju ssh, juju scp, and juju exec to run arbitrary commands. In Juju within k8s, this functionality is provided by kubectl.

Upcoming Changes: Juju will support juju ssh, juju scp, and juju exec directly into container pods in a future release.


Actions are supported by k8s charms.


Upgrades are the same. Upgrade client, upgrade controller, then upgrade models.

Changing the scale of an application

The juju add-unit and juju remove-unit commands are supplemented by a unified command: juju scale-application.


Writing charms that target Kubernetes is very similar to writing charms for other clouds. There are two important differences:

  • You will need to create a Docker image (or, more correctly, an OCI image) that is attached to the charm as a resource
  • Instead of writing 1 or more configuration files, you create a “Pod Spec” that Juju translates into YAML files for Kubernetes

Further details are available in dedicated Discourse threads:

This doesn’t seem to work in Juju 3.3.1. I get the following errors:

$ juju deploy <charm name> --to
ERROR --to cannot be used on k8s models
$ juju deploy <charm name> --constraints
ERROR options provided but not supported when deploying a bundle: --constraints