This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Plugin Catalog

Plugin Catalog overview

This section provides an overview of the available PluginDefinitions in Greenhouse.

1 - Alerts

This plugin extension contains Prometheus Alertmanager via prometheus-operator and Supernova, the holistic alert management UI.

Owner

  1. Richard Tief (@richardtief)
  2. Tommy Sauer (@viennaa)
  3. Martin Vossen (@artherd42)

alerts alertmanager parameters

NameDescriptionValue
alerts.commonLabelsLabels to apply to all resources{}
alerts.alertmanager.enabledDeploy Prometheus Alertmanagertrue
alerts.alertmanager.annotationsAnnotations for Alertmanager{}
alerts.alertmanager.configAlertmanager configuration directives.{}
alerts.alertmanager.ingress.enabledDeploy Alertmanager Ingressfalse
alerts.alertmanager.ingress.hostsMust be provided if Ingress is enabled.[]
alerts.alertmanager.ingress.tlsMust be a valid TLS configuration for Alertmanager Ingress. Supernova UI passes the client certificate to retrieve alerts.{}
alerts.alertmanager.ingress.ingressClassnameSpecifies the ingress-controllernginx
alerts.alertmanager.servicemonitor.additionalLabelskube-monitoring plugin: <plugin.name> to scrape Alertmanager metrics.{}
alerts.alertmanager.alertmanagerConfig.slack.routes[].nameName of the Slack route.""
alerts.alertmanager.alertmanagerConfig.slack.routes[].channelSlack channel to post alerts to. Must be defined with slack.webhookURL.""
alerts.alertmanager.alertmanagerConfig.slack.routes[].webhookURLSlack webhookURL to post alerts to. Must be defined with slack.channel.""
alerts.alertmanager.alertmanagerConfig.slack.routes[].matchersList of matchers that the alert’s label should match. matchType , name , regex , value[]
alerts.alertmanager.alertmanagerConfig.webhook.routes[].nameName of the webhook route.""
alerts.alertmanager.alertmanagerConfig.webhook.routes[].urlWebhook url to post alerts to.""
alerts.alertmanager.alertmanagerConfig.webhook.routes[].matchersList of matchers that the alert’s label should match. matchType , name , regex , value[]
alerts.defaultRules.createCreates community Alertmanager alert rules.true
alerts.defaultRules.labelskube-monitoring plugin: <plugin.name> to evaluate Alertmanager rules.{}
alerts.alertmanager.alertmanagerSpec.alertmanagerConfigurationAlermanagerConfig to be used as top level configurationfalse

alerts supernova parameters

theme: Override the default theme. Possible values are "theme-light" or "theme-dark" (default)

endpoint: Alertmanager API Endpoint URL /api/v2. Should be one of alerts.alertmanager.ingress.hosts

silenceExcludedLabels: SilenceExcludedLabels are labels that are initially excluded by default when creating a silence. However, they can be added if necessary when utilizing the advanced options in the silence form.The labels must be an array of strings. Example: ["pod", "pod_name", "instance"]

filterLabels: FilterLabels are the labels shown in the filter dropdown, enabling users to filter alerts based on specific criteria. The ‘Status’ label serves as a default filter, automatically computed from the alert status attribute and will be not overwritten. The labels must be an array of strings. Example: ["app", "cluster", "cluster_type"]

predefinedFilters: PredefinedFilters are filters applied through in the UI to differentiate between contexts through matching alerts with regular expressions. They are loaded by default when the application is loaded. The format is a list of objects including name, displayname and matchers (containing keys corresponding value). Example:

[
  {
    "name": "prod",
    "displayName": "Productive System",
    "matchers": {
      "region": "^prod-.*"
    }
  }
]

silenceTemplates: SilenceTemplates are used in the Modal (schedule silence) to allow pre-defined silences to be used to scheduled maintenance windows. The format consists of a list of objects including description, editable_labels (array of strings specifying the labels that users can modify), fixed_labels (map containing fixed labels and their corresponding values), status, and title. Example:

"silenceTemplates": [
    {
      "description": "Description of the silence template",
      "editable_labels": ["region"],
      "fixed_labels": {
        "name": "Marvin",
      },
      "status": "active",
      "title": "Silence"
    }
  ]

Managing Alertmanager configuration

ref:

By default, the Alertmanager instances will start with a minimal configuration which isn’t really useful since it doesn’t send any notification when receiving alerts.

You have multiple options to provide the Alertmanager configuration:

  1. You can use alerts.alertmanager.config to define a Alertmanager configuration. Example below.
config:
  global:
    resolve_timeout: 5m
  inhibit_rules:
    - source_matchers:
        - "severity = critical"
      target_matchers:
        - "severity =~ warning|info"
      equal:
        - "namespace"
        - "alertname"
    - source_matchers:
        - "severity = warning"
      target_matchers:
        - "severity = info"
      equal:
        - "namespace"
        - "alertname"
    - source_matchers:
        - "alertname = InfoInhibitor"
      target_matchers:
        - "severity = info"
      equal:
        - "namespace"
  route:
    group_by: ["namespace"]
    group_wait: 30s
    group_interval: 5m
    repeat_interval: 12h
    receiver: "null"
    routes:
      - receiver: "null"
        matchers:
          - alertname =~ "InfoInhibitor|Watchdog"
  receivers:
    - name: "null"
  templates:
    - "/etc/alertmanager/config/*.tmpl"
  1. You can discover AlertmanagerConfig objects. The spec.alertmanagerConfigSelector is always set to matchLabels: plugin: <name> to tell the operator which AlertmanagerConfigs objects should be selected and merged with the main Alertmanager configuration. Note: The default strategy for a AlertmanagerConfig object to match alerts is OnNamespace.
apiVersion: monitoring.coreos.com/v1alpha1
kind: AlertmanagerConfig
metadata:
  name: config-example
  labels:
    alertmanagerConfig: example
    pluginDefinition: alerts-example
spec:
  route:
    groupBy: ["job"]
    groupWait: 30s
    groupInterval: 5m
    repeatInterval: 12h
    receiver: "webhook"
  receivers:
    - name: "webhook"
      webhookConfigs:
        - url: "http://example.com/"
  1. You can use alerts.alertmanager.alertmanagerSpec.alertmanagerConfiguration to reference an AlertmanagerConfig object in the same namespace which defines the main Alertmanager configuration.
# Example with select a global alertmanagerconfig
alertmanagerConfiguration:
  name: global-alertmanager-configuration

Examples

Deploy alerts with Alertmanager

apiVersion: greenhouse.sap/v1alpha1
kind: Plugin
metadata:
  name: alerts
spec:
  pluginDefinition: alerts
  disabled: false
  displayName: Alerts
  optionValues:
    - name: alerts.alertmanager.enabled
      value: true
    - name: alerts.alertmanager.ingress.enabled
      value: true
    - name: alerts.alertmanager.ingress.hosts
      value:
        - alertmanager.dns.example.com
    - name: alerts.alertmanager.ingress.tls
      value:
        - hosts:
            - alertmanager.dns.example.com
          secretName: tls-alertmanager-dns-example-com
    - name: alerts.alertmanagerConfig.slack.routes
      value:
        - channel: slack-warning-channel
          webhookURL: https://hooks.slack.com/services/some-id
          matchers:
            - name: severity
              matchType: "="
              value: "warning"
        - channel: slack-critical-channel
          webhookURL: https://hooks.slack.com/services/some-id
          matchers:
            - name: severity
              matchType: "="
              value: "critical"
    - name: alerts.alertmanagerConfig.webhook.routes
      value:
        - name: webhook-route
          url: https://some-webhook-url
          matchers:
            - name: alertname
              matchType: "=~"
              value: ".*"
    - name: alerts.alertmanager.serviceMonitor.additionalLabels
      value:
        plugin: kube-monitoring
    - name: alerts.defaultRules.create
      value: true
    - name: alerts.defaultRules.labels
      value:
        plugin: kube-monitoring
    - name: endpoint
      value: https://alertmanager.dns.example.com/api/v2
    - name: filterLabels
      value:
        - job
        - severity
        - status
    - name: silenceExcludedLabels
      value:
        - pod
        - pod_name
        - instance

Deploy alerts without Alertmanager (Bring your own Alertmanager - Supernova UI only)

apiVersion: greenhouse.sap/v1alpha1
kind: Plugin
metadata:
  name: alerts
spec:
  pluginDefinition: alerts
  disabled: false
  displayName: Alerts
  optionValues:
    - name: alerts.alertmanager.enabled
      value: false
    - name: alerts.alertmanager.ingress.enabled
      value: false
    - name: alerts.defaultRules.create
      value: false
    - name: endpoint
      value: https://alertmanager.dns.example.com/api/v2
    - name: filterLabels
      value:
        - job
        - severity
        - status
    - name: silenceExcludedLabels
      value:
        - pod
        - pod_name
        - instance

2 - Cert-manager

This Plugin provides the cert-manager to automate the management of TLS certificates.

Configuration

This section highlights configuration of selected Plugin features.
All available configuration options are described in the plugin.yaml.

Ingress shim

An Ingress resource in Kubernetes configures external access to services in a Kubernetes cluster.
Securing ingress resources with TLS certificates is a common use-case and the cert-manager can be configured to handle these via the ingress-shim component.
It can be enabled by deploying an issuer in your organization and setting the following options on this plugin.

OptionTypeDescription
cert-manager.ingressShim.defaultIssuerNamestringName of the cert-manager issuer to use for TLS certificates
cert-manager.ingressShim.defaultIssuerKindstringKind of the cert-manager issuer to use for TLS certificates
cert-manager.ingressShim.defaultIssuerGroupstringGroup of the cert-manager issuer to use for TLS certificates

3 - Decentralized Observer of Policies (Violations)

This directory contains the Greenhouse plugin for the Decentralized Observer of Policies (DOOP).

DOOP

To perform automatic validations on Kubernetes objects, we run a deployment of OPA Gatekeeper in each cluster. This dashboard aggregates all policy violations reported by those Gatekeeper instances.

4 - Designate Ingress CNAME operator (DISCO)

This Plugin provides the Designate Ingress CNAME operator (DISCO) to automate management of DNS entries in OpenStack Designate for Ingress and Services in Kubernetes.

5 - DigiCert issuer

This Plugin provides the digicert-issuer, an external Issuer extending the cert-manager with the DigiCert cert-central API.

6 - External DNS

This Plugin provides the external DNS operator) which synchronizes exposed Kubernetes Services and Ingresses with DNS providers.

7 - Ingress NGINX

This plugin contains the ingress NGINX controller.

Example

To instantiate the plugin create a Plugin like:

apiVersion: greenhouse.sap/v1alpha1
kind: Plugin
metadata:
  name: ingress-nginx
spec:
  pluginDefinition: ingress-nginx-v4.4.0
  values:
    - name: controller.service.loadBalancerIP
      value: 1.2.3.4

8 - Kubernetes monitoring

This Plugin is intended for monitoring Kubernetes clusters and is preconfigured to collect metrics from all Kubernetes components. It provides a standard set of alerting rules. Many of the useful alerts come from the kubernetes-mixin project.

Components included in this Plugin:

Owner

  1. Richard Tief (@richardtief)
  2. Tommy Sauer (@viennaa)
  3. Martin Vossen (@artherd42)

kube-monitoring prometheus-operator parameters

NameDescriptionValue
kubeMonitoring.prometheusOperator.enabledManages Prometheus and Alertmanager componentstrue
kubeMonitoring.prometheusOperator.alertmanagerInstanceNamespacesFilter namespaces to look for prometheus-operator Alertmanager resources[]
kubeMonitoring.prometheusOperator.alertmanagerConfigNamespacesFilter namespaces to look for prometheus-operator AlertmanagerConfig resources[]
kubeMonitoring.prometheusOperator.prometheusInstanceNamespacesFilter namespaces to look for prometheus-operator Prometheus resources[]

kube-monitoring Kubernetes components scraper configuration

NameDescriptionValue
kubeMonitoring.kubernetesServiceMonitors.enabledFlag to disable all the kubernetes component scraperstrue
kubeMonitoring.kubeApiServer.enabledComponent scraping the kube api servertrue
kubeMonitoring.kubelet.enabledComponent scraping the kubelet and kubelet-hosted cAdvisortrue
kubeMonitoring.coreDns.enabledComponent scraping coreDns. Use either this or kubeDnstrue
kubeMonitoring.kubeEtcd.enabledComponent scraping etcdtrue
kubeMonitoring.kubeStateMetrics.enabledComponent scraping kube state metricstrue
kubeMonitoring.nodeExporter.enabledDeploy node exporter as a daemonset to all nodestrue
kubeMonitoring.kubeControllerManager.enabledComponent scraping the kube controller managerfalse
kubeMonitoring.kubeScheduler.enabledComponent scraping kube schedulerfalse
kubeMonitoring.kubeProxy.enabledComponent scraping kube proxyfalse
kubeMonitoring.kubeDns.enabledComponent scraping kubeDns. Use either this or coreDnsfalse

kube-monitoring Prometheus parameters

NameDescriptionValue
kubeMonitoring.prometheus.enabledDeploy a Prometheus instancetrue
kubeMonitoring.prometheus.annotationsAnnotations for Prometheus{}
kubeMonitoring.prometheus.tlsConfig.caCertCA certificate to verify technical clients at Prometheus IngressSecret
kubeMonitoring.prometheus.ingress.enabledDeploy Prometheus Ingresstrue
kubeMonitoring.prometheus.ingress.hostsMust be provided if Ingress is enabled.[]
kubeMonitoring.prometheus.ingress.ingressClassnameSpecifies the ingress-controllernginx
kubeMonitoring.prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storageHow large the persistent volume should be to house the prometheus database. Default 50Gi.""
kubeMonitoring.prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassNameThe storage class to use for the persistent volume.""
kubeMonitoring.prometheus.prometheusSpec.scrapeIntervalInterval between consecutive scrapes. Defaults to 30s""
kubeMonitoring.prometheus.prometheusSpec.scrapeTimeoutNumber of seconds to wait for target to respond before erroring""
kubeMonitoring.prometheus.prometheusSpec.evaluationIntervalInterval between consecutive evaluations""
kubeMonitoring.prometheus.prometheusSpec.externalLabelsExternal labels to add to any time series or alerts when communicating with external systems like Alertmanager{}
kubeMonitoring.prometheus.prometheusSpec.ruleSelectorPrometheusRules to be selected for target discovery. Defaults to matchLabels: pluginconfig: <kubeMonitoring.fullnameOverride>{}
kubeMonitoring.prometheus.prometheusSpec.serviceMonitorSelectorServiceMonitors to be selected for target discovery. Defaults to matchLabels: pluginconfig: <kubeMonitoring.fullnameOverride>{}
kubeMonitoring.prometheus.prometheusSpec.podMonitorSelectorPodMonitors to be selected for target discovery. Defaults to matchLabels: pluginconfig: <kubeMonitoring.fullnameOverride>{}
kubeMonitoring.prometheus.prometheusSpec.probeSelectorProbes to be selected for target discovery. Defaults to matchLabels: pluginconfig: <kubeMonitoring.fullnameOverride>{}
kubeMonitoring.prometheus.prometheusSpec.scrapeConfigSelectorscrapeConfigs to be selected for target discovery. Defaults to matchLabels: pluginconfig: <kubeMonitoring.fullnameOverride>{}
kubeMonitoring.prometheus.prometheusSpec.retentionHow long to retain metrics""
kubeMonitoring.prometheus.prometheusSpec.logLevelLog level for Prometheus be configured in""
kubeMonitoring.prometheus.prometheusSpec.additionalScrapeConfigsNext to ScrapeConfig CRD, you can use AdditionalScrapeConfigs, which allows specifying additional Prometheus scrape configurations""
kubeMonitoring.prometheus.prometheusSpec.additionalArgsAllows setting additional arguments for the Prometheus container[]

kube-monitoring Alertmanager config parameters

NameDescriptionValue
alerts.enabledTo send alerts to Alertmanagerfalse
alerts.alertmanager.hostsList of Alertmanager hosts Prometheus can send alerts to[]
alerts.alertmanager.tlsConfig.certTLS certificate for communication with AlertmanagerSecret
alerts.alertmanager.tlsConfig.keyTLS key for communication with AlertmanagerSecret

Examples

Deploy kube-monitoring into a remote cluster

apiVersion: greenhouse.sap/v1alpha1
kind: Plugin
metadata:
  name: kube-monitoring
spec:
  pluginDefinition: kube-monitoring
  disabled: false
  optionValues:
    - name: kubeMonitoring.prometheus.prometheusSpec.retention
      value: 30d
    - name: kubeMonitoring.prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage
      value: 100Gi
    - name: kubeMonitoring.prometheus.service.labels
      value:
        greenhouse.sap/expose: "true"
    - name: kubeMonitoring.prometheus.prometheusSpec.externalLabels
      value:
        cluster: example-cluster
        organization: example-org
        region: example-region
    - name: alerts.enabled
      value: true
    - name: alerts.alertmanagers.hosts
      value:
        - alertmanager.dns.example.com
    - name: alerts.alertmanagers.tlsConfig.cert
      valueFrom:
        secret:
          key: tls.crt
          name: tls-<org-name>-prometheus-auth
    - name: alerts.alertmanagers.tlsConfig.key
      valueFrom:
        secret:
          key: tls.key
          name: tls-<org-name>-prometheus-auth

Deploy Prometheus only

Example Plugin to deploy Prometheus with the kube-monitoring Plugin.

NOTE: If you are using kube-monitoring for the first time in your cluster, it is necessary to set kubeMonitoring.prometheusOperator.enabled to true.

apiVersion: greenhouse.sap/v1alpha1
kind: Plugin
metadata:
  name: example-prometheus-name
spec:
  pluginDefinition: kube-monitoring
  disabled: false
  optionValues:
    - name: kubeMonitoring.defaultRules.create
      value: false
    - name: kubeMonitoring.kubernetesServiceMonitors.enabled
      value: false
    - name: kubeMonitoring.prometheusOperator.enabled
      value: false
    - name: kubeMonitoring.kubeStateMetrics.enabled
      value: false
    - name: kubeMonitoring.nodeExporter.enabled
      value: false
    - name: kubeMonitoring.prometheus.prometheusSpec.retention
      value: 30d
    - name: kubeMonitoring.prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage
      value: 100Gi
    - name: kubeMonitoring.prometheus.service.labels
      value:
        greenhouse.sap/expose: "true"
    - name: kubeMonitoring.prometheus.prometheusSpec.externalLabels
      value:
        cluster: example-cluster
        organization: example-org
        region: example-region
    - name: alerts.enabled
      value: true
    - name: alerts.alertmanagers.hosts
      value:
        - alertmanager.dns.example.com
    - name: alerts.alertmanagers.tlsConfig.cert
      valueFrom:
        secret:
          key: tls.crt
          name: tls-<org-name>-prometheus-auth
    - name: alerts.alertmanagers.tlsConfig.key
      valueFrom:
        secret:
          key: tls.key
          name: tls-<org-name>-prometheus-auth

9 - Logshipper

This Plugin is intended for shipping container and systemd logs to an Elasticsearch/ OpenSearch cluster. It uses fluentbit to collect logs. The default configuration can be found under chart/templates/fluent-bit-configmap.yaml.

Components included in this Plugin:

Owner

  1. @ivogoman

Parameters

NameDescriptionValue
fluent-bit.parserParser used for container logs. [docker|cri] labels“cri”
fluent-bit.backend.opensearch.hostHost for the Elastic/OpenSearch HTTP Input
fluent-bit.backend.opensearch.portPort for the Elastic/OpenSearch HTTP Input
fluent-bit.backend.opensearch.http_userUsername for the Elastic/OpenSearch HTTP Input
fluent-bit.backend.opensearch.http_passwordPassword for the Elastic/OpenSearch HTTP Input
fluent-bit.backend.opensearch.hostHost for the Elastic/OpenSearch HTTP Input
fluent-bit.filter.additionalValueslist of Key-Value pairs to label logs labels[]
fluent-bit.customConfig.inputsmulti-line string containing additional inputs
fluent-bit.customConfig.filtersmulti-line string containing additional filters
fluent-bit.customConfig.outputsmulti-line string containing additional outputs

Custom Configuration

To add custom configuration to the fluent-bit configuration please check the fluentbit documentation here. The fluent-bit.customConfig.inputs, fluent-bit.customConfig.filters and fluent-bit.customConfig.outputs parameters can be used to add custom configuration to the default configuration. The configuration should be added as a multi-line string. Inputs are rendered after the default inputs, filters are rendered after the default filters and before the additional values are added. Outputs are rendered after the default outputs. The additional values are added to all logs disregaring the source.

Example Input configuration:

fluent-bit:
  config:
    inputs: |
      [INPUT]
          Name             tail-audit
          Path             /var/log/containers/greenhouse-controller*.log
          Parser           {{ default "cri" ( index .Values "fluent-bit" "parser" ) }}
          Tag              audit.*
          Refresh_Interval 5
          Mem_Buf_Limit    50MB
          Skip_Long_Lines  Off
          Ignore_Older     1m
          DB               /var/log/fluent-bit-tail-audit.pos.db      

Logs collected by the default configuration are prefixed with default_. In case that logs from additional inputs are to be send and processed by the same filters and outputs, the prefix should be used as well.

In case additional secrets are required the fluent-bit.env field can be used to add them to the environment of the fluent-bit container. The secrets should be created by adding them to the fluent-bit.backend field.

fluent-bit:
  backend:
    audit:
      http_user: top-secret-audit
      http_password: top-secret-audit
      host: "audit.test"
      tls:
        enabled: true
        verify: true
        debug: false

10 - OpenTelemetry

This Plugin is intended for ingesting, generating, collecting, and exporting telemetry data (metrics, logs, and traces).

Components included in this Plugin:

The Plugin will deploy the OpenTelemetry Operator which works as a manager for the collectors and auto-instrumentation of the workload. By default the Plugin will also

  1. Collect logs via the Filelog Receiver, process and export them to OpenSearch
    • You can disable the collecting of logs by setting open_telemetry.LogCollector.enabled to false.
  2. Collect and expose metrics using a Prometheus interface which defaults to port 8888
    • You can disable the collecting of metrics by setting open_telemetry.MetricsCollector.enabled to false.

Contributors are welcome to provide additional collector configurations.

Owner

  1. Timo Johner (@timojohlo)
  2. Olaf Heydorn (@kuckkuck)
  3. Tommy Sauer (@viennaa)

Parameters

NameDescriptionTyperequired
openTelemetry.logsCollector.enabledActivates the standard configuration for logsboolfalse
openTelemetry.metricsCollector.enabledActivates the standard configuration for metricsboolfalse
openTelemetry.openSearchLogs.usernameUsername for OpenSearch endpointsecretfalse
openTelemetry.openSearchLogs.passwordPassword for OpenSearch endpointsecretfalse
openTelemetry.openSearchLogs.endpointEndpoint URL for OpenSearchsecretfalse
openTelemetry.regionRegion label for loggingstringfalse
openTelemetry.clusterCluster label for loggingstringfalse
openTelemetry.prometheusLabel for Prometheus Service Monitoringstringfalse
openTelemetry.podMonitor.enabledActivates the pod-monitoring for the LogsCollectorboolfalse
opentelemetry-operator.admissionWbhooks.certManager.enabledActivate to use the CertManager for generating self-signed certificatesboolfalse
opentelemetry-operator.admissionWebhooks.autoGenerateCert.enabledActivate to use Helm to create self-signed certificatesboolfalse
opentelemetry-operator.admissionWebhooks.autoGenerateCert.recreateActivate to recreate the cert after a defined period (certPeriodDays default is 365)boolfalse
opentelemetry-operator.kubeRBACProxy.enabledActivate to enable Kube-RBAC-Proxy for OpenTelemetryboolfalse
opentelemetry-operator.manager.prometheusRule.defaultRules.enabledActivate to enable default rules for monitoring the OpenTelemetry Managerboolfalse
opentelemetry-operator.manager.prometheusRule.enabledActivate to enable rules for monitoring the OpenTelemetry Managerboolfalse
opentelemetry-operator.manager.serviceMonitor.enabledActivate to enable the Service Monitor to ingest the metrics of the OpenTelemetry Collector in Prometheusboolfalse

Examples

TBD

11 - Plutono

Installs the web dashboarding system Plutono to easily collect, correlate, and visualize Prometheus metrics with dashboards.

Owner

  1. Richard Tief (@richardtief)

Quick Start

This guide provides a quick and straightforward way how to use Plutono as a Greenhouse Plugin on your Kubernetes cluster.

Prerequisites

  • A running and Greenhouse-managed Kubernetes cluster
  • kube-monitoring Plugin installed to have at least one Prometheus instance running in the cluster

The plugin works by factory default with anonymous access enabled. If you use the standard configuration in the kube-monitoring plugin, the data source and some k8s-monitoring dashboards are already pre-installed.

Step 1: Add your dashboards

Dashboards are selected from ConfigMaps across namespaces. The plugin searches for ConfigMaps with the label plutono-dashboard: "true" and imports them into Plutono. The ConfigMap must contain a key like my-dashboard.json with the dashboard JSON content. Example

Step 2: Add your datasources

Data sources are selected from Secrets across namespaces. The plugin searches for Secrets with the label plutono-dashboard: "true" and imports them into Plutono. The Secrets should contain valid datasource configuration YAML. Example

Configuration

