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
This commit is contained in:
Erich Blume 2026-01-19 14:40:25 -08:00
commit 7e6742ad24
44 changed files with 6707 additions and 6171 deletions

View file

@ -9,7 +9,7 @@ spec:
project: default
source:
repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
targetRevision: feature/k8s-phase1-kickoff
targetRevision: main
path: argocd/apps
destination:
server: https://kubernetes.default.svc

View file

@ -9,7 +9,7 @@ spec:
project: default
source:
repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
targetRevision: feature/k8s-phase1-kickoff
targetRevision: main
path: argocd/manifests/argocd
destination:
server: https://kubernetes.default.svc

View file

@ -13,7 +13,7 @@ spec:
project: default
source:
repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
targetRevision: feature/k8s-phase1-kickoff
targetRevision: main
path: argocd/manifests/databases
destination:
server: https://kubernetes.default.svc

View file

@ -1,5 +1,7 @@
# CloudNativePG Operator - PostgreSQL for Kubernetes
# Deploys the operator only; PostgreSQL clusters are created separately
#
# Chart mirrored from https://github.com/cloudnative-pg/charts to forge
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
@ -8,17 +10,17 @@ metadata:
spec:
project: default
sources:
# Helm chart from upstream
- repoURL: https://cloudnative-pg.github.io/charts
chart: cloudnative-pg
targetRevision: "0.23.0"
# Helm chart from forge mirror (SSH via egress)
- repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/cloudnative-pg-charts.git
targetRevision: cloudnative-pg-v0.23.0
path: charts/cloudnative-pg
helm:
releaseName: cloudnative-pg
valueFiles:
- $values/argocd/manifests/cloudnative-pg/values.yaml
# Values from our git repo
- repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
targetRevision: feature/k8s-phase1-kickoff
targetRevision: main
ref: values
destination:
server: https://kubernetes.default.svc

View file

@ -0,0 +1,25 @@
# Grafana configuration - Tailscale Ingress and Dashboard ConfigMaps
#
# Depends on: grafana app (for the Service to exist)
#
# Before syncing, create the admin password secret:
# kubectl create namespace monitoring
# op inject -i argocd/manifests/grafana-config/secret-admin.yaml.tpl | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: grafana-config
namespace: argocd
spec:
project: default
source:
repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
targetRevision: main
path: argocd/manifests/grafana-config
destination:
server: https://kubernetes.default.svc
namespace: monitoring
syncPolicy:
syncOptions:
- CreateNamespace=true
# Manual sync only - no automated sync on git push

34
argocd/apps/grafana.yaml Normal file
View file

@ -0,0 +1,34 @@
# Grafana - Dashboards & Observability
#
# Chart mirrored from https://github.com/grafana/helm-charts to forge
#
# Before syncing, create the admin password secret:
# kubectl create namespace monitoring
# op inject -i argocd/manifests/grafana-config/secret-admin.yaml.tpl | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: grafana
namespace: argocd
spec:
project: default
sources:
# Helm chart from forge mirror (SSH via egress)
- repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/grafana-helm-charts.git
targetRevision: grafana-8.8.2
path: charts/grafana
helm:
releaseName: grafana
valueFiles:
- $values/argocd/manifests/grafana/values.yaml
# Values from our git repo
- repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
targetRevision: main
ref: values
destination:
server: https://kubernetes.default.svc
namespace: monitoring
syncPolicy:
syncOptions:
- CreateNamespace=true
# Manual sync only - no automated sync on git push

View file

@ -15,7 +15,7 @@ spec:
- /spec/externalName
source:
repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
targetRevision: feature/k8s-phase1-kickoff
targetRevision: main
path: argocd/manifests/tailscale-operator
destination:
server: https://kubernetes.default.svc