Skip to main content

Kubernetes manifest deploy, readiness monitoring, threaded exporter integration, and cleanup tooling.

Project description

swchmonclient

A Python library for deploying the monitoring stack and consuming SLO, constraints and raw metric events over STOMP in the Swarmchestrate project.

Install

pip install swchmonclient

OR

uv add swchmonclient

Overview

  • deploy_monitoring(...) and undeploy_monitoring(...) manage the monitoring manifests from inside Kubernetes.
  • subscribe_metric(...) consumes standard metrics through a shared STOMP listener from EPM.
  • subscribe_metric_raw(...) consumes raw metrics directly from resolved node IPs EPA.
  • Metric values are buffered until query_metric_values(...) or query_metric_values_raw(...) is called.
  • Returned samples are consumed from the in-memory buffers.

Important: deploy_monitoring(...) and undeploy_monitoring(...) use in-cluster Kubernetes configuration. Run them from a pod that has a mounted service account token and RBAC permission to create, patch, get, list, and delete the Kubernetes resources referenced by the monitoring manifests.

Getting started

See the Step-by-step guide for the full deployment and subscription flow.

For runnable scripts, see Examples. For the individual function signatures, see Simple Snippets and the API Reference.

Available Metrics

Metric name Description
cpu_util_prct CPU utilization percentage.

Raw Metric Subscriptions

subscribe_metric_raw(metric, node) supports three selector modes:

  • ["10.0.0.1", "10.0.0.2"] starts one raw listener per explicit node/IP
  • "all" resolves all Kubernetes VM private IPs internally
  • "local" resolves the current Kubernetes node InternalIP and starts one raw listener for it

Important: An explicit node/IP list is the simplest option when running outside Kubernetes-aware environments because it does not require Kubernetes API access.

Important: node="all" requires in-cluster Kubernetes config and RBAC permission to read Kubernetes nodes.

Important: node="local" also uses the Kubernetes API in-cluster. It resolves the current pod, then the node backing that pod, so it needs RBAC permission to read the current pod and its node.

Kubernetes access for all and local

These selectors use the in-cluster Kubernetes API:

  • explicit node/IP list: no Kubernetes API permission needed
  • "all": cluster-wide get and list on nodes
  • "local": get on pods in the service account namespace, plus cluster-wide get and list on nodes

Apply the bundled manifest:

kubectl apply -f ./manifests/mon-client-rbac.yaml

That manifest creates:

  • ServiceAccount mon-client
  • namespace Role + RoleBinding for get pods
  • ClusterRole + ClusterRoleBinding for get,list nodes

If you deploy outside default, update the namespace fields in the manifest before applying it.

The same permissions can be created with imperative kubectl commands:

kubectl create serviceaccount mon-client -n default
kubectl create role mon-client-pod-reader --verb=get --resource=pods -n default
kubectl create rolebinding mon-client-pod-reader \
  --role=mon-client-pod-reader \
  --serviceaccount=default:mon-client \
  -n default
kubectl create clusterrole mon-client-node-reader --verb=get,list --resource=nodes
kubectl create clusterrolebinding mon-client-node-reader \
  --clusterrole=mon-client-node-reader \
  --serviceaccount=default:mon-client

Verify access with:

kubectl auth can-i get pods --as=system:serviceaccount:default:mon-client -n default
kubectl auth can-i get nodes --as=system:serviceaccount:default:mon-client
kubectl auth can-i list nodes --as=system:serviceaccount:default:mon-client

If you see an error like Failed to list Kubernetes nodes: Forbidden or Failed to determine current Kubernetes node IP: Forbidden, the service account can authenticate but does not have enough RBAC to read the required Kubernetes resources.

Testing in a pod

cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: python-shell
spec:
  serviceAccountName: mon-client
  restartPolicy: Never
  containers:
  - name: python-shell
    image: python:3.12-slim
    command: ["bash", "-lc", "sleep infinity"]
    stdin: true
    tty: true
EOF

kubectl exec -it python-shell -- bash
kubectl delete pod python-shell

Inside the pod, verify that the service account token and Kubernetes service env vars are present:

ls /var/run/secrets/kubernetes.io/serviceaccount
env | grep KUBERNETES_SERVICE

Raw subscriptions connect directly to the resolved node IPs. Read buffered raw samples with:

raw_values = query_metric_values_raw("cpu_util_instance", seconds=60)

The returned structure is grouped by node/IP:

{
    "10.0.0.1": [
        {"timestamp": 1716712345.12, "value": 42.0},
    ],
}

