infra/home/cluster/tmobile-exporter/deployment.yaml
Graham McIntire 8466e4590f
tmobile-exporter: switch to stock json_exporter + nginx sidecar
Replaces the vendored Go exporter with two pre-built upstream images:
- quay.io/prometheuscommunity/json-exporter:v0.7.0 maps the gateway JSON
  into prometheus metrics via JSONPath. The G4AR keys signal blocks as
  "5g" / "4g" (digit-prefixed), which the k8s client-go JSONPath dialect
  only reaches via bracket-with-single-quote notation.
- nginxinc/nginx-unprivileged:1.27-alpine-slim sidecar rewrites
  GET /metrics → GET /probe?module=tmhi&target=http://192.168.12.1/...
  so the existing kubernetes-services scrape job picks it up over the
  apiserver proxy with no Prometheus-side config changes.

Avoiding caddy here: its binary carries cap_net_bind_service file caps,
which the kernel refuses to exec under no_new_privs as a non-root user.

Dashboard "Gateway up" panel now reads up{service="tmobile-exporter"}
(Prometheus's built-in scrape-success gauge) since json_exporter's
/probe endpoint does not emit probe_success.
2026-05-10 17:57:13 -05:00

95 lines
2.8 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: tmobile-exporter
namespace: monitoring
labels:
app.kubernetes.io/name: tmobile-exporter
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: tmobile-exporter
template:
metadata:
labels:
app.kubernetes.io/name: tmobile-exporter
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
# json_exporter scrapes the gateway JSON on demand and exposes /probe.
# The nginx sidecar below rewrites the public /metrics URL onto it.
- name: json-exporter
image: quay.io/prometheuscommunity/json-exporter:v0.7.0
args:
- --config.file=/etc/json_exporter/json-exporter.yml
ports:
- name: probe
containerPort: 7979
protocol: TCP
resources:
requests:
cpu: 10m
memory: 24Mi
limits:
memory: 96Mi
securityContext:
runAsUser: 65534
runAsGroup: 65534
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: config
mountPath: /etc/json_exporter
readOnly: true
# nginx rewrites GET /metrics → GET /probe?module=tmhi&target=<gateway>.
# nginxinc/nginx-unprivileged runs as UID 101 (non-root) without file caps,
# so it survives no_new_privs + readOnlyRootFilesystem cleanly.
- name: nginx
image: nginxinc/nginx-unprivileged:1.27-alpine-slim
ports:
- name: metrics
containerPort: 9099
protocol: TCP
resources:
requests:
cpu: 10m
memory: 16Mi
limits:
memory: 64Mi
securityContext:
runAsUser: 101
runAsGroup: 101
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
readOnly: true
- name: nginx-tmp
mountPath: /tmp
readinessProbe:
httpGet:
path: /healthz
port: metrics
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: metrics
periodSeconds: 30
volumes:
- name: config
configMap:
name: tmobile-exporter-config
- name: nginx-tmp
emptyDir: {}