Skip to content

Commit 915a6bc

Browse files
feat(metadata): Adds site deploy metadata to cluster-metadata ConfigMap
1 parent 1151cd2 commit 915a6bc

7 files changed

Lines changed: 255 additions & 0 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{{- if eq (include "understack.isEnabled" (list $.Values.site "cluster_metadata")) "true" }}
2+
---
3+
apiVersion: argoproj.io/v1alpha1
4+
kind: Application
5+
metadata:
6+
name: {{ printf "%s-%s" $.Release.Name "cluster-metadata" }}
7+
finalizers:
8+
- resources-finalizer.argocd.argoproj.io
9+
{{- include "understack.appLabelsBlock" $ | nindent 2 }}
10+
spec:
11+
destination:
12+
namespace: openstack
13+
server: {{ $.Values.cluster_server }}
14+
project: understack
15+
sources:
16+
- path: components/cluster-metadata
17+
repoURL: {{ include "understack.understack_url" $ }}
18+
targetRevision: {{ include "understack.understack_ref" $ }}
19+
syncPolicy:
20+
automated:
21+
prune: true
22+
selfHeal: true
23+
syncOptions:
24+
- ServerSideApply=true
25+
- RespectIgnoreDifferences=true
26+
- ApplyOutOfSyncOnly=true
27+
{{- end }}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{{- if or (eq (include "understack.isEnabled" (list $.Values.global "prometheus_pushgateway")) "true") (eq (include "understack.isEnabled" (list $.Values.site "prometheus_pushgateway")) "true") }}
2+
---
3+
apiVersion: argoproj.io/v1alpha1
4+
kind: Application
5+
metadata:
6+
name: {{ printf "%s-%s" $.Release.Name "prometheus-pushgateway" }}
7+
annotations:
8+
argocd.argoproj.io/compare-options: ServerSideDiff=true,IncludeMutationWebhook=true
9+
{{- include "understack.appLabelsBlock" $ | nindent 2 }}
10+
spec:
11+
destination:
12+
namespace: monitoring
13+
server: {{ $.Values.cluster_server }}
14+
project: understack-operators
15+
sources:
16+
- chart: prometheus-pushgateway
17+
helm:
18+
ignoreMissingValueFiles: true
19+
releaseName: prometheus-pushgateway
20+
valueFiles:
21+
- $understack/operators/prometheus-pushgateway/values.yaml
22+
repoURL: https://prometheus-community.github.io/helm-charts
23+
targetRevision: 3.2.0
24+
- ref: understack
25+
repoURL: {{ include "understack.understack_url" $ }}
26+
targetRevision: {{ include "understack.understack_ref" $ }}
27+
syncPolicy:
28+
automated:
29+
prune: true
30+
selfHeal: true
31+
syncOptions:
32+
- CreateNamespace=true
33+
- ServerSideApply=true
34+
- RespectIgnoreDifferences=true
35+
- ApplyOutOfSyncOnly=true
36+
{{- end }}

charts/argocd-understack/values.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,18 @@ site:
508508
# @default -- false
509509
enabled: false
510510

