add grafana (#987)

diff --git a/kubernetes/grafana/configmap.yaml b/kubernetes/grafana/configmap.yaml
new file mode 100644
index 0000000..cd743c0
--- /dev/null
+++ b/kubernetes/grafana/configmap.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: grafana
+  namespace: default
+  labels:
+    app: grafana
+data:
+  grafana.ini: |
+    [analytics]
+    check_for_updates = true
+    [grafana_net]
+    url = https://grafana.net
+    [log]
+    mode = console
+    [paths]
+    data = /var/lib/grafana/
+    logs = /var/log/grafana
+    plugins = /var/lib/grafana/plugins
+    provisioning = /etc/grafana/provisioning
+    [server]
+    domain = ''
\ No newline at end of file
diff --git a/kubernetes/grafana/rbac.yaml b/kubernetes/grafana/rbac.yaml
new file mode 100644
index 0000000..74f5693
--- /dev/null
+++ b/kubernetes/grafana/rbac.yaml
@@ -0,0 +1,63 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: grafana
+  namespace: default
+  labels:
+    app: grafana
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: grafana-clusterrole
+  labels:
+    app: grafana
+rules: []
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: grafana-clusterrolebinding
+  labels:
+    app: grafana
+subjects:
+  - kind: ServiceAccount
+    name: grafana
+    namespace: default
+roleRef:
+  kind: ClusterRole
+  name: grafana-clusterrole
+  apiGroup: rbac.authorization.k8s.io
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: grafana
+  namespace: default
+  labels:
+    app: grafana
+rules:
+  - apiGroups:
+      - extensions
+    resources:
+      - podsecuritypolicies
+    verbs:
+      - use
+    resourceNames:
+      - grafana
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: grafana
+  namespace: default
+  labels:
+    app: grafana
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: grafana
+subjects:
+  - kind: ServiceAccount
+    name: grafana
+    namespace: default
\ No newline at end of file
diff --git a/kubernetes/grafana/secret.yaml b/kubernetes/grafana/secret.yaml
new file mode 100644
index 0000000..57c4c59
--- /dev/null
+++ b/kubernetes/grafana/secret.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: grafana
+  namespace: default
+  labels:
+    app: grafana
+type: Opaque
+data:
+  admin-user: "YWRtaW4="
+  admin-password: "NnhlY1JVSHJpNm1MSktVRGV5cnBtZ0Jja1RUYkJmNG1ZcmdsVElKZQ=="
+  ldap-toml: ""
\ No newline at end of file
diff --git a/kubernetes/grafana/service.yaml b/kubernetes/grafana/service.yaml
new file mode 100644
index 0000000..269c1cd
--- /dev/null
+++ b/kubernetes/grafana/service.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: grafana
+  namespace: default
+  labels:
+    app: grafana
+spec:
+  type: ClusterIP
+  ports:
+    - name: service
+      port: 80
+      protocol: TCP
+      targetPort: 3000
+  selector:
+    app: grafana
\ No newline at end of file
diff --git a/kubernetes/grafana/statefulset.yaml b/kubernetes/grafana/statefulset.yaml
new file mode 100644
index 0000000..670565e
--- /dev/null
+++ b/kubernetes/grafana/statefulset.yaml
@@ -0,0 +1,93 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: grafana
+  namespace: default
+  labels:
+    app: grafana
+  annotations:
+    checksum/config: 4b9517b76dc0f685555140b24fa94df4dff5a5f3ea72c424290168afe0465276
+    checksum/dashboards-json-config: 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b
+    checksum/sc-dashboard-provider-config: 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b
+    checksum/secret: 87b3dc176b564805256e2f3207f32567cf2dcf805f5ff51c0b48650907047595
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: grafana
+  template:
+    metadata:
+      labels:
+        app: grafana
+    spec:
+      serviceAccountName: grafana
+      containers:
+        - name: grafana
+          image: "grafana/grafana:9.3.6"
+          imagePullPolicy: IfNotPresent
+          volumeMounts:
+            - name: config
+              mountPath: "/etc/grafana/grafana.ini"
+              subPath: grafana.ini
+            - name: storage
+              mountPath: "/etc/grafana"
+          ports:
+            - name: grafana
+              containerPort: 3000
+              protocol: TCP
+            - name: gossip-tcp
+              containerPort: 9094
+              protocol: TCP
+            - name: gossip-udp
+              containerPort: 9094
+              protocol: UDP
+          env:
+            - name: POD_IP
+              valueFrom:
+                fieldRef:
+                  fieldPath: status.podIP
+            - name: GF_SECURITY_ADMIN_USER
+              valueFrom:
+                secretKeyRef:
+                  name: grafana
+                  key: admin-user
+            - name: GF_SECURITY_ADMIN_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: grafana
+                  key: admin-password
+            - name: GF_PATHS_DATA
+              value: /var/lib/grafana/
+            - name: GF_PATHS_LOGS
+              value: /var/log/grafana
+            - name: GF_PATHS_PLUGINS
+              value: /var/lib/grafana/plugins
+            - name: GF_PATHS_PROVISIONING
+              value: /etc/grafana/provisioning
+          livenessProbe:
+            failureThreshold: 10
+            httpGet:
+              path: /api/health
+              port: 3000
+            initialDelaySeconds: 60
+            timeoutSeconds: 30
+          readinessProbe:
+            httpGet:
+              path: /api/health
+              port: 3000
+      volumes:
+        - name: config
+          configMap:
+            name: grafana
+  volumeClaimTemplates:
+    - metadata:
+        name: storage
+        labels:
+          app: grafana
+      spec:
+        storageClassName: local
+        accessModes:
+          - ReadWriteOnce
+        resources:
+          requests:
+            storage: 2Gi
\ No newline at end of file
diff --git a/kubernetes/grafana/storage.yaml b/kubernetes/grafana/storage.yaml
new file mode 100644
index 0000000..a4e2e99
--- /dev/null
+++ b/kubernetes/grafana/storage.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+  name: storage-grafana-pv
+spec:
+  storageClassName: local
+  capacity:
+    storage: 10Gi
+  accessModes:
+    - ReadWriteOnce
+  hostPath:
+    path: /var/lib/grafana
+---
+apiVersion: storage.k8s.io/v1
+kind: StorageClass
+metadata:
+  name: local
+provisioner: kubernetes.io/no-provisioner
+volumeBindingMode: WaitForFirstConsumer
\ No newline at end of file