blumeops/argocd/manifests/grafana-config/README.md
Erich Blume 7e6742ad24 K8s Migration Phase 2: Grafana to Kubernetes (#30)
## Summary
- Migrate Grafana from Homebrew/Ansible to Kubernetes deployment
- Switch CloudNativePG to use forge-mirrored Helm chart (HTTPS, no auth needed)
- Add Grafana Helm chart deployment via ArgoCD with multi-source pattern
- Add Grafana config (Tailscale Ingress, 9 dashboard ConfigMaps)
- Update Loki to bind 0.0.0.0 for k8s pod access via `host.containers.internal`

## Key Changes
- `argocd/apps/grafana.yaml` - Grafana Helm chart Application
- `argocd/apps/grafana-config.yaml` - Ingress + dashboard ConfigMaps
- `argocd/apps/cloudnative-pg.yaml` - Now uses forge mirror instead of external Helm repo
- `ansible/roles/loki/templates/loki-config.yaml.j2` - Bind 0.0.0.0

## Deployment and Testing
- [x] Deploy Loki config change: `mise run provision-indri -- --tags loki`
- [x] Create namespace: `ki create namespace monitoring`
- [x] Create secret: `op inject -i argocd/manifests/grafana-config/secret-admin.yaml.tpl | ki apply -f -`
- [x] Sync ArgoCD apps (grafana, grafana-config)
- [x] Verify Grafana works at https://grafana.tail8d86e.ts.net
- [x] Remove svc:grafana from ansible tailscale_serve
- [x] Stop brew grafana: `ssh indri 'brew services stop grafana'`
- [x] Delete ansible grafana role

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://forge.tail8d86e.ts.net/eblume/blumeops/pulls/30
2026-01-19 14:40:25 -08:00

1.1 KiB

Grafana Configuration

This directory contains Kubernetes manifests for Grafana configuration:

  • Tailscale Ingress for external access
  • Dashboard ConfigMaps for provisioning

Secrets Management

Current approach: Secrets are manually injected using 1Password CLI.

Before deploying Grafana, create the admin password secret:

kubectl create namespace monitoring
op inject -i secret-admin.yaml.tpl | kubectl apply -f -

The secret template (secret-admin.yaml.tpl) references 1Password:

  • Vault: vg6xf6vvfmoh5hqjjhlhbeoaie (blumeops)
  • Item: oxkcr3xtxnewy7noep2izvyr6y
  • Field: password

Future improvement: Migrate to External Secrets Operator or similar for automated secret synchronization from 1Password to Kubernetes.

Dashboards

Dashboard JSON files are stored as ConfigMaps in the dashboards/ directory. The Grafana sidecar automatically discovers ConfigMaps with label grafana_dashboard: "1" and provisions them.

To add a new dashboard:

  1. Export the dashboard JSON from Grafana UI
  2. Create a ConfigMap with the JSON content
  3. Add the grafana_dashboard: "1" label
  4. Add the ConfigMap to kustomization.yaml