The Charmed Operator Framework
The Charmed Operator Framework allows the development of operators in a simple and straightforward way, using standard Python structures to allow for clean, maintainable, and reusable code. Charmcraft is a command line tool used alongside the Operator Framework to create, build, and publish operators (packaged as charms).
A Kubernetes operator is a container that drives lifecycle management, configuration, integration and daily actions for an application. Operators simplify software management and operations. They capture reusable app domain knowledge from experts in a software component that can be shared.
The Charmed Operator Framework extends the operator pattern to enable Charmed Operators, packaged as and often referred to as “charms”. Charms are not just for Kubernetes but also operators for traditional Linux or Windows application management. Operators use an Operator Lifecycle Manager (OLM), like Juju, to coordinate their work in a cluster. The system uses Golang for concurrent event processing under the hood, but enables the operators to be written in Python.
Operators should ‘do one thing and do it well’. Each operator drives a single application or service and can be composed with other operators to deliver a complex application or service. An operator handles instantiation, scaling, configuration, optimisation, networking, service mesh, observability, and day-2 operations specific to that application.
Juju’s beginnings were centered around simplifying the deployment of complex applications and services in a cloud-first world. At the time, many of those applications were run in virtual machines or on bare-metal servers, and deployments to these environments continue to enjoy first-class support. A machine charm can be deployed to a number of different underlying compute/storage resource providers:
- Bare-metal (perhaps using MAAS)
- A virtual machine (on public or private cloud)
- A LXD cluster
More recently, the Juju OLM introduced support for Charmed Operators on Kubernetes. Juju can bring the same benefits to applications deployed on Kubernetes, by placing operators alongside workloads to manage them throughout their lifecycle. When a model is created with Juju, a corresponding Kubernetes namespace is created. When a charm is deployed on Kubernetes, it is deployed as a StatefulSet that manages a set of Pods running the specified application containers alongside a sidecar container containing the charm code.
By definition, the sidecar pattern is designed to allow the augmentation of workloads with additional capabilities and features. The pattern is implemented in this case by a small auxiliary container, located in the same Pod as your application, that provides operations functionality - this is exactly how Juju operates in other environments, and a well-established pattern in the Kubernetes community.
By utilising this pattern, we ensure that there is always an operator right next to every unit of the workload, irrespective of how the application is scaled. The operator will always have direct access to shared memory, the same network namespace and the ability to manipulate the workload as required to keep it running smoothly. This approach simplifies the operation of upstream or third-party application images, enabling administrators to make changes at runtime to suit their environment should they wish, without the requirement to maintain a fleet of bespoke container images.
For charm developers, these benefits are realised by utilising Pebble to manage workloads. Pebble is a lightweight, API-driven process supervisor designed for use with Charmed Operators. Pebble enables charm developers to define how they want workloads to run, and provides an API that enables operations code to manage the workloads throughout their life.
Subordinate charms were created to enable the development of charms that could be deployed alongside existing charms, to augment them with specific functionality that may not be included in the original application charm. They are, in many ways, analogous to the sidecars described above. All charms are principal charms, except those that are subordinates. A subordinate charm depends on the creation of a relationship to a principal charm, it is never deployed as a standalone application. This is best explained with an example:
Consider the deployment of a large web application scaled to
n replicas. Each instance of the charm comprises a
unit, in Juju parlance, and an
App is the sum of all units of a given charm with the same name. When a large web application is scaled to
units will be started by Juju.
The administrators of the web application will likely want to collect logs from the application server. The developer of the application charm may not have included a mechanism for forwarding logs from the service that is compatible with the administrator’s specific environment. By using a subordinate charm such as
rsyslog-forwarder, the administrator can ensure that each deployed unit of their web application is automatically configured to forward logs using
rsyslog. To do this, they must simply deploy the subordinate and
juju relate their web application to it.
Subordinate charms are written in the same way as other charms, with the addition of an extra
subordinate flag in the charm’s metadata.
One of the most powerful concepts in Juju deployments is the way application deployments are modelled. A single Juju controller can interact with multiple underlying substrates, be those bare-metal private clouds, public clouds or a hand-crafted Kubernetes cluster. Irrespective of the substrate they are deployed upon, charms can be related using cross-model relations. This enables seamless interoperability between substrates, where the Juju OLM handles all of the networking, permissions and configuration on your behalf.
For example, if you already bootstrapped a database cluster on bare-metal using Juju, but your new web application runs on Kubernetes, you can just
juju relate your different charms for seamless integration across clouds.
Last updated 2 months ago.