Skip to content

K8s transformer plugins

Advanced usage

K8s transformer plugins are for specific Kubernetes setups. Most users should use the default Prometheus Operator output.

Version

K8s transformer plugins are available on Sloth >=v0.16.0.

Kubernetes controller only

This feature only works with kubernetes specs mode.

The Sloth k8s operator/controller reconcile loop is additive

On each iteration it creates or updates the Kubernetes objects returned by the transform plugin, but never deletes objects from previous iterations. If the transformer output changes between reconciliations (fewer resources, different names, or a different plugin) stale resources will remain in the cluster.

The default PrometheusRule transformer is unaffected because it always produces a single resource with a fixed name, but custom transform plugins that generate multiple or variably-named resources can leave orphans. For environments where this matters, use an external GitOps tool (e.g. Argo CD, Flux) with Sloth in CLI generator mode, which gives the GitOps controller full ownership of the resource lifecycle including pruning.

Introduction

K8s transformer plugins transform generated Prometheus rules into custom Kubernetes objects. By default, Sloth generates Prometheus Operator PrometheusRule CRs. With transformer plugins, you can output to:

  • ConfigMaps
  • VictoriaMetrics VMRule CRs
  • Google Managed Prometheus Rules
  • ... in the end, any custom K8s resource.

These plugins use Kubernetes' Unstructured API to dynamically create any resource type.

Built-in Plugins

Sloth includes built-in transformer plugins. Check these

Configuration and usage

Loading external custom plugins

Use the common --plugins-path (-p) flag (same as SLI/SLO plugins) to load custom plugins not buil-in in Sloth. Sloth autodiscovers all plugins in the provided paths.

sloth generate -p ./plugins/ --k8s-transform-plugin-id="mycompany.com/custom-plugin/v1"

Developing Custom Plugins

Requirements

  • Define PluginVersion = "prometheus/k8stransform/v1"
  • Define unique PluginID
  • Implement NewPlugin() factory function
  • Single file named plugin.go
  • Only Go standard library + approved packages

Plugin Interface

type Plugin interface {
    TransformK8sObjects(
        ctx context.Context,
        kmeta model.K8sMeta,
        sloResult model.PromSLOGroupResult,
    ) (*K8sObjects, error)
}

Parameters:

  • kmeta: Kubernetes metadata (namespace, name, labels, annotations)
  • sloResult: Generated Prometheus rules for all SLOs
  • Returns: List of unstructured.Unstructured K8s objects

Can return multiple objects to split large outputs.

Available Packages

  • Go standard library (no reflect, unsafe)
  • k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
  • github.com/slok/sloth/pkg/common/model
  • github.com/slok/sloth/pkg/common/utils/k8s
  • github.com/slok/sloth/pkg/prometheus/plugin/k8stransform/v1

Example Plugin

Simplified ConfigMap transformer:

package plugin

import (
    "context"
    "github.com/slok/sloth/pkg/common/model"
    k8sutils "github.com/slok/sloth/pkg/common/utils/k8s"
    plugink8stransformv1 "github.com/slok/sloth/pkg/prometheus/plugin/k8stransform/v1"
    "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)

const (
    PluginVersion = "prometheus/k8stransform/v1"
    PluginID      = "mycompany.com/prometheus-configmap/v1"
)

func NewPlugin() (plugink8stransformv1.Plugin, error) {
    return plugin{}, nil
}

type plugin struct{}

func (p plugin) TransformK8sObjects(
    ctx context.Context,
    kmeta model.K8sMeta,
    sloResult model.PromSLOGroupResult,
) (*plugink8stransformv1.K8sObjects, error) {
    u := &unstructured.Unstructured{}
    u.SetAPIVersion("v1")
    u.SetKind("ConfigMap")
    u.SetNamespace(kmeta.Namespace)
    u.SetName(kmeta.Name)
    u.SetLabels(kmeta.Labels)

    // Collect all rules
    groups := []model.PromRuleGroup{}
    for _, slo := range sloResult.SLOResults {
        groups = append(groups,
            slo.PrometheusRules.SLIErrorRecRules,
            slo.PrometheusRules.MetadataRecRules,
            slo.PrometheusRules.AlertRules,
        )
    }

    // Convert to YAML
    rulesYAML, err := k8sutils.UnstructuredToYAMLString(
        map[string]any{"groups": groups},
    )
    if err != nil {
        return nil, err
    }

    u.Object["data"] = map[string]any{
        "prometheus-rules.yaml": rulesYAML,
    }

    return &plugink8stransformv1.K8sObjects{
        Items: []*unstructured.Unstructured{u},
    }, nil
}

Testing

Use Sloth's testing utilities:

import "github.com/slok/sloth/pkg/prometheus/plugin/k8stransform/v1/testing"

Simulates real plugin execution environment and catches errors early.

Examples

Built-in plugins source code: github.com/slok/sloth/tree/main/internal/plugin/k8stransform