Each raw metric on each node/IP keeps up to 1000 cached samples, dropping the oldest entries first when the buffer fills.

If you subscribe multiple raw metrics for the same node/IP, the library reuses the same raw listener thread for that node and dynamically subscribes the additional metric topics on that connection.

API Reference

deploy_monitoring(sat_file: str, optimusdb_url: str = "http://optimusdb.swarmchestrate.sztaki.hu/optimusdb1/swarmkb", use_kb: bool = True, upload_kb: bool = False, logger: logging.Logger | None = None) -> int

Deploys the standard monitoring stack manifests.

This helper uses in-cluster Kubernetes config loaded from the pod's service account. It does not read a local kubeconfig. The service account used by the pod must have RBAC permission to create or patch the Kubernetes resources defined by the monitoring manifests. The sat_file, optimusdb_url, use_kb, and upload_kb values are part of the deployment flow. The sat_file input is a local file path. During deployment, the SAT file is read locally, its basename is converted into a unique filename by appending a UTC timestamp, and that generated filename is injected into the rendered manifest as SAT_FILE. The SAT file content is also deployed as ConfigMap/tosca-model-configmap under the fixed key test-tosca-model.yaml, which is the filename expected by the application. optimusdb_url is optional and defaults to the Swarmchestrate OptimusDB endpoint. By default, use_kb=True, so EMS is configured to resolve the SAT through the knowledge base exposed by the configured optimusdb_url. Set use_kb=False to keep knowledge-base mode disabled in the rendered manifest and use the SAT content from that ConfigMap instead. When upload_kb=True, the SAT file is also uploaded to the knowledge base under that generated unique filename before the Kubernetes resources are deployed. If ./manifests/emsconfig.yaml or ./manifests/ems+netdata-k3s_parametric.yaml is missing locally, the library downloads it from the release assets before deployment. When a local copy already exists, it validates the content against the release asset, logs whether it matches, and keeps the local file if it differs.

Parameter Required Type Description
sat_file Yes str Local SAT file path. Its basename is converted to a unique timestamped filename for SAT_FILE, and its content is loaded into ConfigMap/tosca-model-configmap as test-tosca-model.yaml.
optimusdb_url No str OptimusDB URL injected into the templated manifest. Defaults to the Swarmchestrate OptimusDB endpoint.
use_kb No bool Controls the rendered USE_KB value in emsconfig.yaml. Defaults to True. Set to False to disable knowledge base mode.
upload_kb No bool If True, uploads the SAT file to the knowledge base before deployment. Defaults to False.
logger No logging.Logger | None Custom logger. If omitted, stdout logging is configured automatically.

Output: process-style exit code: 0 on success, 1 if one or more deploy steps fail.

undeploy_monitoring(namespace: str | None = None, logger: logging.Logger | None = None) -> int

Undeploys the monitoring stack manifests and the related cleanup resources.

Like deployment, undeploy uses in-cluster Kubernetes config loaded from the pod's service account and does not read a local kubeconfig. That service account must have RBAC permission to delete the Kubernetes resources defined by the manifests and the additional cleanup resources. Unlike deployment, undeploy does not render emsconfig.yaml and does not require the original sat_file, optimusdb_url, or use_kb values. It deletes ConfigMap/emsconfig and ConfigMap/tosca-model-configmap directly by name and undeploys the remaining manifest-defined resources from the static manifest files.

Parameter Required Type Description
namespace No str | None Namespace override for deleting namespaced resources. If omitted, manifest/default namespaces are used.
logger No logging.Logger | None Custom logger. If omitted, stdout logging is configured automatically.

Output: process-style exit code: 0 on success, 1 if one or more undeploy steps fail.

subscribe_metric(metric: str) -> str

Starts or reuses the shared metric listener for the requested metric topic.

Parameter Required Type Description
metric Yes str Metric name or full topic destination. Plain names are normalized to /topic/<metric>.

Output: str thread name of the shared listener, currently metric-listener.

subscribe_metric_raw(metric: str, node: list[str] | str, cache_size: int | None = None) -> dict[str, str]

Starts raw metric listeners that connect directly to node IPs.

Parameter Required Type Description
metric Yes str Metric name or full topic destination. Plain names are normalized to /topic/<metric>.
node Yes list[str] | str Raw node selector. Use an explicit node/IP list, "all" for all Kubernetes VM private IPs, or "local" for the current Kubernetes node InternalIP.
cache_size No int | None Per raw metric per node sample buffer size. If omitted, the default value 1000 is used.

