Skip to content

Commit 3052f36

Browse files
joelsmithmfojtik
authored andcommitted
UPSTREAM: 52503: Get fallback termination msg from docker when using journald log driver
When using the legacy docker container runtime and when a container has terminationMessagePolicy=FallbackToLogsOnError and when docker is configured with a log driver other than json-log (such as journald), the kubelet should not try to get the container's log from the json log file (since it's not there) but should instead ask docker for the logs.
1 parent 0b7ce15 commit 3052f36

File tree

5 files changed

+59
-2
lines changed

5 files changed

+59
-2
lines changed

pkg/kubelet/dockershim/BUILD

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ go_library(
5959
"//pkg/util/hash:go_default_library",
6060
"//pkg/util/parsers:go_default_library",
6161
"//pkg/util/term:go_default_library",
62+
"//vendor/github.com/armon/circbuf:go_default_library",
6263
"//vendor/github.com/blang/semver:go_default_library",
6364
"//vendor/github.com/docker/docker/api/types:go_default_library",
6465
"//vendor/github.com/docker/docker/api/types/container:go_default_library",
@@ -69,6 +70,7 @@ go_library(
6970
"//vendor/github.com/golang/glog:go_default_library",
7071
"//vendor/k8s.io/api/core/v1:go_default_library",
7172
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
73+
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
7274
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
7375
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
7476
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",

pkg/kubelet/dockershim/docker_service.go

+32
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ import (
2424
"sync"
2525
"time"
2626

27+
"github.com/armon/circbuf"
2728
"github.com/blang/semver"
2829
dockertypes "github.com/docker/docker/api/types"
2930
"github.com/golang/glog"
3031

3132
"k8s.io/api/core/v1"
3233
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34+
kubetypes "k8s.io/apimachinery/pkg/types"
3335
internalapi "k8s.io/kubernetes/pkg/kubelet/apis/cri"
3436
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
3537
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
@@ -524,6 +526,36 @@ func (d *dockerLegacyService) GetContainerLogs(pod *v1.Pod, containerID kubecont
524526
return d.client.Logs(containerID.ID, opts, sopts)
525527
}
526528

529+
// LegacyLogProvider implements the kuberuntime.LegacyLogProvider interface
530+
type LegacyLogProvider struct {
531+
dls DockerLegacyService
532+
}
533+
534+
func NewLegacyLogProvider(dls DockerLegacyService) LegacyLogProvider {
535+
return LegacyLogProvider{dls: dls}
536+
}
537+
538+
// GetContainerLogTail attempts to read up to MaxContainerTerminationMessageLogLength
539+
// from the end of the log when docker is configured with a log driver other than json-log.
540+
// It reads up to MaxContainerTerminationMessageLogLines lines.
541+
func (l LegacyLogProvider) GetContainerLogTail(uid kubetypes.UID, name, namespace string, containerId kubecontainer.ContainerID) (string, error) {
542+
value := int64(kubecontainer.MaxContainerTerminationMessageLogLines)
543+
buf, _ := circbuf.NewBuffer(kubecontainer.MaxContainerTerminationMessageLogLength)
544+
// Although this is not a full spec pod, dockerLegacyService.GetContainerLogs() currently completely ignores its pod param
545+
pod := &v1.Pod{
546+
ObjectMeta: metav1.ObjectMeta{
547+
UID: uid,
548+
Name: name,
549+
Namespace: namespace,
550+
},
551+
}
552+
err := l.dls.GetContainerLogs(pod, containerId, &v1.PodLogOptions{TailLines: &value}, buf, buf)
553+
if err != nil {
554+
return "", err
555+
}
556+
return buf.String(), nil
557+
}
558+
527559
// criSupportedLogDrivers are log drivers supported by native CRI integration.
528560
var criSupportedLogDrivers = []string{"json-file"}
529561

pkg/kubelet/kubelet.go

+4
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,8 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
582582
// It's easier to always probe and initialize plugins till cri
583583
// becomes the default.
584584
klet.networkPlugin = nil
585+
// if left at nil, that means it is unneeded
586+
var legacyLogProvider kuberuntime.LegacyLogProvider
585587

586588
switch kubeCfg.ContainerRuntime {
587589
case kubetypes.DockerContainerRuntime:
@@ -617,6 +619,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
617619
}
618620
if !supported {
619621
klet.dockerLegacyService = dockershim.NewDockerLegacyService(kubeDeps.DockerClient)
622+
legacyLogProvider = dockershim.NewLegacyLogProvider(klet.dockerLegacyService)
620623
}
621624
case kubetypes.RemoteContainerRuntime:
622625
// No-op.
@@ -647,6 +650,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
647650
runtimeService,
648651
imageService,
649652
kubeDeps.ContainerManager.InternalContainerLifecycle(),
653+
legacyLogProvider,
650654
)
651655
if err != nil {
652656
return nil, err

pkg/kubelet/kuberuntime/kuberuntime_container.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,16 @@ func (m *kubeGenericRuntimeManager) getPodContainerStatuses(uid kubetypes.UID, n
425425
fallbackToLogs := annotatedInfo.TerminationMessagePolicy == v1.TerminationMessageFallbackToLogsOnError && cStatus.ExitCode != 0
426426
tMessage, checkLogs := getTerminationMessage(status, annotatedInfo.TerminationMessagePath, fallbackToLogs)
427427
if checkLogs {
428-
path := buildFullContainerLogsPath(uid, labeledInfo.ContainerName, annotatedInfo.RestartCount)
429-
tMessage = m.readLastStringFromContainerLogs(path)
428+
// if dockerLegacyService is populated, we're supposed to use it to fetch logs
429+
if m.legacyLogProvider != nil {
430+
tMessage, err = m.legacyLogProvider.GetContainerLogTail(uid, name, namespace, kubecontainer.ContainerID{Type: m.runtimeName, ID: c.Id})
431+
if err != nil {
432+
tMessage = fmt.Sprintf("Error reading termination message from logs: %v", err)
433+
}
434+
} else {
435+
path := buildFullContainerLogsPath(uid, labeledInfo.ContainerName, annotatedInfo.RestartCount)
436+
tMessage = m.readLastStringFromContainerLogs(path)
437+
}
430438
}
431439
// Use the termination message written by the application is not empty
432440
if len(tMessage) != 0 {

pkg/kubelet/kuberuntime/kuberuntime_manager.go

+11
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ type kubeGenericRuntimeManager struct {
113113

114114
// Internal lifecycle event handlers for container resource management.
115115
internalLifecycle cm.InternalContainerLifecycle
116+
117+
// A shim to legacy functions for backward compatibility.
118+
legacyLogProvider LegacyLogProvider
116119
}
117120

118121
type KubeGenericRuntime interface {
@@ -121,6 +124,12 @@ type KubeGenericRuntime interface {
121124
kubecontainer.ContainerCommandRunner
122125
}
123126

127+
// LegacyLogProvider gives the ability to use unsupported docker log drivers (e.g. journald)
128+
type LegacyLogProvider interface {
129+
// Get the last few lines of the logs for a specific container.
130+
GetContainerLogTail(uid kubetypes.UID, name, namespace string, containerID kubecontainer.ContainerID) (string, error)
131+
}
132+
124133
// NewKubeGenericRuntimeManager creates a new kubeGenericRuntimeManager
125134
func NewKubeGenericRuntimeManager(
126135
recorder record.EventRecorder,
@@ -140,6 +149,7 @@ func NewKubeGenericRuntimeManager(
140149
runtimeService internalapi.RuntimeService,
141150
imageService internalapi.ImageManagerService,
142151
internalLifecycle cm.InternalContainerLifecycle,
152+
legacyLogProvider LegacyLogProvider,
143153
) (KubeGenericRuntime, error) {
144154
kubeRuntimeManager := &kubeGenericRuntimeManager{
145155
recorder: recorder,
@@ -154,6 +164,7 @@ func NewKubeGenericRuntimeManager(
154164
imageService: newInstrumentedImageManagerService(imageService),
155165
keyring: credentialprovider.NewDockerKeyring(),
156166
internalLifecycle: internalLifecycle,
167+
legacyLogProvider: legacyLogProvider,
157168
}
158169

159170
typedVersion, err := kubeRuntimeManager.runtimeService.Version(kubeRuntimeAPIVersion)

0 commit comments

Comments
 (0)