Overview
Duration: 3:00
Before you get started!
Welcome to the world of operators! In this series of tutorials, we will walk you through all the necessary steps to explore and learn operators through some basic examples. Starting with just your laptop, you will learn how to use operators for sophisticated application management at scale, across multiple Kubernetes clusters, cloud virtual machines, and ultimately bare metal.
This tutorial assumes you have successfully completed the previous tutorial - “2. Scale”.
What are operators?
Operators are pieces of software designed to drive other software. They encapsulate the operational code of applications, shifting the burden of lifecycle management from configuration files and manual steps to an operator instance. Operators are a form of automation that is gaining popularity in the Kubernetes domain where traditional configuration management does not work. However, operators work with traditional virtual and bare metal machines as well.
What is Juju OLM?
Juju is a universal Operator Lifecycle Manager (OLM) which provides services to operators. It provides resources for operators, deploys them, manages their lifecycle, delivers configuration updates, etc. Juju OLM is universal, meaning that it supports container substrates like Kubernetes as well as traditional machine substrates like bare metal, VMware, OpenStack, or public cloud instances.
In this tutorial, you will learn how to:
-
Display application configuration options set by operators
-
Modify application configuration options with operators
You will only need:
-
A machine with 8 GB of RAM
-
Microk8s and Juju installed
-
Juju controller bootstrapped on MicroK8s
-
Prometheus deployed to MicroK8s with an operator
Manage application configuration
Duration: 7:00
Operators and Juju OLM provide purposeful config capabilities to abstract many low-level application-specific configuration mechanisms and present them in a form of high-level configuration options, reducing the domain knowledge required to operate applications. All applications come with default values of those configuration options which can be overwritten at a deployment time or post-deployment.
In the following steps, we’ll use purposeful config capabilities to display and modify the configuration options of our application applications.
First, let’s see what the current status of the model is:
$ juju status
Model Controller Cloud/Region Version SLA Timestamp
monitoring mk8s microk8s/localhost 2.9.9 unsupported 11:26:39+01:00
App Version Status Scale Charm Store Channel Rev OS Address Message
prometheus-k8s prom/prometheus:latest active 2 prometheus-k8s charmhub stable 1 kubernetes 10.152.183.7
Unit Workload Agent Address Ports Message
prometheus-k8s/0* active idle 10.1.98.51 9090/TCP
prometheus-k8s/1 active idle 10.1.98.5 9090/TCP
You can display all configuration options for an application using the juju config
command:
$ juju config prometheus-k8s
application: prometheus-k8s
application-config:
juju-application-path:
default: /
description: the relative http path used to access an application
source: default
type: string
value: /
juju-external-hostname:
description: the external hostname of an exposed application
source: unset
type: string
kubernetes-ingress-allow-http:
default: false
description: whether to allow HTTP traffic to the ingress controller
source: default
type: bool
value: false
kubernetes-ingress-class:
default: nginx
description: the class of the ingress controller to be used by the ingress resource
source: default
type: string
value: nginx
kubernetes-ingress-ssl-passthrough:
default: false
description: whether to passthrough SSL traffic to the ingress controller
source: default
type: bool
value: false
kubernetes-ingress-ssl-redirect:
default: false
description: whether to redirect SSL traffic to the ingress controller
source: default
type: bool
value: false
kubernetes-service-annotations:
description: a space separated set of annotations to add to the service
source: unset
type: attrs
kubernetes-service-external-ips:
description: list of IP addresses for which nodes in the cluster will also accept
traffic
source: unset
type: string
kubernetes-service-externalname:
description: external reference that kubedns or equivalent will return as a CNAME
record
source: unset
type: string
kubernetes-service-loadbalancer-ip:
description: LoadBalancer will get created with the IP specified in this field
source: unset
type: string
kubernetes-service-loadbalancer-sourceranges:
description: traffic through the load-balancer will be restricted to the specified
client IPs
source: unset
type: string
kubernetes-service-target-port:
description: name or number of the port to access on the pods targeted by the
service
source: unset
type: string
kubernetes-service-type:
description: determines how the Service is exposed
source: unset
type: string
trust:
default: false
description: Does this application have access to trusted credentials
source: default
type: bool
value: false
charm: prometheus-k8s
settings:
evaluation-interval:
default: 1m
description: |
How frequently rules will be evaluated.
source: default
type: string
value: 1m
external-labels:
default: '{}'
description: |
A JSON string of key-value pairs that specify the labels to
attach to metrics in this Prometheus instance when they get pulled
by an aggregating parent. This is useful in the case of federation
where, for example, you want each datacenter to have its own
Prometheus instance and then have a global instance that pulls from
each of these datacenter instances. By specifying a unique set of
external-labels for each datacenter instance, you can easily determine
in the aggregating Prometheus instance which datacenter a metric is
coming from. Note that you are not limited to one instance per
datacenter. The datacenter example here is arbitrary and you are free
to organize your federation's hierarchy as you see fit.
Ex. '{ "cluster": "datacenter1" }'. Both keys and values may be
arbitrarily chosen as you see fit.
source: default
type: string
value: '{}'
log-level:
description: |
Prometheus server log level (only log messages with the given severity
or above). Must be one of: [debug, info, warn, error, fatal].
If not set, the Prometheus default one (info) will be used.
source: unset
type: string
port:
default: 9090
description: The port prometheus will be listening on
source: default
type: int
value: 9090
prometheus-image-password:
default: ""
description: |
The password associated with prometheus-image-username for
accessing the registry specified in prometheus-image-path.
source: default
type: string
value: ""
prometheus-image-path:
default: prom/prometheus:latest
description: |
The location of the image to use,
e.g. "registry.example.com/prometheus:v1".
This setting is required.
source: default
type: string
value: prom/prometheus:latest
prometheus-image-username:
default: ""
description: |
The username for accessing the registry specified in
prometheus-image-path.
source: default
type: string
value: ""
scrape-interval:
default: 1m
description: |
How frequently to scrape targets by default.
source: default
type: string
value: 1m
scrape-timeout:
default: 10s
description: |
How long until a scrape request times out.
source: default
type: string
value: 10s
ssl-cert:
description: |
SSL certificate to install and use for Prometheus endpoint.
source: unset
type: string
ssl-key:
description: |
SSL key to use with certificate specified as ssl-cert.
source: unset
type: string
tsdb-retention-time:
default: 15d
description: |
How long to retain samples in the storage.
Units Supported: y, w, d, h, m, s
source: default
type: string
value: 15d
tsdb-wal-compression:
default: false
description: |
This flag enables compression of the write-ahead log (WAL).
Depending on your data, you can expect the WAL size to be
halved with little extra cpu load.
source: default
type: boolean
value: false
web-external-url:
default: ""
description: |
The URL under which Prometheus is externally reachable (for example,
if Prometheus is served via a reverse proxy).
Used for generating relative and absolute links back to
Prometheus itself. If the URL has a path portion, it will be used to
prefix all HTTP endpoints served by Prometheus.
If omitted, relevant URL components will be derived automatically.
source: default
type: string
value: ""
Individual configuration values can be viewed by appending a key to the juju config
command:
$ juju config prometheus-k8s web-external-url
You can view the Prometheus web UI by locating the IP address of the Prometheus application and using the browser to navigate to that. Using juju status
locate the Prometheus 0 unit IP address.
$ juju status
...
Unit Workload Agent Address Ports Message
prometheus-k8s/0* active idle 10.1.98.51 9090/TCP
...
Alternatively, you can use jq
to programmatically get that value
$ juju status --format=json | jq -r ".applications | .[\"prometheus-k8s\"] | .units | .[\"prometheus-k8s/0\"] | .address"
Then navigate to the following URL “http://$PROMETHEUS_IP:9090”.
Changing a configuration value will cause the application to evaluate the incoming change and react accordingly. Let’s try changing scrape-interval
from the default value:
$ juju config prometheus-k8s scrape-interval=30s
You can view the change by running:
$ juju config prometheus-k8s scrape-interval
30s
Prometheus will be attempting to scrap any configured endpoints every 30 seconds instead of once a minute.
Next steps
Duration: 2:00
Congratulations! You have reached the end of this tutorial.
You can now move to the next tutorial - “4. Services and ports”.
In this tutorial you have learnt how to:
-
Display application configuration options set by operators
-
Modify application configuration options with operators