Set up your development environment

You can develop a charm however you want, and in any language; however, the current standard is to use Charmcraft and to develop in Python using Ops. To test it, you’ll need a cloud – we recommend MicroK8s / LXD (for Kubernetes / machine charms) which you can set up on your local workstation – and Juju. Finally, you can develop directly on your machine but it is always a good idea to work in an isolated development environment; for that, we recommend a Multipass VM.

See more: Charmcraft (charmcraft), Ops (ops), Juju | MicroK8su, Juju | LXD, Multipass

There are two ways to get all this set up: you can do it all step by step manually or you can take advantage of the Multipass charm-dev blueprint.

We demonstrate both below, starting with the automatic method which is designed to streamline the whole process for you.

Advanced charm development may require integrating with larger deployments. In those cases, a local MicroK8s or LXD provider may not be sufficient, and you may want to work with a bigger cloud. For that see the full list of Juju-supported clouds.

Set up your development environment automatically

  1. Create a directory for your charm
  2. Set up an Ubuntu charm-dev-vm VM with Multipass
  3. Choose your cloud and workload model
  4. Mount your charm directory to the Multipass VM
  5. Clean up

Create a directory for your charm

On your workstation, create a directory for your charm. E.g., on Linux, open a shell and run:

mkdir ~/my-charm

Set up an Ubuntu charm-dev-vm VM with Multipass

Multipass is a tool that will help you quickly spin up an Ubuntu VM.

Read more: Multipass

  1. Install Multipass:
sudo snap install multipass
  1. Use Multipass to launch an Ubuntu VM called ‘charm-dev-vm’ using the charm-dev blueprint:
multipass launch --cpus 4 --memory 8G --disk 50G --name charm-dev-vm charm-dev 

This step may take a few minutes to complete (e.g., 10 mins).

This is because the command downloads, installs, (updates,) and configures a number of packages, and the speed will be affected by network bandwidth (not just your own, but also that of the package sources).

However, once it’s done, you’ll have everything you’ll need – all in a nice isolated environment that you can clean up easily.

  1. Open a shell into the VM:
multipass shell charm-dev-vm
  1. (Optional:) Verify that the VM has indeed come pre-equipped with you’ll need:

Verify that you have Charmcraft:

charmcraft # should show a quick summary

Verify that you have a version of Python that meets the requirements from Ops:

python3 --version # should show Python >= 3.8 

Take stock of any other pre-installed Python packages:

pip list # should show, e.g., requests, tox, toml, virtualenv

Verify that you have Juju, MicroK8s (for k8s charms) / LXD (for machine charms), a MicroK8s / LXD cloud (microk8s / localhost), a controller on that cloud (microk8s / lxd), and a workload model on that controller (welcome-k8s / welcome-lxd) :


Expand to see the instructions for MicroK8s
kubectl version
juju status --model microk8s:controller
juju status --model microk8s:welcome-k8s

Expand to see the instructions for LXD
lxc version
juju status --model lxd:controller
juju status --model lxd:welcome-lxd

Choose your cloud and workload model


Expand to see the instructions for MicroK8s
juju switch microk8s:welcome-k8s

Expand to see the instructions for LXD
juju switch lxd:welcome-lxd

Mount your charm directory to the Multipass VM

Use the multipass mount command. E.g., on Linux, open another shell and run:


multipass mount ~/my-charm charm-dev-vm:~/my-charm

You should now see a copy of your local charm directory on your VM as well. In your Multipass VM shell, run ls to verify:

ubuntu@charm-dev-vm:~$ ls
my-charm  snap

With this setup you’ll be able to use all the tools preinstalled on the VM to initialise, pack, deploy, etc., your charm while also being able to edit the charm files in your own favourite local editor.

  • Going forward:

    • Use your host machine (on Linux, cd ~/my-charm) to create and edit your charm files. This will allow you to use your favorite local editor.
    • Use the Multipass VM shell (on Linux, ubuntu@charm-dev-vm:~$ cd ~/my-charm) to run Charmcraft and Juju commands.
  • At any point:

    • To exit the shell, press mod key + C or type exit.
    • To stop the VM after exiting the VM shell, run multipass stop charm-dev-vm.
    • To restart the VM and re-open a shell into it, type multipass shell charm-dev-vm.

Clean up

Delete the Multipass VM:

multipass delete --purge charm-dev

Uninstall Multipass: Linux | macOS | Windows.

Set up your development environment manually

  1. Create a directory for your charm
  2. (Optional) Set up an Ubuntu VM with Multipass
  3. Set up Charmcraft
  4. Set up all the tools you’ll need for development in Python with Ops
  5. Set up your cloud
  6. Set up Juju
  7. (Optional) Set up Docker to publish your charm on Charmhub
  8. (Optional) Mount your charm directory to the Multipass VM
  9. (Optional) Clean up

Create a directory for your charm

On your workstation, create a directory for your charm. E.g., on Linux, open a shell and run:

mkdir ~/my-charm

(Optional) Set up an Ubuntu VM with Multipass

Multipass is a tool that will help you quickly spin up an Ubuntu VM.

Read more: Multipass

The goal of this section is to help you get a Linux machine that supports installation from snap, so that you can install Charmcraft.

If you already have that, we still recommend this step as a way for you to experiment in an isolated development environment.

If you however wish to continue directly on your existing Linux machine, just skip this step.

However, please keep in mind that the instructions in this tutorial have only been tested for the scenario with Multipass.

  1. Install Multipass: Linux | macOS | Windows. On Linux (assumes you have snapd):
sudo snap install multipass
  1. Use Multipass to launch an Ubuntu VM called ‘charm-dev-vm’:
multipass launch --cpus 4 --memory 8G --disk 50G --name charm-dev-vm
  1. Open a shell into the VM:
multipass shell charm-dev-vm

Set up Charmcraft

E.g., on your Multipass VM:

# Charmcraft relies on LXD. Your Multipass VM already has LXD, but you must configure it:
lxd init --auto

# Install Charmcraft:
sudo snap install charmcraft --classic

See more: Install Charmcraft

Set up all the tools you’ll need for development in Python with Ops

Ops requires Python 3.8+. Check that you have that. E.g., on your Multipass VM:

python3 --version

Development with Ops usually requires some other Python tools as well. Make sure to get them ready. For example, install Tox – on your Multipass VM, as below:

# tox depends on  Python and pip
sudo apt update; sudo apt install python3 python3-pip

# Use pip to get tox:
python3 -m pip install --user tox

Set up your cloud

Depending on whether you want to develop a Kubernetes / machine charm, you will have to set up the MicroK8s / LXD localhost cloud. For example, on Linux:


Expand to set up your MicroK8s cloud
# Install MicroK8s package:
sudo snap install microk8s --channel 1.28-strict

# Add your user to the `microk8s` group for unprivileged access:
sudo adduser $USER snap_microk8s

# Give your user permissions to read the ~/.kube directory:
sudo chown -f -R $USER ~/.kube

# Wait for MicroK8s to finish initialising:
sudo microk8s status --wait-ready

# Enable the 'storage' and 'dns' addons:
# (required for the Juju controller)
sudo microk8s enable hostpath-storage dns

# Alias kubectl so it interacts with MicroK8s by default:
sudo snap alias microk8s.kubectl kubectl

# Ensure your new group membership is apparent in the current terminal:
# (Not required once you have logged out and back in again)
newgrp snap_microk8s

Expand to set up your LXD cloud
# lxd init --auto # should already be there from the Charmcraft setup step
lxc network set lxdbr0 ipv6.address none

Set up Juju

On your Ubuntu VM, install Juju, connect it to your MicroK8s cloud, and create a model:

# Install Juju:
sudo snap install juju --channel 3.1/stable
# >>> juju (3.1/stable) 3.1.2 from Canonical✓ installed

# Since the juju package is strictly confined, you also need to manually create a path:
mkdir -p ~/.local/share

