diff --git a/pkg/kubelet/dockershim/docker_service.go b/pkg/kubelet/dockershim/docker_service.go index 2551b6f58f6..f48d8b1972f 100644 --- a/pkg/kubelet/dockershim/docker_service.go +++ b/pkg/kubelet/dockershim/docker_service.go @@ -18,6 +18,7 @@ package dockershim import ( "fmt" + "io" "net/http" "time" @@ -416,3 +417,46 @@ func toAPIProtocol(protocol Protocol) v1.Protocol { glog.Warningf("Unknown protocol %q: defaulting to TCP", protocol) return v1.ProtocolTCP } + +// DockerLegacyService interface embeds some legacy methods for backward compatibility. +type DockerLegacyService interface { + // GetContainerLogs gets logs for a specific container. + GetContainerLogs(*v1.Pod, kubecontainer.ContainerID, *v1.PodLogOptions, io.Writer, io.Writer) error +} + +// dockerLegacyService implements the DockerLegacyService. We add this for non json-log driver +// support. (See #41996) +type dockerLegacyService struct { + client dockertools.DockerInterface +} + +func NewDockerLegacyService(client dockertools.DockerInterface) DockerLegacyService { + return &dockerLegacyService{client: client} +} + +// GetContainerLogs get container logs directly from docker daemon. +func (d *dockerLegacyService) GetContainerLogs(pod *v1.Pod, containerID kubecontainer.ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error { + container, err := d.client.InspectContainer(containerID.ID) + if err != nil { + return err + } + return dockertools.GetContainerLogs(d.client, pod, containerID, logOptions, stdout, stderr, container.Config.Tty) +} + +// criSupportedLogDrivers are log drivers supported by native CRI integration. +var criSupportedLogDrivers = []string{"json-file"} + +// IsCRISupportedLogDriver checks whether the logging driver used by docker is +// suppoted by native CRI integration. +func IsCRISupportedLogDriver(client dockertools.DockerInterface) (bool, error) { + info, err := client.Info() + if err != nil { + return false, fmt.Errorf("failed to get docker info: %v", err) + } + for _, driver := range criSupportedLogDrivers { + if info.LoggingDriver == driver { + return true, nil + } + } + return false, nil +} diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 7107cc87d09..0ea11a92600 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -570,6 +570,15 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub if err := server.Start(); err != nil { return nil, err } + + // Create dockerLegacyService when the logging driver is not supported. + supported, err := dockershim.IsCRISupportedLogDriver(klet.dockerClient) + if err != nil { + return nil, err + } + if !supported { + klet.dockerLegacyService = dockershim.NewDockerLegacyService(klet.dockerClient) + } case "remote": // No-op. break @@ -1099,6 +1108,10 @@ type Kubelet struct { // GPU Manager gpuManager gpu.GPUManager + + // dockerLegacyService contains some legacy methods for backward compatibility. + // It should be set only when docker is using non json-file logging driver. + dockerLegacyService dockershim.DockerLegacyService } // setupDataDirs creates: diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index 16e792fd882..675c75e1f0e 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -1006,6 +1006,12 @@ func (kl *Kubelet) GetKubeletContainerLogs(podFullName, containerName string, lo return err } + if kl.dockerLegacyService != nil { + // dockerLegacyService should only be non-nil when we actually need it, so + // inject it into the runtimeService. + // TODO(random-liu): Remove this hack after deprecating unsupported log driver. + return kl.dockerLegacyService.GetContainerLogs(pod, containerID, logOptions, stdout, stderr) + } return kl.containerRuntime.GetContainerLogs(pod, containerID, logOptions, stdout, stderr) }