ParameterDescriptionDefault
plutono.replicasNumber of nodes1
plutono.podDisruptionBudget.minAvailablePod disruption minimum availablenil
plutono.podDisruptionBudget.maxUnavailablePod disruption maximum unavailablenil
plutono.podDisruptionBudget.apiVersionPod disruption apiVersionnil
plutono.deploymentStrategyDeployment strategy{ "type": "RollingUpdate" }
plutono.livenessProbeLiveness Probe settings{ "httpGet": { "path": "/api/health", "port": 3000 } "initialDelaySeconds": 60, "timeoutSeconds": 30, "failureThreshold": 10 }
plutono.readinessProbeReadiness Probe settings{ "httpGet": { "path": "/api/health", "port": 3000 } }
plutono.securityContextDeployment securityContext{"runAsUser": 472, "runAsGroup": 472, "fsGroup": 472}
plutono.priorityClassNameName of Priority Class to assign podsnil
plutono.image.registryImage registrydocker.io
plutono.image.repositoryImage repositoryplutono/plutono
plutono.image.tagOverrides the Plutono image tag whose default is the chart appVersion (Must be >= 5.0.0)``
plutono.image.shaImage sha (optional)``
plutono.image.pullPolicyImage pull policyIfNotPresent
plutono.image.pullSecretsImage pull secrets (can be templated)[]
plutono.service.enabledEnable plutono servicetrue
plutono.service.ipFamiliesKubernetes service IP families[]
plutono.service.ipFamilyPolicyKubernetes service IP family policy""
plutono.service.typeKubernetes service typeClusterIP
plutono.service.portKubernetes port where service is exposed80
plutono.service.portNameName of the port on the serviceservice
plutono.service.appProtocolAdds the appProtocol field to the service``
plutono.service.targetPortInternal service is port3000
plutono.service.nodePortKubernetes service nodePortnil
plutono.service.annotationsService annotations (can be templated){}
plutono.service.labelsCustom labels{}
plutono.service.clusterIPinternal cluster service IPnil
plutono.service.loadBalancerIPIP address to assign to load balancer (if supported)nil
plutono.service.loadBalancerSourceRangeslist of IP CIDRs allowed access to lb (if supported)[]
plutono.service.externalIPsservice external IP addresses[]
plutono.service.externalTrafficPolicychange the default externalTrafficPolicynil
plutono.headlessServiceCreate a headless servicefalse
plutono.extraExposePortsAdditional service ports for sidecar containers[]
plutono.hostAliasesadds rules to the pod’s /etc/hosts[]
plutono.ingress.enabledEnables Ingressfalse
plutono.ingress.annotationsIngress annotations (values are templated){}
plutono.ingress.labelsCustom labels{}
plutono.ingress.pathIngress accepted path/
plutono.ingress.pathTypeIngress type of pathPrefix
plutono.ingress.hostsIngress accepted hostnames["chart-example.local"]
plutono.ingress.extraPathsIngress extra paths to prepend to every host configuration. Useful when configuring custom actions with AWS ALB Ingress Controller. Requires ingress.hosts to have one or more host entries.[]
plutono.ingress.tlsIngress TLS configuration[]
plutono.ingress.ingressClassNameIngress Class Name. MAY be required for Kubernetes versions >= 1.18""
plutono.resourcesCPU/Memory resource requests/limits{}
plutono.nodeSelectorNode labels for pod assignment{}
plutono.tolerationsToleration labels for pod assignment[]
plutono.affinityAffinity settings for pod assignment{}
plutono.extraInitContainersInit containers to add to the plutono pod{}
plutono.extraContainersSidecar containers to add to the plutono pod""
plutono.extraContainerVolumesVolumes that can be mounted in sidecar containers[]
plutono.extraLabelsCustom labels for all manifests{}
plutono.schedulerNameName of the k8s scheduler (other than default)nil
plutono.persistence.enabledUse persistent volume to store datafalse
plutono.persistence.typeType of persistence (pvc or statefulset)pvc
plutono.persistence.sizeSize of persistent volume claim10Gi
plutono.persistence.existingClaimUse an existing PVC to persist data (can be templated)nil
plutono.persistence.storageClassNameType of persistent volume claimnil
plutono.persistence.accessModesPersistence access modes[ReadWriteOnce]
plutono.persistence.annotationsPersistentVolumeClaim annotations{}
plutono.persistence.finalizersPersistentVolumeClaim finalizers[ "kubernetes.io/pvc-protection" ]
plutono.persistence.extraPvcLabelsExtra labels to apply to a PVC.{}
plutono.persistence.subPathMount a sub dir of the persistent volume (can be templated)nil
plutono.persistence.inMemory.enabledIf persistence is not enabled, whether to mount the local storage in-memory to improve performancefalse
plutono.persistence.inMemory.sizeLimitSizeLimit for the in-memory local storagenil
plutono.persistence.disableWarningHide NOTES warning, useful when persiting to a databasefalse
plutono.initChownData.enabledIf false, don’t reset data ownership at startuptrue
plutono.initChownData.image.registryinit-chown-data container image registrydocker.io
plutono.initChownData.image.repositoryinit-chown-data container image repositorybusybox
plutono.initChownData.image.taginit-chown-data container image tag1.31.1
plutono.initChownData.image.shainit-chown-data container image sha (optional)""
plutono.initChownData.image.pullPolicyinit-chown-data container image pull policyIfNotPresent
plutono.initChownData.resourcesinit-chown-data pod resource requests & limits{}
plutono.schedulerNameAlternate scheduler namenil
plutono.envExtra environment variables passed to pods{}
plutono.envValueFromEnvironment variables from alternate sources. See the API docs on EnvVarSource for format details. Can be templated{}
plutono.envFromSecretName of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated""
plutono.envFromSecretsList of Kubernetes secrets (must be manually created in the same namespace) containing values to be added to the environment. Can be templated[]
plutono.envFromConfigMapsList of Kubernetes ConfigMaps (must be manually created in the same namespace) containing values to be added to the environment. Can be templated[]
plutono.envRenderSecretSensible environment variables passed to pods and stored as secret. (passed through tpl){}
plutono.enableServiceLinksInject Kubernetes services as environment variables.true
plutono.extraSecretMountsAdditional plutono server secret mounts[]
plutono.extraVolumeMountsAdditional plutono server volume mounts[]
plutono.extraVolumesAdditional Plutono server volumes[]
plutono.automountServiceAccountTokenMounted the service account token on the plutono pod. Mandatory, if sidecars are enabledtrue
plutono.createConfigmapEnable creating the plutono configmaptrue
plutono.extraConfigmapMountsAdditional plutono server configMap volume mounts (values are templated)[]
plutono.extraEmptyDirMountsAdditional plutono server emptyDir volume mounts[]
plutono.pluginsPlugins to be loaded along with Plutono[]
plutono.datasourcesConfigure plutono datasources (passed through tpl){}
plutono.alertingConfigure plutono alerting (passed through tpl){}
plutono.notifiersConfigure plutono notifiers{}
plutono.dashboardProvidersConfigure plutono dashboard providers{}
plutono.dashboardsDashboards to import{}
plutono.dashboardsConfigMapsConfigMaps reference that contains dashboards{}
plutono.plutono.iniPlutono’s primary configuration{}
global.imageRegistryGlobal image pull registry for all images.null
global.imagePullSecretsGlobal image pull secrets (can be templated). Allows either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style).[]
plutono.ldap.enabledEnable LDAP authenticationfalse
plutono.ldap.existingSecretThe name of an existing secret containing the ldap.toml file, this must have the key ldap-toml.""
plutono.ldap.configPlutono’s LDAP configuration""
plutono.annotationsDeployment annotations{}
plutono.labelsDeployment labels{}
plutono.podAnnotationsPod annotations{}
plutono.podLabelsPod labels{}
plutono.podPortNameName of the plutono port on the podplutono
plutono.lifecycleHooksLifecycle hooks for podStart and preStop Example{}
plutono.sidecar.image.registrySidecar image registryquay.io
plutono.sidecar.image.repositorySidecar image repositorykiwigrid/k8s-sidecar
plutono.sidecar.image.tagSidecar image tag1.26.0
plutono.sidecar.image.shaSidecar image sha (optional)""
plutono.sidecar.imagePullPolicySidecar image pull policyIfNotPresent
plutono.sidecar.resourcesSidecar resources{}
plutono.sidecar.securityContextSidecar securityContext{}
plutono.sidecar.enableUniqueFilenamesSets the kiwigrid/k8s-sidecar UNIQUE_FILENAMES environment variable. If set to true the sidecar will create unique filenames where duplicate data keys exist between ConfigMaps and/or Secrets within the same or multiple Namespaces.false
plutono.sidecar.alerts.enabledEnables the cluster wide search for alerts and adds/updates/deletes them in plutonofalse
plutono.sidecar.alerts.labelLabel that config maps with alerts should have to be addedplutono_alert
plutono.sidecar.alerts.labelValueLabel value that config maps with alerts should have to be added""
plutono.sidecar.alerts.searchNamespaceNamespaces list. If specified, the sidecar will search for alerts config-maps inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It’s also possible to specify ALL to search in all namespaces.nil
plutono.sidecar.alerts.watchMethodMethod to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds.WATCH
plutono.sidecar.alerts.resourceShould the sidecar looks into secrets, configmaps or both.both
plutono.sidecar.alerts.reloadURLFull url of datasource configuration reload API endpoint, to invoke after a config-map change"http://localhost:3000/api/admin/provisioning/alerting/reload"
plutono.sidecar.alerts.skipReloadEnabling this omits defining the REQ_URL and REQ_METHOD environment variablesfalse
plutono.sidecar.alerts.initAlertsSet to true to deploy the alerts sidecar as an initContainer. This is needed if skipReload is true, to load any alerts defined at startup time.false
plutono.sidecar.alerts.extraMountsAdditional alerts sidecar volume mounts.[]
plutono.sidecar.dashboards.enabledEnables the cluster wide search for dashboards and adds/updates/deletes them in plutonofalse
plutono.sidecar.dashboards.SCProviderEnables creation of sidecar providertrue
plutono.sidecar.dashboards.provider.nameUnique name of the plutono providersidecarProvider
plutono.sidecar.dashboards.provider.orgidId of the organisation, to which the dashboards should be added1
plutono.sidecar.dashboards.provider.folderLogical folder in which plutono groups dashboards""
plutono.sidecar.dashboards.provider.folderUidAllows you to specify the static UID for the logical folder above""
plutono.sidecar.dashboards.provider.disableDeleteActivate to avoid the deletion of imported dashboardsfalse
plutono.sidecar.dashboards.provider.allowUiUpdatesAllow updating provisioned dashboards from the UIfalse
plutono.sidecar.dashboards.provider.typeProvider typefile
plutono.sidecar.dashboards.provider.foldersFromFilesStructureAllow Plutono to replicate dashboard structure from filesystem.false
plutono.sidecar.dashboards.watchMethodMethod to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds.WATCH
plutono.sidecar.skipTlsVerifySet to true to skip tls verification for kube api callsnil
plutono.sidecar.dashboards.labelLabel that config maps with dashboards should have to be addedplutono_dashboard
plutono.sidecar.dashboards.labelValueLabel value that config maps with dashboards should have to be added""
plutono.sidecar.dashboards.folderFolder in the pod that should hold the collected dashboards (unless sidecar.dashboards.defaultFolderName is set). This path will be mounted./tmp/dashboards
plutono.sidecar.dashboards.folderAnnotationThe annotation the sidecar will look for in configmaps to override the destination folder for filesnil
plutono.sidecar.dashboards.defaultFolderNameThe default folder name, it will create a subfolder under the sidecar.dashboards.folder and put dashboards in there insteadnil
plutono.sidecar.dashboards.searchNamespaceNamespaces list. If specified, the sidecar will search for dashboards config-maps inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It’s also possible to specify ALL to search in all namespaces.nil
plutono.sidecar.dashboards.scriptAbsolute path to shell script to execute after a configmap got reloaded.nil
plutono.sidecar.dashboards.reloadURLFull url of dashboards configuration reload API endpoint, to invoke after a config-map change"http://localhost:3000/api/admin/provisioning/dashboards/reload"
plutono.sidecar.dashboards.skipReloadEnabling this omits defining the REQ_USERNAME, REQ_PASSWORD, REQ_URL and REQ_METHOD environment variablesfalse
plutono.sidecar.dashboards.resourceShould the sidecar looks into secrets, configmaps or both.both
plutono.sidecar.dashboards.extraMountsAdditional dashboard sidecar volume mounts.[]
plutono.sidecar.datasources.enabledEnables the cluster wide search for datasources and adds/updates/deletes them in plutonofalse
plutono.sidecar.datasources.labelLabel that config maps with datasources should have to be addedplutono_datasource
plutono.sidecar.datasources.labelValueLabel value that config maps with datasources should have to be added""
plutono.sidecar.datasources.searchNamespaceNamespaces list. If specified, the sidecar will search for datasources config-maps inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It’s also possible to specify ALL to search in all namespaces.nil
plutono.sidecar.datasources.watchMethodMethod to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds.WATCH
plutono.sidecar.datasources.resourceShould the sidecar looks into secrets, configmaps or both.both
plutono.sidecar.datasources.reloadURLFull url of datasource configuration reload API endpoint, to invoke after a config-map change"http://localhost:3000/api/admin/provisioning/datasources/reload"
plutono.sidecar.datasources.skipReloadEnabling this omits defining the REQ_URL and REQ_METHOD environment variablesfalse
plutono.sidecar.datasources.initDatasourcesSet to true to deploy the datasource sidecar as an initContainer in addition to a container. This is needed if skipReload is true, to load any datasources defined at startup time.false
plutono.sidecar.notifiers.enabledEnables the cluster wide search for notifiers and adds/updates/deletes them in plutonofalse
plutono.sidecar.notifiers.labelLabel that config maps with notifiers should have to be addedplutono_notifier
plutono.sidecar.notifiers.labelValueLabel value that config maps with notifiers should have to be added""
plutono.sidecar.notifiers.searchNamespaceNamespaces list. If specified, the sidecar will search for notifiers config-maps (or secrets) inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It’s also possible to specify ALL to search in all namespaces.nil
plutono.sidecar.notifiers.watchMethodMethod to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds.WATCH
plutono.sidecar.notifiers.resourceShould the sidecar looks into secrets, configmaps or both.both
plutono.sidecar.notifiers.reloadURLFull url of notifier configuration reload API endpoint, to invoke after a config-map change"http://localhost:3000/api/admin/provisioning/notifications/reload"
plutono.sidecar.notifiers.skipReloadEnabling this omits defining the REQ_URL and REQ_METHOD environment variablesfalse
plutono.sidecar.notifiers.initNotifiersSet to true to deploy the notifier sidecar as an initContainer in addition to a container. This is needed if skipReload is true, to load any notifiers defined at startup time.false
plutono.smtp.existingSecretThe name of an existing secret containing the SMTP credentials.""
plutono.smtp.userKeyThe key in the existing SMTP secret containing the username."user"
plutono.smtp.passwordKeyThe key in the existing SMTP secret containing the password."password"
plutono.admin.existingSecretThe name of an existing secret containing the admin credentials (can be templated).""
plutono.admin.userKeyThe key in the existing admin secret containing the username."admin-user"
plutono.admin.passwordKeyThe key in the existing admin secret containing the password."admin-password"
plutono.serviceAccount.automountServiceAccountTokenAutomount the service account token on all pods where is service account is usedfalse
plutono.serviceAccount.annotationsServiceAccount annotations
plutono.serviceAccount.createCreate service accounttrue
plutono.serviceAccount.labelsServiceAccount labels{}
plutono.serviceAccount.nameService account name to use, when empty will be set to created account if serviceAccount.create is set else to default``
plutono.serviceAccount.nameTestService account name to use for test, when empty will be set to created account if serviceAccount.create is set else to defaultnil
plutono.rbac.createCreate and use RBAC resourcestrue
plutono.rbac.namespacedCreates Role and Rolebinding instead of the default ClusterRole and ClusteRoleBindings for the plutono instancefalse
plutono.rbac.useExistingRoleSet to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to the rolename set here.nil
plutono.rbac.pspEnabledCreate PodSecurityPolicy (with rbac.create, grant roles permissions as well)false
plutono.rbac.pspUseAppArmorEnforce AppArmor in created PodSecurityPolicy (requires rbac.pspEnabled)false
plutono.rbac.extraRoleRulesAdditional rules to add to the Role[]
plutono.rbac.extraClusterRoleRulesAdditional rules to add to the ClusterRole[]
plutono.commandDefine command to be executed by plutono container at startupnil
plutono.argsDefine additional args if command is usednil
plutono.testFramework.enabledWhether to create test-related resourcestrue
plutono.testFramework.image.registrytest-framework image registry.docker.io
plutono.testFramework.image.repositorytest-framework image repository.bats/bats
plutono.testFramework.image.tagtest-framework image tag.v1.4.1
plutono.testFramework.imagePullPolicytest-framework image pull policy.IfNotPresent
plutono.testFramework.securityContexttest-framework securityContext{}
plutono.downloadDashboards.envEnvironment variables to be passed to the download-dashboards container{}
plutono.downloadDashboards.envFromSecretName of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated""
plutono.downloadDashboards.resourcesResources of download-dashboards container{}
plutono.downloadDashboardsImage.registryCurl docker image registrydocker.io
plutono.downloadDashboardsImage.repositoryCurl docker image repositorycurlimages/curl
plutono.downloadDashboardsImage.tagCurl docker image tag7.73.0
plutono.downloadDashboardsImage.shaCurl docker image sha (optional)""
plutono.downloadDashboardsImage.pullPolicyCurl docker image pull policyIfNotPresent
plutono.namespaceOverrideOverride the deployment namespace"" (Release.Namespace)
plutono.serviceMonitor.enabledUse servicemonitor from prometheus operatorfalse
plutono.serviceMonitor.namespaceNamespace this servicemonitor is installed in
plutono.serviceMonitor.intervalHow frequently Prometheus should scrape1m
plutono.serviceMonitor.pathPath to scrape/metrics
plutono.serviceMonitor.schemeScheme to use for metrics scrapinghttp
plutono.serviceMonitor.tlsConfigTLS configuration block for the endpoint{}
plutono.serviceMonitor.labelsLabels for the servicemonitor passed to Prometheus Operator{}
plutono.serviceMonitor.scrapeTimeoutTimeout after which the scrape is ended30s
plutono.serviceMonitor.relabelingsRelabelConfigs to apply to samples before scraping.[]
plutono.serviceMonitor.metricRelabelingsMetricRelabelConfigs to apply to samples before ingestion.[]
plutono.revisionHistoryLimitNumber of old ReplicaSets to retain10
plutono.networkPolicy.enabledEnable creation of NetworkPolicy resources.false
plutono.networkPolicy.allowExternalDon’t require client label for connectionstrue
plutono.networkPolicy.explicitNamespacesSelectorA Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed{}
plutono.networkPolicy.ingressEnable the creation of an ingress network policytrue
plutono.networkPolicy.egress.enabledEnable the creation of an egress network policyfalse
plutono.networkPolicy.egress.portsAn array of ports to allow for the egress[]
plutono.enableKubeBackwardCompatibilityEnable backward compatibility of kubernetes where pod’s definition version below 1.13 doesn’t have the enableServiceLinks optionfalse