Output: dict[str, str] mapping each resolved node/IP to the listener thread name started for it.

Notes:

  • Starts one raw listener thread per resolved node/IP and reuses it for additional raw metrics on that same node/IP.
  • Raw subscriptions connect directly to each resolved node/IP instead of MON_CLIENT_STOMP_HOST.
  • Mixing subscribe_metric(...) and subscribe_metric_raw(...) for the same metric is rejected.
  • Important: node="all" and node="local" use in-cluster Kubernetes API access.
  • Important: node="local" needs get pods in the current namespace and get,list nodes cluster-wide.

query_metric_values(metric: str) -> list[Any]

Returns all currently buffered metric values for the metric and consumes those returned samples.

Parameter Required Type Description
metric Yes str Metric name or full topic destination.

Output:

[42.0, 41.7]

query_metric_values_raw(metric: str, seconds: int) -> dict[str, list[dict[str, Any]]]

Returns buffered raw metric values received within the last seconds seconds and consumes those returned samples.

Parameter Required Type Description
metric Yes str Metric name or full topic destination.
seconds Yes int Time window to read from. Must be non-negative.

Output:

{
    "10.0.0.1": [
        {"timestamp": 1716712345.12, "value": 42.0},
    ],
}

unsubscribe_metric(metric: str, nodes: list[str] | None = None) -> None

Stops metric listeners or removes node-specific subscriptions, depending on the subscription mode.

Parameter Required Type Description
metric Yes str Metric name or full topic destination.
nodes No list[str] | None For raw subscriptions, stops only the listed node/IP listeners. For standard subscriptions, blocks those nodes from future samples. If omitted, removes the full subscription.

Output: no return value.

Behavior summary:

  • Standard metric + no nodes: stop the shared listener when the last standard metric is removed.
  • Standard metric + nodes: keep the listener running, but ignore future samples from those nodes.
  • Raw metric + no nodes: stop all raw listeners for that metric.
  • Raw metric + nodes: stop only the listed raw node/IP listeners and remove their cached data buckets.

Examples

Runnable examples are available under examples/:

  • examples/deploy.py
  • examples/undeploy.py
  • examples/subscribe_metric.py
  • examples/subscribe_metric_raw.py

Simple Snippets

deploy_monitoring

from swchmonclient import deploy_monitoring

exit_code = deploy_monitoring(
    "./manifests/stressng.yaml",
    use_kb=True,
    upload_kb=False,
)

undeploy_monitoring

from swchmonclient import undeploy_monitoring

exit_code = undeploy_monitoring(
    namespace="default",
)

subscribe_metric

from swchmonclient import subscribe_metric

thread_name = subscribe_metric("cpu_util_instance")
print(thread_name)

subscribe_metric_raw

from swchmonclient import subscribe_metric_raw

METRIC_NAME = "cpu_util_prct"
NODES = ["10.0.0.1", "10.0.0.2"]

# Option 1: Subscribe to the raw metric for specific nodes.
# Use this when you want metric data only from the nodes listed in the NODES variable.
# threads = subscribe_metric_raw(METRIC_NAME, NODES)

# Option 2: Subscribe to the raw metric for the local node only.
# Use this when you want metric data only from the node running this code.
# threads = subscribe_metric_raw(METRIC_NAME, "local")

# Option 3: Subscribe to the raw metric for all nodes.
# Use this when you want metric data from every available node.
threads = subscribe_metric_raw(METRIC_NAME, "all")

print(threads)

query_metric_values

from swchmonclient import query_metric_values

standard_values = query_metric_values("cpu_util_instance")

query_metric_values_raw

from swchmonclient import query_metric_values_raw

raw_values = query_metric_values_raw("cpu_util_instance", seconds=60)

unsubscribe_metric

from swchmonclient import unsubscribe_metric

unsubscribe_metric("cpu_util_instance")
# or: unsubscribe_metric("cpu_util_instance", nodes=["10.0.0.1"])

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

swchmonclient-0.2.1-py3-none-any.whl (26.5 kB view details)

Uploaded Python 3

File details

Details for the file swchmonclient-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: swchmonclient-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 26.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for swchmonclient-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 63a4ee0a5a4c6eed09bd0029d20953e3872517cfa5b85ead838f331a7efb6a28
MD5 bfa8d079387aec550b9e764792577d89
BLAKE2b-256 dc64521bd1d6be38b48a27cbdf02c76dc96ea94cb6e5b712ae8f714fd8910c35

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page