apiVersion: apps/v1 kind: StatefulSet metadata: name: grafana namespace: observability labels: app: grafana spec: serviceName: grafana replicas: 1 selector: matchLabels: app: grafana template: metadata: labels: app: grafana spec: nodeSelector: kubernetes.io/hostname: hetzner-2 securityContext: fsGroup: 472 runAsGroup: 472 runAsUser: 472 containers: - name: grafana image: grafana/grafana:11.4.0 ports: - name: http containerPort: 3000 protocol: TCP env: - name: GF_SECURITY_ADMIN_USER value: admin - name: GF_SECURITY_ADMIN_PASSWORD value: admin # Change this in production! - name: GF_INSTALL_PLUGINS value: "" - name: GF_FEATURE_TOGGLES_ENABLE value: "traceqlEditor,correlations" - name: GF_AUTH_ANONYMOUS_ENABLED value: "false" - name: GF_ANALYTICS_REPORTING_ENABLED value: "false" - name: GF_ANALYTICS_CHECK_FOR_UPDATES value: "false" livenessProbe: httpGet: path: /api/health port: http initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 5 readinessProbe: httpGet: path: /api/health port: http initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 5 resources: requests: cpu: 250m memory: 512Mi limits: cpu: 1000m memory: 1Gi volumeMounts: - name: grafana-data mountPath: /var/lib/grafana - name: grafana-datasources mountPath: /etc/grafana/provisioning/datasources volumes: - name: grafana-data persistentVolumeClaim: claimName: grafana-data - name: grafana-datasources configMap: name: grafana-datasources --- apiVersion: v1 kind: Service metadata: name: grafana namespace: observability labels: app: grafana spec: type: ClusterIP ports: - port: 3000 targetPort: http protocol: TCP name: http selector: app: grafana