Giter VIP home page Giter VIP logo

kubernetes-grafana's Introduction

Kubernetes Grafana

This project is about running Grafana on Kubernetes with Prometheus as the datasource in a very opinionated and entirely declarative way. This allows easily operating Grafana highly available as if it was a stateless application - no need to run a clustered database for your dashboarding solution anymore!

Note that at this point this is primarily about getting into the same state as kube-prometheus currently is. It is about packaging up Grafana as a reusable component, without dashboards. Dashboards are to be defined when using this Grafana package.

What and why is happening here?

This repository exists because the Grafana stack in kube-prometheus has gotten close to unmaintainable due to the many steps of generation and it's a very steep learning curve for newcomers.

Since Grafana v5, Grafana can be provisioned with dashboards from files. This project is primarily about generating a set of useful Grafana dashboards for use with and on Kubernetes using with Prometheus as the datasource.

In this repository everything is generated via jsonnet:

With a single jsonnet command the whole stack is generated and can be applied against a Kubernetes cluster.

Prerequisites

You need a running Kubernetes cluster in order to try this out, with the kube-prometheus stack deployed on it as have Docker installed to and be able to mount volumes correctly (this is not the case when using the Docker host of minikube).

For trying this out provision minikube with these settings:

minikube start --kubernetes-version=v1.9.3 --memory=4096 --bootstrapper=kubeadm --extra-config=kubelet.authentication-token-webhook=true --extra-config=kubelet.authorization-mode=Webhook --extra-config=scheduler.address=0.0.0.0 --extra-config=controller-manager.address=0.0.0.0

Usage

Use this package in your own infrastructure using jsonnet-bundler:

jb install github.com/brancz/kubernetes-grafana/grafana

An example of how to use it could be:

local grafana = import 'grafana/grafana.libsonnet';

{
  _config:: {
    namespace: 'monitoring-grafana',
  },

  grafana: grafana($._config) + {
    service+: {
      spec+: {
        ports: [
          port {
            nodePort: 30910,
          }
          for port in super.ports
        ],
      },
    },
  },
}

This builds the entire Grafana stack with your own dashboards and a configurable namespace.

Simply run:

$ jsonnet -J vendor example.jsonnet

Customizing

Adding dashboards

This setup is optimized to work best when Grafana is used declaratively, so when adding dashboards they are added declaratively as well. In jsonnet there are libraries available to avoid having to repeat boilerplate of Grafana dashboard json. An example with the grafana/grafonnet-lib:

local grafonnet = import 'github.com/grafana/grafonnet-lib/grafonnet/grafana.libsonnet';
local dashboard = grafonnet.dashboard;
local row = grafonnet.row;
local prometheus = grafonnet.prometheus;
local template = grafonnet.template;
local graphPanel = grafonnet.graphPanel;

local grafana = import 'grafana/grafana.libsonnet';

{
  _config:: {
    namespace: 'monitoring-grafana',
    dashboards+: {
      'my-dashboard.json':
        dashboard.new('My Dashboard')
        .addTemplate(
          {
            current: {
              text: 'Prometheus',
              value: 'Prometheus',
            },
            hide: 0,
            label: null,
            name: 'datasource',
            options: [],
            query: 'prometheus',
            refresh: 1,
            regex: '',
            type: 'datasource',
          },
        )
        .addRow(
          row.new()
          .addPanel(
            graphPanel.new('My Panel', span=6, datasource='$datasource')
            .addTarget(prometheus.target('vector(1)')),
          )
        ),
    },
  },

  grafana: grafana($._config) + {
    service+: {
      spec+: {
        ports: [
          port {
            nodePort: 30910,
          }
          for port in super.ports
        ],
      },
    },
  },
}

Organizing dashboards

If you have many dashboards and would like to organize them into folders, you can do that as well by specifying them in folderDashboards rather than dashboards.

local grafonnet = import 'github.com/grafana/grafonnet-lib/grafonnet/grafana.libsonnet';
local dashboard = grafonnet.dashboard;
local row = grafonnet.row;
local prometheus = grafonnet.prometheus;
local template = grafonnet.template;
local graphPanel = grafonnet.graphPanel;

local grafana = import 'grafana/grafana.libsonnet';

{
  _config:: {
    namespace: 'monitoring-grafana',
    folderDashboards+: {
      Services: {
        'regional-services-dashboard.json': (import 'dashboards/regional-services-dashboard.json'),
        'global-services-dashboard.json': (import 'dashboards/global-services-dashboard.json'),
      },
      AWS: {
        'aws-ec2-dashboard.json': (import 'dashboards/aws-ec2-dashboard.json'),
        'aws-rds-dashboard.json': (import 'dashboards/aws-rds-dashboard.json'),
        'aws-sqs-dashboard.json': (import 'dashboards/aws-sqs-dashboard.json'),
      },
      ISTIO: {
        'istio-citadel-dashboard.json': (import 'dashboards/istio-citadel-dashboard.json'),
        'istio-galley-dashboard.json': (import 'dashboards/istio-galley-dashboard.json'),
        'istio-mesh-dashboard.json': (import 'dashboards/istio-mesh-dashboard.json'),
        'istio-pilot-dashboard.json': (import 'dashboards/istio-pilot-dashboard.json'),
      },
    },
  },

  grafana: grafana($._config) + {
    service+: {
      spec+: {
        ports: [
          port {
            nodePort: 30910,
          }
          for port in super.ports
        ],
      },
    },
  },
}

