Skip to content

Deprecate legacy_stderr_threshold_behavior=true default #436

@pierluigilenoci

Description

@pierluigilenoci

Problem

PR #432 fixed the long-standing issue #212 where -stderrthreshold was silently ignored when -logtostderr=true. The fix introduced a legacy_stderr_threshold_behavior flag (defaulting to true) so consumers can opt into the corrected behavior.

While backward-safe, this design has a significant adoption problem: every downstream klog consumer must independently discover and opt into the fix. In practice, most klog users will never know this flag exists and will continue living with the broken behavior indefinitely.

This has already surfaced in the metrics-server review (kubernetes-sigs/metrics-server#1782), where the maintainer @RainbowMango asked:

Would it have been more appropriate to flip the default to false in a new klog version, or at least deprecate the legacy behavior with a timeline?

Current state

Over 15 downstream projects have already adopted the fix by manually calling:
```go
local.Set("legacy_stderr_threshold_behavior", "false")
```

Including: secrets-store-csi-driver, metrics-server, cluster-autoscaler, keda, kyverno, velero, kind, dapr, cert-manager, and others. Each required a separate PR just to opt in.

Proposed deprecation timeline

Step 1 — Deprecation warning (PR #437)

Add a one-time warning to stderr when both conditions are met:

  1. `legacy_stderr_threshold_behavior=true` (the current default)
  2. `-stderrthreshold` was explicitly set by the user

This warns users that their threshold setting is being silently ignored. The warning guides them to set `-legacy_stderr_threshold_behavior=false` to get the corrected behavior.

Flag descriptions and package documentation are updated to mark the legacy behavior as deprecated.

Step 2 — Flip the default (future release)

After the deprecation warning has been in a release for a reasonable period:

  1. Change `legacy_stderr_threshold_behavior` default from `true` to `false`
  2. Change `stderrthreshold` default from `ERROR` to `INFO` (preserves backward compatibility: with `logtostderr=true`, all logs still appear on stderr by default)

Historical context

A previous attempt to flip the defaults directly was reverted in #50 (2019) because it violated the Kubernetes deprecation policy. This proposal follows the gradual approach: warn first, flip later.

Benefits

  • Follows the Kubernetes deprecation policy (warn → change)
  • No breaking changes in Step 1
  • Downstream consumers get advance notice before any behavior change
  • After Step 2, projects that already opted in via `local.Set("legacy_stderr_threshold_behavior", "false")` can remove that boilerplate

/kind feature

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/featureCategorizes issue or PR as related to a new feature.needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions