Skip to content
This repository was archived by the owner on Mar 9, 2022. It is now read-only.

Conversation

@Random-Liu
Copy link
Member

@Random-Liu Random-Liu commented May 5, 2018

Fixes #283.

This PR added a configuration max_container_log_size for configuring max container log line size. Log line longer than the size limit will be split into multiple lines.

@yujuhong

@Random-Liu Random-Liu added this to the v1.11 milestone May 5, 2018
@thaJeztah
Copy link
Member

I know user configurable buffer size has been a hot topic on dockerd; configuring a huge size can easily lead to memory issues if there's congestion; is that an issue here as well?

/cc @cpuguy83

@k8s-ci-robot
Copy link

@thaJeztah: GitHub didn't allow me to request PR reviews from the following users: cpuguy83.

Note that only containerd members and repo collaborators can review this PR, and authors cannot review their own PRs.

Details

In response to this:

I know user configurable buffer size has been a hot topic on dockerd; configuring a huge size can easily lead to memory issues if there's congestion; is that an issue here as well?

/cc @cpuguy83

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@Random-Liu
Copy link
Member Author

Random-Liu commented May 7, 2018

@thaJeztah The read buffer size is 4096 fixed for now. If there is no long line, the memory usage will be 4096 (fixed read buffer size); if there is, the memory usage grows once for the log line.

Since docker is a user facing tool, I agree that we may not want user to care about and configure this directly.

However, to Kubernetes, containerd and cri are just building block. And the configuration is just for system admin. They should be able to configure the behavior according to their system environment. For example, in GCP, stackdriver has a 100kb log length limit, we want the log generated by container runtime to match that limit.

Another solution of this is to do this in fluentd. We've thought about it, and https://github.com/fluent-plugins-nursery/fluent-plugin-concat can probably be used. However, since not everyone is using fluentd, we think that it is still better to make this configurable in container runtime instead.

Copy link
Member

@mikebrow mikebrow left a comment

Choose a reason for hiding this comment

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

See comments.

docs/config.md Outdated

# max_container_log_size is the maximum log line size in bytes for a container.
# Log line longer than the limit will be split into multiple lines. Negative
# value means no limit.
Copy link
Member

Choose a reason for hiding this comment

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

Wrt. negative value .. we might want to be more explicit about which negative value has no limit.. say -1

Copy link
Member Author

Choose a reason for hiding this comment

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

SGTM.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

t.Log("Create a container with log path")
defaultMaxSize := config.DefaultConfig().MaxContainerLogSize
shortLineCmd := fmt.Sprintf("i=0; while [ $i -lt %d ]; do printf %s; i=$((i+1)); done", defaultMaxSize-1, "a")
longLineCmd := fmt.Sprintf("i=0; while [ $i -lt %d ]; do printf %s; i=$((i+1)); done", defaultMaxSize+1, "b")
Copy link
Member

Choose a reason for hiding this comment

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

one short one long and one == to max?

Copy link
Member

Choose a reason for hiding this comment

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

I think if max is negative this test won't work right?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe run the bucket through with a few different sizes?

Copy link
Member Author

Choose a reason for hiding this comment

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

Will get this from Status function in CRI.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

EnableTLSStreaming bool `toml:"enable_tls_streaming" json:"enableTLSStreaming"`
// MaxContainerLogSize is the maximum log line size in bytes for a container.
// Log line longer than the limit will be split into multiple lines. Negative
// value means no limit.
Copy link
Member

Choose a reason for hiding this comment

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

see above comment on negative value..

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's make the description in the comment more accurate. This is not user facing anyway.

return nil, nil, errors.Wrap(err, "failed to start container stdout logger")
f, err := os.OpenFile(logPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0640)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to open log file")
Copy link
Member

Choose a reason for hiding this comment

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

failed to create / open log file

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

if stderrCh != nil {
<-stderrCh
}
logrus.Debugf("Finish redirecting log file %q, close it", logPath)
Copy link
Member

Choose a reason for hiding this comment

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

closing log file %q

Copy link
Member

Choose a reason for hiding this comment

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

if we're going to have a "closing" comment in debug probably should have an opening comment above on success from line 141..

Copy link
Member

Choose a reason for hiding this comment

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

though it might be better to just remove as this may just clutter up the debug log .. no?

Copy link
Member Author

Choose a reason for hiding this comment

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

The log here is to indicate the goroutine stops.