Example ingress with path

With plutono 6.3 and above

plutono.ini:
  server:
    domain: monitoring.example.com
    root_url: "%(protocol)s://%(domain)s/plutono"
    serve_from_sub_path: true
ingress:
  enabled: true
  hosts:
    - "monitoring.example.com"
  path: "/plutono"

Example of extraVolumeMounts and extraVolumes

Configure additional volumes with extraVolumes and volume mounts with extraVolumeMounts.

Example for extraVolumeMounts and corresponding extraVolumes:

extraVolumeMounts:
  - name: plugins
    mountPath: /var/lib/plutono/plugins
    subPath: configs/plutono/plugins
    readOnly: false
  - name: dashboards
    mountPath: /var/lib/plutono/dashboards
    hostPath: /usr/shared/plutono/dashboards
    readOnly: false

extraVolumes:
  - name: plugins
    existingClaim: existing-plutono-claim
  - name: dashboards
    hostPath: /usr/shared/plutono/dashboards

Volumes default to emptyDir. Set to persistentVolumeClaim, hostPath, csi, or configMap for other types. For a persistentVolumeClaim, specify an existing claim name with existingClaim.

Import dashboards

There are a few methods to import dashboards to Plutono. Below are some examples and explanations as to how to use each method:

dashboards:
  default:
    some-dashboard:
      json: |
        {
          "annotations":

          ...
          # Complete json file here
          ...

          "title": "Some Dashboard",
          "uid": "abcd1234",
          "version": 1
        }        
    custom-dashboard:
      # This is a path to a file inside the dashboards directory inside the chart directory
      file: dashboards/custom-dashboard.json
    prometheus-stats:
      # Ref: https://plutono.com/dashboards/2
      gnetId: 2
      revision: 2
      datasource: Prometheus
    loki-dashboard-quick-search:
      gnetId: 12019
      revision: 2
      datasource:
      - name: DS_PROMETHEUS
        value: Prometheus
      - name: DS_LOKI
        value: Loki
    local-dashboard:
      url: https://raw.githubusercontent.com/user/repository/master/dashboards/dashboard.json