# For MicroK8s, if you are working with an existing snap installation, and it is not strictly confined: 
# (https://microk8s.io/docs/strict-confinement), you must also:
#
# # Share the MicroK8s config with Juju:
# sudo sh -c "mkdir -p /var/snap/juju/current/microk8s/credentials"
# sudo sh -c "microk8s config | tee /var/snap/juju/current/microk8s/credentials/client.config"
#
# # Give the current user permission to this file:
# sudo chown -f -R $USER:$USER /var/snap/juju/current/microk8s/credentials/client.config

# Register your MicroK8s / LXD cloud with Juju:
# Not necessary --juju recognises a local MicroK8s / LXD cloud automatically, as you can see by running 'juju clouds'. 
juju clouds
# >>> Cloud      Regions  Default    Type  Credentials  Source    Description
# >>> localhost  1        localhost  lxd   0            built-in  LXD Container Hypervisor
# >>> microk8s   1        localhost  k8s   1            built-in  A Kubernetes Cluster
# (If for any reason this doesn't happen, you can register it manually using 'juju add-k8s microk8s'.)

# Replace <cloud> with 'microk8s' or 'localhost' 
# to bootstrap a Juju controller into your  MicroK8s / LXD cloud. 
# We'll name our controller "dev-controller".
juju bootstrap <cloud> dev-controller

# Create a workspace, or 'model', on this controller. 
# We'll call ours "dev-model".
# Reminder: In Kubernetes this corresponds to a namespace "dev-model".
juju add-model dev-model

# Check status:
juju status
# >>> Model         Controller           Cloud/Region        Version  SLA          Timestamp
# >>> dev-model  tutorial-controller  microk8s/localhost  3.0.2    unsupported  16:05:03+01:00

# >>> Model "admin/dev-model" is empty.

# There's your charm model!

(Optional) Set up Docker to publish your charm on Charmhub

E.g., on your Multipass VM:

sudo addgroup --system docker
sudo adduser $USER docker
newgrp docker
sudo snap install docker

(Optional) Mount your charm directory to the Multipass VM

If earlier you decided to use Multipass, mount your local charm directory to the charm VM. E.g., on Linux:

multipass mount ~/my-charm charm-dev:~/my-charm

This will allow you to use all the tools from the VM to initialise, pack, deploy, etc., your charm while also being able to edit the charm files in your own favourite local editor.

(Optional) Clean up

If earlier you decided to use Multipass, delete the Multipass VM:

multipass delete --purge charm-dev-vm

Uninstall Multipass: Linux | macOS | Windows.

Contributors: @jnsgruk , @kos.tsakalozos , @rbarry , @facundo , @saviq , @sed-i , @tmihoc , @gbeuzeboc , @acsgn , @gzanchi , @jose-mingorance

Hi, here are some suggestions that might improve this page.

  • The structure in this page is confusing. We start by saying that in order to create a charm we need Multipass (optional), MicroK8s, Juju and Charmcraft. The page assumes we are building a K8s charms and we go as far to say in the instructions of Juju to bootstrap onto MicroK8s. Then comes a disconnected section saying “If you are doing a machine charm use LXD”. Instead we should be clear at the very beginning stating that the tools you need to build a charm are Charmcraft, Juju and Multipas (optional). If you target k8s charms you can use MicroK8s if you target machine charms use LXD. When describing the MicroK8s and LXD substrates we should mention the way Juju bootstraps on them.

  • I would expect to be able to find the charmcraft snap with snap search charmcraft but it is not there.

I’m surprised charmcraft doesn’t appear considering it is in fact on the Snapcraft store. @facundo any idea why?

My guess is that it is “unlisted” - that is you can install it, and you can navigate directly to the URL in the Snap store, but it doesn’t appear in listings/searches. Same for the store search: Snap search results for 'charmcraft' — Linux software in the Snap Store

@facundo @roadmr Do we think now that Charmcraft is in latest/stable we should tidy up the store page and get it listed? We just need someone that’s handy with a pencil to come up with a catchy icon for it :sunglasses:

I’ll bring this to the team.

Multipass isn’t --classic for a while now, care to remove that bit?

1 Like

