# ============================================================================= # Factory monitoring stack — namespace `monitoring` (TASK-0135, phase-15). # # APPLY ROOT (standalone): # kubectl apply -k infrastructure/kubernetes/observability/ # # WHY NOT appended to the parent kustomization (infrastructure/kubernetes/)? # The parent sets `namespace: factory`, and kustomize's namespace transformer # overrides the namespace on EVERY object in the tree (verified with # kustomize v5.3.0: a child object pinned to `namespace: monitoring` still # renders as `factory`). This stack must live in `monitoring` — the apps' # configmap already points the OTLP exporter at # `otel-collector.monitoring.svc.cluster.local` (factory-config, # infrastructure/kubernetes/configmap.yaml). Appending this directory to the # parent would silently render the whole stack into `factory` and break the # FQDN. The decision (incl. the verified behavior) is recorded in the # TASK-0135 report per AGENTS rule 29. The parent kustomization therefore # gains NO resources for this stack. # # Objects (all in namespace `monitoring` — set here, so the manifests below # also pin it for readers): # namespace.yaml Namespace monitoring # prometheus.yaml Deployment + PVC (10Gi) + Service :9090 # alertmanager.yaml Deployment + Service :9093 # grafana.yaml Deployment + Service :3000 # otel-collector.yaml Deployment + Service :4318 (OTLP/HTTP) # node-exporter.yaml DaemonSet :9100 # # ConfigMaps are GENERATED from the source files in # infrastructure/observability/ (single source of truth — the generator # paths below are relative to THIS file): # prometheus-config ← observability/prometheus/{scrape,recording-rules,alerts}.yaml # alertmanager-config ← observability/alertmanager/alertmanager.yaml # grafana-datasources ← observability/grafana/provisioning/datasources/datasource.yaml # grafana-dashboards-provider ← observability/grafana/provisioning/dashboards/dashboards.yaml # grafana-dashboards ← observability/grafana/dashboards/*.json (the six) # # Secrets referenced but NOT created here (like factory-secrets — create via # SealedSecrets/SOPS/ExternalSecrets before applying): # - grafana-admin key: admin-password (Grafana admin login) # Images PINNED explicitly (third-party, not factory builds): # prom/prometheus:v2.51.0, grafana/grafana:10.4.0, # prom/alertmanager:v0.27.0, otel/opentelemetry-collector-contrib:0.98.0, # prom/node-exporter:v1.7.0 # ============================================================================= apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: monitoring labels: - pairs: app.kubernetes.io/part-of: ai-software-factory includeSelectors: false # The ConfigMap SOURCES live in infrastructure/observability/ (the spec's # location — the dashboards/README/scripts live there too). kustomize's # configMapGenerator refuses to read files OUTSIDE this kustomization's # directory (security boundary), so the files are MIRROR-COPIED into this # directory (prometheus/, alertmanager/, grafana/) — and # scripts/sync-sources.mjs (CI + pre-commit) asserts the mirror is byte-identical # to the source (it exits 1 on drift, so a stale mirror can never ship). configMapGenerator: - name: prometheus-config files: - prometheus.yml=prometheus/scrape.yaml - rules/recording-rules.yaml=prometheus/recording-rules.yaml - rules/alerts.yaml=prometheus/alerts.yaml - name: alertmanager-config files: - alertmanager.yaml=alertmanager/alertmanager.yaml - name: grafana-datasources files: - datasource.yaml=grafana/provisioning/datasources/datasource.yaml - name: grafana-dashboards-provider files: - dashboards.yaml=grafana/provisioning/dashboards/dashboards.yaml - name: grafana-dashboards files: - api-overview.json=grafana/dashboards/api-overview.json - realtime.json=grafana/dashboards/realtime.json - workers-queues.json=grafana/dashboards/workers-queues.json - search.json=grafana/dashboards/search.json - ai.json=grafana/dashboards/ai.json - infra.json=grafana/dashboards/infra.json resources: - namespace.yaml - prometheus.yaml - alertmanager.yaml - grafana.yaml - otel-collector.yaml - node-exporter.yaml