defer func() {
if err != nil {
stdout.Close()
f.Close()
Copy link
Member

Choose a reason for hiding this comment

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

in the error case I don't think we need to close "f" ...

Copy link
Member Author

Choose a reason for hiding this comment

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

Why not?

Copy link
Member

Choose a reason for hiding this comment

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

maybe I'm reading wrong but it looks like f didn't open if err != nil..

Copy link
Member Author

Choose a reason for hiding this comment

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

That error is checked before this defer.

Copy link
Member

Choose a reason for hiding this comment

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

exactly and the only way the function can return error (atm) is if it failed to open.. see "return" statements :-)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I thought about this for a while. We have this defer because we do return an error before in the code below, but the error is removed in this PR.

However, i decide to keep this defer to make sure we don't miss the close when we introduce an error in the code below in the future.

Copy link
Member

Choose a reason for hiding this comment

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

ok.. yeah that's true that it could become useful in the future..

}
}

func TestSerialWriteCloesr(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

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

/s/Cloesr/Closer/

Copy link
Member Author

Choose a reason for hiding this comment

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

Will do.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

@Random-Liu
Copy link
Member Author

@mikebrow Thanks for reviewing! Will address comments today.


func TestSerialWriteCloser(t *testing.T) {
const (
// Test 100 times to make sure it always pass.
Copy link
Member Author

Choose a reason for hiding this comment

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

100 --> 10

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

defer func() {
if err != nil {
stdout.Close()
f.Close()
Copy link
Member Author

Choose a reason for hiding this comment

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

That error is checked before this defer.

docs/config.md Outdated
# max_container_log_size is the maximum log line size in bytes for a container.
# Log line longer than the limit will be split into multiple lines. -1 means no
# limit.
max_container_log_size = 16384
Copy link
Member

Choose a reason for hiding this comment

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

Use max_container_log_line_size instead? It's longer but more accurate.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

pipeBufSize = 4096
// bufSize is the size of the read buffer.
bufSize = pipeBufSize - len(timestampFormat) - len(Stdout) - len(runtime.LogTagPartial) - 3 /*3 delimiter*/ - 1 /*eol*/
bufSize = 4096
Copy link
Member

Choose a reason for hiding this comment

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

nit: make it clear in the comment that these are bytes.

Copy link
Member

Choose a reason for hiding this comment

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

Rename this to defaultBufferSize to avoid confusion?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

logrus.WithError(err).Errorf("Fail to write %q log to log file %q", s, path)
}
// Continue on write error to drain the input.
if stop {
Copy link
Member

Choose a reason for hiding this comment

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

If there was an error draining the input, should you still break?

Copy link
Member Author

Choose a reason for hiding this comment

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

We've already drain the input. I just mean we should not return error if we fail to write one line, because we should continue draining the container output.

I put the comment in a wrong place. Updated.

switch {
case maxLen < 0:
// Always try reading the full line, if no max length limit.
fallthrough
Copy link
Member

Choose a reason for hiding this comment

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

Why fallthrough? Should this be break instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

Simplified and fixed the logic here.

@Random-Liu
Copy link
Member Author

@mikebrow @yujuhong Thanks for reviewing! Will try to address comments today.

@Random-Liu
Copy link
Member Author

Distracted by other things. Will address comments today.

@Random-Liu Random-Liu force-pushed the add-log-max-size branch 4 times, most recently from adb5824 to 37d7369 Compare June 13, 2018 01:25
@Random-Liu
Copy link
Member Author

@yujuhong @mikebrow Addressed comments.

Copy link
Member

@mikebrow mikebrow left a comment

Choose a reason for hiding this comment

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

/LGTM

require.Len(t, resultData, goroutine)
sort.Strings(resultData)
for i := 0; i < goroutine; i++ {
expected := strings.Repeat(strconv.Itoa(i), dataLen)
Copy link
Member

Choose a reason for hiding this comment

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

nit: make strings.Repeat(strconv.Itoa(i), dataLen) a function to reuse.

Copy link
Member Author

Choose a reason for hiding this comment

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

Will do.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

testCount = 10

goroutine = 10
dataLen = 100000 // larger than PIPE_BUF=4096
Copy link
Member

Choose a reason for hiding this comment

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

Does the same test fail if non-serial writer is used?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member Author

@Random-Liu Random-Liu Jun 14, 2018

Choose a reason for hiding this comment

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

It only has problem with old kernel. I can't reproduce this in my desktop. :)

Updated the comment to explain the use case.

Signed-off-by: Lantao Liu <[email protected]>
Signed-off-by: Lantao Liu <[email protected]>
@yujuhong
Copy link
Member

/lgtm

@Random-Liu Random-Liu merged commit e3d57d2 into containerd:master Jun 15, 2018
@Random-Liu Random-Liu deleted the add-log-max-size branch June 15, 2018 22:56
Random-Liu added a commit that referenced this pull request Jul 11, 2018
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.

5 participants