done, thanks! (fwiw these posts are wikis so they should be editable by most people on here :))

Ah, I only just created an account, thought I’d need a bit more trust to edit, didn’t actually check ¯\(ツ)/¯.

Should ingress be included here?

So I included this because this guide was linked extensively during the “Hello, Kubecon!” talk at the last Operator Day, which included using the nginx-ingress-integrator library. It’s not strictly necessary, but it is if you want to use an nginx ingress controller without doing all the work yourself :slight_smile:

The command

$ sudo snap install charmcraft

Doesn’t seem to work. Charmcraft appear to be a classic snap.

$ sudo snap install charmcraft --classic

On the contrary, juju is mentioned to be installed with --classic while it’s a strictly confined snap.

It appears that the new group of the strictly confined microk8s is no longer microk8s but snap_microk8s.

Thanks for this! I’ve fixed this and the MicroK8s group name issue.

Hi,

Thanks for the tutorial, I went through it and would like to raise 2 small typos in commands:

Replace

python 3 --version

with

python3 --version

(link to doc)

And replace

snap install microk8s --channel 1.28-strict

with

sudo snap install microk8s --channel 1.28-strict

(link to doc)

1 Like

@ggouzi Fixed, thanks! (Also added you as a contributor to this doc.)

1 Like

The statement

# sudo sh -c "microk8s config | tee /var/snap/juju/current/microk8s/credentials/client.config"

shall silently fail if the directory /var/snap/juju/current/microk8s/credentials does not exist prior to executing the command. This is a real use case and I experienced it as Microk8s user multiple times. In that case, Juju is not able to access Microk8s and the user reading this document will not immediately understand why, since there is no error message produced to the CLI.

Therefore, I believe the statement should become this:

# sudo sh -c "mkdir -p /var/snap/juju/current/microk8s/credentials && microk8s config | tee /var/snap/juju/current/microk8s/credentials/client.config"

or alternatively:

# sudo sh -c "mkdir -p /var/snap/juju/current/microk8s/credentials"
# sudo sh -c "microk8s config | tee /var/snap/juju/current/microk8s/credentials/client.config"

@jnsgruk let me know if that makes sense, and is a change we can incorporate in to this document. I think it is a bit of a negative experience for a beginner with Juju, who reads Juju is aware of Microk8s out-of-the-box and then finds out it is not.

Hey! Yes we can certainly update that - you should be able to edit it but I’ll just loop in @tmihoc too.

I’m a bit confused why this happens, though - I wonder if we should just fix Juju! @jameinel?

1 Like

@jose-mingorance Thanks for catching this. Imo the two-step version is easier to look at. That said, please feel free to edit directly. Also add yourself to the list of contributors on the bottom of the doc. And thanks again!

@jameinel pinging you again so we remember to look into this.

As I understand it, the issue is that juju is aware of microk8s, but because Juju 3.* and beyond is a confined snap (no longer --classic), it can only be aware of other confined snaps (the snap confinement model says that auto-connecting a confined snap to an unconfined snap would essentially unconfine the snap).

To get automatic connection, you have to install microk8s from one of the -strictchannels (sudo snap install microk8s --channel 1.30-strict, 1.29-strict, etc).

We do explicitly state this fact, but maybe not in the most obvious of ways:

$ juju bootstrap microk8s mk8s
ERROR "/var/snap/juju/28060/microk8s/credentials/client.config" does not exist: juju "3.5.3" can only work with strictly confined microk8s

Because of historical reasons, they aren’t ready to make -strict the default channel. I think we were avoiding doing a lot of work here, because we were hoping they would move more quickly towards getting strict to be the default installation.

Looking at the snap install, we already have a ‘/var/snap/juju/current/microk8s’ directory, we just don’t have ‘/var/snap/juju/current/microk8s/credentials’ by default. There doesn’t seem to be any reason why we shouldn’t be able to build the extra directory.

Though I also wonder why we’re suggesting to tee to the directory vs

microk8s config | juju add-k8s --client microk8s

That avoids poking at secret configuration files, and sudo access, etc.

1 Like