1# ============================================================================= 2# Factory monitoring stack — namespace `monitoring` (TASK-0135, phase-15). 3# 4# APPLY ROOT (standalone): 5# kubectl apply -k infrastructure/kubernetes/observability/ 6# 7# WHY NOT appended to the parent kustomization (infrastructure/kubernetes/)? 8# The parent sets `namespace: factory`, and kustomize's namespace transformer 9# overrides the namespace on EVERY object in the tree (verified with 10# kustomize v5.3.0: a child object pinned to `namespace: monitoring` still 11# renders as `factory`). This stack must live in `monitoring` — the apps' 12# configmap already points the OTLP exporter at 13# `otel-collector.monitoring.svc.cluster.local` (factory-config, 14# infrastructure/kubernetes/configmap.yaml). Appending this directory to the 15# parent would silently render the whole stack into `factory` and break the 16# FQDN. The decision (incl. the verified behavior) is recorded in the 17# TASK-0135 report per AGENTS rule 29. The parent kustomization therefore 18# gains NO resources for this stack. 19# 20# Objects (all in namespace `monitoring` — set here, so the manifests below 21# also pin it for readers): 22# namespace.yaml Namespace monitoring 23# prometheus.yaml Deployment + PVC (10Gi) + Service :9090 24# alertmanager.yaml Deployment + Service :9093 25# grafana.yaml Deployment + Service :3000 26# otel-collector.yaml Deployment + Service :4318 (OTLP/HTTP) 27# node-exporter.yaml DaemonSet :9100 28# 29# ConfigMaps are GENERATED from the source files in 30# infrastructure/observability/ (single source of truth — the generator 31# paths below are relative to THIS file): 32# prometheus-config ← observability/prometheus/{scrape,recording-rules,alerts}.yaml 33# alertmanager-config ← observability/alertmanager/alertmanager.yaml 34# grafana-datasources ← observability/grafana/provisioning/datasources/datasource.yaml 35# grafana-dashboards-provider ← observability/grafana/provisioning/dashboards/dashboards.yaml 36# grafana-dashboards ← observability/grafana/dashboards/*.json (the six) 37# 38# Secrets referenced but NOT created here (like factory-secrets — create via 39# SealedSecrets/SOPS/ExternalSecrets before applying): 40# - grafana-admin key: admin-password (Grafana admin login) 41# Images PINNED explicitly (third-party, not factory builds): 42# prom/prometheus:v2.51.0, grafana/grafana:10.4.0, 43# prom/alertmanager:v0.27.0, otel/opentelemetry-collector-contrib:0.98.0, 44# prom/node-exporter:v1.7.0 45# ============================================================================= 46apiVersion: kustomize.config.k8s.io/v1beta1 47kind: Kustomization 48 49namespace: monitoring 50 51labels: 52 - pairs: 53 app.kubernetes.io/part-of: ai-software-factory 54 includeSelectors: false 55 56# The ConfigMap SOURCES live in infrastructure/observability/ (the spec's 57# location — the dashboards/README/scripts live there too). kustomize's 58# configMapGenerator refuses to read files OUTSIDE this kustomization's 59# directory (security boundary), so the files are MIRROR-COPIED into this 60# directory (prometheus/, alertmanager/, grafana/) — and 61# scripts/sync-sources.mjs (CI + pre-commit) asserts the mirror is byte-identical 62# to the source (it exits 1 on drift, so a stale mirror can never ship). 63configMapGenerator: 64 - name: prometheus-config 65 files: 66 - prometheus.yml=prometheus/scrape.yaml 67 - rules/recording-rules.yaml=prometheus/recording-rules.yaml 68 - rules/alerts.yaml=prometheus/alerts.yaml 69 - name: alertmanager-config 70 files: 71 - alertmanager.yaml=alertmanager/alertmanager.yaml 72 - name: grafana-datasources 73 files: 74 - datasource.yaml=grafana/provisioning/datasources/datasource.yaml 75 - name: grafana-dashboards-provider 76 files: 77 - dashboards.yaml=grafana/provisioning/dashboards/dashboards.yaml 78 - name: grafana-dashboards 79 files: 80 - api-overview.json=grafana/dashboards/api-overview.json 81 - realtime.json=grafana/dashboards/realtime.json 82 - workers-queues.json=grafana/dashboards/workers-queues.json 83 - search.json=grafana/dashboards/search.json 84 - ai.json=grafana/dashboards/ai.json 85 - infra.json=grafana/dashboards/infra.json 86 87resources: 88 - namespace.yaml 89 - prometheus.yaml 90 - alertmanager.yaml 91 - grafana.yaml 92 - otel-collector.yaml 93 - node-exporter.yaml 94