Repository navigation
[amazon-cloudwatch-observability] feat: add ServiceMonitor/PodMonitor v2 OTLP scraping path - #329
wenegiemepraise wants to merge 1 commit into
Conversation
| - "--auto-instrumentation-nodejs-image={{ template "auto-instrumentation-nodejs.image" . }}" | ||
| - "--target-allocator-image={{ template "target-allocator.image" (merge .Values.agent.prometheus.targetAllocator.image (dict "region" $.Values.region)) }}" | ||
| - "--feature-gates=operator.autoinstrumentation.multiinstrumentation,operator.autoinstrumentation.multiinstrumentation.skipcontainervalidation" | ||
| - "--feature-gates=operator.autoinstrumentation.multi-instrumentation,operator.autoinstrumentation.multi-instrumentation.skip-container-validation" |
There was a problem hiding this comment.
These --feature-gates values are hyphenated (multi-instrumentation), but the pinned operator only registers the unhyphenated forms, so it rejects the gate and CrashLoopBackOffs and nothing reconciles. This also looks out of scope here. Can we restore the unhyphenated line?
| ## Allocator's prometheusCR discovery. Defaults to true: when | ||
| ## otelContainerInsights is enabled, ServiceMonitor scraping is on unless | ||
| ## explicitly disabled here. Only takes effect when otelContainerInsights.enabled is true. | ||
| serviceMonitor: |
There was a problem hiding this comment.
serviceMonitor.enabled and podMonitor.enabled default to true, so the moment someone turns on otelContainerInsights they silently get prometheusCR discovery, whose CRD and RBAC this PR doesn't set up yet. Could we default them to false, or gate the path on the CRDs being present?
There was a problem hiding this comment.
The default-on behavior is intentional, the product goal is that enabling otelContainerInsights gives you working SM/PM scraping out of the box, and the surrounding work is built to make that safe: the operator's CRD-resilience change(#394) makes missing CRDs non-fatal (no crash/loop), and CRD bundling (#331) puts the CRDs in-cluster. So I'd like to keep SM/PM default-on rather than invert to opt-in.
| - set(attributes["cloudwatch.solution"], "k8s-otel-container-insights") | ||
| - set(attributes["cloudwatch.pipeline"], "efa") | ||
|
|
||
| transform/cw_k8s_ci_v0_set_scope_prometheuscr: |
There was a problem hiding this comment.
The scraping receiver and pipeline are guarded on serviceMonitor.enabled/podMonitor.enabled, but the transform/cw_k8s_ci_v0_set_scope_prometheuscr processor isn't, so turning both monitors off leaves it orphaned and the collector warns. Can we guard it the same way via otelCIScrapeEnabled?
| {{- if .Values.agent.enabled }} | ||
| {{- range $i, $customAgent := .Values.agents }} | ||
| {{- if and (and (hasKey ($customAgent.prometheus) "targetAllocator") (hasKey ($customAgent.prometheus.targetAllocator) "enabled")) $customAgent.prometheus.targetAllocator.enabled }} | ||
| {{- $otelCIScrape := eq (include "cloudwatch-agent.otelCIScrapeEnabled" (dict "agentName" $customAgent.name "context" $)) "true" }} |
There was a problem hiding this comment.
This renders the ClusterRole inside range .Values.agents with a static name, so two matching agents produce duplicate ClusterRoles and Kubernetes just keeps the last write. Could we namespace the name per agent (same for the ClusterRoleBinding), or document that only one agent is supported?
| {{- define "cloudwatch-agent.otelCIScrapeEnabled" -}} | ||
| {{- $ctx := .context -}} | ||
| {{- $agentName := .agentName -}} | ||
| {{- if and $ctx.Values.otelContainerInsights.enabled (eq $agentName $ctx.Values.otelContainerInsights.targetAgent) (or $ctx.Values.otelContainerInsights.serviceMonitor.enabled $ctx.Values.otelContainerInsights.podMonitor.enabled) -}} |
There was a problem hiding this comment.
This helper reads otelContainerInsights.serviceMonitor.enabled directly. Fine today since the PR ships those keys as defaults, but it goes nil if a user replaces the whole map, so a dig with a default fallback might be safer.
There was a problem hiding this comment.
Since the subkeys ship as chart defaults and Helm deep-merges them, they're present under any partial override, so this is safe as-is I'll leave the direct access
| prometheus/cw_k8s_ci_v0_prometheuscr: | ||
| target_allocator: | ||
| endpoint: https://{{ .Values.otelContainerInsights.targetAgent }}-target-allocator-service:80 | ||
| interval: {{ .Values.otelContainerInsights.metricResolution }} |
There was a problem hiding this comment.
interval here is the collector to Target Allocator refresh cadence, but it reuses otelContainerInsights.metricResolution, which is really the scrape cadence (prometheusCR.scrapeInterval). Worth a comment or a separate field so the two can diverge later?
There was a problem hiding this comment.
Agreed they're distinct knobs. I'd rather not add a second field preemptively, but the shared value being non-obvious is fair
|
Makes sense. The pinned cloudwatch-agent-target-allocator:1.0.0 predates the discovery path, and enabling scraping against it CrashLoops the TA rather than degrading, so a discovery-capable TA image must be pinned before this path is enabled (landing in the same release that exposes it, or the path stays off until then). |
…node-allocation Re-sync aws-observability#330 onto the updated scraping-path branch: inherit the feature-gate ID fix, co-gated CRD RBAC render-once ClusterRole/Binding, the $$$1 comment correction, and the prometheuscr scope-processor guard, alongside aws-observability#330's per-node work.
…bundling Re-sync onto the updated scraping-path branch to inherit the feature-gate ID fix, the co-gated customresourcedefinitions RBAC rule (render-once ClusterRole/ Binding), the $$$1 comment correction, and the prometheuscr scope-processor guard. Resolves the CRD-RBAC matrix assertion (now 11/0) and the feature-gate blocker on this branch.
…bundling Re-sync aws-observability#331 onto aws-observability#330 so the stack is linear (aws-observability#329 -> aws-observability#330 -> aws-observability#331): inherit the per-node allocationStrategy scoping/gating, the SM/PM node-stamping removal, and the context-aware allocationStrategy default, on top of aws-observability#331's CRD bundling.
…cture Re-sync aws-observability#332 onto the updated stack (aws-observability#329->aws-observability#330->aws-observability#331). Resolutions favor the settled older-PR fixes applied onto aws-observability#332's prometheusScrape.* restructure: - prometheusCRDsEnabled: keep aws-observability#331's explicit auto branch + invalid-value fail, gated on aws-observability#332's otelContainerInsights.enabled && prometheusScrape.enabled. - allocationStrategy: use aws-observability#332's precomputed $allocationStrategy (per-node on the otelCI path via prometheusScrape.allocationStrategy, consistent-hashing for direct-TA) -- supersedes aws-observability#330's ternary while preserving its intent. - Fix a stale old-key guard (otelContainerInsights.serviceMonitor.enabled) left by auto-merge in the prometheuscr scope-processor to prometheusScrape.enabled. - Keep aws-observability#330's SM/PM node-stamping removal; port aws-observability#331's GitOps opt-out caveat into the new prometheusScrape.crds doc. Verified: lint clean, CRD matrix 21/0, flag matrix 8/8.
movence
left a comment
There was a problem hiding this comment.
Every other Container Insights metrics pipeline runs clear_schema_url, set_cloud_resource_id, and awsattributelimit before batch, but this prometheuscr one skips all three. That means ServiceMonitor/PodMonitor metrics ship uncapped and without the schema-url and cloud-resource-id normalization the rest of the pipelines get. Could we add those same three processors here?
(_otel-container-insights-config.tpl, prometheuscr pipeline ~L863)
|
Fixed the issue around: For the issue with the looping over the raw |
| */}} | ||
| {{- $needsTA := false }} | ||
| {{- $needsCR := false }} | ||
| {{- range $i, $customAgent := .Values.agents }} |
There was a problem hiding this comment.
This loops over the raw .Values.agents entries, but the CR template merges the shared agent defaults first (mergeOverwrite (deepCopy .Values.agent) at cloudwatch-agent-custom-resource.yaml:67). So if someone turns on the target allocator or prometheusCR through the shared agent block, the CR gets created but this RBAC does not, and the TA's CRD informer ends up denied at runtime. Can we merge .Values.agent here the same way?
…node-allocation Picks up aws-observability#329's latest commits (TA RBAC via the singular agent block, and the normalization/cap processors on the prometheuscr pipeline) plus origin/main. Conflicts resolved by keeping this branch's per-node allocationStrategy ternary and adopting main's quoted 'include target-allocator.image ... | quote'.
…bundling Brings in aws-observability#330, aws-observability#329's latest commits and origin/main. The values.yaml conflict was two non-overlapping additions at the end of the file: main's nested otelContainerInsights.solutions block and this branch's top-level prometheusCRDs block. Both kept, with solutions left inside otelContainerInsights and prometheusCRDs at top level.
…cture Completes the chain: brings in aws-observability#331, aws-observability#330 and aws-observability#329's latest commits. Conflicts resolved in favour of this branch's restructure, which is its purpose: the $allocationStrategy variable form is kept, and the top-level prometheusCRDs block is intentionally NOT re-added since this PR moves it to otelContainerInsights.prometheusScrape.crds.
…ion-scraper-routing Brings in the full chain (aws-observability#332, aws-observability#331, aws-observability#330, aws-observability#329) and origin/main. The cluster-scraper OTEL config conflicted structurally: main added the Karpenter/KEDA solution pipelines (aws-observability#325, aws-observability#345) in the same receivers / processors / pipelines sections where this branch adds its prometheuscr blocks, and git interleaved the {{- if }}/{{- end }} boundaries. Rather than untangle the markers, the file was reconstructed from main's version with this branch's three self-contained, individually-gated prometheuscr blocks re-inserted at their anchors (after each kubeStateMetrics block). Verified: all five cluster-scraper pipelines render (prometheuscr, karpenter, keda, apiserver, kube_state_metrics), scraperRole is still set only on the cluster-scraper, and the TA ClusterRole/Binding still render exactly once.
|
Checklist posted for the PR author to move into the PR description under a PR Checklist
|
b18ffd2 to
651229b
Compare
Adds the prometheuscr receiver and metrics pipeline driven by the Target Allocator's PrometheusCR discovery, the otelCIScrape gating helper, the serviceMonitor/podMonitor enablement values, and the read-only RBAC the discovery path needs (including the CRD-watch grant, and rendering the Target Allocator ClusterRole/Binding once rather than per agent). Verified: helm lint clean; helm template renders the prometheuscr receiver/pipeline when otelContainerInsights.enabled=true and omits it by default.
651229b to
7e17bbd
Compare
Summary
Add the ServiceMonitor/PodMonitor v2 OTLP scraping path to the chart: a
prometheuscrreceiver + pipeline driven by the Target Allocator's PrometheusCR discovery, plus the
enablement flags and gating helper. This is the foundation that lets the CloudWatch Agent
scrape community
monitoring.coreos.comServiceMonitor/PodMonitor CRs into CloudWatch viathe OTEL Container Insights path.
What this enables
When
otelContainerInsights.enabledis set, the chart wires the Target Allocator +prometheuscrreceiver so SM/PM CRs are discovered and scraped (default consistent-hashingallocation). ServiceMonitor and PodMonitor discovery can each be toggled via
otelContainerInsights.serviceMonitor.enabled/podMonitor.enabled(default on).Scope
prometheuscrreceiver + metrics pipeline in the OTEL Container Insights configotelCIScrapegating helperotelContainerInsights.serviceMonitor/podMonitor.enabledvalues (only take effect whenotelContainerInsights.enabled)This is the base of a small stack; per-node allocation + node-enrichment transforms land
in a follow-up that builds on this path.
Testing
helm template:otelContainerInsights.enabled=true→ theprometheuscrreceiver/pipeline renders.helm lintclean (pre-existingfluent-bit-windowsregion warning is unrelated).