grafana/pkg/services/store/entity
Prem Saraswat 196134b0b4
Storage Server: Avoid incorrect parsing of connection string (#85293)
Storage Server: avoid incorrect parsing of connection string

In storage server, a connection string is generated to connect to the
backing database. In case of Postgres, we were generating the string
like `"user=grafana pass= host=postgres.example port=4567"`.

This triggered an edge case in `pq` (the go postgres driver) to parse
`pass` to be equal to `host=postgres.example`, and host being reset to
default value.

Using single quotes in the connection string fixed this.

Signed-off-by: Prem Kumar <prem.saraswat@grafana.com>
2024-05-03 10:54:39 -04:00
..
db Storage Server: Avoid incorrect parsing of connection string (#85293) 2024-05-03 10:54:39 -04:00
dummy Unified Storage: Adds health check service for entity server (#86471) 2024-05-01 11:36:44 -06:00
grpc use in-process grpc client instead of wrapping server interface (#81926) 2024-02-07 13:17:02 -05:00
server Unified Storage: Adds health check service for entity server (#86471) 2024-05-01 11:36:44 -06:00
sqlstash Unified Storage: Adds health check service for entity server (#86471) 2024-05-01 11:36:44 -06:00
tests Storage Api: Adds traces (#85391) 2024-04-16 08:30:51 -06:00
client_wrapper.go Chore: Upgrade grpc-ecosystem/go-grpc-middleware to v2 (#86724) 2024-04-25 17:25:48 +02:00
entity_grpc.pb.go Unified Storage: Adds health check service for entity server (#86471) 2024-05-01 11:36:44 -06:00
entity.pb.go Unified Storage: Adds health check service for entity server (#86471) 2024-05-01 11:36:44 -06:00
entity.proto Unified Storage: Adds health check service for entity server (#86471) 2024-05-01 11:36:44 -06:00
generate.sh Chore: Replace entity GRN with infra/grn GRN (#74198) 2023-08-31 15:43:35 -04:00
health_test.go Unified Storage: Adds health check service for entity server (#86471) 2024-05-01 11:36:44 -06:00
health.go Unified Storage: Adds health check service for entity server (#86471) 2024-05-01 11:36:44 -06:00
key.go Storage: Use our own key format and support unnamespaced objects (#83929) 2024-03-05 16:31:39 -05:00
models.go K8s/Folders: Add folders api service (with legacy storage) (#79413) 2023-12-20 20:28:56 +02:00
README.md k8s: remove dependency on app_mode development (#85474) 2024-05-03 11:28:15 +03:00

Unified Storage

The unified storage projects aims to provide a simple and extensible backend to unify the way we store different objects within the Grafana app platform.

It provides generic storage for k8s objects, and can store data either within dedicated tables in the main Grafana database, or in separate storage.

By default it runs in-process within Grafana, but it can also be run as a standalone GRPC service (storage-server).

Storage Overview

There are 2 main tables, the entity table stores a "current" view of the objects, and the entity_history table stores a record of each revision of a given object.

Running Unified Storage

Baseline configuration

The minimum config settings required are:

; need to specify target here for override to work later
target = all

[server]
; https is required for kubectl
protocol = https

[feature_toggles]
; enable unified storage
unifiedStorage = true
; enable k8s apiserver
grafanaAPIServer = true
; store playlists in k8s
kubernetesPlaylists = true
; store json id token in context
idForwarding = true

[grafana-apiserver]
; use unified storage for k8s apiserver
storage_type = unified

With this configuration, you can run everything in-process. Run the Grafana backend with:

bra run

or

make run

The default kubeconfig sends requests directly to the apiserver, to authenticate as a grafana user, create grafana.kubeconfig:

apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://127.0.0.1:3000
  name: default-cluster
contexts:
- context:
    cluster: default-cluster
    namespace: default
    user: default
  name: default-context
current-context: default-context
kind: Config
preferences: {}
users:
- name: default
  user:
    username: <username>
    password: <password>

Where <username> and <password> are credentials for basic auth against Grafana. For example, with the default credentials:

    username: admin
    password: admin

In this mode, you can interact with the k8s api. Make sure you are in the directory where you created grafana.kubeconfig. Then run:

kubectl --kubeconfig=./grafana.kubeconfig get playlist

If this is your first time running the command, a successful response would be:

No resources found in default namespace.

To create a playlist, create a file playlist-generate.yaml:

apiVersion: playlist.grafana.app/v0alpha1
kind: Playlist
metadata:
  generateName: x # anything is ok here... except yes or true -- they become boolean!
  labels:
    foo: bar
  annotations:
    grafana.app/slug: "slugger"
    grafana.app/updatedBy: "updater"
spec:
  title: Playlist with auto generated UID
  interval: 5m
  items:
  - type: dashboard_by_tag
    value: panel-tests
  - type: dashboard_by_uid
    value: vmie2cmWz # dashboard from devenv

then run:

kubectl --kubeconfig=./grafana.kubeconfig create -f playlist-generate.yaml

For example, a successful response would be:

playlist.playlist.grafana.app/u394j4d3-s63j-2d74-g8hf-958773jtybf2 created

When running

kubectl --kubeconfig=./grafana.kubeconfig get playlist

you should now see something like:

NAME                                   TITLE                              INTERVAL   CREATED AT
u394j4d3-s63j-2d74-g8hf-958773jtybf2   Playlist with auto generated UID   5m         2023-12-14T13:53:35Z 

To update the playlist, update the playlist-generate.yaml file then run:

kubectl --kubeconfig=./grafana.kubeconfig patch playlist <NAME> --patch-file playlist-generate.yaml

In the example, <NAME> would be u394j4d3-s63j-2d74-g8hf-958773jtybf2.

Use a separate database

By default Unified Storage uses the Grafana database. To run against a separate database, update custom.ini by adding the following section to it:

[entity_api]
db_type = mysql
db_host = localhost:3306
db_name = grafana
db_user = <username>
db_pass = <password>

MySQL and Postgres are both supported. The <username> and <password> values can be found in the following devenv docker compose files: MySQL and Postgres.

Then, run

make devenv sources=<source>

where source is either mysql or postgres.

Finally, run the Grafana backend with

bra run

or

make run

Run as a GRPC service

Start GRPC storage-server

This currently only works with a separate database configuration (see previous section).

Start the storage-server with:

GF_DEFAULT_TARGET=storage-server ./bin/grafana server target

The GRPC service will listen on port 10000

Use GRPC server

To run grafana against the storage-server, override the storage_type setting:

GF_GRAFANA_APISERVER_STORAGE_TYPE=unified-grpc ./bin/grafana server

You can then list the previously-created playlists with:

kubectl --kubeconfig=./grafana.kubeconfig get playlist

Changing protobuf interface

  • install protoc
  • install the protocol compiler plugin for Go
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
  • make changes in .proto file
  • to compile all protobuf files in the repository run make protobuf at its top level