BASE64 dashboards

Dashboards could be stored on a server that does not return JSON directly and instead of it returns a Base64 encoded file (e.g. Gerrit) A new parameter has been added to the url use case so if you specify a b64content value equals to true after the url entry a Base64 decoding is applied before save the file to disk. If this entry is not set or is equals to false not decoding is applied to the file before saving it to disk.

Gerrit use case

Gerrit API for download files has the following schema: https://yourgerritserver/a/{project-name}/branches/{branch-id}/files/{file-id}/content where {project-name} and {file-id} usually has ‘/’ in their values and so they MUST be replaced by %2F so if project-name is user/repo, branch-id is master and file-id is equals to dir1/dir2/dashboard the url value is https://yourgerritserver/a/user%2Frepo/branches/master/files/dir1%2Fdir2%2Fdashboard/content

Sidecar for dashboards

If the parameter sidecar.dashboards.enabled is set, a sidecar container is deployed in the plutono pod. This container watches all configmaps (or secrets) in the cluster and filters out the ones with a label as defined in sidecar.dashboards.label. The files defined in those configmaps are written to a folder and accessed by plutono. Changes to the configmaps are monitored and the imported dashboards are deleted/updated.

A recommendation is to use one configmap per dashboard, as a reduction of multiple dashboards inside one configmap is currently not properly mirrored in plutono.

NOTE: Configure your data sources in your dashboards as variables to keep them portable across clusters.

Example dashboard config:

Folder structure:

dashboards/
├── dashboard1.json
├── dashboard2.json
templates/
├──dashboard-json-configmap.yaml

Helm template to create a configmap for each dashboard:

{{- range $path, $bytes := .Files.Glob "dashboards/*.json" }}
---
apiVersion: v1
kind: ConfigMap

metadata:
  name: {{ printf "%s-%s" $.Release.Name $path | replace "/" "-" | trunc 63 }}
  labels:
    plutono-dashboard: "true"

data:
{{ printf "%s: |-" $path | replace "/" "-" | indent 2 }}
{{ printf "%s" $bytes | indent 4 }}

{{- end }}

Sidecar for datasources

If the parameter sidecar.datasources.enabled is set, an init container is deployed in the plutono pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and filters out the ones with a label as defined in sidecar.datasources.label. The files defined in those secrets are written to a folder and accessed by plutono on startup. Using these yaml files, the data sources in plutono can be imported.

Should you aim for reloading datasources in Plutono each time the config is changed, set sidecar.datasources.skipReload: false and adjust sidecar.datasources.reloadURL to http://<svc-name>.<namespace>.svc.cluster.local/api/admin/provisioning/datasources/reload.

Secrets are recommended over configmaps for this usecase because datasources usually contain private data like usernames and passwords. Secrets are the more appropriate cluster resource to manage those.

Example datasource config:

apiVersion: v1
kind: Secret
metadata:
  name: plutono-datasources
  labels:
    # default value for: sidecar.datasources.label
    plutono-datasource: "true"
stringData:
  datasources.yaml: |-
    apiVersion: 1
    datasources:
      - name: my-prometheus 
        type: prometheus
        access: proxy
        orgId: 1
        url: my-url-domain:9090
        isDefault: false
        jsonData:
          httpMethod: 'POST'
        editable: false    

NOTE: If you might include credentials in your datasource configuration, make sure to not use stringdata but base64 encoded data instead.

apiVersion: v1
kind: Secret
metadata:
  name: my-datasource
  labels:
    plutono-datasource: "true"
data:
  # The key must contain a unique name and the .yaml file type
  my-datasource.yaml: {{ include (print $.Template.BasePath "my-datasource.yaml") . | b64enc }}

Example values to add a datasource adapted from Grafana:

datasources:
 datasources.yaml:
  apiVersion: 1
  datasources:
      # <string, required> Sets the name you use to refer to
      # the data source in panels and queries.
    - name: my-prometheus 
      # <string, required> Sets the data source type.
      type: prometheus
      # <string, required> Sets the access mode, either
      # proxy or direct (Server or Browser in the UI).
      # Some data sources are incompatible with any setting
      # but proxy (Server).
      access: proxy
      # <int> Sets the organization id. Defaults to orgId 1.
      orgId: 1
      # <string> Sets a custom UID to reference this
      # data source in other parts of the configuration.
      # If not specified, Plutono generates one.
      uid:
      # <string> Sets the data source's URL, including the
      # port.
      url: my-url-domain:9090
      # <string> Sets the database user, if necessary.
      user:
      # <string> Sets the database name, if necessary.
      database:
      # <bool> Enables basic authorization.
      basicAuth:
      # <string> Sets the basic authorization username.
      basicAuthUser:
      # <bool> Enables credential headers.
      withCredentials:
      # <bool> Toggles whether the data source is pre-selected
      # for new panels. You can set only one default
      # data source per organization.
      isDefault: false
      # <map> Fields to convert to JSON and store in jsonData.
      jsonData:
        httpMethod: 'POST'
        # <bool> Enables TLS authentication using a client
        # certificate configured in secureJsonData.
        # tlsAuth: true
        # <bool> Enables TLS authentication using a CA
        # certificate.
        # tlsAuthWithCACert: true
      # <map> Fields to encrypt before storing in jsonData.
      secureJsonData:
        # <string> Defines the CA cert, client cert, and
        # client key for encrypted authentication.
        # tlsCACert: '...'
        # tlsClientCert: '...'
        # tlsClientKey: '...'
        # <string> Sets the database password, if necessary.
        # password:
        # <string> Sets the basic authorization password.
        # basicAuthPassword:
      # <int> Sets the version. Used to compare versions when
      # updating. Ignored when creating a new data source.
      version: 1
      # <bool> Allows users to edit data sources from the
      # Plutono UI.
      editable: false

How to serve Plutono with a path prefix (/plutono)

