This guide covers three main topics for the when writing a charm: preparing the environment, the code and being able to develop it iteratively.
The environment
To ease the development, we suggest you to setup a microk8s environment by running:
snap install juju --classic
snap install microk8s --classic
microk8s enable dns hostpath-storage
juju bootstrap microk8s micro
juju add-model my-charm-model
At this point you have a controller named “micro” in the “microk8s” cloud. This cloud is actually your local machine, how neat! In Juju, you interact with the client (the juju command on your local machine). It connects to a controller. The controller is hosted on a cloud and controls models.
To get you started with the actual first lines of your charm charmcraft has a init
command, so run:
sudo snap install charmcraft --classic
mkdir mycharm
cd mycharm
charmcraft init --name=mycharm
The code
From here on consider that you are in the mycharm
directory. At this point this charm although simple is fully functional. The core of the charm code is in src/charm.py
. You can build and deploy it on your microk8s cloud as following:
charmcraft pack
juju deploy ./mycharm_ubuntu-20.04-amd64.charm --resource httpbin-image=kennethreitz/httpbin
It may take a while to have the deployment finished, in the meantime you can check the status by running:
juju status
The development
You just made a change on the source code of your charm.py
. In order to apply it, rebuild and upgrade the charm:
charmcraft pack
juju upgrade-charm --path="./mycharm.charm" my-charm-model --force-units
Or, if for some reason you want to start from scratch, you can clean up things on different levels, application, model, and controller:
# "mycharm" is the name of the application in the next command,
# which is in "name: mycharm" tag inside metadata.yaml
juju remove-application mycharm --force --no-wait
juju destroy-model my-charm-model --destroy-storage --force --no-wait
juju destroy-controller micro --destroy-all-models
After applying those changes you want to see their effect. Juju logs are handy. First, enable them so that you can see if something fails and a stacktrace is shown or if you add custom log messages. In order to enable TRACE
level at the unit to make everything shows:
juju model-config logging-config="<root>=WARNING;unit=TRACE"
To show the logs for a specific mode:
juju debug-log -m my-charm-model
To show the logs for all the units in the model:
microk8s kubectl get all --namespace=my-charm-model
To see the logs for a specific pod:
microk8s kubectl --namespace=my-charm-model logs mycharm-0
Going further
Now you are ready to start discovering how the operator framework works and learn some more specifics about config, log, testing among other topics.
If you are curious on how other existing operators are implemented refer to the source code of the MongoDB and Elasticsearch operators for inspiration on other topics such as relation, replication and lifecycle management.
If still in doubt you can ask questions about the operator framework. There are multiple communication channels.