Skip to content

Commit a29aa12

Browse files
committed
address comments
Signed-off-by: Jian Zeng <[email protected]>
1 parent a6e88b3 commit a29aa12

File tree

1 file changed

+74
-79
lines changed
  • keps/sig-node/3288-separate-stdout-from-stderr

1 file changed

+74
-79
lines changed

keps/sig-node/3288-separate-stdout-from-stderr/README.md

Lines changed: 74 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ retrieve certain log stream of a container, so it is great to implement this lon
171171

172172
### Goals
173173

174-
- Enable api-server to return certain log stream of a container
175-
- Enable users to fetch certain log stream of a container
174+
- Enable api-server to return specific log stream of a container
175+
- Enable users to fetch specific log stream of a container
176176

177177
### Non-Goals
178178

@@ -216,21 +216,34 @@ This might be a good place to talk about core concepts and how they relate.
216216
Add a new field `Stream` to `k8s.io/kubernetes/pkg/apis/core.PodLogOptions`:
217217

218218
```go
219+
// LogStreamType represents the desired log stream type.
220+
type LogStreamType string
221+
222+
const (
223+
// LogStreamTypeStdout is the stream type for stdout.
224+
LogStreamTypeStdout LogStreamType = "stdout"
225+
// LogStreamTypeStderr is the stream type for stderr.
226+
LogStreamTypeStderr LogStreamType = "stderr"
227+
// LogStreamTypeAll represents the combined stdout and stderr.
228+
LogStreamTypeAll LogStreamType = "all"
229+
)
230+
219231
// PodLogOptions is the query options for a Pod's logs REST call
220232
type PodLogOptions struct {
221-
...
222-
// If set, return the given log stream of the container.
223-
// Otherwise, the combined stdout and stderr from the container is returned.
224-
// Available values are: "stdout", "stderr", "" (empty string).
225-
Stream string
233+
...
234+
// If set to "stdout" or "stderr", return the given log stream of the container.
235+
// If set to "all" or not set, the combined stdout and stderr from the container is returned.
236+
// Available values are: "stdout", "stderr", "all", "" (empty string).
237+
// +optional
238+
Stream LogStreamType
226239
}
227240
```
228241

229242
When users want to query certain stream from container, they need to add a new query named `stream`
230243
to the URL, i.e. `/api/v1/namespaces/default/pods/foo/log?stream=stderr&container=nginx`.
231244
Then the kube-apiserver is able to know the desired `stream` and passes it to the kubelet.
232245

