Kubelet: Use RepoDigest for ImageID when available

Previously, we used the docker config digest (also called "image ID"
by Docker) for the value of the `ImageID` field in the container status.
This was not particularly useful, since the config manifest is not
what's used to identify the image in a registry, which uses the manifest
digest instead.  Docker 1.12+ always populates the RepoDigests field
with the manifest digests, and Docker 1.10 and 1.11 populate it when
images are pulled by digest.

This commit changes `ImageID` to point to the the manifest digest when
available, using the prefix `docker-pullable://` (instead of
`docker://`)
pull/6/head
Solly Ross 2016-09-30 14:51:26 -04:00
parent b46dbbec1b
commit 135f87dc15
5 changed files with 87 additions and 1 deletions

View File

@ -43,6 +43,7 @@ import (
const (
PodInfraContainerName = leaky.PodInfraContainerName
DockerPrefix = "docker://"
DockerPullablePrefix = "docker-pullable://"
LogSuffix = "log"
ext4MaxFileNameLen = 255
)

View File

@ -397,11 +397,26 @@ func (dm *DockerManager) inspectContainer(id string, podName, podNamespace strin
parseTimestampError("FinishedAt", iResult.State.FinishedAt)
}
// default to the image ID, but try and inspect for the RepoDigests
imageID := DockerPrefix + iResult.Image
imgInspectResult, err := dm.client.InspectImageByID(iResult.Image)
if err != nil {
utilruntime.HandleError(fmt.Errorf("unable to inspect docker image %q while inspecting docker container %q: %v", containerName, iResult.Image, err))
} else {
if len(imgInspectResult.RepoDigests) > 1 {
glog.V(4).Infof("Container %q had more than one associated RepoDigest (%v), only using the first", containerName, imgInspectResult.RepoDigests)
}
if len(imgInspectResult.RepoDigests) > 0 {
imageID = DockerPullablePrefix + imgInspectResult.RepoDigests[0]
}
}
status := kubecontainer.ContainerStatus{
Name: containerName,
RestartCount: containerInfo.RestartCount,
Image: iResult.Config.Image,
ImageID: DockerPrefix + iResult.Image,
ImageID: imageID,
ID: kubecontainer.DockerID(id).ContainerID(),
ExitCode: iResult.State.ExitCode,
CreatedAt: createdAt,

View File

@ -86,6 +86,9 @@ func newClientWithVersionAndClock(version, apiVersion string, c clock.Clock) *Fa
Errors: make(map[string]error),
ContainerMap: make(map[string]*dockertypes.ContainerJSON),
Clock: c,
// default this to an empty result, so that we never have a nil non-error response from InspectImage
Image: &dockertypes.ImageInspect{},
}
}

View File

@ -0,0 +1,66 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package e2e_node
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/kubelet/dockertools"
"k8s.io/kubernetes/test/e2e/framework"
"github.com/davecgh/go-spew/spew"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = framework.KubeDescribe("ImageID", func() {
busyBoxImage := "gcr.io/google_containers/busybox@sha256:4bdd623e848417d96127e16037743f0cd8b528c026e9175e22a84f639eca58ff"
f := framework.NewDefaultFramework("image-id-test")
It("should be set to the manifest digest (from RepoDigests) when available", func() {
podDesc := &api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-with-repodigest",
},
Spec: api.PodSpec{
Containers: []api.Container{{
Name: "test",
Image: busyBoxImage,
Command: []string{"sh"},
}},
RestartPolicy: api.RestartPolicyNever,
},
}
pod := f.PodClient().Create(podDesc)
framework.ExpectNoError(framework.WaitTimeoutForPodNoLongerRunningInNamespace(
f.Client, pod.Name, f.Namespace.Name, "", framework.PodStartTimeout))
runningPod, err := f.PodClient().Get(pod.Name)
framework.ExpectNoError(err)
status := runningPod.Status
if len(status.ContainerStatuses) == 0 {
framework.Failf("Unexpected pod status; %s", spew.Sdump(status))
return
}
Expect(status.ContainerStatuses[0].ImageID).To(Equal(dockertools.DockerPullablePrefix + busyBoxImage))
})
})

View File

@ -41,6 +41,7 @@ var NodeImageWhiteList = sets.NewString(
"google/cadvisor:latest",
"gcr.io/google-containers/stress:v1",
"gcr.io/google_containers/busybox:1.24",
"gcr.io/google_containers/busybox@sha256:4bdd623e848417d96127e16037743f0cd8b528c026e9175e22a84f639eca58ff",
"gcr.io/google_containers/nginx-slim:0.7",
"gcr.io/google_containers/serve_hostname:v1.4",
"gcr.io/google_containers/netexec:1.7",