511+
# -- Cluster metadata sync to Prometheus via Pushgateway
512+
cluster_metadata:
513+
# -- Enable/disable syncing cluster-metadata ConfigMap to Prometheus
514+
# @default -- true
515+
enabled: true
516+
517+
# -- Prometheus Pushgateway for batch job metrics
518+
prometheus_pushgateway:
519+
# -- Enable/disable deploying Prometheus Pushgateway
520+
# @default -- true
521+
enabled: true
522+
511523
# -- OpenEBS
512524
openebs:
513525
# -- Enable/disable deploying OpenEBS
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: cluster-metadata-sync-script
6+
namespace: openstack
7+
labels:
8+
app.kubernetes.io/name: cluster-metadata
9+
app.kubernetes.io/component: prometheus-sync
10+
data:
11+
sync-cluster-metadata.py: |
12+
#!/usr/bin/env python3
13+
"""Sync cluster-metadata ConfigMap data to Prometheus Pushgateway.
14+
15+
Reads the cluster-metadata ConfigMap mounted as files and pushes
16+
its key/value pairs as labels on an info-style gauge metric to the
17+
Prometheus Pushgateway. This makes cluster identity information
18+
(partition, site, etc.) available for Prometheus queries and joins.
19+
"""
20+
21+
import os
22+
import sys
23+
import urllib.request
24+
25+
METADATA_DIR = "/etc/cluster-metadata"
26+
PUSHGATEWAY_URL = os.environ.get(
27+
"PUSHGATEWAY_URL",
28+
"http://kube-prometheus-stack-prometheus-pushgateway.monitoring.svc.cluster.local:9091",
29+
)
30+
METRIC_JOB_NAME = os.environ.get("METRIC_JOB_NAME", "cluster_metadata")
31+
32+
33+
def read_metadata():
34+
"""Read all key/value pairs from the mounted ConfigMap directory."""
35+
data = {}
36+
for filename in os.listdir(METADATA_DIR):
37+
filepath = os.path.join(METADATA_DIR, filename)
38+
if os.path.isfile(filepath) and not filename.startswith(".."):
39+
with open(filepath) as f:
40+
data[filename] = f.read().strip()
41+
return data
42+
43+
44+
def format_pushgateway_payload(cm_data):
45+
"""Format ConfigMap data as Prometheus exposition format.
46+
47+
Creates an info-style gauge metric 'cluster_metadata_info' with value 1
48+
and all ConfigMap keys as labels.
49+
"""
50+
labels = {}
51+
for key, value in cm_data.items():
52+
label_name = key.lower().replace("-", "_").replace(".", "_")
53+
label_value = (
54+
value.replace("\\", "\\\\")
55+
.replace("\n", "\\n")
56+
.replace('"', '\\"')
57+
)
58+
labels[label_name] = label_value
59+
60+
if not labels:
61+
print("WARNING: ConfigMap has no data keys, nothing to push")
62+
return None
63+
64+
label_str = ",".join(f'{k}="{v}"' for k, v in sorted(labels.items()))
65+
lines = [
66+
"# HELP cluster_metadata_info Cluster metadata from ConfigMap as labels.",
67+
"# TYPE cluster_metadata_info gauge",
68+
f"cluster_metadata_info{{{label_str}}} 1",
69+
"",
70+
]
71+
return "\n".join(lines)
72+
73+
74+
def push_to_gateway(payload):
75+
"""Push metrics payload to the Prometheus Pushgateway."""
76+
url = f"{PUSHGATEWAY_URL}/metrics/job/{METRIC_JOB_NAME}"
77+
data = payload.encode("utf-8")
78+
req = urllib.request.Request(
79+
url,
80+
data=data,
81+
method="PUT",
82+
headers={"Content-Type": "text/plain; version=0.0.4"},
83+
)
84+
with urllib.request.urlopen(req) as resp:
85+
if resp.status not in (200, 202):
86+
print(f"ERROR: Pushgateway returned status {resp.status}")
87+
sys.exit(1)
88+
89+
90+
def main():
91+
print("Reading cluster-metadata from mounted ConfigMap...")
92+
cm_data = read_metadata()
93+
print(f"Found {len(cm_data)} keys: {list(cm_data.keys())}")
94+
95+
payload = format_pushgateway_payload(cm_data)
96+
if payload is None:
97+
sys.exit(0)
98+
99+
print(f"Pushing cluster_metadata_info metric to {PUSHGATEWAY_URL}...")
100+
push_to_gateway(payload)
101+
print("Successfully pushed cluster metadata to Prometheus Pushgateway")
102+
103+
104+
if __name__ == "__main__":
105+
main()
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
apiVersion: batch/v1
3+
kind: Job
4+
metadata:
5+
name: sync-cluster-metadata-to-prometheus
6+
namespace: openstack
7+
labels:
8+
app.kubernetes.io/name: cluster-metadata
9+
app.kubernetes.io/component: prometheus-sync
10+
annotations:
11+
argocd.argoproj.io/hook: PostSync
12+
argocd.argoproj.io/sync-wave: "5"
13+
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
14+
spec:
15+
backoffLimit: 3
16+
ttlSecondsAfterFinished: 3600
17+
template:
18+
spec:
19+
securityContext:
20+
runAsNonRoot: true
21+
runAsUser: 65534
22+
fsGroup: 65534
23+
seccompProfile:
24+
type: RuntimeDefault
25+
restartPolicy: OnFailure
26+
containers:
27+
- name: sync-metadata
28+
image: python:3-slim
29+
imagePullPolicy: IfNotPresent
30+
command:
31+
- python
32+
- /scripts/sync-cluster-metadata.py
33+
resources:
34+
requests:
35+
cpu: "50m"
36+
memory: "64Mi"
37+
limits:
38+
cpu: "200m"
39+
memory: "128Mi"
40+
securityContext:
41+
allowPrivilegeEscalation: false
42+
capabilities:
43+
drop:
44+
- ALL
45+
readOnlyRootFilesystem: false
46+
env:
47+
- name: PUSHGATEWAY_URL
48+
value: http://prometheus-pushgateway.monitoring.svc.cluster.local:9091
49+
- name: METRIC_JOB_NAME
50+
value: cluster_metadata
51+
volumeMounts:
52+
- name: scripts
53+
mountPath: /scripts
54+
readOnly: true
55+
- name: cluster-metadata
56+
mountPath: /etc/cluster-metadata
57+
readOnly: true
58+
volumes:
59+
- name: scripts
60+
configMap:
61+
name: cluster-metadata-sync-script
62+
- name: cluster-metadata
63+
configMap:
64+
name: cluster-metadata
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
apiVersion: kustomize.config.k8s.io/v1beta1
3+
kind: Kustomization
4+
5+
resources:
6+
- configmap-cluster-metadata-sync-script.yaml
7+
- job-sync-cluster-metadata.yaml
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
serviceMonitor:
2+
enabled: true
3+
additionalLabels:
4+
release: monitoring

0 commit comments

Comments
 (0)