233-
To tell kubelet which stream to return, we need to update the `LogLocation` function to make it be aware of
246+
To tell kubelet which stream to return, we need to update the [`LogLocation`](https://github.com/kubernetes/kubernetes/blob/ba502ee555924a49c1455b0d3fa96ec1e787715d/pkg/registry/core/pod/strategy.go#L398) function to make it be aware of
234247
the new parameter:
235248

236249
```go
@@ -243,14 +256,18 @@ func LogLocation(
243256
opts *api.PodLogOptions,
244257
) (*url.URL, http.RoundTripper, error) {
245258
...
246-
params := url.Values{}
247-
// validate stream
248-
switch opts.Stream {
249-
case "stdout", "stderr", "":
250-
default:
251-
return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid container log stream %s", opts.Stream))
252-
}
253-
params.Add("stream", opts.Stream)
259+
params := url.Values{}
260+
// validate stream
261+
switch opts.Stream {
262+
case LogStreamTypeStdout, LogStreamTypeStderr, LogStreamTypeAll, "":
263+
default:
264+
return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid container log stream %s", opts.Stream))
265+
}
266+
// keep backwards compatibility
267+
if opts.Stream == "" {
268+
opts.Stream = LogStreamTypeAll
269+
}
270+
params.Add("stream", string(opts.Stream))
254271
...
255272
}
256273
```
@@ -265,45 +282,46 @@ Add a new field `Stream` to `k8s.io/api/core/v1.PodLogOptions`:
265282
type LogStreamType string
266283

267284
const (
268-
// LogStreamTypeStdout is the stream type for stdout.
269-
LogStreamTypeStdout LogStreamType = "stdout"
270-
// LogStreamTypeStderr is the stream type for stderr.
285+
// LogStreamTypeStdout is the stream type for stdout.
286+
LogStreamTypeStdout LogStreamType = "stdout"
287+
// LogStreamTypeStderr is the stream type for stderr.
271288
LogStreamTypeStderr LogStreamType = "stderr"
272-
// LogStreamTypeAll represents the combined stdout and stderr.
273-
LogStreamTypeAll LogStreamType = ""
289+
// LogStreamTypeAll represents the combined stdout and stderr.
290+
LogStreamTypeAll LogStreamType = "all"
274291
)
275292
// PodLogOptions is the query options for a Pod's logs REST call.
276293
type PodLogOptions struct {
277-
...
278-
// If set, return the given log stream of the container.
279-
// Otherwise, the combined stdout and stderr from the container is returned.
280-
// +optional
281-
Stream LogStreamType
294+
...
295+
// If set, return the given log stream of the container.
296+
// Otherwise, the combined stdout and stderr from the container is returned.
297+
// +optional
298+
Stream LogStreamType
282299
}
300+
283301
```
284302

285-
In the `getContainerLogs` method of `k8s.io/kubernetes/pkg/kubelet/server.Server`, we examine the `Stream` field
303+
In the [`getContainerLogs`](https://github.com/kubernetes/kubernetes/blob/ba502ee555924a49c1455b0d3fa96ec1e787715d/pkg/kubelet/server/server.go#L610) method of `k8s.io/kubernetes/pkg/kubelet/server.Server`, we examine the `Stream` field
286304
of `PodLogOptions` to decide which stream to return:
287305

288306
```go
289307
// getContainerLogs handles containerLogs request against the Kubelet
290308
func (s *Server) getContainerLogs(request *restful.Request, response *restful.Response) {
291-
...
292-
fw := flushwriter.Wrap(response.ResponseWriter)
293-
var stdout, stderr io.Writer
309+
...
310+
fw := flushwriter.Wrap(response.ResponseWriter)
311+
var stdout, stderr io.Writer
294312
switch logOptions.Stream {
295-
case corev1.LogStreamTypeStdout:
296-
stdout, stderr = fw, io.Discard
297-
case corev1.LogStreamTypeStderr:
298-
stdout, stderr = io.Discard, fw
299-
case corev1.LogStreamTypeAll:
300-
stdout, stderr = fw, fw
301-
}
302-
response.Header().Set("Transfer-Encoding", "chunked")
303-
if err := s.host.GetKubeletContainerLogs(ctx, kubecontainer.GetPodFullName(pod), containerName, logOptions, stdout, stderr); err != nil {
304-
response.WriteError(http.StatusBadRequest, err)
305-
return
306-
}
313+
case corev1.LogStreamTypeStdout:
314+
stdout, stderr = fw, io.Discard
315+
case corev1.LogStreamTypeStderr:
316+
stdout, stderr = io.Discard, fw
317+
case corev1.LogStreamTypeAll:
318+
stdout, stderr = fw, fw
319+
}
320+
response.Header().Set("Transfer-Encoding", "chunked")
321+
if err := s.host.GetKubeletContainerLogs(ctx, kubecontainer.GetPodFullName(pod), containerName, logOptions, stdout, stderr); err != nil {
322+
response.WriteError(http.StatusBadRequest, err)
323+
return
324+
}
307325
}
308326
```
309327

@@ -546,7 +564,7 @@ well as the [existing list] of feature gates.
546564
###### Does enabling the feature change any default behavior?
547565

548566
No. If the query parameter `stream` in the url of fetching logs from kube-apiserver is empty or not set,
549-
combined stdout and stderr is returned.
567+
combined stdout and stderr is returned, which is the default behavior.
550568

551569
###### Can the feature be disabled once it has been enabled (i.e. can we roll back the enablement)?
552570

@@ -646,40 +664,15 @@ Recall that end users cannot usually observe component logs or access metrics.
646664

647665
###### What are the reasonable SLOs (Service Level Objectives) for the enhancement?
648666

649-
<!--
650-
This is your opportunity to define what "normal" quality of service looks like
651-
for a feature.
652-
653-
It's impossible to provide comprehensive guidance, but at the very
654-
high level (needs more precise definitions) those may be things like:
655-
- per-day percentage of API calls finishing with 5XX errors <= 1%
656-
- 99% percentile over day of absolute value from (job creation time minus expected
657-
job creation time) for cron job <= 10%
658-
- 99.9% of /health requests per day finish with 200 code
659-
660-
These goals will help you determine what you need to measure (SLIs) in the next
661-
question.
662-
-->
667+
N/A
663668

664669
###### What are the SLIs (Service Level Indicators) an operator can use to determine the health of the service?
665670

666-
<!--
667-
Pick one more of these and delete the rest.
668-
-->
669-
670-
- [ ] Metrics
671-
- Metric name:
672-
- [Optional] Aggregation method:
673-
- Components exposing the metric:
674-
- [ ] Other (treat as last resort)
675-
- Details:
671+
N/A
676672

677673
###### Are there any missing metrics that would be useful to have to improve observability of this feature?
678674

679-
<!--
680-
Describe the metrics themselves and the reasons why they weren't added (e.g., cost,
681-
implementation difficulties, etc.).
682-
-->
675+
N/A
683676

684677
### Dependencies
685678

@@ -735,14 +728,6 @@ No.
735728

736729
###### Will enabling / using this feature result in increasing time taken by any operations covered by existing SLIs/SLOs?
737730

738-
<!--
739-
Look at the [existing SLIs/SLOs].
740-
741-
Think about adding additional work or introducing new steps in between
742-
(e.g. need to do X to start a container), etc. Please describe the details.
743-
744-
[existing SLIs/SLOs]: https://git.k8s.io/community/sig-scalability/slos/slos.md#kubernetes-slisslos
745-
-->
746731
No.
747732

748733
###### Will enabling / using this feature result in non-negligible increase of resource usage (CPU, RAM, disk, IO, ...) in any components?
@@ -807,6 +792,16 @@ What other approaches did you consider, and why did you rule them out? These do
807792
not need to be as detailed as the proposal, but should include enough
808793
information to express the idea and why it was not acceptable.
809794
-->
795+
Instead of filtering log stream on the server side, we could return a stream of CRI-format logs,
796+
something like the following:
797+
```
798+
2016-10-06T00:17:09.669794202Z stdout P log content 1
799+
2016-10-06T00:17:09.669794203Z stderr F log content 2
800+
```
801+
so that we could demultiplex the log stream on the client side.
802+
803+
The main drawback of this approach is that we change the format of the log stream and break backward compatibility,
804+
there is extra overhead to demultiplex the stream on the client side.
810805

811806
## Infrastructure Needed (Optional)
812807

0 commit comments

Comments
 (0)