From 4b8c7763577f84101486be6082547cc164254200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Sun, 10 May 2026 09:12:21 +0400 Subject: [PATCH] feat: grafana subpath /grafana on fission.kube5s.ru (temp, easy migration to grafana.kube5s.ru) --- .../grafana/configmap-dashboard-fission.yaml | 102 ++++++++++++++++++ .../configmap-dashboard-providers.yaml | 15 +++ deploy/grafana/configmap-datasources.yaml | 22 ++++ deploy/grafana/deployment.yaml | 98 +++++++++++++++++ deploy/grafana/ingress-subpath.yaml | 28 +++++ deploy/grafana/namespace.yaml | 4 + deploy/grafana/pvc.yaml | 11 ++ deploy/grafana/secret.yaml | 9 ++ deploy/grafana/service-ingress.yaml | 37 +++++++ 9 files changed, 326 insertions(+) create mode 100644 deploy/grafana/configmap-dashboard-fission.yaml create mode 100644 deploy/grafana/configmap-dashboard-providers.yaml create mode 100644 deploy/grafana/configmap-datasources.yaml create mode 100644 deploy/grafana/deployment.yaml create mode 100644 deploy/grafana/ingress-subpath.yaml create mode 100644 deploy/grafana/namespace.yaml create mode 100644 deploy/grafana/pvc.yaml create mode 100644 deploy/grafana/secret.yaml create mode 100644 deploy/grafana/service-ingress.yaml diff --git a/deploy/grafana/configmap-dashboard-fission.yaml b/deploy/grafana/configmap-dashboard-fission.yaml new file mode 100644 index 0000000..1c2167a --- /dev/null +++ b/deploy/grafana/configmap-dashboard-fission.yaml @@ -0,0 +1,102 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboard-fission + namespace: grafana +data: + fission-overview.json: | + { + "title": "Fission — Operator Overview", + "uid": "fission-overview", + "tags": ["fission"], + "timezone": "browser", + "refresh": "30s", + "time": { "from": "now-24h", "to": "now" }, + "templating": { + "list": [ + { + "name": "namespace", + "type": "query", + "datasource": { "type": "postgres", "uid": "fission-pg" }, + "query": "SELECT DISTINCT namespace FROM invocations ORDER BY 1", + "includeAll": true, + "multi": true, + "label": "Namespace", + "current": { "text": "All", "value": "$__all" } + } + ] + }, + "panels": [ + { + "id": 1, + "title": "Вызовы в час", + "type": "timeseries", + "gridPos": { "x": 0, "y": 0, "w": 16, "h": 8 }, + "datasource": { "type": "postgres", "uid": "fission-pg" }, + "targets": [ + { + "rawSql": "SELECT date_trunc('hour', started_at) AS time, count(*) AS value, namespace FROM invocations WHERE started_at BETWEEN $__timeFrom() AND $__timeTo() AND ('$namespace' = '$__all' OR namespace = ANY(string_to_array('$namespace', ','))) GROUP BY 1, namespace ORDER BY 1", + "format": "time_series", + "refId": "A" + } + ] + }, + { + "id": 2, + "title": "Успех vs Ошибки", + "type": "piechart", + "gridPos": { "x": 16, "y": 0, "w": 8, "h": 8 }, + "datasource": { "type": "postgres", "uid": "fission-pg" }, + "targets": [ + { + "rawSql": "SELECT CASE WHEN status_code >= 200 AND status_code < 300 THEN 'success' ELSE 'error' END AS metric, count(*) AS value FROM invocations WHERE started_at BETWEEN $__timeFrom() AND $__timeTo() AND ('$namespace' = '$__all' OR namespace = ANY(string_to_array('$namespace', ','))) GROUP BY 1", + "format": "table", + "refId": "A" + } + ] + }, + { + "id": 3, + "title": "Топ функций по вызовам", + "type": "bargauge", + "gridPos": { "x": 0, "y": 8, "w": 12, "h": 8 }, + "datasource": { "type": "postgres", "uid": "fission-pg" }, + "targets": [ + { + "rawSql": "SELECT function_name AS metric, count(*) AS value FROM invocations WHERE started_at BETWEEN $__timeFrom() AND $__timeTo() AND ('$namespace' = '$__all' OR namespace = ANY(string_to_array('$namespace', ','))) GROUP BY 1 ORDER BY 2 DESC LIMIT 10", + "format": "table", + "refId": "A" + } + ] + }, + { + "id": 4, + "title": "Средняя латентность (ms)", + "type": "timeseries", + "gridPos": { "x": 12, "y": 8, "w": 12, "h": 8 }, + "datasource": { "type": "postgres", "uid": "fission-pg" }, + "targets": [ + { + "rawSql": "SELECT date_trunc('hour', started_at) AS time, round(avg(duration_ms)) AS avg_ms, round(percentile_cont(0.95) WITHIN GROUP (ORDER BY duration_ms)) AS p95_ms FROM invocations WHERE started_at BETWEEN $__timeFrom() AND $__timeTo() AND ('$namespace' = '$__all' OR namespace = ANY(string_to_array('$namespace', ','))) GROUP BY 1 ORDER BY 1", + "format": "time_series", + "refId": "A" + } + ] + }, + { + "id": 5, + "title": "Последние вызовы", + "type": "table", + "gridPos": { "x": 0, "y": 16, "w": 24, "h": 8 }, + "datasource": { "type": "postgres", "uid": "fission-pg" }, + "targets": [ + { + "rawSql": "SELECT started_at AS time, namespace, function_name, trigger_type, event_type, status_code, duration_ms FROM invocations WHERE ('$namespace' = '$__all' OR namespace = ANY(string_to_array('$namespace', ','))) ORDER BY started_at DESC LIMIT 50", + "format": "table", + "refId": "A" + } + ] + } + ], + "schemaVersion": 38 + } diff --git a/deploy/grafana/configmap-dashboard-providers.yaml b/deploy/grafana/configmap-dashboard-providers.yaml new file mode 100644 index 0000000..d0e8e82 --- /dev/null +++ b/deploy/grafana/configmap-dashboard-providers.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboard-providers + namespace: grafana +data: + providers.yaml: | + apiVersion: 1 + providers: + - name: fission + type: file + disableDeletion: false + editable: true + options: + path: /var/lib/grafana/dashboards diff --git a/deploy/grafana/configmap-datasources.yaml b/deploy/grafana/configmap-datasources.yaml new file mode 100644 index 0000000..262cc87 --- /dev/null +++ b/deploy/grafana/configmap-datasources.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-datasources + namespace: grafana +data: + postgres.yaml: | + apiVersion: 1 + datasources: + - name: PostgreSQL + type: postgres + uid: fission-pg + url: postgresqlk8s-master.dc5db45d-f8b4-4fd0-ad33-ec4dd017f2d5.svc.cluster.local:5432 + database: sqsdb + user: super + secureJsonData: + password: "BQUF5ruECa1ZFlq4wYt3gPJUEmtBMkA9QNK4MM5Sd8al4ArMDlmT16DIKHYBPyif" + jsonData: + sslmode: disable + postgresVersion: 1700 + timescaledb: false + editable: false diff --git a/deploy/grafana/deployment.yaml b/deploy/grafana/deployment.yaml new file mode 100644 index 0000000..0fb86c3 --- /dev/null +++ b/deploy/grafana/deployment.yaml @@ -0,0 +1,98 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: grafana + namespace: grafana + labels: + app: grafana +spec: + replicas: 1 + selector: + matchLabels: + app: grafana + template: + metadata: + labels: + app: grafana + spec: + securityContext: + fsGroup: 472 + runAsUser: 472 + containers: + - name: grafana + image: grafana/grafana:11.6.1 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + env: + - name: GF_SECURITY_ADMIN_USER + valueFrom: + secretKeyRef: + name: grafana-admin + key: admin-user + - name: GF_SECURITY_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: grafana-admin + key: admin-password + - name: GF_SERVER_ROOT_URL + value: "https://fission.kube5s.ru/grafana" + - name: GF_SERVER_DOMAIN + value: "fission.kube5s.ru" + - name: GF_SERVER_SERVE_FROM_SUB_PATH + value: "true" + - name: GF_USERS_ALLOW_SIGN_UP + value: "false" + - name: GF_AUTH_ANONYMOUS_ENABLED + value: "false" + - name: GF_ORGS_AUTO_ASSIGN_ORG + value: "true" + - name: GF_ORGS_AUTO_ASSIGN_ORG_ID + value: "1" + - name: GF_ORGS_AUTO_ASSIGN_ORG_ROLE + value: "Viewer" + - name: GF_FEATURE_TOGGLES_ENABLE + value: "publicDashboards" + - name: GF_PATHS_PROVISIONING + value: "/etc/grafana/provisioning" + volumeMounts: + - name: storage + mountPath: /var/lib/grafana + - name: datasources + mountPath: /etc/grafana/provisioning/datasources + - name: dashboard-providers + mountPath: /etc/grafana/provisioning/dashboards + - name: dashboards + mountPath: /var/lib/grafana/dashboards + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + cpu: 500m + memory: 256Mi + livenessProbe: + httpGet: + path: /grafana/api/health + port: 3000 + initialDelaySeconds: 30 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /grafana/api/health + port: 3000 + initialDelaySeconds: 10 + periodSeconds: 10 + volumes: + - name: storage + persistentVolumeClaim: + claimName: grafana-storage + - name: datasources + configMap: + name: grafana-datasources + - name: dashboard-providers + configMap: + name: grafana-dashboard-providers + - name: dashboards + configMap: + name: grafana-dashboard-fission diff --git a/deploy/grafana/ingress-subpath.yaml b/deploy/grafana/ingress-subpath.yaml new file mode 100644 index 0000000..c61a8c7 --- /dev/null +++ b/deploy/grafana/ingress-subpath.yaml @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: grafana-subpath + namespace: grafana + annotations: + # Без rewrite — Grafana сама обрабатывает /grafana/... через serve_from_sub_path + nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + nginx.ingress.kubernetes.io/proxy-send-timeout: "600" +spec: + ingressClassName: nginx + rules: + - host: fission.kube5s.ru + http: + paths: + - path: /grafana + pathType: Prefix + backend: + service: + name: grafana + port: + number: 3000 +# TLS не нужен — управляется Ingress в namespace fission (fission-tls) +# При миграции на grafana.kube5s.ru: +# 1. Поменять GF_SERVER_ROOT_URL → https://grafana.kube5s.ru +# 2. Убрать GF_SERVER_SERVE_FROM_SUB_PATH (или оставить false) +# 3. Создать Ingress в namespace grafana с host grafana.kube5s.ru + TLS +# 4. Удалить этот файл diff --git a/deploy/grafana/namespace.yaml b/deploy/grafana/namespace.yaml new file mode 100644 index 0000000..201d7d3 --- /dev/null +++ b/deploy/grafana/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: grafana diff --git a/deploy/grafana/pvc.yaml b/deploy/grafana/pvc.yaml new file mode 100644 index 0000000..175fc24 --- /dev/null +++ b/deploy/grafana/pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: grafana-storage + namespace: grafana +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi diff --git a/deploy/grafana/secret.yaml b/deploy/grafana/secret.yaml new file mode 100644 index 0000000..36086fe --- /dev/null +++ b/deploy/grafana/secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: grafana-admin + namespace: grafana +type: Opaque +stringData: + admin-user: admin + admin-password: "GrafanaAdmin2026!" diff --git a/deploy/grafana/service-ingress.yaml b/deploy/grafana/service-ingress.yaml new file mode 100644 index 0000000..80686f7 --- /dev/null +++ b/deploy/grafana/service-ingress.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: Service +metadata: + name: grafana + namespace: grafana +spec: + selector: + app: grafana + ports: + - port: 3000 + targetPort: 3000 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: grafana + namespace: grafana + annotations: + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" +spec: + ingressClassName: nginx + tls: + - hosts: + - grafana.kube5s.ru + secretName: grafana-tls + rules: + - host: grafana.kube5s.ru + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: grafana + port: + number: 3000