Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
de73e459
Commit
de73e459
authored
Nov 17, 2017
by
Lantao Liu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add constants in CRI.
parent
a82460d7
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
111 additions
and
71 deletions
+111
-71
constants.go
pkg/kubelet/apis/cri/v1alpha1/runtime/constants.go
+28
-0
BUILD
pkg/kubelet/kuberuntime/logs/BUILD
+1
-0
logs.go
pkg/kubelet/kuberuntime/logs/logs.go
+52
-58
logs_test.go
pkg/kubelet/kuberuntime/logs/logs_test.go
+30
-13
No files found.
pkg/kubelet/apis/cri/v1alpha1/runtime/constants.go
View file @
de73e459
...
@@ -25,3 +25,31 @@ const (
...
@@ -25,3 +25,31 @@ const (
// NetworkReady means the runtime network is up and ready to accept containers which require network.
// NetworkReady means the runtime network is up and ready to accept containers which require network.
NetworkReady
=
"NetworkReady"
NetworkReady
=
"NetworkReady"
)
)
// LogStreamType is the type of the stream in CRI container log.
type
LogStreamType
string
const
(
// Stdout is the stream type for stdout.
Stdout
LogStreamType
=
"stdout"
// Stderr is the stream type for stderr.
Stderr
LogStreamType
=
"stderr"
)
// LogTag is the tag of a log line in CRI container log.
// Currently defined log tags:
// * First tag: Partial/End - P/E.
// The field in the container log format can be extended to include multiple
// tags by using a delimiter, but changes should be rare. If it becomes clear
// that better extensibility is desired, a more extensible format (e.g., json)
// should be adopted as a replacement and/or addition.
type
LogTag
string
const
(
// LogTagPartial means the line is part of multiple lines.
LogTagPartial
LogTag
=
"P"
// LogTagFull means the line is a single full line or the end of multiple lines.
LogTagFull
LogTag
=
"F"
// LogTagDelimiter is the delimiter for different log tags.
LogTagDelimiter
=
":"
)
pkg/kubelet/kuberuntime/logs/BUILD
View file @
de73e459
...
@@ -22,6 +22,7 @@ go_test(
...
@@ -22,6 +22,7 @@ go_test(
importpath = "k8s.io/kubernetes/pkg/kubelet/kuberuntime/logs",
importpath = "k8s.io/kubernetes/pkg/kubelet/kuberuntime/logs",
library = ":go_default_library",
library = ":go_default_library",
deps = [
deps = [
"//pkg/kubelet/apis/cri/v1alpha1/runtime:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
...
...
pkg/kubelet/kuberuntime/logs/logs.go
View file @
de73e459
...
@@ -45,13 +45,7 @@ import (
...
@@ -45,13 +45,7 @@ import (
// * If the rotation is using copytruncate, we'll be reading at the original position and get nothing.
// * If the rotation is using copytruncate, we'll be reading at the original position and get nothing.
// TODO(random-liu): Support log rotation.
// TODO(random-liu): Support log rotation.
// streamType is the type of the stream.
type
streamType
string
const
(
const
(
stderrType
streamType
=
"stderr"
stdoutType
streamType
=
"stdout"
// timeFormat is the time format used in the log.
// timeFormat is the time format used in the log.
timeFormat
=
time
.
RFC3339Nano
timeFormat
=
time
.
RFC3339Nano
// blockSize is the block size used in tail.
// blockSize is the block size used in tail.
...
@@ -66,14 +60,16 @@ const (
...
@@ -66,14 +60,16 @@ const (
var
(
var
(
// eol is the end-of-line sign in the log.
// eol is the end-of-line sign in the log.
eol
=
[]
byte
{
'\n'
}
eol
=
[]
byte
{
'\n'
}
// delimiter is the delimiter for timestamp and streamtype in log line.
// delimiter is the delimiter for timestamp and stream
type in log line.
delimiter
=
[]
byte
{
' '
}
delimiter
=
[]
byte
{
' '
}
// tagDelimiter is the delimiter for log tags.
tagDelimiter
=
[]
byte
(
runtimeapi
.
LogTagDelimiter
)
)
)
// logMessage is the CRI internal log type.
// logMessage is the CRI internal log type.
type
logMessage
struct
{
type
logMessage
struct
{
timestamp
time
.
Time
timestamp
time
.
Time
stream
s
treamType
stream
runtimeapi
.
LogS
treamType
log
[]
byte
log
[]
byte
}
}
...
@@ -126,8 +122,8 @@ var parseFuncs = []parseFunc{
...
@@ -126,8 +122,8 @@ var parseFuncs = []parseFunc{
}
}
// parseCRILog parses logs in CRI log format. CRI Log format example:
// parseCRILog parses logs in CRI log format. CRI Log format example:
// 2016-10-06T00:17:09.669794202Z stdout log content 1
// 2016-10-06T00:17:09.669794202Z stdout
P
log content 1
// 2016-10-06T00:17:09.669794203Z stderr log content 2
// 2016-10-06T00:17:09.669794203Z stderr
F
log content 2
func
parseCRILog
(
log
[]
byte
,
msg
*
logMessage
)
error
{
func
parseCRILog
(
log
[]
byte
,
msg
*
logMessage
)
error
{
var
err
error
var
err
error
// Parse timestamp
// Parse timestamp
...
@@ -146,11 +142,25 @@ func parseCRILog(log []byte, msg *logMessage) error {
...
@@ -146,11 +142,25 @@ func parseCRILog(log []byte, msg *logMessage) error {
if
idx
<
0
{
if
idx
<
0
{
return
fmt
.
Errorf
(
"stream type is not found"
)
return
fmt
.
Errorf
(
"stream type is not found"
)
}
}
msg
.
stream
=
s
treamType
(
log
[
:
idx
])
msg
.
stream
=
runtimeapi
.
LogS
treamType
(
log
[
:
idx
])
if
msg
.
stream
!=
stdoutType
&&
msg
.
stream
!=
stderrType
{
if
msg
.
stream
!=
runtimeapi
.
Stdout
&&
msg
.
stream
!=
runtimeapi
.
Stderr
{
return
fmt
.
Errorf
(
"unexpected stream type %q"
,
msg
.
stream
)
return
fmt
.
Errorf
(
"unexpected stream type %q"
,
msg
.
stream
)
}
}
// Parse log tag
log
=
log
[
idx
+
1
:
]
idx
=
bytes
.
Index
(
log
,
delimiter
)
if
idx
<
0
{
return
fmt
.
Errorf
(
"log tag is not found"
)
}
// Keep this forward compatible.
tags
:=
bytes
.
Split
(
log
[
:
idx
],
tagDelimiter
)
partial
:=
(
runtimeapi
.
LogTag
(
tags
[
0
])
==
runtimeapi
.
LogTagPartial
)
// Trim the tailing new line if this is a partial line.
if
partial
&&
len
(
log
)
>
0
&&
log
[
len
(
log
)
-
1
]
==
'\n'
{
log
=
log
[
:
len
(
log
)
-
1
]
}
// Get log content
// Get log content
msg
.
log
=
log
[
idx
+
1
:
]
msg
.
log
=
log
[
idx
+
1
:
]
...
@@ -170,7 +180,7 @@ func parseDockerJSONLog(log []byte, msg *logMessage) error {
...
@@ -170,7 +180,7 @@ func parseDockerJSONLog(log []byte, msg *logMessage) error {
return
fmt
.
Errorf
(
"failed with %v to unmarshal log %q"
,
err
,
l
)
return
fmt
.
Errorf
(
"failed with %v to unmarshal log %q"
,
err
,
l
)
}
}
msg
.
timestamp
=
l
.
Created
msg
.
timestamp
=
l
.
Created
msg
.
stream
=
s
treamType
(
l
.
Stream
)
msg
.
stream
=
runtimeapi
.
LogS
treamType
(
l
.
Stream
)
msg
.
log
=
[]
byte
(
l
.
Log
)
msg
.
log
=
[]
byte
(
l
.
Log
)
return
nil
return
nil
}
}
...
@@ -230,9 +240,9 @@ func (w *logWriter) write(msg *logMessage) error {
...
@@ -230,9 +240,9 @@ func (w *logWriter) write(msg *logMessage) error {
// Get the proper stream to write to.
// Get the proper stream to write to.
var
stream
io
.
Writer
var
stream
io
.
Writer
switch
msg
.
stream
{
switch
msg
.
stream
{
case
stdoutType
:
case
runtimeapi
.
Stdout
:
stream
=
w
.
stdout
stream
=
w
.
stdout
case
stderrType
:
case
runtimeapi
.
Stderr
:
stream
=
w
.
stderr
stream
=
w
.
stderr
default
:
default
:
return
fmt
.
Errorf
(
"unexpected stream type %q"
,
msg
.
stream
)
return
fmt
.
Errorf
(
"unexpected stream type %q"
,
msg
.
stream
)
...
@@ -277,63 +287,47 @@ func ReadLogs(path, containerID string, opts *LogOptions, runtimeService interna
...
@@ -277,63 +287,47 @@ func ReadLogs(path, containerID string, opts *LogOptions, runtimeService interna
// Do not create watcher here because it is not needed if `Follow` is false.
// Do not create watcher here because it is not needed if `Follow` is false.
var
watcher
*
fsnotify
.
Watcher
var
watcher
*
fsnotify
.
Watcher
var
parse
parseFunc
var
parse
parseFunc
var
stop
bool
writer
:=
newLogWriter
(
stdout
,
stderr
,
opts
)
writer
:=
newLogWriter
(
stdout
,
stderr
,
opts
)
msg
:=
&
logMessage
{}
msg
:=
&
logMessage
{}
for
{
for
{
if
stop
{
glog
.
V
(
2
)
.
Infof
(
"Finish parsing log file %q"
,
path
)
return
nil
}
l
,
err
:=
r
.
ReadBytes
(
eol
[
0
])
l
,
err
:=
r
.
ReadBytes
(
eol
[
0
])
if
err
!=
nil
{
if
err
!=
nil
{
if
err
!=
io
.
EOF
{
// This is an real error
if
err
!=
io
.
EOF
{
// This is an real error
return
fmt
.
Errorf
(
"failed to read log file %q: %v"
,
path
,
err
)
return
fmt
.
Errorf
(
"failed to read log file %q: %v"
,
path
,
err
)
}
}
if
!
opts
.
follow
{
if
opts
.
follow
{
// Return directly when reading to the end if not follow.
// Reset seek so that if this is an incomplete line,
if
len
(
l
)
>
0
{
// it will be read again.
glog
.
Warningf
(
"Incomplete line in log file %q: %q"
,
path
,
l
)
if
_
,
err
:=
f
.
Seek
(
-
int64
(
len
(
l
)),
os
.
SEEK_CUR
);
err
!=
nil
{
if
parse
==
nil
{
return
fmt
.
Errorf
(
"failed to reset seek in log file %q: %v"
,
path
,
err
)
// Intialize the log parsing function.
}
parse
,
err
=
getParseFunc
(
l
)
if
watcher
==
nil
{
if
err
!=
nil
{
// Intialize the watcher if it has not been initialized yet.
return
fmt
.
Errorf
(
"failed to get parse function: %v"
,
err
)
if
watcher
,
err
=
fsnotify
.
NewWatcher
();
err
!=
nil
{
}
return
fmt
.
Errorf
(
"failed to create fsnotify watcher: %v"
,
err
)
}
// Log a warning and exit if we can't parse the partial line.
if
err
:=
parse
(
l
,
msg
);
err
!=
nil
{
glog
.
Warningf
(
"Failed with err %v when parsing partial line for log file %q: %q"
,
err
,
path
,
l
)
return
nil
}
}
// Write the log line into the stream.
defer
watcher
.
Close
()
if
err
:=
writer
.
write
(
msg
);
err
!=
nil
{
if
err
:=
watcher
.
Add
(
f
.
Name
());
err
!=
nil
{
if
err
==
errMaximumWrite
{
return
fmt
.
Errorf
(
"failed to watch file %q: %v"
,
f
.
Name
(),
err
)
glog
.
V
(
2
)
.
Infof
(
"Finish parsing log file %q, hit bytes limit %d(bytes)"
,
path
,
opts
.
bytes
)
return
nil
}
glog
.
Errorf
(
"Failed with err %v when writing partial log for log file %q: %+v"
,
err
,
path
,
msg
)
return
err
}
}
}
}
glog
.
V
(
2
)
.
Infof
(
"Finish parsing log file %q"
,
path
)
// Wait until the next log change.
return
nil
if
found
,
err
:=
waitLogs
(
containerID
,
watcher
,
runtimeService
);
!
found
{
}
return
err
// Reset seek so that if this is an incomplete line,
// it will be read again.
if
_
,
err
:=
f
.
Seek
(
-
int64
(
len
(
l
)),
os
.
SEEK_CUR
);
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to reset seek in log file %q: %v"
,
path
,
err
)
}
if
watcher
==
nil
{
// Intialize the watcher if it has not been initialized yet.
if
watcher
,
err
=
fsnotify
.
NewWatcher
();
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to create fsnotify watcher: %v"
,
err
)
}
defer
watcher
.
Close
()
if
err
:=
watcher
.
Add
(
f
.
Name
());
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to watch file %q: %v"
,
f
.
Name
(),
err
)
}
}
continue
}
}
// Wait until the next log change.
// Should stop after writing the remaining content.
if
found
,
err
:=
waitLogs
(
containerID
,
watcher
,
runtimeService
);
!
found
{
stop
=
true
return
err
if
len
(
l
)
==
0
{
continue
}
}
continue
glog
.
Warningf
(
"Incomplete line in log file %q: %q"
,
path
,
l
)
}
}
if
parse
==
nil
{
if
parse
==
nil
{
// Intialize the log parsing function.
// Intialize the log parsing function.
...
...
pkg/kubelet/kuberuntime/logs/logs_test.go
View file @
de73e459
...
@@ -25,6 +25,7 @@ import (
...
@@ -25,6 +25,7 @@ import (
"k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
runtimeapi
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
)
)
func
TestLogOptions
(
t
*
testing
.
T
)
{
func
TestLogOptions
(
t
*
testing
.
T
)
{
...
@@ -78,7 +79,7 @@ func TestParseLog(t *testing.T) {
...
@@ -78,7 +79,7 @@ func TestParseLog(t *testing.T) {
line
:
`{"log":"docker stdout test log","stream":"stdout","time":"2016-10-20T18:39:20.57606443Z"}`
+
"
\n
"
,
line
:
`{"log":"docker stdout test log","stream":"stdout","time":"2016-10-20T18:39:20.57606443Z"}`
+
"
\n
"
,
msg
:
&
logMessage
{
msg
:
&
logMessage
{
timestamp
:
timestamp
,
timestamp
:
timestamp
,
stream
:
stdoutType
,
stream
:
runtimeapi
.
Stdout
,
log
:
[]
byte
(
"docker stdout test log"
),
log
:
[]
byte
(
"docker stdout test log"
),
},
},
},
},
...
@@ -86,23 +87,23 @@ func TestParseLog(t *testing.T) {
...
@@ -86,23 +87,23 @@ func TestParseLog(t *testing.T) {
line
:
`{"log":"docker stderr test log","stream":"stderr","time":"2016-10-20T18:39:20.57606443Z"}`
+
"
\n
"
,
line
:
`{"log":"docker stderr test log","stream":"stderr","time":"2016-10-20T18:39:20.57606443Z"}`
+
"
\n
"
,
msg
:
&
logMessage
{
msg
:
&
logMessage
{
timestamp
:
timestamp
,
timestamp
:
timestamp
,
stream
:
stderrType
,
stream
:
runtimeapi
.
Stderr
,
log
:
[]
byte
(
"docker stderr test log"
),
log
:
[]
byte
(
"docker stderr test log"
),
},
},
},
},
{
// CRI log format stdout
{
// CRI log format stdout
line
:
"2016-10-20T18:39:20.57606443Z stdout cri stdout test log
\n
"
,
line
:
"2016-10-20T18:39:20.57606443Z stdout
F
cri stdout test log
\n
"
,
msg
:
&
logMessage
{
msg
:
&
logMessage
{
timestamp
:
timestamp
,
timestamp
:
timestamp
,
stream
:
stdoutType
,
stream
:
runtimeapi
.
Stdout
,
log
:
[]
byte
(
"cri stdout test log
\n
"
),
log
:
[]
byte
(
"cri stdout test log
\n
"
),
},
},
},
},
{
// CRI log format stderr
{
// CRI log format stderr
line
:
"2016-10-20T18:39:20.57606443Z stderr cri stderr test log
\n
"
,
line
:
"2016-10-20T18:39:20.57606443Z stderr
F
cri stderr test log
\n
"
,
msg
:
&
logMessage
{
msg
:
&
logMessage
{
timestamp
:
timestamp
,
timestamp
:
timestamp
,
stream
:
stderrType
,
stream
:
runtimeapi
.
Stderr
,
log
:
[]
byte
(
"cri stderr test log
\n
"
),
log
:
[]
byte
(
"cri stderr test log
\n
"
),
},
},
},
},
...
@@ -111,6 +112,22 @@ func TestParseLog(t *testing.T) {
...
@@ -111,6 +112,22 @@ func TestParseLog(t *testing.T) {
msg
:
&
logMessage
{},
msg
:
&
logMessage
{},
err
:
true
,
err
:
true
,
},
},
{
// Partial CRI log line
line
:
"2016-10-20T18:39:20.57606443Z stdout P cri stdout partial test log
\n
"
,
msg
:
&
logMessage
{
timestamp
:
timestamp
,
stream
:
runtimeapi
.
Stdout
,
log
:
[]
byte
(
"cri stdout partial test log"
),
},
},
{
// Partial CRI log line with multiple log tags.
line
:
"2016-10-20T18:39:20.57606443Z stdout P:TAG1:TAG2 cri stdout partial test log
\n
"
,
msg
:
&
logMessage
{
timestamp
:
timestamp
,
stream
:
runtimeapi
.
Stdout
,
log
:
[]
byte
(
"cri stdout partial test log"
),
},
},
}
{
}
{
t
.
Logf
(
"TestCase #%d: %+v"
,
c
,
test
)
t
.
Logf
(
"TestCase #%d: %+v"
,
c
,
test
)
parse
,
err
:=
getParseFunc
([]
byte
(
test
.
line
))
parse
,
err
:=
getParseFunc
([]
byte
(
test
.
line
))
...
@@ -130,26 +147,26 @@ func TestWriteLogs(t *testing.T) {
...
@@ -130,26 +147,26 @@ func TestWriteLogs(t *testing.T) {
log
:=
"abcdefg
\n
"
log
:=
"abcdefg
\n
"
for
c
,
test
:=
range
[]
struct
{
for
c
,
test
:=
range
[]
struct
{
stream
s
treamType
stream
runtimeapi
.
LogS
treamType
since
time
.
Time
since
time
.
Time
timestamp
bool
timestamp
bool
expectStdout
string
expectStdout
string
expectStderr
string
expectStderr
string
}{
}{
{
// stderr log
{
// stderr log
stream
:
stderrType
,
stream
:
runtimeapi
.
Stderr
,
expectStderr
:
log
,
expectStderr
:
log
,
},
},
{
// stdout log
{
// stdout log
stream
:
stdoutType
,
stream
:
runtimeapi
.
Stdout
,
expectStdout
:
log
,
expectStdout
:
log
,
},
},
{
// since is after timestamp
{
// since is after timestamp
stream
:
stdoutType
,
stream
:
runtimeapi
.
Stdout
,
since
:
timestamp
.
Add
(
1
*
time
.
Second
),
since
:
timestamp
.
Add
(
1
*
time
.
Second
),
},
},
{
// timestamp enabled
{
// timestamp enabled
stream
:
stderrType
,
stream
:
runtimeapi
.
Stderr
,
timestamp
:
true
,
timestamp
:
true
,
expectStderr
:
timestamp
.
Format
(
timeFormat
)
+
" "
+
log
,
expectStderr
:
timestamp
.
Format
(
timeFormat
)
+
" "
+
log
,
},
},
...
@@ -226,13 +243,13 @@ func TestWriteLogsWithBytesLimit(t *testing.T) {
...
@@ -226,13 +243,13 @@ func TestWriteLogsWithBytesLimit(t *testing.T) {
stderrBuf
:=
bytes
.
NewBuffer
(
nil
)
stderrBuf
:=
bytes
.
NewBuffer
(
nil
)
w
:=
newLogWriter
(
stdoutBuf
,
stderrBuf
,
&
LogOptions
{
timestamp
:
test
.
timestamp
,
bytes
:
int64
(
test
.
bytes
)})
w
:=
newLogWriter
(
stdoutBuf
,
stderrBuf
,
&
LogOptions
{
timestamp
:
test
.
timestamp
,
bytes
:
int64
(
test
.
bytes
)})
for
i
:=
0
;
i
<
test
.
stdoutLines
;
i
++
{
for
i
:=
0
;
i
<
test
.
stdoutLines
;
i
++
{
msg
.
stream
=
stdoutType
msg
.
stream
=
runtimeapi
.
Stdout
if
err
:=
w
.
write
(
msg
);
err
!=
nil
{
if
err
:=
w
.
write
(
msg
);
err
!=
nil
{
assert
.
EqualError
(
t
,
err
,
errMaximumWrite
.
Error
())
assert
.
EqualError
(
t
,
err
,
errMaximumWrite
.
Error
())
}
}
}
}
for
i
:=
0
;
i
<
test
.
stderrLines
;
i
++
{
for
i
:=
0
;
i
<
test
.
stderrLines
;
i
++
{
msg
.
stream
=
stderrType
msg
.
stream
=
runtimeapi
.
Stderr
if
err
:=
w
.
write
(
msg
);
err
!=
nil
{
if
err
:=
w
.
write
(
msg
);
err
!=
nil
{
assert
.
EqualError
(
t
,
err
,
errMaximumWrite
.
Error
())
assert
.
EqualError
(
t
,
err
,
errMaximumWrite
.
Error
())
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment