Compare commits
3
Commits
4843eb95f7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3f9989943 | ||
|
|
128712c4c9 | ||
|
|
ed040bc606 |
@@ -120,6 +120,40 @@ kubectl exec -n jenkins deploy/jenkins -c jenkins -- cat /run/secrets/additional
|
|||||||
is set inside its own database on first boot, so it cannot be swapped via a
|
is set inside its own database on first boot, so it cannot be swapped via a
|
||||||
`kubectl patch` the way ArgoCD's can.
|
`kubectl patch` the way ArgoCD's can.
|
||||||
|
|
||||||
|
**Grafana → actual-http-api datasource** (Infinity plugin, queries
|
||||||
|
`homelab-docker-compose-prod/actual-http-api`'s ActualQL `run-query` endpoint
|
||||||
|
directly — see `homelab-services` README for why the Prometheus exporter
|
||||||
|
alone can't answer arbitrary group-by/amount questions). The chart install
|
||||||
|
just gets the plugin onto the pod; the datasource itself is added by hand in
|
||||||
|
the Grafana UI (not provisioned/GitOps) so the API key never needs its own
|
||||||
|
K8s Secret:
|
||||||
|
|
||||||
|
1. Grafana → **Connections → Data sources → Add data source** → search
|
||||||
|
**Infinity** → select it.
|
||||||
|
2. URL: `http://192.168.1.41:8003`.
|
||||||
|
3. **Auth** → enable **Custom HTTP Headers** → add header
|
||||||
|
`x-api-key` = `<actual-http-api API_KEY, same value as its compose
|
||||||
|
file>`. Grafana stores this encrypted in its own DB (uses
|
||||||
|
`kube-prometheus-stack-grafana`'s secret key), not in git.
|
||||||
|
4. **Save & test**.
|
||||||
|
|
||||||
|
Datasource then shows up in Grafana as whatever name you gave it — build a panel
|
||||||
|
with method `POST`, URL path `/budgets/<sync-id>/run-query`, and an
|
||||||
|
`ActualQLquery` JSON body, e.g. sum of $ per category:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ActualQLquery": {
|
||||||
|
"table": "transactions",
|
||||||
|
"groupBy": ["category"],
|
||||||
|
"select": ["category", { "total": { "$sum": "amount" } }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep the panel's refresh interval long (≥1m) — each call is a real login
|
||||||
|
against `actual_server`, same rate-limit risk hit by the exporter earlier.
|
||||||
|
|
||||||
**Headlamp login token** (ServiceAccount created by `headlamp/rbac.yaml`):
|
**Headlamp login token** (ServiceAccount created by `headlamp/rbac.yaml`):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ spec:
|
|||||||
destination:
|
destination:
|
||||||
server: https://kubernetes.default.svc
|
server: https://kubernetes.default.svc
|
||||||
namespace: external-secrets
|
namespace: external-secrets
|
||||||
|
# Leaf app — manual sync only; root `platform` app-of-apps stays automated.
|
||||||
syncPolicy:
|
syncPolicy:
|
||||||
automated:
|
|
||||||
prune: true
|
|
||||||
selfHeal: true
|
|
||||||
syncOptions:
|
syncOptions:
|
||||||
- CreateNamespace=true
|
- CreateNamespace=true
|
||||||
- ServerSideApply=true
|
- ServerSideApply=true
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ spec:
|
|||||||
destination:
|
destination:
|
||||||
server: https://kubernetes.default.svc
|
server: https://kubernetes.default.svc
|
||||||
namespace: harbor
|
namespace: harbor
|
||||||
|
# Leaf app — manual sync only; root `platform` app-of-apps stays automated.
|
||||||
syncPolicy:
|
syncPolicy:
|
||||||
automated:
|
|
||||||
prune: true
|
|
||||||
selfHeal: true
|
|
||||||
syncOptions:
|
syncOptions:
|
||||||
- CreateNamespace=true
|
- CreateNamespace=true
|
||||||
- SkipDryRunOnMissingResource=true
|
- SkipDryRunOnMissingResource=true
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ spec:
|
|||||||
destination:
|
destination:
|
||||||
server: https://kubernetes.default.svc
|
server: https://kubernetes.default.svc
|
||||||
namespace: headlamp
|
namespace: headlamp
|
||||||
|
# Leaf app — manual sync only; root `platform` app-of-apps stays automated.
|
||||||
syncPolicy:
|
syncPolicy:
|
||||||
automated:
|
|
||||||
prune: true
|
|
||||||
selfHeal: true
|
|
||||||
syncOptions:
|
syncOptions:
|
||||||
- CreateNamespace=true
|
- CreateNamespace=true
|
||||||
- SkipDryRunOnMissingResource=true
|
- SkipDryRunOnMissingResource=true
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ spec:
|
|||||||
destination:
|
destination:
|
||||||
server: https://kubernetes.default.svc
|
server: https://kubernetes.default.svc
|
||||||
namespace: jenkins
|
namespace: jenkins
|
||||||
|
# Leaf app — manual sync only; root `platform` app-of-apps stays automated.
|
||||||
syncPolicy:
|
syncPolicy:
|
||||||
automated:
|
|
||||||
prune: true
|
|
||||||
selfHeal: true
|
|
||||||
syncOptions:
|
syncOptions:
|
||||||
- CreateNamespace=true
|
- CreateNamespace=true
|
||||||
- SkipDryRunOnMissingResource=true
|
- SkipDryRunOnMissingResource=true
|
||||||
|
|||||||
@@ -36,10 +36,8 @@ spec:
|
|||||||
jsonPointers:
|
jsonPointers:
|
||||||
- /spec/rules/0/backendRefs/0/group
|
- /spec/rules/0/backendRefs/0/group
|
||||||
- /spec/rules/0/backendRefs/0/weight
|
- /spec/rules/0/backendRefs/0/weight
|
||||||
|
# Leaf app — manual sync only; root `platform` app-of-apps stays automated.
|
||||||
syncPolicy:
|
syncPolicy:
|
||||||
automated:
|
|
||||||
prune: true
|
|
||||||
selfHeal: true
|
|
||||||
syncOptions:
|
syncOptions:
|
||||||
- CreateNamespace=true
|
- CreateNamespace=true
|
||||||
- ServerSideApply=true
|
- ServerSideApply=true
|
||||||
|
|||||||
@@ -3,6 +3,24 @@ grafana:
|
|||||||
enabled: true
|
enabled: true
|
||||||
storageClassName: nfs-delete
|
storageClassName: nfs-delete
|
||||||
size: 5Gi
|
size: 5Gi
|
||||||
|
# Installs the Infinity datasource plugin so Grafana can query a plain
|
||||||
|
# REST API (actual-http-api) directly — see README for wiring it up.
|
||||||
|
# The datasource itself (URL + x-api-key) is added by hand in the Grafana
|
||||||
|
# UI, not provisioned here — avoids a second hand-created Secret just for
|
||||||
|
# this one credential.
|
||||||
|
plugins:
|
||||||
|
- yesoreyeram-infinity-datasource
|
||||||
|
# Not a WAN-latency problem — default ndots:5 makes every external FQDN
|
||||||
|
# lookup (grafana.com here) burn through 4 failed cluster-search-domain
|
||||||
|
# queries before trying the bare name, costing several seconds. That
|
||||||
|
# alone exceeded grafana-cli's request timeout on plugin install and
|
||||||
|
# crash-looped the pod (confirmed: 4-7s hang with ndots:5 vs 8ms with
|
||||||
|
# ndots:1 for the exact same lookup, from the same node). Same root cause
|
||||||
|
# already hit and fixed this way in homelab-services' ignis chart.
|
||||||
|
dnsConfig:
|
||||||
|
options:
|
||||||
|
- name: ndots
|
||||||
|
value: "1"
|
||||||
|
|
||||||
prometheus:
|
prometheus:
|
||||||
prometheusSpec:
|
prometheusSpec:
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ spec:
|
|||||||
destination:
|
destination:
|
||||||
server: https://kubernetes.default.svc
|
server: https://kubernetes.default.svc
|
||||||
namespace: sonarqube
|
namespace: sonarqube
|
||||||
|
# Leaf app — manual sync only; root `platform` app-of-apps stays automated.
|
||||||
syncPolicy:
|
syncPolicy:
|
||||||
automated:
|
|
||||||
prune: true
|
|
||||||
selfHeal: true
|
|
||||||
syncOptions:
|
syncOptions:
|
||||||
- CreateNamespace=true
|
- CreateNamespace=true
|
||||||
- SkipDryRunOnMissingResource=true
|
- SkipDryRunOnMissingResource=true
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ spec:
|
|||||||
destination:
|
destination:
|
||||||
server: https://kubernetes.default.svc
|
server: https://kubernetes.default.svc
|
||||||
namespace: vault
|
namespace: vault
|
||||||
|
# Leaf app — manual sync only; root `platform` app-of-apps stays automated.
|
||||||
syncPolicy:
|
syncPolicy:
|
||||||
automated:
|
|
||||||
prune: true
|
|
||||||
selfHeal: true
|
|
||||||
syncOptions:
|
syncOptions:
|
||||||
- CreateNamespace=true
|
- CreateNamespace=true
|
||||||
- SkipDryRunOnMissingResource=true
|
- SkipDryRunOnMissingResource=true
|
||||||
|
|||||||
Reference in New Issue
Block a user