Dashboards mixins

Using the kubernetes-mixins, simply install:

$ jb install github.com/kubernetes-monitoring/kubernetes-mixin

And apply the mixin:

local kubernetesMixin = import 'github.com/kubernetes-monitoring/kubernetes-mixin/mixin.libsonnet';
local grafana = import 'grafana/grafana.libsonnet';

{
  _config:: {
    namespace: 'monitoring-grafana',
    dashboards: kubernetesMixin.grafanaDashboards,
  },

  grafana: grafana($._config) + {
    service+: {
      spec+: {
        ports: [
          port {
            nodePort: 30910,
          }
          for port in super.ports
        ],
      },
    },
  },
}

To generate, again simply run:

$ jsonnet -J vendor example-with-mixin.jsonnet

This yields a fully configured Grafana stack with useful Kubernetes dashboards.

Config customization

Grafana can be run with many different configurations. Different organizations have different preferences, therefore the Grafana configuration can be arbitrary modified. The configuration happens via the the $._config.grafana.config variable. The $._config.grafana.config field is compiled using jsonnet's std.manifestIni function. Additionally you can specify your organizations' LDAP configuration through $._config.grafana.ldap variable.

For example to modify Grafana configuration and set up LDAP use:

local grafana = import 'grafana/grafana.libsonnet';

{
  local customIni =
    grafana({
      _config+:: {
        namespace: 'monitoring-grafana',
        grafana+:: {
          config: {
            sections: {
              metrics: { enabled: true },
              'auth.ldap': {
                enabled: true,
                config_file: '/etc/grafana/ldap.toml',
                allow_sign_up: true,
              },
            },
          },
          ldap: |||
            [[servers]]
            host = "127.0.0.1"
            port = 389
            use_ssl = false
            start_tls = false
            ssl_skip_verify = false

            bind_dn = "cn=admin,dc=grafana,dc=org"
            bind_password = 'grafana'

            search_filter = "(cn=%s)"

            search_base_dns = ["dc=grafana,dc=org"]
          |||,
        },
      },
    }),

  apiVersion: 'v1',
  kind: 'List',
  items:
    customIni.dashboardDefinitions.items +
    [
      customIni.config,
      customIni.dashboardSources,
      customIni.dashboardDatasources,
      customIni.deployment,
      customIni.serviceAccount,
      customIni.service {
        spec+: { ports: [
          port {
            nodePort: 30910,
          }
          for port in super.ports
        ] },
      },
    ],
}

Plugins

The config object allows specifying an array of plugins to install at startup.

local grafana = import 'grafana/grafana.libsonnet';

{
  _config:: {
    namespace: 'monitoring-grafana',
    plugins: ['camptocamp-prometheus-alertmanager-datasource'],
  },

  grafana: grafana($._config) + {
    service+: {
      spec+: {
        ports: [
          port {
            nodePort: 30910,
          }
          for port in super.ports
        ],
      },
    },
  },
}

Roadmap

There are a number of things missing for the Grafana stack and tooling to be fully migrated.

If you are interested in working on any of these, please open a respective issue to avoid duplicating efforts.

  1. A tool to review Grafana dashboard changes on PRs. While reviewing jsonnet code is a lot easier than the large Grafana json sources, it's hard to imagine what that will actually end up looking like once rendered. Ideally a production-like environment is spun up and produces metrics to be graphed, then a tool could take a screenshot and Grafana snapshot of the rendered Grafana dashboards. That way the changes can not only be reviewed in code but also visually. Similar to point 2 this should eventually be it's own project.

kubernetes-grafana's People

Contributors

adinhodovic avatar aknuds1 avatar albertdb avatar arthursens avatar benoitknecht avatar brancz avatar c0ffeec0der avatar johannwillgrubs avatar karlskewes avatar lentil1016 avatar ly avatar maxbrunet avatar metalmatze avatar michaelpietzsch avatar mr00wka avatar osela avatar paulfantom avatar pharaujo avatar pierdipi avatar pschulten avatar rajatvig avatar shouichi avatar slashpai avatar snuggie12 avatar starfox64 avatar toran414 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kubernetes-grafana's Issues

Add Readiness Probe for Grafana

Hi! I was curious what you thought of adding a Readiness Probe to the Grafana container? Grafana exposes a health endpoint at /api/health that

returns HTTP 200 OK if everything is up and HTTP 503 Error if the Grafana database cannot be pinged.

Having a readiness probe would allow load balancers to probe the health of Grafana instance. As an example, the GCE Ingress Controller uses the readiness probes of pods to configure the GCE Load Balancer's HTTP check (by default the controller will configure the health check to hit /, but this doesn't work in the case of Grafana because the health check only considers 200 responses to be healthy, but Grafana responds with a 302).

Grafana 7.x is not installing unsigned community plugins

