Skip to content

Instantly share code, notes, and snippets.

@DnPlas
Last active May 16, 2022 12:33
Show Gist options
  • Save DnPlas/f7563261311a77da5f0fcb923720e313 to your computer and use it in GitHub Desktop.
Save DnPlas/f7563261311a77da5f0fcb923720e313 to your computer and use it in GitHub Desktop.
Operator Day 2022 - Slide Gist
~Operator Day 2022 - Slides Gist
# Copyright 2021 Canonical Ltd.
# See LICENSE file for licensing details.
name: zinc-k8s
display-name: Zinc
description: |
Zinc is a search engine that does full text indexing. It is a lightweight alternative to
elasticsearch and runs in less than 100 MB of RAM. It uses bluge as the underlying indexing
library.
It is very simple and easy to operate as opposed to elasticsearch which requires a couple dozen
knobs to understand and tune.
It is a drop-in replacement for elasticsearch if you are just ingesting data using APIs and
searching using kibana (Kibana is not supported with zinc. Zinc provides its own UI).
summary: |
Zinc is a search engine that does full text indexing. It is a lightweight alternative to
elasticsearch and runs in less than 100 MB of RAM. It uses bluge as the underlying indexing
library.
containers:
zinc:
resource: zinc-image
mounts:
- storage: data
location: /go/bin/data
resources:
zinc-image:
type: oci-image
description: OCI image for zinc
# Included for simplicity in integration tests
upstream-source: public.ecr.aws/m5j1b6u0/zinc:latest
storage:
data:
type: filesystem
location: /zinc-data
# Install/Setup MicroK8s
$ sudo snap install --classic microk8s
$ sudo usermod -aG microk8s $(whoami)
$ sudo microk8s status --wait-ready
$ sudo microk8s enable storage dns ingress
$ sudo snap alias microk8s.kubectl kubectl
$ newgrp microk8s
# Install Charmcraft
$ sudo snap install charmcraft
# Install Juju
$ sudo snap install juju --classic
# Bootstrap MicroK8s
$ juju bootstrap microk8s uk8s
$ juju add-model development
juju bootstrap microk8s micro
juju add-model development
#!/usr/bin/env python3
# Copyright 2021 Canonical Ltd.
# See LICENSE file for licensing details.
#
# Learn more at: https://juju.is/docs/sdk
"""Charmed Operator for Zinc; a lightweight elasticsearch alternative."""
import logging
from ops.charm import CharmBase
from ops.main import main
from ops.model import ActiveStatus
logger = logging.getLogger(__name__)
class ZincCharm(CharmBase):
"""Charmed Operator for Zinc; a lightweight elasticsearch alternative."""
def __init__(self, *args):
super().__init__(*args)
self.framework.observe(self.on.zinc_pebble_ready, self._on_zinc_pebble_ready)
def _on_zinc_pebble_ready(self, event):
"""Define and start a workload using the Pebble API."""
# Get a reference the container attribute on the PebbleReadyEvent
container = event.workload
# Define an initial Pebble layer configuration
pebble_layer = {
"summary": "zinc layer",
"description": "pebble config layer for zinc",
"services": {
"zinc": {
"override": "replace",
"summary": "zinc",
"command": "/go/bin/zinc",
"startup": "enabled",
"environment": {
"DATA_PATH": "/go/bin/data",
"FIRST_ADMIN_USER": "admin",
"FIRST_ADMIN_PASSWORD": "#Pa55word!",
},
}
},
}
container.add_layer("zinc", pebble_layer, combine=True)
container.autostart()
self.unit.status = ActiveStatus()
if __name__ == "__main__":
main(ZincCharm)
# ---- BUILD & DEPLOY
# Build the charm
$ charmcraft pack
# Deploy the charm
$ juju deploy ./zinc-k8s_*.charm --resource zinc-image=public.ecr.aws/m5j1b6u0/zinc:latest
# ---- CHECK STATUS
# Check the Juju status
$ watch -n1 --color juju status --color
# ---- VERIFY
# You should then be able to browse to http://<address>:4080
# In this example http://10.1.184.215:4080
# ---- JUJU DEBUG-LOG
# Set the log level to DEBUG for the development model
$ juju model-config logging-config="<root>=WARNING;unit=DEBUG"
# Follow the debug-log
$ juju debug-log
# ---- KUBECTL
$ kubectl -n development get pods
NAME READY STATUS RESTARTS AGE
modeloperator-6576fc7b6f-k4mb5 1/1 Running 1 22h
zinc-k8s-0
# Copyright 2021 Canonical Ltd.
# See LICENSE file for licensing details.
get-admin-password:
description: |
Get the initial admin password for Zinc. This is generated at charm deployment time. If the
password has been changed using the Zinc UI/API, this will not be valid.
#!/usr/bin/env python3
# Copyright 2021 Canonical Ltd.
# See LICENSE file for licensing details.
"""Charmed Operator for Zinc; a lightweight elasticsearch alternative."""
import logging
import secrets
import string
from charms.observability_libs.v0.kubernetes_service_patch import KubernetesServicePatch
from ops.charm import ActionEvent, CharmBase, WorkloadEvent
from ops.framework import StoredState
from ops.main import main
from ops.model import ActiveStatus
from ops.pebble import Layer
logger = logging.getLogger(__name__)
class ZincCharm(CharmBase):
"""Charmed Operator for Zinc; a lightweight elasticsearch alternative."""
_stored = StoredState()
def __init__(self, *args):
super().__init__(*args)
self._stored.set_default(initial_admin_password="")
self.framework.observe(self.on.zinc_pebble_ready, self._on_zinc_pebble_ready)
self.framework.observe(self.on.get_admin_password_action, self._on_get_admin_password)
self._service_patcher = KubernetesServicePatch(self, [(self.app.name, 4080, 4080)])
def _on_zinc_pebble_ready(self, event: WorkloadEvent):
"""Define and start a workload using the Pebble API."""
# Get a reference the container attribute on the PebbleReadyEvent
container = event.workload
# If we've not got an initial admin password, then generate one
if not self._stored.initial_admin_password:
self._stored.initial_admin_password = self._generate_password()
# Define an initial Pebble layer configuration
container.add_layer("zinc", self._pebble_layer, combine=True)
container.autostart()
self.unit.status = ActiveStatus()
def _on_get_admin_password(self, event: ActionEvent) -> None:
"""Returns the initial generated password for the admin user as an action response."""
if not self._stored.initial_admin_password:
self._stored.initial_admin_password = self._generate_password()
event.set_results({"admin-password": self._stored.initial_admin_password})
@property
def _pebble_layer(self) -> Layer:
return Layer(
{
"services": {
"zinc": {
"override": "replace",
"summary": "zinc",
"command": "/go/bin/zinc",
"startup": "enabled",
"environment": {
"DATA_PATH": "/go/bin/data",
"FIRST_ADMIN_USER": "admin",
"FIRST_ADMIN_PASSWORD": self._stored.initial_admin_password,
},
}
},
}
)
def _generate_password(self) -> str:
"""Generates a random 24 character password."""
chars = string.ascii_letters + string.digits
return "".join(secrets.choice(chars) for _ in range(24))
if __name__ == "__main__": # pragma: nocover
main(ZincCharm, use_juju_for_storage=True)
# canonical/template-operator
https://github.com/canonical/template-operator
# zinc-k8s-operator
https://github.com/jnsgruk/zinc-k8s-operator
# ---- BUILD AGAIN
# Build the charm
$ charmcraft pack
# Remove old charm (cannot refresh -- storage)
$ juju remove-application zinc-k8s –destroy-storage
# Refresh the deployment
$ juju deploy ./zinc-k8s_*.charm --resource zinc-image=public.ecr.aws/m5j1b6u0/zinc:v0.1.1
# Check the juju status
$ watch -n1 --color juju status --color
# ---- RUN ACTION
# Run the action
$ juju run-action zinc-k8s/0 get-admin-password --wait
unit-zinc-k8s-0:
UnitId: zinc-k8s/0
id: "4"
results:
admin-password: axGqZeFWJGlLZH7OpQXCRPM8
status: completed
# ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment