Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

log: split streams also for text output #114672

Merged
merged 3 commits into from Feb 26, 2024

Conversation

pohly
Copy link
Contributor

@pohly pohly commented Dec 23, 2022

What type of PR is this?

/kind feature

What this PR does / why we need it:

Buffering info messages and letting error messages be written without first flushing info messages increases performance. This was previously implemented only for JSON, but some users may also want it for text.

The other aspect of the PR is to completely replace legacy code in klog with a cleaner, simpler implementation. The k8s.io/klog/v2/textlogger does that. When it gets installed as logger in klog, message routing is as follows:

  • klog.Background().Info -> textlogger -> message formatting -> file
  • klog.InfoS -> textlogger -> message formatting -> file
  • klog.Infof -> message formatting -> textlogger -> message formatting -> file

Without it, legacy klog code is involved:

  • klog.Background().Info -> klog.logger -> klog -> message formatting -> klog output routing -> file
  • klog.InfoS -> message formatting -> klog output routing -> file
  • klog.Infof -> message formatting -> klog output routing -> file

Special notes for your reviewer:

All opens were resolved:

  • Depends on PR runtime log verbosity level changes #114609.
  • Overhead for unstructured calls (klog.Infof) increases because previously, klog would write the formatted message directly. The formatting also changes (klog didn't quote the message, textlogger does). See textlogger write through klog#363 for the solution.
  • How should the k8s.io/component-base/log/api/v1 be changed? The same settings now get duplicated, to make it clear where they are supported.

Does this PR introduce a user-facing change?

Text logging in Kubernetes components now uses [textlogger](https://pkg.go.dev/k8s.io/klog/v2@v2.120.0/textlogger). The same split streams of info and error log entries with buffering of info entries is now also supported for text output (off by default, alpha feature). Previously, this was only supported for JSON. Performance is better also without split streams.

/wg structured-logging
/sig instrumentation

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. kind/feature Categorizes issue or PR as related to a new feature. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. wg/structured-logging Categorizes an issue or PR as relevant to WG Structured Logging. sig/instrumentation Categorizes an issue or PR as relevant to SIG Instrumentation. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. area/apiserver area/cloudprovider area/code-generation area/dependency Issues or PRs related to dependency changes area/kubectl area/test kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. sig/architecture Categorizes an issue or PR as relevant to SIG Architecture. sig/auth Categorizes an issue or PR as relevant to SIG Auth. sig/cli Categorizes an issue or PR as relevant to SIG CLI. sig/cloud-provider Categorizes an issue or PR as relevant to SIG Cloud Provider. sig/cluster-lifecycle Categorizes an issue or PR as relevant to SIG Cluster Lifecycle. sig/node Categorizes an issue or PR as relevant to SIG Node. sig/storage Categorizes an issue or PR as relevant to SIG Storage. sig/testing Categorizes an issue or PR as relevant to SIG Testing. labels Dec 23, 2022
@pohly
Copy link
Contributor Author

pohly commented Jan 12, 2024

This PR is now complete and ready for review and merging.

@kaisoz: you wanted to learn more about logging. This PR shows off some of the machinery that we have for it in Kubernetes, but admittedly it throws you in at the deep end...

@mengjiao-liu : you are better suited to do the actual review.

/assign @mengjiao-liu

I would have asked @serathius for a review as he originally suggested implementing split output, but he probably has no time.

As this PR claims to improve performance, let's run benchmarks.

The base is commit a15bda8, without changes to text logging. When comparing against the new implementation with textlogger, performance is indeed better:

name                                               old msgs/s  new msgs/s   delta
Encoding/error-value/printf-36                      312k ± 1%    312k ± 3%      ~     (p=0.841 n=5+5)
Encoding/error-value/structured-36                  269k ± 2%    246k ± 1%    -8.57%  (p=0.008 n=5+5)
Encoding/error-value/JSON-36                        165k ± 2%    159k ± 1%    -3.66%  (p=0.008 n=5+5)
Encoding/error/printf-36                            335k ± 3%    328k ± 4%      ~     (p=0.095 n=5+5)
Encoding/error/structured-36                        271k ± 3%    274k ± 3%      ~     (p=0.548 n=5+5)
Encoding/error/JSON-36                              195k ± 2%    187k ± 2%    -4.37%  (p=0.008 n=5+5)
Encoding/kind-worker-kubelet/printf-36              469k ± 1%    461k ± 1%    -1.70%  (p=0.008 n=5+5)
Encoding/kind-worker-kubelet/structured-36          243k ± 0%    266k ± 1%    +9.52%  (p=0.008 n=5+5)
Encoding/kind-worker-kubelet/JSON-36                315k ± 0%    311k ± 0%    -1.28%  (p=0.008 n=5+5)
Encoding/kube-apiserver/printf-36                   272k ± 2%    272k ± 1%      ~     (p=0.841 n=5+5)
Encoding/kube-apiserver/structured-36              97.4k ± 2%  118.2k ± 1%   +21.42%  (p=0.008 n=5+5)
Encoding/kube-apiserver/JSON-36                     210k ± 1%    209k ± 1%      ~     (p=0.310 n=5+5)
Encoding/kube-controller-manager/printf-36          411k ± 0%    410k ± 1%      ~     (p=0.421 n=5+5)
Encoding/kube-controller-manager/structured-36      204k ± 1%    216k ± 0%    +6.03%  (p=0.008 n=5+5)
Encoding/kube-controller-manager/JSON-36            233k ± 0%    232k ± 1%    -0.64%  (p=0.032 n=5+5)
Encoding/kube-scheduler/printf-36                   393k ± 1%    392k ± 1%      ~     (p=0.151 n=5+5)
Encoding/kube-scheduler/structured-36               192k ± 1%    208k ± 1%    +8.23%  (p=0.008 n=5+5)
Encoding/kube-scheduler/JSON-36                     228k ± 1%    226k ± 1%      ~     (p=0.222 n=5+5)
Encoding/simple/printf-36                           280k ± 2%    262k ± 2%    -6.27%  (p=0.008 n=5+5)
Encoding/simple/structured-36                       241k ± 2%    206k ± 1%   -14.31%  (p=0.008 n=5+5)
Encoding/simple/JSON-36                             151k ± 1%    143k ± 2%    -5.13%  (p=0.008 n=5+5)
Encoding/split/printf-36                            281k ± 1%    262k ± 1%    -6.62%  (p=0.008 n=5+5)
Encoding/split/structured-36                        233k ± 2%    201k ± 1%   -13.80%  (p=0.008 n=5+5)
Encoding/split/JSON-36                              147k ± 1%    143k ± 1%    -2.32%  (p=0.008 n=5+5)
Encoding/v3/kind-worker-kubelet/printf-36           303k ± 0%    300k ± 1%      ~     (p=0.151 n=5+5)
Encoding/v3/kind-worker-kubelet/structured-36       199k ± 1%    219k ± 0%   +10.16%  (p=0.008 n=5+5)
Encoding/v3/kind-worker-kubelet/JSON-36             240k ± 0%    237k ± 0%    -1.06%  (p=0.008 n=5+5)
Encoding/v3/kube-apiserver/printf-36                132k ± 1%    131k ± 1%    -0.98%  (p=0.032 n=5+5)
Encoding/v3/kube-apiserver/structured-36           63.9k ± 1%   75.3k ± 1%   +17.93%  (p=0.008 n=5+5)
Encoding/v3/kube-apiserver/JSON-36                  125k ± 1%    125k ± 2%      ~     (p=1.000 n=5+5)
Encoding/v3/kube-controller-manager/printf-36       394k ± 1%    393k ± 1%      ~     (p=0.690 n=5+5)
Encoding/v3/kube-controller-manager/structured-36   199k ± 1%    213k ± 1%    +7.10%  (p=0.008 n=5+5)
Encoding/v3/kube-controller-manager/JSON-36         225k ± 1%    227k ± 1%      ~     (p=0.056 n=5+5)
Encoding/v3/kube-scheduler/printf-36                332k ± 1%    335k ± 0%    +0.96%  (p=0.016 n=5+5)
Encoding/v3/kube-scheduler/structured-36            243k ± 1%    261k ± 1%    +7.41%  (p=0.008 n=5+5)
Encoding/v3/kube-scheduler/JSON-36                  185k ± 1%    191k ± 0%    +3.49%  (p=0.008 n=5+5)
Encoding/values/printf-36                           202k ± 1%    191k ± 1%    -5.40%  (p=0.008 n=5+5)
Encoding/values/structured-36                       194k ± 1%    194k ± 1%      ~     (p=1.000 n=5+5)
Encoding/values/JSON-36                            94.2k ± 1%   94.8k ± 1%      ~     (p=0.095 n=5+5)
Encoding/versionresponse/printf-36                  0.00         0.00           ~     (all equal)
Encoding/versionresponse/structured-36              0.00         0.00           ~     (all equal)
Encoding/versionresponse/JSON-36                    0.00         0.00           ~     (all equal)
Writing/discard/structured/single-stream-36         302k ± 4%   1171k ±10%  +287.88%  (p=0.008 n=5+5)
Writing/discard/structured/split-stream-36          323k ± 1%    467k ± 7%   +44.79%  (p=0.008 n=5+5)
Writing/discard/JSON/single-stream-36              1.93M ± 3%   2.19M ± 3%   +13.86%  (p=0.008 n=5+5)
Writing/discard/JSON/split-stream-36                569k ± 3%    627k ± 4%   +10.20%  (p=0.008 n=5+5)
Writing/tmp-files/structured/single-stream-36       110k ± 1%    127k ± 1%   +16.27%  (p=0.008 n=5+5)
Writing/tmp-files/structured/split-stream-36        110k ± 1%    234k ± 1%  +111.84%  (p=0.008 n=5+5)
Writing/tmp-files/JSON/single-stream-36             138k ± 1%    140k ± 1%    +1.87%  (p=0.008 n=5+5)
Writing/tmp-files/JSON/split-stream-36              282k ± 1%    286k ± 0%    +1.57%  (p=0.008 n=5+5)

Comparing Writing/tmp-files/structured/split-stream against Writing/tmp-files/structured/single-stream shows that the new features are worthwhile: 234k messages/s instead of 127k messages/s.

The most striking difference is Writing/discard/structured/single-stream: +287.88%!

With textlogger, the path from log call to io.Discard.Write is:

0  0x00000000004dcc24 in io.discard.Write
   at /nvme/gopath/go-1.21.0/src/io/io.go:639
1  0x00000000004defd9 in io.(*discard).Write
   at <autogenerated>:1
2  0x00000000013f2164 in k8s.io/klog/v2/textlogger.(*tlogger).printWithInfos
   at ./vendor/k8s.io/klog/v2/textlogger/textlogger.go:130
3  0x00000000013f1cd3 in k8s.io/klog/v2/textlogger.(*tlogger).print
   at ./vendor/k8s.io/klog/v2/textlogger/textlogger.go:105
4  0x00000000013f18d6 in k8s.io/klog/v2/textlogger.(*tlogger).Info
   at ./vendor/k8s.io/klog/v2/textlogger/textlogger.go:85
5  0x0000000000876fb1 in github.com/go-logr/logr.Logger.Info
   at ./vendor/github.com/go-logr/logr/logr.go:284
6  0x00000000008969ac in k8s.io/klog/v2.(*loggingT).infoS
   at ./vendor/k8s.io/klog/v2/klog.go:793
7  0x000000000089a7ec in k8s.io/klog/v2.InfoS
   at ./vendor/k8s.io/klog/v2/klog.go:1526
8  0x00000000014aaf1f in k8s.io/kubernetes/test/integration/logs/benchmark.generateOutput.func1
   at ./test/integration/logs/benchmark/benchmark_test.go:290

There's no mutex locking involved at all.

Previously with klog, the path is more convoluted:

 0  0x00000000004dcc24 in io.discard.Write
    at /nvme/gopath/go-1.21.0/src/io/io.go:639
 1  0x00000000004defd9 in io.(*discard).Write
    at <autogenerated>:1
 2  0x0000000000896632 in k8s.io/klog/v2.(*redirectBuffer).Write
    at ./vendor/k8s.io/klog/v2/klog.go:831
 3  0x0000000000897002 in k8s.io/klog/v2.(*loggingT).output
    at ./vendor/k8s.io/klog/v2/klog.go:926
 4  0x00000000008956e6 in k8s.io/klog/v2.(*loggingT).printWithInfos
    at ./vendor/k8s.io/klog/v2/klog.go:723
 5  0x0000000000895431 in k8s.io/klog/v2.(*loggingT).printDepth
    at ./vendor/k8s.io/klog/v2/klog.go:705
 6  0x00000000008964de in k8s.io/klog/v2.(*loggingT).printS
    at ./vendor/k8s.io/klog/v2/klog.go:812
 7  0x00000000008961c9 in k8s.io/klog/v2.(*loggingT).infoS
    at ./vendor/k8s.io/klog/v2/klog.go:796
 8  0x0000000000899fac in k8s.io/klog/v2.InfoS
    at ./vendor/k8s.io/klog/v2/klog.go:1526
 9  0x00000000014a45bf in k8s.io/kubernetes/test/integration/logs/benchmark.generateOutput.func1
    at ./test/integration/logs/benchmark/benchmark_test.go:281

In particular, output needs a mutex:
https://github.com/kubernetes/klog/blob/2d0829603f74534b4b4e09551c8d003da4558143/klog.go#L886-L894

Somewhere I also managed to remove some allocations (only benchmarked for this case, with less performance improvements when using -benchmem):

name                                         old msgs/s     new msgs/s     delta
Writing/discard/structured/single-stream-36      280k ± 4%      433k ± 7%  +54.40%  (p=0.008 n=5+5)

name                                         old alloc/op   new alloc/op   delta
Writing/discard/structured/single-stream-36     243MB ± 0%     170MB ± 0%  -30.07%  (p=0.008 n=5+5)

name                                         old allocs/op  new allocs/op  delta
Writing/discard/structured/single-stream-36     1.31M ± 0%     1.00M ± 0%  -23.44%  (p=0.008 n=5+5)

The Writing/tmp-files/structured/split-stream benefits from the output buffering in memory and increases more than the corresponding Writing/discard/structured/split-stream where the Write call has no overhead.

The Writing benchmark uses an artificial stream of log entries. To see the difference between klog-based output and textlogger + split output + buffering, I also benchmarked with real log data from a CI run and this patch:

diff --git a/test/integration/logs/benchmark/benchmark_test.go b/test/integration/logs/benchmark/benchmark_test.go
index abc92e55531..da01b404247 100644
--- a/test/integration/logs/benchmark/benchmark_test.go
+++ b/test/integration/logs/benchmark/benchmark_test.go
@@ -77,11 +77,16 @@ func BenchmarkEncoding(b *testing.B) {
                                // To make the tests a bit more realistic, at
                                // least do system calls during each write.
                                output := newBytesWritten(b, "/dev/null")
+                               output2 := newBytesWritten(b, "/dev/null")
                                c := logsapi.NewLoggingConfiguration()
                                c.Format = format
+                               c.Options.Text.SplitStream = true
+                               if err := c.Options.Text.InfoBufferSize.Set("1Mi"); err != nil {
+                                       b.Fatalf("set info buffer size: %v", err)
+                               }
                                o := logsapi.LoggingOptions{
                                        ErrorStream: output,
-                                       InfoStream:  output,
+                                       InfoStream:  output2,
                                }
                                klog.SetOutput(output)
                                defer func() {

Using textlogger in both cases shows the advantage of the new features:

name                                               old msgs/s  new msgs/s   delta
Encoding/v3/kind-worker-kubelet/printf-36           300k ± 1%    339k ± 1%  +12.83%  (p=0.008 n=5+5)
Encoding/v3/kind-worker-kubelet/structured-36       219k ± 0%    240k ± 0%   +9.57%  (p=0.008 n=5+5)
Encoding/v3/kind-worker-kubelet/JSON-36             237k ± 0%    238k ± 1%     ~     (p=0.222 n=5+5)
Encoding/v3/kube-apiserver/printf-36                131k ± 1%    191k ± 1%  +45.68%  (p=0.008 n=5+5)
Encoding/v3/kube-apiserver/structured-36           75.3k ± 1%  145.2k ± 2%  +92.89%  (p=0.008 n=5+5)
Encoding/v3/kube-apiserver/JSON-36                  125k ± 2%    198k ± 1%  +58.86%  (p=0.008 n=5+5)
Encoding/v3/kube-controller-manager/printf-36       393k ± 1%    732k ± 1%  +86.08%  (p=0.008 n=5+5)
Encoding/v3/kube-controller-manager/structured-36   213k ± 1%    409k ± 1%  +92.02%  (p=0.008 n=5+5)
Encoding/v3/kube-controller-manager/JSON-36         227k ± 1%    345k ± 0%  +52.26%  (p=0.008 n=5+5)
Encoding/v3/kube-scheduler/printf-36                335k ± 0%    595k ± 1%  +77.71%  (p=0.008 n=5+5)
Encoding/v3/kube-scheduler/structured-36            261k ± 1%    477k ± 1%  +83.15%  (p=0.008 n=5+5)
Encoding/v3/kube-scheduler/JSON-36                  191k ± 0%    304k ± 0%  +58.98%  (p=0.008 n=5+5)

However, here it is a bit suspicious that JSON also runs faster. Perhaps I made a mistake somewhere with my invocations or my machine wasn't fully idle during some run.

Overall I think this is a good step forward and worth merging.

@pohly pohly changed the title WIP: log: split streams also for text output log: split streams also for text output Jan 12, 2024
@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Jan 12, 2024
@kaisoz
Copy link
Contributor

kaisoz commented Jan 12, 2024

Thanks @pohly ! I'll have a look, this will definitely help me to learn and go deeper 👍🏻

@mengjiao-liu
Copy link
Member

Copy that. Let me look into it.

Comment on lines +357 to +370
fs.BoolVar(&c.Options.Text.SplitStream, "log-text-split-stream", false, "[Alpha] In text format, write error messages to stderr and info messages to stdout. The default is to write a single stream to stdout. Enable the LoggingAlphaOptions feature gate to use this.")
fs.Var(&c.Options.Text.InfoBufferSize, "log-text-info-buffer-size", "[Alpha] In text format with split output streams, the info messages can be buffered for a while to increase performance. The default value of zero bytes disables buffering. The size can be specified as number of bytes (512), multiples of 1000 (1K), multiples of 1024 (2Ki), or powers of those (3M, 4G, 5Mi, 6Gi). Enable the LoggingAlphaOptions feature gate to use this.")
Copy link
Member

Choose a reason for hiding this comment

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

From the code implementation point of view, I do not see the feature gate LoggingAlphaOptions restrictions on these fields c.Options.Text.SplitStream and c.Options.Text.InfoBufferSize, are these missing? Or did I miss something?

I only found validation for the JSON format, not Text format.

func validateJSONOptions(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
errs := field.ErrorList{}
if gate := LoggingAlphaOptions; c.Options.JSON.SplitStream && !featureEnabled(featureGate, gate) {
errs = append(errs, field.Forbidden(fldPath.Child("splitStream"), fmt.Sprintf("Feature %s is disabled", gate)))
}
if gate := LoggingAlphaOptions; c.Options.JSON.InfoBufferSize.Value() != 0 && !featureEnabled(featureGate, gate) {
errs = append(errs, field.Forbidden(fldPath.Child("infoBufferSize"), fmt.Sprintf("Feature %s is disabled", gate)))
}
return errs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right, that was missing for text options. Fixed.

I copied the code although it's the same because (theoretically) the options might progress towards beta at a different pace and/or other options might be added to the structs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ready for LGTM now?

@mengjiao-liu
Copy link
Member

Text logging in Kubernetes components now uses [textlogger](https://pkg.go.dev/k8s.io/klog/v2@v2.120.0/textlogger). The same split streams of info and error log entries with buffering of info entries is now also supported for text output (off by default, alpha feature). Previously, this was only supported for JSON. Performance is better also without split streams.

There is a sentence in the release note: "Performance is better also without split streams." Is this sentence wrong? Judging from the overall description and the performance test results you posted, the performance is better after splitting the streams.

This replaces the klog formatting and message routing with a simpler
implementation that uses less code. The main difference is that we skip the
entire unused message routing.

Instead, the same split output streams as for JSON gets implemented in the
io.Writer implementation that gets passed to the textlogger.
@pohly
Copy link
Contributor Author

pohly commented Jan 17, 2024

Tests cases like Writing/tmp-files/structured/single-stream also benefit from the new code (+16.27%). For Encoding/v3/kube-apiserver/structured it's +17.93%. In both cases, none of the new features are used. So I think the release note summary is correct.

@mengjiao-liu
Copy link
Member

mengjiao-liu commented Jan 18, 2024

Tests cases like Writing/tmp-files/structured/single-stream also benefit from the new code (+16.27%). For Encoding/v3/kube-apiserver/structured it's +17.93%. In both cases, none of the new features are used. So I think the release note summary is correct.

That makes sense.

@k8s-triage-robot
Copy link

This PR may require API review.

If so, when the changes are ready, complete the pre-review checklist and request an API review.

Status of requested reviews is tracked in the API Review project.

Copy link
Member

@mengjiao-liu mengjiao-liu left a comment

Choose a reason for hiding this comment

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

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jan 25, 2024
@k8s-ci-robot
Copy link
Contributor

LGTM label has been added.

Git tree hash: 960fb3f875bada4474eedb79814bb260ac7f95b9

@pohly
Copy link
Contributor Author

pohly commented Jan 25, 2024

/assign @thockin

For component-base/logging API + implementation approval.

@bart0sh bart0sh moved this from WIP to Needs Approver in SIG Node PR Triage Jan 25, 2024
@thockin
Copy link
Member

thockin commented Feb 17, 2024

Can you explain the motivation for this? I, perhaps naively, thought that our goal was to replace klog as an API with logr or slog, and klog as an implementation with some other log library which is actively maintained. I am reticent to make klog better and better - it's not our "core competency".

Performance is better also without split streams

How much better, and if so - why are we doing this?

@pohly
Copy link
Contributor Author

pohly commented Feb 19, 2024

our goal was to replace klog as an API with logr or slog ...

This is not a goal of any KEP at the moment. I keep thinking about it from time to time, but I'm always coming to the conclusion that it's going to cause breakage that isn't justified by the benefits.

If we were to replace klog as we know it today, then this PR is a step in that direction. That's because the actual code that then gets used from klog gets reduced to just textlogger and the shared output formatting under internal. We no longer need most of klog.go.

There are other parts in klog that we would need to keep (like klog.KObj and other helpers), but those aren't hard. They don't even need to be in klog. They were just added there to ensure that all logging in Kubernetes can be done with a single import klog/v2.

The idea that I keep coming back to is a klog v3 with most of klog.go removed. The unsolved problem is choosing a default logger. No matter which one I pick (klog text format, slog default), it's always going to be different or have different behavior compared to what downstream currently gets from klog/v2.

... and klog as an implementation with some other log library which is actively maintained

klog is actively maintained. It has to be, because it is so widely used. I also find the text output more useful than JSON and the slog text output, so I think Kubernetes should keep supporting both JSON and klog text output.

How much better, and if so - why are we doing this?

See #114672 (comment) above. We are doing this because the text output is being used in Kubernetes.

@thockin
Copy link
Member

thockin commented Feb 26, 2024

Thanks!

/lgtm
/approve

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: pohly, thockin

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 26, 2024
@k8s-ci-robot k8s-ci-robot merged commit 98bd90f into kubernetes:master Feb 26, 2024
15 checks passed
SIG Node CI/Test Board automation moved this from PRs Waiting on Author to Done Feb 26, 2024
SIG Node PR Triage automation moved this from Needs Approver to Done Feb 26, 2024
@k8s-ci-robot k8s-ci-robot added this to the v1.30 milestone Feb 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/apiserver area/cloudprovider area/code-generation area/dependency Issues or PRs related to dependency changes area/kube-proxy area/kubectl area/kubelet area/test cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API kind/feature Categorizes issue or PR as related to a new feature. lgtm "Looks good to me", indicates that a PR is ready to be merged. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. sig/architecture Categorizes an issue or PR as relevant to SIG Architecture. sig/auth Categorizes an issue or PR as relevant to SIG Auth. sig/cli Categorizes an issue or PR as relevant to SIG CLI. sig/cloud-provider Categorizes an issue or PR as relevant to SIG Cloud Provider. sig/cluster-lifecycle Categorizes an issue or PR as relevant to SIG Cluster Lifecycle. sig/instrumentation Categorizes an issue or PR as relevant to SIG Instrumentation. sig/network Categorizes an issue or PR as relevant to SIG Network. sig/node Categorizes an issue or PR as relevant to SIG Node. sig/storage Categorizes an issue or PR as relevant to SIG Storage. sig/testing Categorizes an issue or PR as relevant to SIG Testing. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. triage/accepted Indicates an issue or PR is ready to be actively worked on. wg/structured-logging Categorizes an issue or PR as relevant to WG Structured Logging.
Projects
Archived in project
Archived in project
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

9 participants