Skip to content

Commit

Permalink
docs: document how to add persistent volumes and keycloak integration…
Browse files Browse the repository at this point in the history
… to grafana instance (#1397)

* added an example for persistent volume using existing storage class

* added an example for Keycloak OAuth2 integration

* added an example for Keycloak OAuth2 integration

* added an example for Keycloak OAuth2 integration

* added a new line at the end of file to satisfy CI

---------

Co-authored-by: Hubert Stefanski <[email protected]>
  • Loading branch information
armagankaratosun and hubeadmin authored Feb 5, 2024
1 parent 7e53f32 commit 34d284e
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 0 deletions.
91 changes: 91 additions & 0 deletions examples/grafana_keycloak_sso/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
title: "Grafana deployment with Keycloak OAuth2 SSO configuration"
linkTitle: "Grafana deployment with Keycloak OAuth2 SSO configuration"
---

A basic example of a Grafana Deployment that overrides generic oauth configuration, it's important to note that most configuration that is valid in the `grafana` container can be done with grafana-operator.

## Steps

### Create Keycloak Client for Grafana

Follow official Grafana guide in how to create a Keycloak client and role mappers for Grafana [here](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/keycloak/#keycloak-configuration).

### Create a Kubernetes Secret

In order to safely store the client-id and client-secret for the Keycloak client you have created in the first step, we recommend you creating a Kubernetes secrets to store the client-id and client-secret that Keycloak will use.

The grafana-operator is agnostic to any secret management solution you might use to get this secret (Vault, external-secrets, vanilla K8s secrets, etc).

```yaml
apiVersion: v1
data:
client-id: c29tZXJlYWxseWxvbmdzZWNyZXRqdXN0dG9jb3ZlcnN0dWZmCg==
client-secret: c29tZXJlYWxseWxvbmdzZWNyZXRqdXN0dG9jb3ZlcnN0dWZmCg==
kind: Secret
metadata:
name: grafana-oauth
type: Opaque
```
### Creating our Grafana Instance
Create a Grafana instance overriding the configuration for `auth.generic_oauth:`.

```yaml
apiVersion: grafana.integreatly.org/v1beta1
kind: Grafana
metadata:
name: grafana
labels:
dashboards: "grafana"
spec:
config:
log:
mode: "console"
auth:
disable_login_form: "false"
auth.generic_oauth:
# For variables see https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#env-provider
enabled: "true"
name: "Keycloak SSO"
allow_sign_up: "true"
client_id: ${AUTH_CLIENT_ID}
client_secret: ${AUTH_CLIENT_SECRET}
scopes: "openid email profile offline_access roles"
email_attribute_path: email
login_attribute_path: username
name_attribute_path: full_name
groups_attribute_path: groups
auth_url: "https://<PROVIDER_DOMAIN>/realms/<REALM_NAME>/protocol/openid-connect/auth"
token_url: "https://<PROVIDER_DOMAIN>/realms/<REALM_NAME>/protocol/openid-connect/token"
api_url: "https://<PROVIDER_DOMAIN>/realms/<REALM_NAME>/protocol/openid-connect/userinfo"
role_attribute_path: "contains(roles[*], 'admin') && 'Admin' || contains(roles[*], 'editor') && 'Editor' || 'Viewer'"
...
```
Now, we need to set `secretKeyRef` to the Grafana container to pass the values inside the secret you have created in the previous step as environment variables. Please make sure to point to the right secret name and key.

```yaml
...
deployment:
spec:
template:
spec:
containers:
- name: grafana
env:
- name: AUTH_CLIENT_ID
valueFrom:
secretKeyRef:
name: grafana-oauth
key: client-id
- name: AUTH_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: grafana-oauth
key: client-secret
...
```
Full configuration is below.

{{< readfile file="resources.yaml" code="true" lang="yaml" >}}
81 changes: 81 additions & 0 deletions examples/grafana_keycloak_sso/resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
apiVersion: v1
data:
client-id: c29tZXJlYWxseWxvbmdzZWNyZXRqdXN0dG9jb3ZlcnN0dWZmCg==
client-secret: c29tZXJlYWxseWxvbmdzZWNyZXRqdXN0dG9jb3ZlcnN0dWZmCg==
kind: Secret
metadata:
name: grafana-oauth
namespace: monitoring
type: Opaque
---
apiVersion: grafana.integreatly.org/v1beta1
kind: Grafana
metadata:
name: grafana
labels:
dashboards: "grafana"
spec:
config:
log:
mode: "console"
auth:
disable_login_form: "false"
auth.generic_oauth:
# For variables see https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#env-provider
enabled: "true"
name: "Keycloak SSO"
allow_sign_up: "true"
client_id: ${AUTH_CLIENT_ID}
client_secret: ${AUTH_CLIENT_SECRET}
scopes: "openid email profile offline_access roles"
email_attribute_path: email
login_attribute_path: username
name_attribute_path: full_name
groups_attribute_path: groups
auth_url: "https://<PROVIDER_DOMAIN>/realms/<REALM_NAME>/protocol/openid-connect/auth"
token_url: "https://<PROVIDER_DOMAIN>/realms/<REALM_NAME>/protocol/openid-connect/token"
api_url: "https://<PROVIDER_DOMAIN>/realms/<REALM_NAME>/protocol/openid-connect/userinfo"
role_attribute_path: "contains(roles[*], 'admin') && 'Admin' || contains(roles[*], 'editor') && 'Editor' || 'Viewer'"
server:
root_url: https://grafana.your-domain.com
deployment:
spec:
template:
spec:
containers:
- name: grafana
env:
- name: AUTH_CLIENT_ID
valueFrom:
secretKeyRef:
name: grafana-oauth
key: client-id
- name: AUTH_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: grafana-oauth
key: client-secret
image: grafana/grafana:10.0.3
ingress:
metadata:
annotations:
kubernetes.io/ingress.class: nginx
external-dns.alpha.kubernetes.io/hostname: grafana.your-domain.com
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
rules:
- host: grafana.your-domain.com
http:
paths:
- backend:
service:
name: grafana-service
port:
number: 3000
path: /
pathType: Prefix
tls:
- hosts:
- grafana.your-domain.com
secretName: grafana-tls-secret
8 changes: 8 additions & 0 deletions examples/persistent_volume/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: "Grafana deployment with a Persistent Volume"
linkTitle: "Grafana deployment with a Persistent Volume"
---

A basic deployment of Grafana with a persistent volume attached using existing Storage Class.

{{< readfile file="resources.yaml" code="true" lang="yaml" >}}
40 changes: 40 additions & 0 deletions examples/persistent_volume/resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
apiVersion: grafana.integreatly.org/v1beta1
kind: Grafana
metadata:
name: grafana
labels:
dashboards: "grafana"
spec:
persistentVolumeClaim:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: <storage-class-name>
config:
log:
mode: "console"
auth:
disable_login_form: "false"
security:
admin_user: root
admin_password: secret
deployment:
spec:
template:
spec:
containers:
- name: grafana
image: grafana/grafana:9.4.3
securityContext:
allowPrivilegeEscalation: true
readOnlyRootFilesystem: false
readinessProbe:
failureThreshold: 3
volumes:
- name: grafana-data
persistentVolumeClaim:
claimName: grafana-pvc

0 comments on commit 34d284e

Please sign in to comment.