In order to serve Plutono with a prefix (e.g., http://example.com/plutono), add the following to your values.yaml.

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/use-regex: "true"

  path: /plutono/?(.*)
  hosts:
    - k8s.example.dev

plutono.ini:
  server:
    root_url: http://localhost:3000/plutono # this host can be localhost

How to securely reference secrets in plutono.ini

This example uses Plutono file providers for secret values and the extraSecretMounts configuration flag (Additional plutono server secret mounts) to mount the secrets.

In plutono.ini:

plutono.ini:
  [auth.generic_oauth]
  enabled = true
  client_id = $__file{/etc/secrets/auth_generic_oauth/client_id}
  client_secret = $__file{/etc/secrets/auth_generic_oauth/client_secret}

Existing secret, or created along with helm:

---
apiVersion: v1
kind: Secret
metadata:
  name: auth-generic-oauth-secret
type: Opaque
stringData:
  client_id: <value>
  client_secret: <value>

Include in the extraSecretMounts configuration flag:

- extraSecretMounts:
  - name: auth-generic-oauth-secret-mount
    secretName: auth-generic-oauth-secret
    defaultMode: 0440
    mountPath: /etc/secrets/auth_generic_oauth
    readOnly: true

extraSecretMounts using a Container Storage Interface (CSI) provider

This example uses a CSI driver e.g. retrieving secrets using Azure Key Vault Provider

- extraSecretMounts:
  - name: secrets-store-inline
    mountPath: /run/secrets
    readOnly: true
    csi:
      driver: secrets-store.csi.k8s.io
      readOnly: true
      volumeAttributes:
        secretProviderClass: "my-provider"
      nodePublishSecretRef:
        name: akv-creds

12 - Service exposure test

This Plugin is just providing a simple exposed service for manual testing.

By adding the following label to a service it will become accessible from the central greenhouse system via a service proxy:

greenhouse.sap/expose: "true"

This plugin create an nginx deployment with an exposed service for testing.

Configuration

Specific port

By default expose would always use the first port. If you need another port, you’ve got to specify it by name:

greenhouse.sap/exposeNamedPort: YOURPORTNAME

13 - Teams2Slack

Introduction

This Plugin provides a Slack integration for a Greenhouse organization.
It manages Slack entities like channels, groups, handles, etc. and its members based on the teams configured in your Greenhouse organization.

Important: Please ensure that only one deployment of Teams2slack runs against the same set of groups in slack. Secondary instances should run in the provided Dry-Run mode. Otherwise you might notice inconsistencies if the Teammembership object of a cluster are uneqal.

Requirments

  • A Kubernetes Cluster to run against
  • The presence of the Greenhouse Teammemberships CRD and corresponding objects.

Architecture

architecture

The Teammembership contain the members of a team. Changes to an object will create an event in Kubernetes. This event will be consumed by the first controller. It creates a mirrored SlackGroup object that reflects the content of the Teammembership Object. This approach has the advantage that deletion of a team can be securely detected with the utilization of finalizers. The second controller detects changes on SlackGroup objects. The users present in a team will be aligned to a slack group.

Configuration

Deploy a the Teams2Slack Plugin and it’s Plugin which looks like the following structure (the following structure only includes the mandatory fields):

apiVersion: greenhouse.sap/v1alpha1
kind: Plugin
metadata:
  name: teams2slack
  namespace: default
spec:
  pluginDefinition: teams2slack
  disabled: false
  optionValues:
    - name: groupNamePrefix
      value: 
    - name: groupNameSuffix
      value: 
    - name: infoChannelID
      value:
    - name: token
      valueFrom:
        secret:
          key: SLACK_TOKEN
          name: teams2slack-secret
---
apiVersion: v1
kind: Secret

metadata:
  name: teams2slack-secret
type: Opaque
data:
  SLACK_TOKEN: // Slack token b64 encoded

The values that can or need to be provided have the following meaning:

Environment VariableMeaning
groupNamePrefix (mandatory)The prefix the created slack group should have. Choose a prefix that matches your organization.
groupNameSuffix (mandatory)The suffix the created slack group should have. Choose a suffix that matches your organization.
infoChannelID (mandatory)The channel ID created Slack Groups should have. You can currently define one slack ID which will be applied to all created groups. Make sure to take the channel ID and not the channel name.
token(mandatory)the slack token to authenticate against Slack.
eventRequeueTimer (optional)If a slack API requests fails due to a network error, or because data is currently fetched, it will be requed to the operators workQueue. Uses the golang date format. (1s = every second 1m = every minute )
loadDataBackoffTimer (optional)Defines, when a Slack-API data call occurs. Uses the golang data format.
dryRun (optional)Slack write operations are not executed if value is set to true. Requires a valid. Requires: A valid SLACK_TOKEN; the other environment variables can be mocked.

14 - Thanos

Information

This plugin deploys the following Thanos components:

  • Query
  • Compact
  • Store

Requirements (detailed steps below):

Owner

  1. Tommy Sauer (@viennaa)
  2. Richard Tief (@richardtief)
  3. Martin Vossen (@artherd42)

Configuration

Object Store preparation

To run Thanos, you need object storage credentials. Get the credentials of your provider and add them to a Kubernetes Secret. The Thanos documentation provides a great overview on the different supported store types.

Usually this looks somewhat like this

type: $STORAGE_TYPE
config:
    user:
    password:
    domain:
    ...

If you’ve got everything in a file, deploy it in your remote cluster in the namespace, where Prometheus and Thanos will be.

Important: $THANOS_PLUGIN_NAME is needed later for the respective Thanos plugin and they must not be different!

kubectl create secret generic $THANOS_PLUGIN_NAME-metrics-objectstore --from-file=thanos.yaml=/path/to/your/file

kube-monitoring plugin enablement

Prometheus in kube-monitoring needs to be altered to have a sidecar and ship metrics to the new object store too. You have to provide the Secret you’ve just created to the (most likely already existing) kube-monitoring plugin. Add this:

spec:
    optionValues:
      - name: kubeMonitoring.prometheus.prometheusSpec.thanos.objectStorageConfig.existingSecret.key
        value: thanos.yaml
      - name: kubeMonitoring.prometheus.prometheusSpec.thanos.objectStorageConfig.existingSecret.name
        value: $THANOS_PLUGIN_NAME-metrics-objectstore

Thanos Query

This is the real deal now: Define your Thanos Query by creating a plugin.

NOTE1: $THANOS_PLUGIN_NAME needs to be consistent with your secret created earlier.

NOTE2: The releaseNamespace needs to be the same as to where kube-monitoring resides. By default this is kube-monitoring.

apiVersion: greenhouse.sap/v1alpha1
kind: Plugin
metadata:
  name: $YOUR_CLUSTER_NAME
spec:
  pluginDefinition: thanos
  disabled: false
  clusterName: $YOUR_CLUSTER_NAME 
  releaseNamespace: kube-monitoring

[OPTIONAL] Handling your Prometheus and Thanos Stores.

Default Prometheus and Thanos Endpoint

Thanos Query is automatically adding the Prometheus and Thanos endpoints. If you just have a single Prometheus with Thanos enabled this will work out of the box. Details in the next two chapters. See Standalone Query for your own configuration.

Prometheus Endpoint

Thanos Query would check for a service prometheus-operated in the same namespace with this GRPC port to be available 10901. The cli option looks like this and is configured in the Plugin itself:

--store=prometheus-operated:10901

Thanos Endpoint

Thanos Query would check for a Thanos endpoint named like releaseName-store. The associated command line flag for this parameter would look like:

--store=thanos-kube-store:10901

If you just have one occurence of this Thanos plugin dpeloyed, the default option would work and does not need anything else.

Standalone Query

In case you want to have a Query to run with multiple Stores, you can set it to standalone and add your own store list. Set up your plugin like this:

spec:
  optionsValues:
  - name: thanos.query.standalone
    value: true

This would enable you to either:

  • query multiple stores with a single Query

    spec:
      optionsValues:
      - name: thanos.query.stores
        value:
          - thanos-kube-1-store:10901 
          - thanos-kube-2-store:10901 
          - kube-monitoring-1-prometheus:10901 
          - kube-monitoring-2-prometheus:10901 
    
  • query multiple Thanos Queries with a single Query Note that there is no -store suffix here in this case.

    spec:
      optionsValues:
      - name: thanos.query.stores
        value:
          - thanos-kube-1:10901
          - thanos-kube-2:10901
    

Operations

Thanos Compactor

If you deploy the plugin with the default values, Thanos compactor will be shipped too and use the same secret ($THANOS_PLUGIN_NAME-metrics-objectstore) to retrieve, compact and push back timeseries.

It will use a 100Gi PVC to not extensively occupy ephermeral storage. Depending on the amount of metrics this might be not enought and bigger volumes are needed. It is always safe to delete the compactor volume and increase it as needed.

The object storage costs will be heavily impacted on how granular timeseries are being stored (reference Downsampling). These are the pre-configured defaults, you can change them as needed:

raw: 777600s (90d)
5m: 777600s (90d)
1h: 157680000 (5y)