After upgrade to a newer version Clickhouse plugin is no longer available (https://grafana.com/grafana/plugins/vertamedia-clickhouse-datasource?src=grafana_plugin_list)

New env variable introduced to allow loading of unsigned plugins (see https://grafana.com/grafana/plugins/vertamedia-clickhouse-datasource?src=grafana_plugin_list):
GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=vertamedia-clickhouse-datasource
but GF_INSTALL_PLUGINS is still used.

What happened?
Clickhouse plugin is not installed

Did you expect to see some different?
Clickhouse plugin to be installed

How to reproduce it (as minimally and precisely as possible):
Add this to the config and generate a deployment:

grafana+:: {
      plugins: ['vertamedia-clickhouse-datasource']
}

Originally from prometheus-operator/kube-prometheus#807

BUG : Grafana RAW dashboards create malformed grafana-rawDashboardDefinitions file

Since latest commit 567be6b15b7f3b747c48dc7b111c1860cab121c7 a file grafana-rawDashboardDefinitions is created with the content :

[ ]

when rawDashboards is empty or not specified.
This is a bad yaml/json content.

Reproducing :

mkdir test
cd test
jb init
jb install github.com/coreos/kube-prometheus/jsonnet/kube-prometheus@master
mkdir manifests
cp ../cluster.jsonnet .
jsonnet  -J vendor -m manifests cluster.jsonnet

content of cluster.jsonnet :

local k = import 'ksonnet/ksonnet.beta.3/k.libsonnet';

local kp = (import 'kube-prometheus/kube-prometheus.libsonnet') + (import 'etcd-mixin/mixin.libsonnet') + {
  prometheus+:: {
  },
  _config+:: {
    namespace: 'monitoring',
    },
    grafana+:: {
      config+:{
      // rawDashboards: {},
      datasources: [{
        name: 'prometheus',
        type: 'prometheus',
        access: 'proxy',
        orgId: 1,
        url: 'http://prometheus-k8s.monitoring.svc:9090',
        version: 1,
        isDefault: true,
        editable: true,
      }, ],
      plugins: [
        'grafana-piechart-panel', 'camptocamp-prometheus-alertmanager-datasource'
      ],
    },
  },
};

{ ['00namespace-' + name]: kp.kubePrometheus[name] for name in std.objectFields(kp.kubePrometheus) } +
{ ['0prometheus-operator-' + name]: kp.prometheusOperator[name] for name in std.objectFields(kp.prometheusOperator) } +
{ ['node-exporter-' + name]: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } +
{ ['kube-state-metrics-' + name]: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } +
{ ['alertmanager-' + name]: kp.alertmanager[name] for name in std.objectFields(kp.alertmanager) } +
{ ['prometheus-' + name]: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } +
{ ['grafana-' + name]: kp.grafana[name] for name in std.objectFields(kp.grafana) }

attended result

The file manifests/grafana-rawDashboardDefinitions should not be created when rawDashboards is empty or not defined.

solution :

I wasn't able to find a clean solution where the manifests/grafana-rawDashboardDefinitions file is not created when empty.

Note that there may be the same problem with manifests/grafana-DashboardDefinitions, it just never happen as there are some defaults dashboards.

versions

Jsonnet commandline interpreter v0.14.0 from go get and official C++ version throuth OsX Brew

examples/dashboard-definition.jsonnet dashboardDefinitions is emtpy

I run dashboard-definition.jsonnet on my mac, result of dashboardDefinitions is []

I found the addTemplate here is different from grafonnet-lib example

// line 21
             dashboard.new('My Dashboard')
             .addTemplate(..)

and many projects use this libs grafana-builder/grafana.libsonnet to build grafana dashboard, what is the difference between grafana-builder and grafonnet-lib?

Set replicas for grafana

How to adjust config for more or less replicas?

I have tried

grafana+:: {
    deployment+:: {
        replicas: 0
    },
    container: {
etc...

without luck

grafana - shows no graphs

Here we have the details.
kube-spray and kubebernets.

kubectl version

Server Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.3", GitCommit:"a4529464e4629c21224b3d52edfe0ea91b072862", GitTreeState:"clean", BuildDate:"2018-09-09T17:53:03Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}

When opening the Grafana webpage i get no graphs
The debug windows shows:

โ€‹data: ""
โ€‹headers: function Rt()
โ€‹status: 502
โ€‹statusText: "Bad Gateway"
โ€‹xhrStatus: "complete"
โ€‹__proto__: Object { โ€ฆ }

all the pods are running:

monitoring       alertmanager-main-1                       2/2     Running   0          6d
monitoring       alertmanager-main-2                       2/2     Running   0          6d
monitoring       grafana-566fcc7956-cf9vt                  1/1     Running   0          6d
monitoring       kube-state-metrics-5479479c44-rz94m       4/4     Running   0          6d
monitoring       node-exporter-4gnxn                       2/2     Running   0          6d
monitoring       node-exporter-4wrbk                       2/2     Running   0          6d
monitoring       node-exporter-7hmv7                       2/2     Running   0          6d
monitoring       node-exporter-btztv                       2/2     Running   0          6d
monitoring       node-exporter-ckhmj                       2/2     Running   0          6d
monitoring       node-exporter-mxt9b                       2/2     Running   0          6d
monitoring       node-exporter-sxw86                       2/2     Running   0          6d
monitoring       prometheus-k8s-0                          3/3     Running   1          3d
monitoring       prometheus-k8s-1                          3/3     Running   1          3d
monitoring       prometheus-operator-c4b75f7cd-hv7hh       1/1     Running   0          3d

kubectl logs -n monitoring grafana-566fcc7956-cf9vt is showing:

t=2018-11-09T08:21:43+0000 lvl=info msg="Request Completed" logger=context userId=1 orgId=1 uname=admin method=GET path=/api/datasources/proxy/1/api/v1/query_range status=502 remote_addr=10.233.78.0 time_ms=30000 size=0 referer="http://10.160.25.13/d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-use-method-node?refresh=10s&orgId=1"
2018/11/09 08:21:43 http: proxy error: dial tcp 1.1.1.8:9090: i/o timeout
t=2018-11-09T08:21:43+0000 lvl=info msg="Request Completed" logger=context userId=1 orgId=1 uname=admin method=GET path=/api/datasources/proxy/1/api/v1/query_range status=502 remote_addr=10.233.78.0 time_ms=30000 size=0 referer="http://10.160.25.13/d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-use-method-node?refresh=10s&orgId=1"
2018/11/09 08:21:43 http: proxy error: dial tcp 1.1.1.8:9090: i/o timeout
t=2018-11-09T08:21:43+0000 lvl=info msg="Request Completed" logger=context userId=1 orgId=1 uname=admin method=GET path=/api/datasources/proxy/1/api/v1/query_range status=502 remote_addr=10.233.78.0 time_ms=30000 size=0 referer="http://10.160.25.13/d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-use-method-node?refresh=10s&orgId=1"
2018/11/09 08:22:13 http: proxy error: dial tcp 1.1.1.8:9090: i/o timeout
t=2018-11-09T08:22:13+0000 lvl=info msg="Request Completed" logger=context userId=1 orgId=1 uname=admin method=GET path=/api/datasources/proxy/1/api/v1/query_range status=502 remote_addr=10.233.78.0 time_ms=30001 size=0 referer="http://10.160.25.13/d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-use-method-node?refresh=10s&orgId=1"
2018/11/09 08:22:13 http: proxy error: dial tcp 1.1.1.8:9090: i/o timeout
t=2018-11-09T08:22:13+0000 lvl=info msg="Request Completed" logger=context userId=1 orgId=1 uname=admin method=GET path=/api/datasources/proxy/1/api/v1/query_range status=502 remote_addr=10.233.78.0 time_ms=30000 size=0 referer="http://10.160.25.13/d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-use-method-node?refresh=10s&orgId=1"
2018/11/09 08:22:13 http: proxy error: dial tcp 1.1.1.8:9090: i/o timeout

any suggestions?

Manage the default datasource

Hi,

Is there a way to interact with the default datasource (the one named prometheus)?

Specifically, I would like to rename it through config/jsonnet.
Or completely disable it and to add it myself in the _config.grafana+.datasources+

Thank you

Grafana folders support

Hello, is there a way currently to make use of the grafana folders feature?

See:
https://grafana.com/docs/reference/dashboard_folders/
and
https://grafana.com/docs/administration/provisioning/#dashboards

I've tried a few hacks to make this work, as currently providing the configuration for dashboards with a composite path currently is not supported.

As the only limitation seems to be creating multiple folders within the container and separating the dashboards into the appropriate folders, I've tried the following:

local volumeMounts =
        [
          storageVolumeMount,
          datasourcesVolumeMount,
          dashboardsVolumeMount,
        ] +
        [
          local splitName = std.splitLimit(name, '/', 1);
          local folderName = if std.length(splitName) > 1 then splitName[0] else "0";
          local dashboardName = if std.length(splitName) < 2 then std.strReplace(splitName[0], '.json', '') else std.strReplace(splitName[1], '.json', '');
          containerVolumeMount.new('grafana-dashboard-' + dashboardName, '/grafana-dashboard-definitions/' + folderName + '/' + dashboardName),
          for name in std.objectFields($._config.grafana.dashboards)
        ] +
        if std.length($._config.grafana.config) > 0 then [configVolumeMount] else [];

(apply this change anywhere where it's relevant)
Which allowed the following convention to be used:

grafanaDashboards+:: {
    'folder/example.json': (import 'configs/dashboards/example.json')
}

However due to changing the core vendor file, it would make keeping up to date difficult so I would prefer it if I didn't have extra maintenance should this repo be updated.

I've also faced multiple problems related to volume mounts while doing that.

My approach should be a non-breaking change, however I don't fully understand jsonnet, grafana or kubernetes so there may be implications I'm not aware of or a better and cleaner way of doing it.

Thanks!

Provision dashboards at runtime

Hi,
We're using this project through the prometheus-operator, and are finding the workflow of adding dashboards a little clunky.

I've noticed that in the official helm charts for grafana, there's an option for using a sidecar to provision dashboards by monitoring configmaps with a given label/namespace. Is this something that this project is interested in porting over?

using raw dashboards in folders

The kube-prometheus documentation mentions using the rawDashboards field instead of the dashboards field when passing in pre-rendered JSON dashboards for "performance" reasons. However, I want to put my dashboards in folders which appears to only be possible with the folderDashboards field. Is there some undocumented folderRawDashboards field or does folderDashboards support using importstr?

How do I add service metadata annotations?

I'm using this through the kube-prometheus jsonnet library (as intended and recommended in the Readme), but it lacks the documentation of adding annotation metadata to services, for example using external-dns as follows:

kind: Service
metadata:
  annotations:
    external-dns.alpha.kubernetes.io/hostname: <my hostname>

How can this be done, whilst at the same time being able to us jb update etc?

At the moment, the only way I can successfully see to do this would be to add
service.mixin.metadata.withAnnotations($._config.grafana.annotations),
to vendor/grafana/grafana.libsonnet, but that would mean that the change would get overwritten when we run jb update

Make grafana datasource URL configurable

I don't run my Prometheus on http://prometheus-k8s.monitoring.svc:9090. Instead of creating my own datasource object, maybe there's a way to have this in the config?

How do I add my own labels to all of my grafana dashboards?

Currently, I'm deploying prometheus-operator using the helm charts without the default grafana dashboards and prometheus alerts/rules. These are currently disabled.

I am now using the kube-prometheus repo to build and compile my alerts, rules and dashboards. The alerts and rules for prometheus worked great, i managed to modify them to include my custom labels for each alert.

However the grafana dashboards are proving problematic. Currently, my grafana is configured to automatically pull in any dashboards with a specific metadata label. This way, i don't need to constantly list all of my configmap dashboards into the grafana deployment as a volume mount.

I need to be able to add custom metadata labels to all of my grafana dashboard configmaps (grafana_datasource or custom_label):

apiVersion: v1
items:
- apiVersion: v1
  data:
    apiserver.json: |-
      { dashboard json here }
  kind: ConfigMap
  metadata:
    name: grafana-dashboard-apiserver
    namespace: monitoring
    grafana_datasource: true
    custom_label: custom_value

Below is my current libsonnet file:

local kp =
  (import 'kube-prometheus/kube-prometheus.libsonnet') +
  // Uncomment the following imports to enable its patches
  // (import 'kube-prometheus/kube-prometheus-anti-affinity.libsonnet') +
  // (import 'kube-prometheus/kube-prometheus-managed-cluster.libsonnet') +
  // (import 'kube-prometheus/kube-prometheus-node-ports.libsonnet') +
  // (import 'kube-prometheus/kube-prometheus-static-etcd.libsonnet') +
  // (import 'kube-prometheus/kube-prometheus-thanos-sidecar.libsonnet') +
  // (import 'kube-prometheus/kube-prometheus-custom-metrics.libsonnet') +
  {
    _config+:: {
      namespace: 'monitoring',
    },

    prometheusAlerts+:: {
      groups: std.map(
        function(group)
            group {
              rules: std.map(
                function(rule)
                  if std.objectHas(rule, 'labels') && std.objectHas(rule.labels, 'severity') && rule.labels.severity == "warning" then 
                      rule {
                        labels: {
                          application: "{{ if $labels.service }} {{ $labels.service }} {{ else }} UKISS GKE {{ end }}",
                          severity: "P4",
                          sparkGroup: "UK IS DOST Containerisation Support",
                          affectedCi: "{{ $labels.sparkCi }}",                      
                        },
                      }
                  else if std.objectHas(rule, 'labels') && std.objectHas(rule.labels, 'severity') && rule.labels.severity == "critical" then 
                      rule {
                        labels: {
                          application: "{{ if $labels.service }} {{ $labels.service }} {{ else }} UKISS GKE {{ end }}",
                          severity: "P3",
                          sparkGroup: "UK IS DOST Containerisation Support",
                          affectedCi: "{{ $labels.sparkCi }}",                         
                          },
                      }
                  else
                    rule,
                group.rules
              ),
            },
        super.groups
      ),
    },

    grafanaDashboards+:: {  //  monitoring-mixin compatibility
    'multi-cluster.json': (import 'grafana-dashboards/multi-cluster-dashboard.json'),
    },
    grafana+:: {
      dashboards+:: {  // use this method to import your dashboards to Grafana
        'multi-cluster.json': (import 'grafana-dashboards/multi-cluster-dashboard.json'),
      },
    },

  };

{ ['setup/0namespace-' + name]: kp.kubePrometheus[name] for name in std.objectFields(kp.kubePrometheus) } +
{
  ['setup/prometheus-operator-' + name]: kp.prometheusOperator[name]
  for name in std.filter((function(name) name != 'serviceMonitor'), std.objectFields(kp.prometheusOperator))
} +
// serviceMonitor is separated so that it can be created after the CRDs are ready
// { 'prometheus-operator-serviceMonitor': kp.prometheusOperator.serviceMonitor } +
// { ['node-exporter-' + name]: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } +
// { ['kube-state-metrics-' + name]: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } +
// { ['alertmanager-' + name]: kp.alertmanager[name] for name in std.objectFields(kp.alertmanager) } +
{ ['prometheus-' + name]: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } +
// { ['prometheus-adapter-' + name]: kp.prometheusAdapter[name] for name in std.objectFields(kp.prometheusAdapter) } +
{ ['grafana-' + name]: kp.grafana[name] for name in std.objectFields(kp.grafana) }


It doesn't seem like there's a possible way to do this.

Where are the dashboards definition?

Hi @brancz, just wondering where are the definitions of the dashboards used on kube-prometheus. I saw several commits using the src directory but that directory is gone in master now.

Importing playlists

Is there a way to import playlists similar to how dashboards are imported through .json files, or are there any plans to provide such a way in the future?

I've tried looking around on how to persist playlists for a stateless Grafana deployment, but it seems that from Grafana's side importing and exporting playlists is rather limited. The only decent documentation I've found so far is by use of the HTTP API: https://grafana.com/docs/grafana/latest/http_api/playlist/#create-a-playlist
The API is very straightforward and provides a (temporary) workaround for me, but being able to import playlists through jsonnet patches would streamline the deployment process.

Where do I configure SMTP

I have been unable to determine where I configure SMTP. I have checked all the yaml and config files in /prometheus-operator and reviewed the value.ini in /prometheus-operator/helm/grafana. Am I supposed to create the grafana.ini or is there another file this configuration gets added to?
My Alert manager pod is running and sendmail is configured, but I still get an error when I try to send a test message that SMTP is not configured in grafana.ini.

Thanks

Override default jsonnet variables for storage

I'm building a jsonnet deployment for the Prometheus/Grafana stack and would like to override the default config for some of the volumeMounts.

For example the persistent storage for Grafana is an emptyDir but I would like to use a PVC. Can these variables be overwritten by my jsonnet file?

The default is:

local storageVolumeName = 'grafana-storage';
local storageVolume = volume.fromEmptyDir(storageVolumeName);
local storageVolumeMount = containerVolumeMount.new(storageVolumeName, '/var/lib/grafana');

I'd like to do something like this:

local kp = (import 'kube-prometheus/kube-prometheus.libsonnet') + {
...
 grafana+:: {
    deployment+:
      {
      local storageVolumeName = 'grafana-storage';
      local storageVolume = volume.withName(storageVolumeName);
      local storageVolumeMount = containerVolumeMount.new(storageVolumeName, '/var/lib/grafana');
...
},

Another question is if it's possible to override a mount path, like replacing local storageVolumeMount = containerVolumeMount.new(storageVolumeName, '/var/lib/grafana'); with local storageVolumeMount = containerVolumeMount.new(storageVolumeName, '/data'); for example.

And I make a separate PVC for this. Is it possible?
Thanks!

possibility to add server certificates to grafana

Is it possible to add server certificates?
I can generate the correct config for grafana (see below) but how do I add the certificates themselves as secrets? I guess I have to rewrite grafana.libsonnet?

local kp = (import 'kube-prometheus/kube-prometheus.libsonnet') +
(import 'kube-prometheus/kube-prometheus-anti-affinity.libsonnet') +
{
_config+:: {
namespace: 'monitoring',
grafana+:: {
config: { // http://docs.grafana.org/installation/configuration/
sections: {
"security": {admin_password: 'supersecret'},
"server": { protocol: 'https', cert_file: 'server.crt', cert_key: 'server.key' },
},
},
},
},
};

User experience when creating/editing dashboards

Hi,

The project's roadmap mentions the following problem:

A tool to review Grafana dashboard changes on PRs. While reviewing jsonnet code is a lot easier than the large Grafana json sources, it's hard to imagine what that will actually end up looking like once rendered. Ideally a production-like environment is spun up and produces metrics to be graphed, then a tool could take a screenshot and Grafana snapshot of the rendered Grafana dashboards. That way the changes can not only be reviewed in code but also visually. Similar to point 2 this should eventually be it's own project.

However, I believe the issue is deeper than that.
There are a few tools this days which attempt to generate grafana dashboards json files, for example:

  1. https://github.com/grafana/grafonnet-lib
  2. https://github.com/jakubplichta/grafana-dashboard-builder
  3. https://github.com/deliveryhero/grafyaml

In the end, I don't believe any tool can really provide an easy straight forward experience for the user when creating dashboards as they can be very complex.
Even if the final dashboard snapshot is generated within a PR, the user still needs to understand how to build this dashboard entirely via code.

How can we overcome this issue, considering that the goal of this project is to make Grafana stateless?
Perhaps a sandbox environment is needed here where the user can actually build the dashboard and then export the json in the end?

Grafana does not find Datasources or Dashboards

After deploying Grafana with the Kube-prometheus stack, Grafana does not find the Prometheus Datasource or default dashboards.

In it's logs it shows that the provisioning path is /usr/share/grafana/conf/provisioning:

Pod: grafana-6c4f67b8d8-gpd5m

t=2018-12-07T20:50:26+0000 lvl=info msg="Starting Grafana" logger=server version=5.4.0 commit=69c5191 branch=HEAD compiled=2018-12-03T10:17:42+0000
t=2018-12-07T20:50:26+0000 lvl=info msg="Config loaded from" logger=settings file=/usr/share/grafana/conf/defaults.ini
t=2018-12-07T20:50:26+0000 lvl=info msg="Config loaded from" logger=settings file=/grafana/conf/config.ini
t=2018-12-07T20:50:26+0000 lvl=info msg="Path Home" logger=settings path=/usr/share/grafana
t=2018-12-07T20:50:26+0000 lvl=info msg="Path Data" logger=settings path=/data
t=2018-12-07T20:50:26+0000 lvl=info msg="Path Logs" logger=settings path=/data/log
t=2018-12-07T20:50:26+0000 lvl=info msg="Path Plugins" logger=settings path=/data/plugins
t=2018-12-07T20:50:26+0000 lvl=info msg="Path Provisioning" logger=settings path=/usr/share/grafana/conf/provisioning
t=2018-12-07T20:50:26+0000 lvl=info msg="App mode production" logger=settings
t=2018-12-07T20:50:26+0000 lvl=info msg="Initializing HTTPServer" logger=server
t=2018-12-07T20:50:26+0000 lvl=info msg="Initializing SqlStore" logger=server
t=2018-12-07T20:50:26+0000 lvl=info msg="Connecting to DB" logger=sqlstore dbtype=sqlite3
t=2018-12-07T20:50:26+0000 lvl=info msg="Starting DB migration" logger=migrator
t=2018-12-07T20:50:26+0000 lvl=info msg="Executing migration" logger=migrator id="create migration_log table"
t=2018-12-07T20:50:26+0000 lvl=info msg="Executing migration" logger=migrator id="create user table"

After changing the manifests/grafana-deployment.yaml mount points to the correct path, it loaded correctly:

...
        volumeMounts:
        - mountPath: /var/lib/grafana
          name: grafana-storage
          readOnly: false
        #- mountPath: /etc/grafana/provisioning/datasources
        - mountPath: /usr/share/grafana/conf/provisioning/datasources
          name: grafana-datasources
          readOnly: false
        #- mountPath: /etc/grafana/provisioning/dashboards
        - mountPath: /usr/share/grafana/conf/provisioning/dashboards
          name: grafana-dashboards
          readOnly: false

No custom config.ini was used.

Grafana does not reload its configuration on change

The easiest workaround I have found is adding checksum annotations to the pod template (like Helm does) to restart it:

deployment.mixin.spec.template.metadata.withAnnotationsMixin({
  'checksum/grafana-config': std.md5(std.toString($.grafana.config)),
  'checksum/grafana-datasources': std.md5(std.toString($.grafana.dashboardDatasources)),
})

deployment customization

I'm using kube-prometheus, and I'd like to customize the grafana deployment spec, to add a couple of environment variables. I'm unsure if it's supported or how it can be done with a mixin.

Changing default credentials for Grafana

As I am going to expose Grafana via an Ingress, I'd like to change the credentials of Grafana.
Should we build some kind of jsonnet wrapper for that, or do we simply allow for adding env vars to the container in the deployment?

Set seccompProfile to RuntimeDefault

I think we can simply set this to RuntimeDefault.

Warning: would violate PodSecurity "restricted:latest": seccompProfile (pod or container "grafana" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")

Simple dashboard sanity checks

Not sure if this can be part of this project, I just want to share this somewhere.

It can be quiet cumbersome to check for things like unique UID and titles, so I integrated the logic in Jsonnet, and then generating the deployment simply fails if the condition are not met.

local folderDashboards = {
  // Example
  AWS: import 'aws/folder.libsonnet',
  Datastores: import 'datastores/folder.libsonnet',
  Kubernetes: import 'kubernetes/folder.libsonnet',
  myServices: import 'myServices/folder.libsonnet',
  System: import 'system/folder.libsonnet',
};

local titles = [
  folderDashboards[folder][filename].title
  for folder in std.objectFields(folderDashboards)
  for filename in std.objectFields(folderDashboards[folder])
];

local filenames = [
  filename
  for folder in std.objectFields(folderDashboards)
  for filename in std.objectFields(folderDashboards[folder])
];

local isTitleUnique(title) =
  if std.count(titles, title) > 1 then
    error 'Title "%s" is used more than once' % [title]
  else true;

local isFilenameUnique(filename) =  // Means UID will be unique
  if std.count(filenames, filename) > 1 then
    error 'Filename "%s" is used more than once' % [filename]
  else true;

{
  [folder]: {
    [filename]: folderDashboards[folder][filename] {
      uid:
        // Checks need to be included into a non-hidden field
        // else they would never be evaluated
        if isFilenameUnique(filename) && isTitleUnique(self.title) then
          // We could hash folder+filename, but this would break
          // the dashboard URL if it is moved
          std.md5(filename),
    }
    for filename in std.objectFields(folderDashboards[folder])
  }
  for folder in std.objectFields(folderDashboards)
}

Every dashboard needs a UID, so the checks are called while setting it.

and then, pass the output to _config.grafana.folderDashboards.

dashboard outdated?

When grafana pods starts up it logs:
t=2018-08-03T14:38:55+0000 lvl=warn msg="[Deprecated] the dashboard provisioning config is outdated. please upgrade" logger=provisioning.dashboard filename=/etc/grafana/provisioning/dashboards/dashboards.yaml

Grafana HA and stateless with authentication possible?

The README states:

This allows easily operating Grafana highly available as if it was a stateless application - no need to run a clustered database for your dashboarding solution anymore!

But with multiple replicas, I found that I need to re-authenticate to each of them.

So I would like to know what is your approach to scale Grafana horizontally and avoid downtime during restarts?


A few things I have tried without luck:

Remote cache

https://grafana.com/docs/grafana/latest/administration/configuration/#remote_cache

[remote_cache]
type = memcached
connstr = grafana-memcached-0.grafana-memcached:11211

But apparently, this is not used to store sessions ๐Ÿ˜ž: grafana/grafana#25735 (comment)

Oauth auto login

We use Google OAuth, so I thought Grafana could just validate this.

https://grafana.com/docs/grafana/latest/administration/configuration/#oauth_auto_login

[auth]
oauth_auto_login = true
[auth.google]
enabled = true
allow_sign_up = true
client_id = <REDACTED>
scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email
token_url = https://accounts.google.com/o/oauth2/token
[server]
root_url = <REDACTED>

This goes into a redirect loop between Grafana and Google.


I see LDAP is supported, is there something different about it?

The last option, I have thought about is disabling authentication on Grafana and using https://github.com/oauth2-proxy/oauth2-proxy in front of it.

Question on using secret for admin username/password

General question:

Would it be possible to have the admin username/password stored in a secret that is loaded in the grafana container env, ie:

env:

  • name: GF_SECURITY_ADMIN_USER
    valueFrom:
    secretKeyRef:
    key: admin-user
    name: grafana-admin
  • name: GF_SECURITY_ADMIN_PASSWORD
    valueFrom:
    secretKeyRef:
    key: admin-password
    name: grafana-admin

Using manually created PVs/PVCs as volumes in container of deployment

I have mounted an EFS from AWS into my current grafana deployment to keep grafana as stateless as possible with minimal cost. However, I do not see how I would go about overwriting the storageVolume and storageVolumeMount to use my manually defined values. I could open a PR which makes configuring the volumes possible, if there is no other way to achieve this.

Additional datasources

Hi,

Looking at the code in grafana.libsonnet I'm wondering how we could/should add a new datasource to be populated into grafana. Currently we have:

grafana+:: {
dashboards: {},
datasources: [{
name: 'prometheus',
type: 'prometheus',
access: 'proxy',
orgId: 1,
url: 'http://prometheus-k8s.' + $._config.namespace + '.svc:9090',
version: 1,
editable: false,
}],
config: {},
ldap: null,
plugins: [],
},

I guess it should be somewhere inside the [ in datasources section but I'm not sure how to specifiy both of them (prometheus and the new one).

Thanks!

Links are broken

Hey the following links in README are broken
The Grafana dashboard sources configuration.
The Grafana datasources configuration.
The Grafana dashboard definitions with the help of grafana/grafonnet-lib.
The Grafana Kubernetes manifests with the help of ksonnet/ksonnet-lib.

Custom grafana.ini prevents datasources and dashboards mounts

If a custom config: section is defined, then the secret will be mounted at /etc/grafana per: https://github.com/brancz/kubernetes-grafana/blob/master/grafana/grafana.libsonnet#L88

This seems to prevent datasources and dashboardSources from being mounted under sub-directories of /etc/grafana as intended here:
https://github.com/brancz/kubernetes-grafana/blob/master/grafana/grafana.libsonnet#L97

Options?

  1. Add subPath to deployment for secret volume mount with ksonnet mixin. Downside is no automatic updates on secret (config) change. eg:
      local configVolumeMount = containerVolumeMount.new(configVolumeName, '/etc/grafana/grafana.ini') +
                                containerVolumeMount.withSubPath('grafana.ini');
  1. Overwrite provisioning dir, but this makes installation non standard. grafana.ini line

  2. Other?

Grafana provisioning logs errors when dashboards list is empty

Since folderDashboards is supported, I do not use dashboards, this result in the following log lines on every provisioning interval:

t=2020-07-22T17:20:57+0000 lvl=eror msg="Cannot read directory" logger=provisioning.dashboard type=file name=0 error="stat /grafana-dashboard-definitions/0: no such file or directory"
t=2020-07-22T17:20:57+0000 lvl=eror msg="Failed to read content of symlinked path" logger=provisioning.dashboard type=file name=0 path=/grafana-dashboard-definitions/0 error="lstat /grafana-dashboard-definitions/0: no such file or directory"
t=2020-07-22T17:20:57+0000 lvl=info msg="falling back to original path due to EvalSymlink/Abs failure" logger=provisioning.dashboard type=file name=0
t=2020-07-22T17:20:57+0000 lvl=eror msg="failed to search for dashboards" logger=provisioning.dashboard type=file name=0 error="stat /grafana-dashboard-definitions/0: no such file or directory"

I have worked around it by adding an emptyDir locally:

deployment.mixin.spec.template.spec.withVolumesMixin(volume.fromEmptyDir(defaultFolderVolumeName)) + {
  spec+: {
    template+: {
      spec+: {
        containers: [
          if c.name == 'grafana' then
            c + container.withVolumeMountsMixin([
              containerVolumeMount.new(defaultFolderVolumeName, '/grafana-dashboard-definitions/0'),
            ])
          else c
          for c in super.containers
        ],
      },
    },
  },
},

But ideally, the provisioning config should not be created.

Authentication and user/groups persistence

Hi,

I enabled Google OAuth authentication, which is working fine, all my users can log into grafana.
As an admin I can create teams/permission but all this is lost upon grafana reboot.

Is there a way to save this ?

Adding md5 hash to config map name

Hi,

Adding md5 hash to the generated config map name would be nice because changing dashboard settings redeploys grafana. This strategy is used by kustomize too.

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.