Skip to content

feat(helm): Support externally-managed HPAs via controller.autoscaling.horizontal.externalHPA#6311

Merged
kalleep merged 3 commits into
mainfrom
feature/chart-external-hpa-support
Jun 1, 2026
Merged

feat(helm): Support externally-managed HPAs via controller.autoscaling.horizontal.externalHPA#6311
kalleep merged 3 commits into
mainfrom
feature/chart-external-hpa-support

Conversation

@jmichalek132

@jmichalek132 jmichalek132 commented May 26, 2026

Copy link
Copy Markdown
Contributor

Brief description of Pull Request

Adds controller.autoscaling.horizontal.externalHPA so KEDA (and other external scalers) can own spec.replicas without fighting the chart. Default false — no behavior change for existing users.

(The configmap-key fix originally bundled here was moved to #6312 (now merged) per @kalleep's request.)

Pull Request Details

When controller.autoscaling.horizontal.externalHPA: true:

  • Chart omits spec.replicas from the StatefulSet / Deployment.
  • Chart does NOT render its own HorizontalPodAutoscaler.

Mutually exclusive with horizontal.enabled. Setting both fails the template with a clear multi-line message.

Behavior matrix:

autoscaling.enabled horizontal.enabled horizontal.externalHPA Result
false (default) false (default) false (default) Chart writes replicas. No HPA. (today's default)
true (any) false Chart omits replicas. Renders deprecated HPA. (today's behavior)
(any) true false Chart omits replicas. Renders new HPA. (today's behavior)
(any) (any) true Chart omits replicas. No HPA rendered. (NEW)

Upgrade note: flipping externalHPA from falsetrue on an existing release causes a one-time single-cycle dip to 1 replica on the next helm upgrade. Helm removes the field via {"spec":{"replicas":null}}, which Kubernetes resets to default 1 (see helm/helm#12650). The external HPA corrects it within its next polling interval. Documented in the values.yaml comment.

How I tested this

Reproduced the bug (pre-fix): kind + KEDA 2.13 + Prometheus + alloy-operator + alloy chart 1.8.1. Alloy CR with controller.replicas: 5, autoscaling off, KEDA ScaledObject forcing target=10. Operator reconciles every ~15s and asserts replicas:5; KEDA briefly wins between reconciles:

19:02:52 replicas:5 ready:5   keda-hpa REPLICAS=5
19:02:57 replicas:8 ready:5   keda-hpa REPLICAS=5   <- KEDA bumps
19:03:02 replicas:5 ready:5   keda-hpa REPLICAS=5   <- operator reverts

5-min capture: replicas:5 = 59 occurrences, replicas:(8|9|10) = 1.

Patched chart (post-fix): monotonic ramp 1→5→8, stable for the rest of the capture window:

19:15:30 replicas:1 ready:1
19:15:40 replicas:5 ready:1   <- KEDA scales to minReplicaCount
19:15:55 replicas:8 ready:5   <- KEDA scales to target
... (stable replicas:8 ready:8 for 5+ minutes)
19:20:31 replicas:8 ready:8

kubectl get hpa -o name → only keda-hpa-alloy-repro. kubectl get sts alloy-repro -o yaml | yq '.spec | has("replicas")'false.

Caveat: I ran the post-fix repro with the patched chart installed standalone, not through a patched alloy-operator image — building a custom operator image just for verification felt like overkill. The fix removes the field the operator was re-asserting on every reconcile, so the operator-level scenario should be resolved by construction. Let me know if you want me to rebuild the operator image and re-capture; happy to.

Template smoke tests (helm template):

  • Default values: replicas: 1, no HPA. Existing behavior unchanged.
  • externalHPA: true: yq '.spec | has("replicas")'false on StatefulSet AND Deployment, no HPA.
  • Both flags set: helm template fails with the multi-line "mutually exclusive" message. Newlines render correctly (printf wrapping per helm/helm#9981).

ct lint: clean on all three new ci/*-values.yaml files.

ct install: the two new positive CI files install cleanly. Verified via direct helm install --wait because ct install on main is blocked by a pre-existing configmap-key-values.yaml issue (fixed in #6312 (merged)).

make generate-helm-tests: new goldens under operations/helm/tests/create-statefulset-external-hpa/ and operations/helm/tests/create-deployment-external-hpa/. Both have no spec.replicas and no HPA file.

helm-docs: README.md updated with the new externalHPA row and the upgrade-dip note.

Issue(s) fixed by this Pull Request

Fixes #6310

Notes to the Reviewer

The custom shell step in helm-test.yml (Assert external HPA validation failure) asserts that the validation file causes helm template to fail. ct doesn't have a native "this values file MUST fail" mode. The cleaner alternative is helm-unittest (which k8s-monitoring-helm uses for the same kind of thing), but that's a new tool for this chart and felt out of scope. Happy to switch if you'd prefer.

The negative CI values file intentionally drops the -values suffix so ct / make generate-helm-tests discovery skips it.

Chart.yaml not bumped — followed the existing pattern of adding to Unreleased and letting maintainers bump at release time. Tell me if I should bump it.

Local Helm was 4.2.0; CI uses 3.10.3. The committed goldens may have minor whitespace deltas from what CI renders. I'll iterate if regenerate-tests flags anything.

PR Checklist

  • Documentation added (values.yaml doc comment + README.md auto-generated + CHANGELOG.md entry under Unreleased)
  • Tests updated (3 new ci/*-values.yaml files + CI shell-step assertion + regenerated operations/helm/tests/ goldens)
  • Config converters updated (N/A — chart-only change)

@jmichalek132 jmichalek132 requested a review from a team as a code owner May 26, 2026 09:28
@cla-assistant

cla-assistant Bot commented May 26, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@jmichalek132 jmichalek132 force-pushed the feature/chart-external-hpa-support branch 2 times, most recently from 6ed9fca to 8efc6a6 Compare May 26, 2026 09:43
@kalleep

kalleep commented May 26, 2026

Copy link
Copy Markdown
Contributor

Side fix (commit 905fe73): I noticed templates/configmap.yaml hardcoded the ConfigMap data key as config.alloy, ignoring alloy.configMap.key. The pod template DOES honor that value (via the alloy.config-map.key helper in templates/_config.tpl), so setting configMap.key: collector.yaml produced a ConfigMap with key config.alloy and a pod expecting collector.yaml — alloy crash-looped with reading config path '/etc/alloy/collector.yaml': no such file or directory. Wired the existing helper into the ConfigMap template; default behavior unchanged. Self-contained commit, easy to split if you'd rather it land separately.

Please create another pr for this and add a changelog entry for this specific fix

@jmichalek132

Copy link
Copy Markdown
Contributor Author

Side fix (commit 905fe73): I noticed templates/configmap.yaml hardcoded the ConfigMap data key as config.alloy, ignoring alloy.configMap.key. The pod template DOES honor that value (via the alloy.config-map.key helper in templates/_config.tpl), so setting configMap.key: collector.yaml produced a ConfigMap with key config.alloy and a pod expecting collector.yaml — alloy crash-looped with reading config path '/etc/alloy/collector.yaml': no such file or directory. Wired the existing helper into the ConfigMap template; default behavior unchanged. Self-contained commit, easy to split if you'd rather it land separately.

Please create another pr for this and add a changelog entry for this specific fix

Done — split out to #6312 with its own CHANGELOG entry. Rebased this PR to drop the configmap commit.

kalleep added a commit that referenced this pull request May 28, 2026
### Brief description of Pull Request

Split off from #6311 per [@kalleep's
request](#6311 (comment)).
Fixes `templates/configmap.yaml` ignoring `alloy.configMap.key`.

### Pull Request Details

The chart hardcoded the ConfigMap data key as `config.alloy`, but the
pod template derives the mount subPath / `--config.file` from
`alloy.configMap.key` (via the `alloy.config-map.key` helper). Setting
`configMap.key: collector.yaml` produced a ConfigMap with key
`config.alloy` and a pod expecting `collector.yaml`:

```
reading config path '/etc/alloy/collector.yaml': no such file or directory
```

Wires the existing helper into the ConfigMap template. Default (no key
set) renders `config.alloy:` unchanged. Also unblocks `ct install` on
the pre-existing `configmap-key-values.yaml` test case.

### How I tested this

`helm install configmap-key-verify . -f ci/configmap-key-values.yaml
--wait` reaches `STATUS=deployed`; Alloy pod starts cleanly. With
default values, ConfigMap key is still `config.alloy`. Golden under
`operations/helm/tests/configmap-key/` regenerated (one-line change).

### Issue(s) fixed by this Pull Request

N/A — surfaced during work on #6311.

### Notes to the Reviewer

CHANGELOG entry uses `(#TBD)` placeholder; I'll fix up with the PR
number once it's assigned.

### PR Checklist

- [x] Documentation added (`CHANGELOG.md` entry under `Unreleased` >
`Bug fixes`)
- [x] Tests updated (golden regenerated)
- [ ] Config converters updated (N/A)

---------

Co-authored-by: Kalle <23356117+kalleep@users.noreply.github.com>
@kalleep

kalleep commented May 28, 2026

Copy link
Copy Markdown
Contributor

I think this looks ok, @petewall any input on this one?

…g.horizontal.externalHPA

When set, the chart omits spec.replicas from the workload AND does not render its
own HorizontalPodAutoscaler, enabling clean coexistence with external scalers such
as KEDA's ScaledObject-generated HPAs. Strict validation rejects setting both
horizontal.enabled and horizontal.externalHPA simultaneously.

Default value is false; existing rendered manifests are byte-identical for users
who do not set the new field.
Adds three values files under operations/helm/charts/alloy/ci/ covering
StatefulSet, Deployment, and the mutual-exclusion validation failure case.
The validation-failure file intentionally lacks the -values suffix so ct
discovery skips it; an explicit CI shell step in helm-test.yml asserts that
helm template fails with the expected "mutually exclusive" message —
regression guard the chart-testing tool cannot provide natively.

Regenerates README.md via helm-docs and the golden manifests under
operations/helm/tests/ for the two positive cases. Adds a CHANGELOG entry
under the Unreleased section.
@jmichalek132 jmichalek132 force-pushed the feature/chart-external-hpa-support branch from e30a70d to 3984429 Compare May 28, 2026 16:56

@petewall petewall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love that this is added!

@kalleep kalleep merged commit a1e61c7 into main Jun 1, 2026
48 checks passed
@kalleep kalleep deleted the feature/chart-external-hpa-support branch June 1, 2026 06:45
@kalleep kalleep mentioned this pull request Jun 4, 2026
4 tasks
kgeckhart pushed a commit that referenced this pull request Jun 12, 2026
🤖 I have created a release *beep* *boop*
---


## [1.17.0](v1.16.0...v1.17.0)
(2026-06-11)


### Features 🌟

* Add gql subcommand
([#6242](#6242))
([ec09c43](ec09c43))
* **database_observability.mysql:** Add
database_observability_wait_event_seconds_total counter
([#6106](#6106))
([602b0b5](602b0b5))
* **database_observability.mysql:** Refactor bulk table metadata
collection ([#6222](#6222))
([e8d441b](e8d441b))
* **database_observability.mysql:** Refactor schema_details logging
strategy ([#6239](#6239))
([fd51530](fd51530))
* **database_observability.postgres:** Add `exclude_current_user`
top-level setting
([#6187](#6187))
([f019b5e](f019b5e))
* **database_observability.postgres:** Improve monitoring user
privileges check ([#6177](#6177))
([96b50d1](96b50d1))
* **database_observability.postgres:** Make health_check respect
user/database exclusions settings
([#6144](#6144))
([b4ee0a7](b4ee0a7))
* **database_observability.postgres:** Throttle schema details
create_statement logs
([#6260](#6260))
([fcb3d3e](fcb3d3e))
* **database_observability:** Add wait_event_v2 op with pre-classified
wait_event_type ([#6105](#6105))
([f7a1ebd](f7a1ebd))
* **database_observability:** Always extract traceparent in MySQL
query_samples collector
([#6081](#6081))
([bf2b436](bf2b436))
* **database_observability:** Always extract traceparent in Postgres
query_samples collector
([#6411](#6411))
([74d595a](74d595a))
* **database_observability:** Set query_sample, wait_event timestamps at
query start for MySQL
([#6291](#6291))
([a47de00](a47de00))
* **database_observability:** Set timestamp query_sample at query start
for Postgres ([#6393](#6393))
([62d8ecc](62d8ecc))
* **database_observability:** Update wait_event_v2 to a 6-bucket
taxonomy and surface Mysql nested events
([#6143](#6143))
([3df9542](3df9542))
* **faro.receiver:** Support gzip-compressed request bodies
([#6195](#6195))
([4fa44d2](4fa44d2))
* GraphQL server ([#5580](#5580))
([5a2562f](5a2562f))
* **helm:** Support externally-managed HPAs via
controller.autoscaling.horizontal.externalHPA
([#6311](#6311))
([a1e61c7](a1e61c7))
* Integration tests for aws firehose and cloudflare logpull
([#6089](#6089))
([f55f780](f55f780))
* Integration tests for loki.source.azure_event_hubs
([#6113](#6113))
([8e40165](8e40165))
* Integration tests for loki.source.gcplog
([#6161](#6161))
([feceb8d](feceb8d))
* **loki.process:** Add regex field to logfmt and json stages
([#4941](#4941))
([cfbabda](cfbabda))
* **loki.rules.kubernetes:** Add external_labels support
([#6320](#6320))
([9166a61](9166a61))
* **loki.source.heroku:** Drop github.com/heroku/x package
([#6064](#6064))
([3382721](3382721))
* Migrate from Docker to Moby
([#6167](#6167))
([1e2bbf9](1e2bbf9))
* **mimir.rules.kubernetes, loki.rules.kubernetes:** Add configurable
`mimir_namespace_separator` and `loki_namespace_separator` arguments to
allow using a URL-safe separator
([#5961](#5961))
([7dba4f1](7dba4f1))
* **otelcol.exporter.prometheus:** Config option to prevent stripping
`service.*` attributes
([#6434](#6434))
([c229b3c](c229b3c))
* **otelcol.exporter.prometheus:** Convert classic histograms to NHCB
([#6281](#6281))
([46f4fb6](46f4fb6))
* **otelcol:** Add Nginx receiver
([#6141](#6141))
([fa8d520](fa8d520))
* **prometheus.enrich:** Support multi-label matching
([#5822](#5822))
([04a1aba](04a1aba))
* **prometheus.relabel:** Add opt-in TTL cache mode
([#6169](#6169))
([40632c3](40632c3))
* **telemetry:** Add graph connection metrics
([#6243](#6243))
([4f3bbbe](4f3bbbe))
* **telemetry:** Add pyroscope_forwarded_entries_total metric
([#6244](#6244))
([65ad64c](65ad64c))
* Update to Beyla 3.9.7
([#6175](#6175))
([4015bd9](4015bd9))
* Update to Beyla 3.9.8
([#6189](#6189))
([6fffa30](6fffa30))


### Bug Fixes 🐛

* Address Critical CVE's From Scanner
([#6232](#6232))
([e713e7a](e713e7a))
* **alloycli:** Use filepath.Base for CLI Use name to fix shell
completions ([#6217](#6217))
([17cfd01](17cfd01))
* **cluster:** Fix nodes failing to join the cluster when TLS is enabled
([#6437](#6437))
([efbad6d](efbad6d))
* **database_observability.mysql:** Exclude system schemas from MySQL
health check ([#6116](#6116))
([fcae6f4](fcae6f4))
* **database_observability.postgres:** Count error logs when
log_timezone is non-UTC
([#6274](#6274))
([2eaa769](2eaa769))
* **database_observability.postgres:** Do not retain query text in
`explain_plans` collector
([#6461](#6461))
([4c06a64](4c06a64))
* **database_observability:** Exclude more explain plan output keywords
([#6145](#6145))
([3ff6c14](3ff6c14))
* **deb:** Restart Alloy only on upgrade in postinst script
([#6094](#6094))
([8c15cb3](8c15cb3))
* **deps:** Pin dependencies
([#6376](#6376))
([79323b5](79323b5))
* **deps:** Update dependencies for catchpoint, databricks, and
snowflake exporters
([#6188](#6188))
([c1b740c](c1b740c))
* **deps:** Update module go.opentelemetry.io/obi to v0.8.0 [SECURITY]
([#6091](#6091))
([05c14af](05c14af))
* **documentation:** Fix documentation for loki.rules.kubernetes
([#6088](#6088))
([61f2b8a](61f2b8a))
* Enforce Singleton For Running Alloy Extension Instances
([#5763](#5763))
([83da6f0](83da6f0))
* **faro:** Abort on context cancelation
([#6104](#6104))
([bf733a6](bf733a6))
* Fix bug that caused 'logging' block's 'write_to' to be used after
config update even if not set
([#6264](#6264))
([cba7243](cba7243))
* **graphql:** Update cli flags for consistency
([#6441](#6441))
([7749d4f](7749d4f))
* **helm:** Honor alloy.configMap.key in templates/configmap.yaml
([#6312](#6312))
([415af2c](415af2c))
* **integration-tests:** Forward GO_TAGS to k8s integration tests
([#6220](#6220))
([b00f79c](b00f79c))
* **logging:** Fix startup deadlock when components log before logging
config is evaluated
([#6112](#6112))
([6cdce9e](6cdce9e))
* **loki.process:** Make limit stage shutdown cancelable
([#6215](#6215))
([20717b5](20717b5))
* **loki.process:** New `action_on_duplicate_timestamp` config attribute
to fudge identical log timestamps
([#5615](#5615))
([7d56f50](7d56f50))
* **loki.process:** No longer mutate rules in stage.truncate causing
every config update to reload pipeline when this stage is used
([#6271](#6271))
([b52a4d8](b52a4d8))
* **loki.process:** Potential deadlock on update with stage and receiver
changes ([#6270](#6270))
([cb22e82](cb22e82))
* **loki.process:** Wrap NewPipeline error correctly in match stage
([#6216](#6216))
([f3af2dd](f3af2dd))
* **loki.rules.kubernetes:** Add timeout to ruler sync calls
([26170d4](26170d4))
* **loki.source.syslog:** Fix goroutine leak in UDP listener
([#6231](#6231))
([268b260](268b260))
* **loki:** Clone structured metadata so we can perform fan-out
correctly ([#6138](#6138))
([473244d](473244d))
* **oracledb_exporter:** Support CGO_ENABLED=0 cross-compilation
([#6168](#6168))
([63ab53d](63ab53d))
* **otelcol.exporter.awss3:** Add missing `unique_key_func_name`
attribute ([#6184](#6184))
([9ad2b44](9ad2b44))
* **prometheus.exporter.oracledb:** Fix issue with custom metrics not
appearing when more than one instance of prometheus.exporter.oracledb is
used ([#6228](#6228))
([57de4f4](57de4f4))
* **prometheus.operator.*:** Pass ScrapeNativeHistograms to
ScrapeOptions ([#6356](#6356))
([a44fced](a44fced))
* **remotewrite:** Use blocking send with timeout in test server
([#6208](#6208))
([a279088](a279088))
* **security:** Update module github.com/jackc/pgx/v5 to v5.9.2
[SECURITY] ([#6326](#6326))
([bf3ff2e](bf3ff2e))
* **security:** Update x/crypto and x/net for CVEs
([#6336](#6336))
([4c7b93b](4c7b93b))
* **ui:** Reduce UI dependencies
([#6349](#6349))
([85e12ba](85e12ba))
* **ui:** Update dependency minor versions
([#6288](#6288))
([52a28d2](52a28d2))
* Update go to v1.26.4
([#6418](#6418))
([51fb7d2](51fb7d2))
* **validation:** Improve type checking of ast.LiteralExpr
([#5916](#5916))
([d0a1177](d0a1177))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: grafana-alloybot[bot] <167359181+grafana-alloybot[bot]@users.noreply.github.com>
dadezzz pushed a commit to dadezzz/infra_docker-compose that referenced this pull request Jun 15, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [docker.io/grafana/alloy](https://github.com/grafana/alloy) | minor | `v1.16.3` → `v1.17.0` |

---

### Release Notes

<details>
<summary>grafana/alloy (docker.io/grafana/alloy)</summary>

### [`v1.17.0`](https://github.com/grafana/alloy/releases/tag/v1.17.0)

[Compare Source](grafana/alloy@v1.16.3...v1.17.0)

##### Features 🌟

- Add gql subcommand ([#&#8203;6242](grafana/alloy#6242)) ([ec09c43](grafana/alloy@ec09c43)) ([@&#8203;jharvey10](https://github.com/jharvey10))
- **database\_observability.mysql:** Add database\_observability\_wait\_event\_seconds\_total counter ([#&#8203;6106](grafana/alloy#6106)) ([602b0b5](grafana/alloy@602b0b5)) ([@&#8203;gaantunes](https://github.com/gaantunes))
- **database\_observability.mysql:** Refactor bulk table metadata collection ([#&#8203;6222](grafana/alloy#6222)) ([e8d441b](grafana/alloy@e8d441b)) ([@&#8203;cristiangreco](https://github.com/cristiangreco))
- **database\_observability.mysql:** Refactor schema\_details logging strategy ([#&#8203;6239](grafana/alloy#6239)) ([fd51530](grafana/alloy@fd51530)) ([@&#8203;cristiangreco](https://github.com/cristiangreco))
- **database\_observability.postgres:** Add `exclude_current_user` top-level setting ([#&#8203;6187](grafana/alloy#6187)) ([f019b5e](grafana/alloy@f019b5e)) ([@&#8203;cristiangreco](https://github.com/cristiangreco), [@&#8203;matthewnolf](https://github.com/matthewnolf))
- **database\_observability.postgres:** Improve monitoring user privileges check ([#&#8203;6177](grafana/alloy#6177)) ([96b50d1](grafana/alloy@96b50d1)) ([@&#8203;cristiangreco](https://github.com/cristiangreco))
- **database\_observability.postgres:** Make health\_check respect user/database exclusions settings ([#&#8203;6144](grafana/alloy#6144)) ([b4ee0a7](grafana/alloy@b4ee0a7)) ([@&#8203;cristiangreco](https://github.com/cristiangreco))
- **database\_observability.postgres:** Throttle schema details create\_statement logs ([#&#8203;6260](grafana/alloy#6260)) ([fcb3d3e](grafana/alloy@fcb3d3e)) ([@&#8203;cristiangreco](https://github.com/cristiangreco))
- **database\_observability:** Add wait\_event\_v2 op with pre-classified wait\_event\_type ([#&#8203;6105](grafana/alloy#6105)) ([f7a1ebd](grafana/alloy@f7a1ebd)) ([@&#8203;gaantunes](https://github.com/gaantunes))
- **database\_observability:** Always extract traceparent in MySQL query\_samples collector ([#&#8203;6081](grafana/alloy#6081)) ([bf2b436](grafana/alloy@bf2b436)) ([@&#8203;fridgepoet](https://github.com/fridgepoet))
- **database\_observability:** Always extract traceparent in Postgres query\_samples collector ([#&#8203;6411](grafana/alloy#6411)) ([74d595a](grafana/alloy@74d595a)) ([@&#8203;fridgepoet](https://github.com/fridgepoet))
- **database\_observability:** Set query\_sample, wait\_event timestamps at query start for MySQL ([#&#8203;6291](grafana/alloy#6291)) ([a47de00](grafana/alloy@a47de00)) ([@&#8203;fridgepoet](https://github.com/fridgepoet))
- **database\_observability:** Set timestamp query\_sample at query start for Postgres ([#&#8203;6393](grafana/alloy#6393)) ([62d8ecc](grafana/alloy@62d8ecc)) ([@&#8203;fridgepoet](https://github.com/fridgepoet))
- **database\_observability:** Update wait\_event\_v2 to a 6-bucket taxonomy and surface Mysql nested events ([#&#8203;6143](grafana/alloy#6143)) ([3df9542](grafana/alloy@3df9542)) ([@&#8203;gaantunes](https://github.com/gaantunes), [@&#8203;cristiangreco](https://github.com/cristiangreco))
- **faro.receiver:** Support gzip-compressed request bodies ([#&#8203;6195](grafana/alloy#6195)) ([4fa44d2](grafana/alloy@4fa44d2)) ([@&#8203;d0ugal](https://github.com/d0ugal))
- GraphQL server ([#&#8203;5580](grafana/alloy#5580)) ([5a2562f](grafana/alloy@5a2562f)) ([@&#8203;jharvey10](https://github.com/jharvey10))
- **helm:** Support externally-managed HPAs via controller.autoscaling.horizontal.externalHPA ([#&#8203;6311](grafana/alloy#6311)) ([a1e61c7](grafana/alloy@a1e61c7)) ([@&#8203;jmichalek132](https://github.com/jmichalek132))
- Integration tests for aws firehose and cloudflare logpull ([#&#8203;6089](grafana/alloy#6089)) ([f55f780](grafana/alloy@f55f780)) ([@&#8203;x1unix](https://github.com/x1unix))
- Integration tests for loki.source.azure\_event\_hubs ([#&#8203;6113](grafana/alloy#6113)) ([8e40165](grafana/alloy@8e40165)) ([@&#8203;x1unix](https://github.com/x1unix))
- Integration tests for loki.source.gcplog ([#&#8203;6161](grafana/alloy#6161)) ([feceb8d](grafana/alloy@feceb8d)) ([@&#8203;x1unix](https://github.com/x1unix))
- **loki.process:** Add regex field to logfmt and json stages ([#&#8203;4941](grafana/alloy#4941)) ([cfbabda](grafana/alloy@cfbabda)) ([@&#8203;timonegk](https://github.com/timonegk))
- **loki.rules.kubernetes:** Add external\_labels support ([#&#8203;6320](grafana/alloy#6320)) ([9166a61](grafana/alloy@9166a61)) ([@&#8203;gianvetter](https://github.com/gianvetter))
- **loki.source.heroku:** Drop github.com/heroku/x package ([#&#8203;6064](grafana/alloy#6064)) ([3382721](grafana/alloy@3382721)) ([@&#8203;x1unix](https://github.com/x1unix))
- Migrate from Docker to Moby ([#&#8203;6167](grafana/alloy#6167)) ([1e2bbf9](grafana/alloy@1e2bbf9)) ([@&#8203;x1unix](https://github.com/x1unix))
- **mimir.rules.kubernetes, loki.rules.kubernetes:** Add configurable `mimir_namespace_separator` and `loki_namespace_separator` arguments to allow using a URL-safe separator ([#&#8203;5961](grafana/alloy#5961)) ([7dba4f1](grafana/alloy@7dba4f1)) ([@&#8203;QuentinBisson](https://github.com/QuentinBisson), [@&#8203;clayton-cornell](https://github.com/clayton-cornell))
- **otelcol.exporter.prometheus:** Config option to prevent stripping `service.*` attributes ([#&#8203;6434](grafana/alloy#6434)) ([c229b3c](grafana/alloy@c229b3c)) ([@&#8203;jcreixell](https://github.com/jcreixell))
- **otelcol.exporter.prometheus:** Convert classic histograms to NHCB ([#&#8203;6281](grafana/alloy#6281)) ([46f4fb6](grafana/alloy@46f4fb6)) ([@&#8203;madaraszg-tulip](https://github.com/madaraszg-tulip))
- **otelcol:** Add Nginx receiver ([#&#8203;6141](grafana/alloy#6141)) ([fa8d520](grafana/alloy@fa8d520)) ([@&#8203;henworth](https://github.com/henworth), [@&#8203;clayton-cornell](https://github.com/clayton-cornell), [@&#8203;blewis12](https://github.com/blewis12))
- **prometheus.enrich:** Support multi-label matching ([#&#8203;5822](grafana/alloy#5822)) ([04a1aba](grafana/alloy@04a1aba)) ([@&#8203;dtrejod](https://github.com/dtrejod))
- **prometheus.relabel:** Add opt-in TTL cache mode ([#&#8203;6169](grafana/alloy#6169)) ([40632c3](grafana/alloy@40632c3)) ([@&#8203;kgeckhart](https://github.com/kgeckhart))
- **telemetry:** Add graph connection metrics ([#&#8203;6243](grafana/alloy#6243)) ([4f3bbbe](grafana/alloy@4f3bbbe)) ([@&#8203;theSuess](https://github.com/theSuess))
- **telemetry:** Add pyroscope\_forwarded\_entries\_total metric ([#&#8203;6244](grafana/alloy#6244)) ([65ad64c](grafana/alloy@65ad64c)) ([@&#8203;theSuess](https://github.com/theSuess))
- Update to Beyla 3.9.7 ([#&#8203;6175](grafana/alloy#6175)) ([4015bd9](grafana/alloy@4015bd9)) ([@&#8203;rafaelroquetto](https://github.com/rafaelroquetto))
- Update to Beyla 3.9.8 ([#&#8203;6189](grafana/alloy#6189)) ([6fffa30](grafana/alloy@6fffa30)) ([@&#8203;skl](https://github.com/skl))

##### Bug Fixes 🐛

- Address Critical CVE's From Scanner ([#&#8203;6232](grafana/alloy#6232)) ([e713e7a](grafana/alloy@e713e7a)) ([@&#8203;blewis12](https://github.com/blewis12))
- **alloycli:** Use filepath.Base for CLI Use name to fix shell completions ([#&#8203;6217](grafana/alloy#6217)) ([17cfd01](grafana/alloy@17cfd01)) ([@&#8203;IngmarStein](https://github.com/IngmarStein))
- **cluster:** Fix nodes failing to join the cluster when TLS is enabled ([#&#8203;6437](grafana/alloy#6437)) ([efbad6d](grafana/alloy@efbad6d)) ([@&#8203;kgeckhart](https://github.com/kgeckhart))
- **database\_observability.mysql:** Exclude system schemas from MySQL health check ([#&#8203;6116](grafana/alloy#6116)) ([fcae6f4](grafana/alloy@fcae6f4)) ([@&#8203;matthewnolf](https://github.com/matthewnolf))
- **database\_observability.postgres:** Count error logs when log\_timezone is non-UTC ([#&#8203;6274](grafana/alloy#6274)) ([2eaa769](grafana/alloy@2eaa769)) ([@&#8203;gaantunes](https://github.com/gaantunes), [@&#8203;cristiangreco](https://github.com/cristiangreco))
- **database\_observability.postgres:** Do not retain query text in `explain_plans` collector ([#&#8203;6461](grafana/alloy#6461)) ([4c06a64](grafana/alloy@4c06a64)) ([@&#8203;cristiangreco](https://github.com/cristiangreco))
- **database\_observability:** Exclude more explain plan output keywords ([#&#8203;6145](grafana/alloy#6145)) ([3ff6c14](grafana/alloy@3ff6c14)) ([@&#8203;cristiangreco](https://github.com/cristiangreco))
- **deb:** Restart Alloy only on upgrade in postinst script ([#&#8203;6094](grafana/alloy#6094)) ([8c15cb3](grafana/alloy@8c15cb3)) ([@&#8203;guoard](https://github.com/guoard), [@&#8203;jharvey10](https://github.com/jharvey10))
- **deps:** Pin dependencies ([#&#8203;6376](grafana/alloy#6376)) ([79323b5](grafana/alloy@79323b5))
- **deps:** Update dependencies for catchpoint, databricks, and snowflake exporters ([#&#8203;6188](grafana/alloy#6188)) ([c1b740c](grafana/alloy@c1b740c)) ([@&#8203;Dasomeone](https://github.com/Dasomeone))
- **deps:** Update module go.opentelemetry.io/obi to v0.8.0 \[SECURITY] ([#&#8203;6091](grafana/alloy#6091)) ([05c14af](grafana/alloy@05c14af))
- **documentation:** Fix documentation for loki.rules.kubernetes ([#&#8203;6088](grafana/alloy#6088)) ([61f2b8a](grafana/alloy@61f2b8a)) ([@&#8203;timonegk](https://github.com/timonegk), [@&#8203;clayton-cornell](https://github.com/clayton-cornell))
- Enforce Singleton For Running Alloy Extension Instances ([#&#8203;5763](grafana/alloy#5763)) ([83da6f0](grafana/alloy@83da6f0)) ([@&#8203;blewis12](https://github.com/blewis12), [@&#8203;clayton-cornell](https://github.com/clayton-cornell))
- **faro:** Abort on context cancelation ([#&#8203;6104](grafana/alloy#6104)) ([bf733a6](grafana/alloy@bf733a6)) ([@&#8203;kalleep](https://github.com/kalleep))
- Fix bug that caused 'logging' block's 'write\_to' to be used after config update even if not set ([#&#8203;6264](grafana/alloy#6264)) ([cba7243](grafana/alloy@cba7243)) ([@&#8203;ptodev](https://github.com/ptodev))
- **graphql:** Update cli flags for consistency ([#&#8203;6441](grafana/alloy#6441)) ([7749d4f](grafana/alloy@7749d4f)) ([@&#8203;jharvey10](https://github.com/jharvey10))
- **helm:** Honor alloy.configMap.key in templates/configmap.yaml ([#&#8203;6312](grafana/alloy#6312)) ([415af2c](grafana/alloy@415af2c)) ([@&#8203;jmichalek132](https://github.com/jmichalek132), [@&#8203;kalleep](https://github.com/kalleep))
- **integration-tests:** Forward GO\_TAGS to k8s integration tests ([#&#8203;6220](grafana/alloy#6220)) ([b00f79c](grafana/alloy@b00f79c)) ([@&#8203;thampiotr](https://github.com/thampiotr))
- **logging:** Fix startup deadlock when components log before logging config is evaluated ([#&#8203;6112](grafana/alloy#6112)) ([6cdce9e](grafana/alloy@6cdce9e)) ([@&#8203;kgeckhart](https://github.com/kgeckhart))
- **loki.process:** Make limit stage shutdown cancelable ([#&#8203;6215](grafana/alloy#6215)) ([20717b5](grafana/alloy@20717b5)) ([@&#8203;boinger](https://github.com/boinger))
- **loki.process:** New `action_on_duplicate_timestamp` config attribute to fudge identical log timestamps ([#&#8203;5615](grafana/alloy#5615)) ([7d56f50](grafana/alloy@7d56f50)) ([@&#8203;boussaffawalid](https://github.com/boussaffawalid))
- **loki.process:** No longer mutate rules in stage.truncate causing every config update to reload pipeline when this stage is used ([#&#8203;6271](grafana/alloy#6271)) ([b52a4d8](grafana/alloy@b52a4d8)) ([@&#8203;kalleep](https://github.com/kalleep))
- **loki.process:** Potential deadlock on update with stage and receiver changes ([#&#8203;6270](grafana/alloy#6270)) ([cb22e82](grafana/alloy@cb22e82)) ([@&#8203;kalleep](https://github.com/kalleep))
- **loki.process:** Wrap NewPipeline error correctly in match stage ([#&#8203;6216](grafana/alloy#6216)) ([f3af2dd](grafana/alloy@f3af2dd)) ([@&#8203;boinger](https://github.com/boinger))
- **loki.rules.kubernetes:** Add timeout to ruler sync calls ([26170d4](grafana/alloy@26170d4)) ([@&#8203;QuentinBisson](https://github.com/QuentinBisson))
- **loki.source.syslog:** Fix goroutine leak in UDP listener ([#&#8203;6231](grafana/alloy#6231)) ([268b260](grafana/alloy@268b260)) ([@&#8203;x1unix](https://github.com/x1unix))
- **loki:** Clone structured metadata so we can perform fan-out correctly ([#&#8203;6138](grafana/alloy#6138)) ([473244d](grafana/alloy@473244d)) ([@&#8203;kalleep](https://github.com/kalleep))
- **oracledb\_exporter:** Support CGO\_ENABLED=0 cross-compilation ([#&#8203;6168](grafana/alloy#6168)) ([63ab53d](grafana/alloy@63ab53d)) ([@&#8203;korniltsev-grafanista](https://github.com/korniltsev-grafanista))
- **otelcol.exporter.awss3:** Add missing `unique_key_func_name` attribute ([#&#8203;6184](grafana/alloy#6184)) ([9ad2b44](grafana/alloy@9ad2b44)) ([@&#8203;kalleep](https://github.com/kalleep))
- **prometheus.exporter.oracledb:** Fix issue with custom metrics not appearing when more than one instance of prometheus.exporter.oracledb is used ([#&#8203;6228](grafana/alloy#6228)) ([57de4f4](grafana/alloy@57de4f4)) ([@&#8203;ptodev](https://github.com/ptodev))
- **prometheus.operator.\*:** Pass ScrapeNativeHistograms to ScrapeOptions ([#&#8203;6356](grafana/alloy#6356)) ([a44fced](grafana/alloy@a44fced)) ([@&#8203;sberz](https://github.com/sberz))
- **remotewrite:** Use blocking send with timeout in test server ([#&#8203;6208](grafana/alloy#6208)) ([a279088](grafana/alloy@a279088)) ([@&#8203;kgeckhart](https://github.com/kgeckhart))
- **security:** Update module github.com/jackc/pgx/v5 to v5.9.2 \[SECURITY] ([#&#8203;6326](grafana/alloy#6326)) ([bf3ff2e](grafana/alloy@bf3ff2e))
- **security:** Update x/crypto and x/net for CVEs ([#&#8203;6336](grafana/alloy#6336)) ([4c7b93b](grafana/alloy@4c7b93b)) ([@&#8203;thampiotr](https://github.com/thampiotr))
- **ui:** Reduce UI dependencies ([#&#8203;6349](grafana/alloy#6349)) ([85e12ba](grafana/alloy@85e12ba)) ([@&#8203;jharvey10](https://github.com/jharvey10))
- **ui:** Update dependency minor versions ([#&#8203;6288](grafana/alloy#6288)) ([52a28d2](grafana/alloy@52a28d2)) ([@&#8203;jharvey10](https://github.com/jharvey10))
- Update go to v1.26.4 ([#&#8203;6418](grafana/alloy#6418)) ([51fb7d2](grafana/alloy@51fb7d2)) ([@&#8203;kalleep](https://github.com/kalleep))
- **validation:** Improve type checking of ast.LiteralExpr ([#&#8203;5916](grafana/alloy#5916)) ([d0a1177](grafana/alloy@d0a1177)) ([@&#8203;kalleep](https://github.com/kalleep))

#### Upgrading

Read the [release notes] for specific instructions on upgrading from older versions:

[release notes]: https://grafana.com/docs/alloy/v1.17/release-notes/

#### Installation

Refer to our [installation guide] for how to install Grafana Alloy.

[installation guide]: https://grafana.com/docs/alloy/v1.17/get-started/install/

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMTQuNSIsInVwZGF0ZWRJblZlciI6IjQzLjIxNC41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jun 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

helm: KEDA example from k8s-monitoring fights the chart's static replicas

3 participants