From fe70be9261d2834283869b0c9480f99c08d0f779 Mon Sep 17 00:00:00 2001 From: Yu-Ju Hong Date: Thu, 26 Feb 2015 12:27:14 -0800 Subject: [PATCH] kubelet: revamp the pod/container naming scheme There are two main goals for this change. 1. Fix the naming scheme in kubelet so that it accepts DNS subdomain name/namespaces correctly (#4920). The design is discussed in #3453. 2. Prepare for syncing the static pods back to the apiserver(#4090). This includes - Eliminate the source component in the internal full pod name (#4922). Pods no longer need sources as they will all be sync'd via apiserver. - Changing the naming scheme for the static (file-, http-, and etcd-based) pods such that they are distinguishable when syncing back to the apiserver. The changes includes: * name = - * namespace = (i.e. "default" for now). * container_name = k8s_.____ Note that this is not backward-compatible, meaning the kubelet won't recognize existing running containers using the old naming scheme. --- pkg/kubelet/config/config.go | 23 +-- pkg/kubelet/config/etcd.go | 7 +- pkg/kubelet/config/etcd_test.go | 14 +- pkg/kubelet/config/file.go | 18 +- pkg/kubelet/config/file_test.go | 59 ++++--- pkg/kubelet/config/http.go | 27 +-- pkg/kubelet/config/http_test.go | 19 ++- pkg/kubelet/dockertools/docker.go | 9 +- pkg/kubelet/dockertools/docker_test.go | 56 +++--- pkg/kubelet/kubelet.go | 2 + pkg/kubelet/kubelet_test.go | 225 ++++++++++++------------- pkg/kubelet/runonce_test.go | 9 +- pkg/kubelet/server_test.go | 34 ++-- pkg/kubelet/types.go | 11 +- 14 files changed, 265 insertions(+), 248 deletions(-) diff --git a/pkg/kubelet/config/config.go b/pkg/kubelet/config/config.go index 8c1e5ac59d..aa3c0b064f 100644 --- a/pkg/kubelet/config/config.go +++ b/pkg/kubelet/config/config.go @@ -18,6 +18,7 @@ package config import ( "fmt" + "os" "reflect" "sync" @@ -206,7 +207,7 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de filtered := filterInvalidPods(update.Pods, source, s.recorder) for _, ref := range filtered { - name := podUniqueName(ref) + name := kubelet.GetPodFullName(ref) if existing, found := pods[name]; found { if !reflect.DeepEqual(existing.Spec, ref.Spec) { // this is an update @@ -229,7 +230,7 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de case kubelet.REMOVE: glog.V(4).Infof("Removing a pod %v", update) for _, value := range update.Pods { - name := podUniqueName(&value) + name := kubelet.GetPodFullName(&value) if existing, found := pods[name]; found { // this is a delete delete(pods, name) @@ -248,7 +249,7 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de filtered := filterInvalidPods(update.Pods, source, s.recorder) for _, ref := range filtered { - name := podUniqueName(ref) + name := kubelet.GetPodFullName(ref) if existing, found := oldPods[name]; found { pods[name] = existing if !reflect.DeepEqual(existing.Spec, ref.Spec) { @@ -306,7 +307,7 @@ func filterInvalidPods(pods []api.BoundPod, source string, recorder record.Event // If validation fails, don't trust it any further - // even Name could be bad. } else { - name := podUniqueName(pod) + name := kubelet.GetPodFullName(pod) if names.Has(name) { errlist = append(errlist, apierrs.NewFieldDuplicate("name", pod.Name)) } else { @@ -349,12 +350,6 @@ func (s *podStorage) MergedState() interface{} { return pods } -// podUniqueName returns a value for a given pod that is unique across a source, -// which is the combination of namespace and name. -func podUniqueName(pod *api.BoundPod) string { - return fmt.Sprintf("%s.%s", pod.Name, pod.Namespace) -} - func bestPodIdentString(pod *api.BoundPod) string { namespace := pod.Namespace if namespace == "" { @@ -366,3 +361,11 @@ func bestPodIdentString(pod *api.BoundPod) string { } return fmt.Sprintf("%s.%s", name, namespace) } + +func GeneratePodName(name string) (string, error) { + hostname, err := os.Hostname() //TODO: kubelet name would be better + if err != nil { + return "", err + } + return fmt.Sprintf("%s-%s", name, hostname), nil +} diff --git a/pkg/kubelet/config/etcd.go b/pkg/kubelet/config/etcd.go index e272d2fdf7..ec77388410 100644 --- a/pkg/kubelet/config/etcd.go +++ b/pkg/kubelet/config/etcd.go @@ -108,11 +108,8 @@ func eventToPods(ev watch.Event) ([]api.BoundPod, error) { } for _, pod := range boundPods.Items { - // Backwards compatibility with old api servers - // TODO: Remove this after 1.0 release. - if len(pod.Namespace) == 0 { - pod.Namespace = api.NamespaceDefault - } + // Always overrides the namespace provided by the etcd event. + pod.Namespace = kubelet.NamespaceDefault pods = append(pods, pod) } diff --git a/pkg/kubelet/config/etcd_test.go b/pkg/kubelet/config/etcd_test.go index 8debafe23f..12760593f2 100644 --- a/pkg/kubelet/config/etcd_test.go +++ b/pkg/kubelet/config/etcd_test.go @@ -102,8 +102,14 @@ func TestEventToPods(t *testing.T) { }, }, pods: []api.BoundPod{ - {ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "foo"}, Spec: api.PodSpec{}}, - {ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: "bar"}, Spec: api.PodSpec{}}, + { + ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: kubelet.NamespaceDefault}, + Spec: api.PodSpec{}, + }, + { + ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: kubelet.NamespaceDefault}, + Spec: api.PodSpec{}, + }, }, fail: false, }, @@ -116,7 +122,9 @@ func TestEventToPods(t *testing.T) { }, }, pods: []api.BoundPod{ - {ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "default"}, Spec: api.PodSpec{}}, + { + ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: kubelet.NamespaceDefault}, + Spec: api.PodSpec{}}, }, fail: false, }, diff --git a/pkg/kubelet/config/file.go b/pkg/kubelet/config/file.go index a53b826235..c082c1832d 100644 --- a/pkg/kubelet/config/file.go +++ b/pkg/kubelet/config/file.go @@ -21,7 +21,6 @@ import ( "crypto/md5" "encoding/hex" "fmt" - "hash/adler32" "io/ioutil" "os" "path/filepath" @@ -186,17 +185,16 @@ func extractFromFile(filename string) (api.BoundPod, error) { // completely deprecate ContainerManifest. if len(pod.Name) == 0 { pod.Name = string(pod.UID) - glog.V(5).Infof("Generated Name %q for UID %q from file %s", pod.Name, pod.UID, filename) } - if len(pod.Namespace) == 0 { - hasher := adler32.New() - fmt.Fprint(hasher, filename) - // TODO: file-.hostname would be better, if DNS subdomains - // are allowed for namespace (some places only allow DNS - // labels). - pod.Namespace = fmt.Sprintf("file-%08x-%s", hasher.Sum32(), hostname) - glog.V(5).Infof("Generated namespace %q for pod %q from file %s", pod.Namespace, pod.Name, filename) + if pod.Name, err = GeneratePodName(pod.Name); err != nil { + return pod, err } + glog.V(5).Infof("Generated Name %q for UID %q from file %s", pod.Name, pod.UID, filename) + + // Always overrides the namespace provided by the file. + pod.Namespace = kubelet.NamespaceDefault + glog.V(5).Infof("Using namespace %q for pod %q from file %s", pod.Namespace, pod.Name, filename) + // TODO(dchen1107): BoundPod is not type of runtime.Object. Once we allow kubelet talks // about Pod directly, we can use SelfLinker defined in package: latest // Currently just simply follow the same format in resthandler.go diff --git a/pkg/kubelet/config/file_test.go b/pkg/kubelet/config/file_test.go index 16777ec943..fd61bb7673 100644 --- a/pkg/kubelet/config/file_test.go +++ b/pkg/kubelet/config/file_test.go @@ -54,8 +54,9 @@ func ExampleManifestAndPod(id string) (v1beta1.ContainerManifest, api.BoundPod) } expectedPod := api.BoundPod{ ObjectMeta: api.ObjectMeta{ - Name: id, - UID: types.UID(id), + Name: id, + UID: types.UID(id), + Namespace: kubelet.NamespaceDefault, }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -131,27 +132,30 @@ func TestReadFromFile(t *testing.T) { update := got.(kubelet.PodUpdate) expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.BoundPod{ ObjectMeta: api.ObjectMeta{ - Name: "test", + Name: "", UID: "12345", - Namespace: "", + Namespace: kubelet.NamespaceDefault, SelfLink: "", }, Spec: api.PodSpec{Containers: []api.Container{{Image: "test/image"}}}, }) + if !strings.HasPrefix(update.Pods[0].Name, "test-") { + t.Errorf("Unexpected name: %s", update.Pods[0].Name) + } // There's no way to provide namespace in ContainerManifest, so // it will be defaulted. - if !strings.HasPrefix(update.Pods[0].ObjectMeta.Namespace, "file-") { - t.Errorf("Unexpected namespace: %s", update.Pods[0].ObjectMeta.Namespace) + if update.Pods[0].Namespace != kubelet.NamespaceDefault { + t.Errorf("Unexpected namespace: %s", update.Pods[0].Namespace) } - update.Pods[0].ObjectMeta.Namespace = "" - // SelfLink depends on namespace. - if !strings.HasPrefix(update.Pods[0].ObjectMeta.SelfLink, "/api/") { - t.Errorf("Unexpected selflink: %s", update.Pods[0].ObjectMeta.SelfLink) + if !strings.HasPrefix(update.Pods[0].SelfLink, "/api/") { + t.Errorf("Unexpected selflink: %s", update.Pods[0].SelfLink) } - update.Pods[0].ObjectMeta.SelfLink = "" + // Reset the fileds that we don't want to compare. + update.Pods[0].Name = "" + update.Pods[0].SelfLink = "" if !api.Semantic.DeepDerivative(expected, update) { t.Fatalf("Expected %#v, Got %#v", expected, update) } @@ -179,7 +183,7 @@ func TestReadFromFileWithoutID(t *testing.T) { ObjectMeta: api.ObjectMeta{ Name: "", UID: "12345", - Namespace: "", + Namespace: kubelet.NamespaceDefault, SelfLink: "", }, Spec: api.PodSpec{Containers: []api.Container{{Image: "test/image"}}}, @@ -188,10 +192,9 @@ func TestReadFromFileWithoutID(t *testing.T) { if len(update.Pods[0].ObjectMeta.Name) == 0 { t.Errorf("Name did not get defaulted") } - update.Pods[0].ObjectMeta.Name = "" - update.Pods[0].ObjectMeta.Namespace = "" - update.Pods[0].ObjectMeta.SelfLink = "" - + // Reset the fileds that we don't want to compare. + update.Pods[0].Name = "" + update.Pods[0].SelfLink = "" if !api.Semantic.DeepDerivative(expected, update) { t.Fatalf("Expected %#v, Got %#v", expected, update) } @@ -218,17 +221,17 @@ func TestReadV1Beta2FromFile(t *testing.T) { update := got.(kubelet.PodUpdate) expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.BoundPod{ ObjectMeta: api.ObjectMeta{ - Name: "test", + Name: "", UID: "12345", - Namespace: "", + Namespace: kubelet.NamespaceDefault, SelfLink: "", }, Spec: api.PodSpec{Containers: []api.Container{{Image: "test/image"}}}, }) - update.Pods[0].ObjectMeta.Namespace = "" - update.Pods[0].ObjectMeta.SelfLink = "" - + // Reset the fileds that we don't want to compare. + update.Pods[0].Name = "" + update.Pods[0].SelfLink = "" if !api.Semantic.DeepDerivative(expected, update) { t.Fatalf("Expected %#v, Got %#v", expected, update) } @@ -252,8 +255,8 @@ func TestReadFromFileWithDefaults(t *testing.T) { select { case got := <-ch: update := got.(kubelet.PodUpdate) - if update.Pods[0].ObjectMeta.UID == "" { - t.Errorf("Unexpected UID: %s", update.Pods[0].ObjectMeta.UID) + if update.Pods[0].UID == "" { + t.Errorf("Unexpected UID: %s", update.Pods[0].UID) } case <-time.After(time.Second): @@ -337,12 +340,16 @@ func TestExtractFromDir(t *testing.T) { update := (<-ch).(kubelet.PodUpdate) for i := range update.Pods { - update.Pods[i].Namespace = "foobar" + // Pod name is generated with hash and is unique. Skip the comparision + // here by setting it to a simple value. + update.Pods[i].Name = manifests[i].ID update.Pods[i].SelfLink = "" } expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, pods...) for i := range expected.Pods { - expected.Pods[i].Namespace = "foobar" + // Pod name is generated with hash and is unique. Skip the comparision + // here by setting it to a simple value. + expected.Pods[i].Name = manifests[i].ID } sort.Sort(sortedPods(update.Pods)) sort.Sort(sortedPods(expected.Pods)) @@ -351,7 +358,7 @@ func TestExtractFromDir(t *testing.T) { } for i := range update.Pods { if errs := validation.ValidateBoundPod(&update.Pods[i]); len(errs) != 0 { - t.Errorf("Expected no validation errors on %#v, Got %#v", update.Pods[i], errs) + t.Errorf("Expected no validation errors on %#v, Got %q", update.Pods[i], errs) } } } diff --git a/pkg/kubelet/config/http.go b/pkg/kubelet/config/http.go index fb30489e86..5f7d1db8fc 100644 --- a/pkg/kubelet/config/http.go +++ b/pkg/kubelet/config/http.go @@ -22,7 +22,6 @@ import ( "crypto/md5" "encoding/hex" "fmt" - "hash/adler32" "io/ioutil" "net/http" "time" @@ -92,7 +91,9 @@ func (s *sourceURL) extractFromURL() error { return singleErr } // It parsed! - applyDefaults(&pod, s.url) + if err = applyDefaults(&pod, s.url); err != nil { + return err + } s.updates <- kubelet.PodUpdate{[]api.BoundPod{pod}, kubelet.SET, kubelet.HTTPSource} return nil } @@ -114,7 +115,9 @@ func (s *sourceURL) extractFromURL() error { // Assume it parsed. for i := range pods.Items { pod := &pods.Items[i] - applyDefaults(pod, s.url) + if err = applyDefaults(pod, s.url); err != nil { + return err + } } s.updates <- kubelet.PodUpdate{pods.Items, kubelet.SET, kubelet.HTTPSource} return nil @@ -180,7 +183,7 @@ func tryDecodeList(data []byte) (parsed bool, manifests []v1beta1.ContainerManif return true, manifests, pods, nil } -func applyDefaults(pod *api.BoundPod, url string) { +func applyDefaults(pod *api.BoundPod, url string) error { if len(pod.UID) == 0 { hasher := md5.New() fmt.Fprintf(hasher, "url:%s", url) @@ -190,14 +193,18 @@ func applyDefaults(pod *api.BoundPod, url string) { } // This is required for backward compatibility, and should be removed once we // completely deprecate ContainerManifest. + var err error if len(pod.Name) == 0 { pod.Name = string(pod.UID) - glog.V(5).Infof("Generate Name %q from UID %q from URL %s", pod.Name, pod.UID, url) } - if len(pod.Namespace) == 0 { - hasher := adler32.New() - fmt.Fprint(hasher, url) - pod.Namespace = fmt.Sprintf("url-%08x", hasher.Sum32()) - glog.V(5).Infof("Generated namespace %q for pod %q from URL %s", pod.Namespace, pod.Name, url) + pod.Name, err = GeneratePodName(pod.Name) + if err != nil { + return err } + glog.V(5).Infof("Generated Name %q for UID %q from URL %s", pod.Name, pod.UID, url) + + // Always overrides the namespace. + pod.Namespace = kubelet.NamespaceDefault + glog.V(5).Infof("Using namespace %q for pod %q from URL %s", pod.Namespace, pod.Name, url) + return nil } diff --git a/pkg/kubelet/config/http_test.go b/pkg/kubelet/config/http_test.go index 5036ab55db..b804b33bfc 100644 --- a/pkg/kubelet/config/http_test.go +++ b/pkg/kubelet/config/http_test.go @@ -19,7 +19,7 @@ package config import ( "encoding/json" "net/http/httptest" - "strings" + "os" "testing" "time" @@ -117,6 +117,8 @@ func TestExtractInvalidManifest(t *testing.T) { } func TestExtractFromHTTP(t *testing.T) { + hostname, _ := os.Hostname() + var testCases = []struct { desc string manifests interface{} @@ -131,7 +133,7 @@ func TestExtractFromHTTP(t *testing.T) { api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "111", - Name: "foo", + Name: "foo" + "-" + hostname, Namespace: "foobar", }, Spec: api.PodSpec{ @@ -153,7 +155,7 @@ func TestExtractFromHTTP(t *testing.T) { api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "111", - Name: "111", + Name: "111" + "-" + hostname, Namespace: "foobar", }, Spec: api.PodSpec{ @@ -171,7 +173,7 @@ func TestExtractFromHTTP(t *testing.T) { api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "111", - Name: "foo", + Name: "foo" + "-" + hostname, Namespace: "foobar", }, Spec: api.PodSpec{ @@ -198,7 +200,7 @@ func TestExtractFromHTTP(t *testing.T) { api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "111", - Name: "foo", + Name: "foo" + "-" + hostname, Namespace: "foobar", }, Spec: api.PodSpec{ @@ -214,7 +216,7 @@ func TestExtractFromHTTP(t *testing.T) { api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "222", - Name: "bar", + Name: "bar" + "-" + hostname, Namespace: "foobar", }, Spec: api.PodSpec{ @@ -234,6 +236,7 @@ func TestExtractFromHTTP(t *testing.T) { expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource), }, } + for _, testCase := range testCases { data, err := json.Marshal(testCase.manifests) if err != nil { @@ -256,8 +259,8 @@ func TestExtractFromHTTP(t *testing.T) { for i := range update.Pods { // There's no way to provide namespace in ContainerManifest, so // it will be defaulted. - if !strings.HasPrefix(update.Pods[i].ObjectMeta.Namespace, "url-") { - t.Errorf("Unexpected namespace: %s", update.Pods[0].ObjectMeta.Namespace) + if update.Pods[i].Namespace != kubelet.NamespaceDefault { + t.Errorf("Unexpected namespace: %s", update.Pods[0].Namespace) } update.Pods[i].ObjectMeta.Namespace = "foobar" } diff --git a/pkg/kubelet/dockertools/docker.go b/pkg/kubelet/dockertools/docker.go index 1b536b0617..9f63b7fff0 100644 --- a/pkg/kubelet/dockertools/docker.go +++ b/pkg/kubelet/dockertools/docker.go @@ -719,11 +719,11 @@ func ParseDockerName(name string) (podFullName string, podUID types.UID, contain if len(parts) == 0 || parts[0] != containerNamePrefix { return } - if len(parts) < 5 { + if len(parts) < 6 { // We have at least 5 fields. We may have more in the future. // Anything with less fields than this is not something we can // manage. - glog.Warningf("found a container with the %q prefix, but too few fields (%d): ", containerNamePrefix, len(parts), name) + glog.Warningf("found a container with the %q prefix, but too few fields (%d): %q", containerNamePrefix, len(parts), name) return } @@ -739,11 +739,10 @@ func ParseDockerName(name string) (podFullName string, podUID types.UID, contain } // Pod fullname. - podFullName = parts[2] + podFullName = parts[2] + "_" + parts[3] // Pod UID. - podUID = types.UID(parts[3]) - + podUID = types.UID(parts[4]) return } diff --git a/pkg/kubelet/dockertools/docker_test.go b/pkg/kubelet/dockertools/docker_test.go index dde7f729e2..71baccdf4c 100644 --- a/pkg/kubelet/dockertools/docker_test.go +++ b/pkg/kubelet/dockertools/docker_test.go @@ -54,11 +54,11 @@ func TestGetContainerID(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { ID: "foobar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, { ID: "barbar", - Names: []string{"/k8s_bar_qux_2565_42"}, + Names: []string{"/k8s_bar_qux_ns_2565_42"}, }, } fakeDocker.Container = &docker.Container{ @@ -73,7 +73,7 @@ func TestGetContainerID(t *testing.T) { t.Errorf("Expected %#v, Got %#v", fakeDocker.ContainerList, dockerContainers) } verifyCalls(t, fakeDocker, []string{"list"}) - dockerContainer, found, _ := dockerContainers.FindPodContainer("qux", "", "foo") + dockerContainer, found, _ := dockerContainers.FindPodContainer("qux_ns", "", "foo") if dockerContainer == nil || !found { t.Errorf("Failed to find container %#v", dockerContainer) } @@ -91,7 +91,7 @@ func verifyPackUnpack(t *testing.T, podNamespace, podUID, podName, containerName hasher := adler32.New() util.DeepHashObject(hasher, *container) computedHash := uint64(hasher.Sum32()) - podFullName := fmt.Sprintf("%s.%s", podName, podNamespace) + podFullName := fmt.Sprintf("%s_%s", podName, podNamespace) name := BuildDockerName(types.UID(podUID), podFullName, container) returnedPodFullName, returnedUID, returnedContainerName, hash := ParseDockerName(name) if podFullName != returnedPodFullName || podUID != string(returnedUID) || containerName != returnedContainerName || computedHash != hash { @@ -111,8 +111,8 @@ func TestContainerManifestNaming(t *testing.T) { container := &api.Container{Name: "container"} podName := "foo" podNamespace := "test" - name := fmt.Sprintf("k8s_%s_%s.%s_%s_42", container.Name, podName, podNamespace, podUID) - podFullName := fmt.Sprintf("%s.%s", podName, podNamespace) + name := fmt.Sprintf("k8s_%s_%s_%s_%s_42", container.Name, podName, podNamespace, podUID) + podFullName := fmt.Sprintf("%s_%s", podName, podNamespace) returnedPodFullName, returnedPodUID, returnedContainerName, hash := ParseDockerName(name) if returnedPodFullName != podFullName || string(returnedPodUID) != podUID || returnedContainerName != container.Name || hash != 0 { @@ -463,15 +463,15 @@ func TestFindContainersByPod(t *testing.T) { DockerContainers{ "foobar": &docker.APIContainers{ ID: "foobar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, "barbar": &docker.APIContainers{ ID: "barbar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, "baz": &docker.APIContainers{ ID: "baz", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, }, types.UID("1234"), @@ -479,15 +479,15 @@ func TestFindContainersByPod(t *testing.T) { DockerContainers{ "foobar": &docker.APIContainers{ ID: "foobar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, "barbar": &docker.APIContainers{ ID: "barbar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, "baz": &docker.APIContainers{ ID: "baz", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, }, }, @@ -495,15 +495,15 @@ func TestFindContainersByPod(t *testing.T) { DockerContainers{ "foobar": &docker.APIContainers{ ID: "foobar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, "barbar": &docker.APIContainers{ ID: "barbar", - Names: []string{"/k8s_foo_qux_2343_42"}, + Names: []string{"/k8s_foo_qux_ns_2343_42"}, }, "baz": &docker.APIContainers{ ID: "baz", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, }, types.UID("1234"), @@ -511,11 +511,11 @@ func TestFindContainersByPod(t *testing.T) { DockerContainers{ "foobar": &docker.APIContainers{ ID: "foobar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, "baz": &docker.APIContainers{ ID: "baz", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, }, }, @@ -523,15 +523,15 @@ func TestFindContainersByPod(t *testing.T) { DockerContainers{ "foobar": &docker.APIContainers{ ID: "foobar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, "barbar": &docker.APIContainers{ ID: "barbar", - Names: []string{"/k8s_foo_qux_2343_42"}, + Names: []string{"/k8s_foo_qux_ns_2343_42"}, }, "baz": &docker.APIContainers{ ID: "baz", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, }, types.UID("5678"), @@ -542,7 +542,7 @@ func TestFindContainersByPod(t *testing.T) { DockerContainers{ "foobar": &docker.APIContainers{ ID: "foobar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, "barbar": &docker.APIContainers{ ID: "barbar", @@ -550,7 +550,7 @@ func TestFindContainersByPod(t *testing.T) { }, "baz": &docker.APIContainers{ ID: "baz", - Names: []string{"/k8s_foo_qux_5678_42"}, + Names: []string{"/k8s_foo_qux_ns_5678_42"}, }, }, types.UID("5678"), @@ -558,7 +558,7 @@ func TestFindContainersByPod(t *testing.T) { DockerContainers{ "baz": &docker.APIContainers{ ID: "baz", - Names: []string{"/k8s_foo_qux_5678_42"}, + Names: []string{"/k8s_foo_qux_ns_5678_42"}, }, }, }, @@ -566,23 +566,23 @@ func TestFindContainersByPod(t *testing.T) { DockerContainers{ "foobar": &docker.APIContainers{ ID: "foobar", - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, "barbar": &docker.APIContainers{ ID: "barbar", - Names: []string{"/k8s_foo_abc_5678_42"}, + Names: []string{"/k8s_foo_abc_ns_5678_42"}, }, "baz": &docker.APIContainers{ ID: "baz", - Names: []string{"/k8s_foo_qux_5678_42"}, + Names: []string{"/k8s_foo_qux_ns_5678_42"}, }, }, "", - "abc", + "abc_ns", DockerContainers{ "barbar": &docker.APIContainers{ ID: "barbar", - Names: []string{"/k8s_foo_abc_5678_42"}, + Names: []string{"/k8s_foo_abc_ns_5678_42"}, }, }, }, diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index c87606ddcd..c13a9d756b 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -1404,6 +1404,7 @@ func (kl *Kubelet) SyncPods(allPods []api.BoundPod, podSyncTypes map[types.UID]m glog.V(4).Infof("Skipping deletes, sources aren't ready yet.") return nil } + // Kill any containers we don't need. killed := []string{} for ix := range dockerContainers { @@ -1413,6 +1414,7 @@ func (kl *Kubelet) SyncPods(allPods []api.BoundPod, podSyncTypes map[types.UID]m // syncPod() will handle this one. continue } + pc := podContainer{podFullName, uid, containerName} if _, ok := desiredContainers[pc]; !ok { glog.V(1).Infof("Killing unwanted container %+v", pc) diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 38ecc10ce0..fe6c93b8ba 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -396,22 +396,21 @@ func TestSyncPodsDoesNothing(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // format is // k8s____ - Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo.new.test_12345678_0"}, + Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo_new_12345678_0"}, ID: "1234", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_12345678_0"}, + Names: []string{"/k8s_POD_foo_new_12345678_0"}, ID: "9876", }, } kubelet.pods = []api.BoundPod{ { ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -439,10 +438,9 @@ func TestSyncPodsWithTerminationLog(t *testing.T) { kubelet.pods = []api.BoundPod{ { ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -486,10 +484,9 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) { kubelet.pods = []api.BoundPod{ { ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -521,8 +518,8 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) { } if len(fakeDocker.Created) != 2 || - !matchString(t, "k8s_POD\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) || - !matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[1]) { + !matchString(t, "k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) || + !matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) { t.Errorf("Unexpected containers created %v", fakeDocker.Created) } fakeDocker.Unlock() @@ -537,10 +534,9 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) { kubelet.pods = []api.BoundPod{ { ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -566,8 +562,8 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) { } if len(fakeDocker.Created) != 2 || - !matchString(t, "k8s_POD\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) || - !matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[1]) { + !matchString(t, "k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) || + !matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) { t.Errorf("Unexpected containers created %v", fakeDocker.Created) } fakeDocker.Unlock() @@ -578,17 +574,16 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_12345678_0"}, + Names: []string{"/k8s_POD_foo_new_12345678_0"}, ID: "9876", }, } kubelet.pods = []api.BoundPod{ { ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -609,7 +604,7 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) { fakeDocker.Lock() if len(fakeDocker.Created) != 1 || - !matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) { + !matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) { t.Errorf("Unexpected containers created %v", fakeDocker.Created) } fakeDocker.Unlock() @@ -622,17 +617,16 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_12345678_0"}, + Names: []string{"/k8s_POD_foo_new_12345678_0"}, ID: "9876", }, } kubelet.pods = []api.BoundPod{ { ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -664,7 +658,7 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) { fakeDocker.Lock() if len(fakeDocker.Created) != 1 || - !matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) { + !matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) { t.Errorf("Unexpected containers created %v", fakeDocker.Created) } fakeDocker.Unlock() @@ -678,17 +672,16 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // format is // k8s___ - Names: []string{"/k8s_bar_foo.new.test_12345678_0"}, + Names: []string{"/k8s_bar_foo_new_12345678_0"}, ID: "1234", }, } kubelet.pods = []api.BoundPod{ { ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -727,12 +720,12 @@ func TestSyncPodsDeletesWhenSourcesAreReady(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // the k8s prefix is required for the kubelet to manage the container - Names: []string{"/k8s_foo_bar.new.test_12345678_42"}, + Names: []string{"/k8s_foo_bar_new_12345678_42"}, ID: "1234", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_12345678_42"}, + Names: []string{"/k8s_POD_foo_new_12345678_42"}, ID: "9876", }, } @@ -767,12 +760,12 @@ func TestSyncPodsDeletes(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // the k8s prefix is required for the kubelet to manage the container - Names: []string{"/k8s_foo_bar.new.test_12345678_42"}, + Names: []string{"/k8s_foo_bar_new_12345678_42"}, ID: "1234", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_12345678_42"}, + Names: []string{"/k8s_POD_foo_new_12345678_42"}, ID: "9876", }, { @@ -805,26 +798,25 @@ func TestSyncPodDeletesDuplicate(t *testing.T) { dockerContainers := dockertools.DockerContainers{ "1234": &docker.APIContainers{ // the k8s prefix is required for the kubelet to manage the container - Names: []string{"/k8s_foo_bar.new.test_12345678_1111"}, + Names: []string{"/k8s_foo_bar_new_12345678_1111"}, ID: "1234", }, "9876": &docker.APIContainers{ // pod infra container - Names: []string{"/k8s_POD_bar.new.test_12345678_2222"}, + Names: []string{"/k8s_POD_bar_new_12345678_2222"}, ID: "9876", }, "4567": &docker.APIContainers{ // Duplicate for the same container. - Names: []string{"/k8s_foo_bar.new.test_12345678_3333"}, + Names: []string{"/k8s_foo_bar_new_12345678_3333"}, ID: "4567", }, } bound := api.BoundPod{ ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "bar", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "bar", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -850,21 +842,20 @@ func TestSyncPodBadHash(t *testing.T) { dockerContainers := dockertools.DockerContainers{ "1234": &docker.APIContainers{ // the k8s prefix is required for the kubelet to manage the container - Names: []string{"/k8s_bar.1234_foo.new.test_12345678_42"}, + Names: []string{"/k8s_bar.1234_foo_new_12345678_42"}, ID: "1234", }, "9876": &docker.APIContainers{ // pod infra container - Names: []string{"/k8s_POD_foo.new.test_12345678_42"}, + Names: []string{"/k8s_POD_foo_new_12345678_42"}, ID: "9876", }, } bound := api.BoundPod{ ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -899,21 +890,20 @@ func TestSyncPodUnhealthy(t *testing.T) { dockerContainers := dockertools.DockerContainers{ "1234": &docker.APIContainers{ // the k8s prefix is required for the kubelet to manage the container - Names: []string{"/k8s_bar_foo.new.test_12345678_42"}, + Names: []string{"/k8s_bar_foo_new_12345678_42"}, ID: "1234", }, "9876": &docker.APIContainers{ // pod infra container - Names: []string{"/k8s_POD_foo.new.test_12345678_42"}, + Names: []string{"/k8s_POD_foo_new_12345678_42"}, ID: "9876", }, } bound := api.BoundPod{ ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -1234,11 +1224,11 @@ func TestGetContainerInfo(t *testing.T) { ID: containerID, // pod id: qux // container id: foo - Names: []string{"/k8s_foo_qux_1234_42"}, + Names: []string{"/k8s_foo_qux_ns_1234_42"}, }, } - stats, err := kubelet.GetContainerInfo("qux", "", "foo", cadvisorReq) + stats, err := kubelet.GetContainerInfo("qux_ns", "", "foo", cadvisorReq) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1308,11 +1298,11 @@ func TestGetContainerInfoWhenCadvisorFailed(t *testing.T) { ID: containerID, // pod id: qux // container id: foo - Names: []string{"/k8s_foo_qux_uuid_1234"}, + Names: []string{"/k8s_foo_qux_ns_uuid_1234"}, }, } - stats, err := kubelet.GetContainerInfo("qux", "uuid", "foo", cadvisorReq) + stats, err := kubelet.GetContainerInfo("qux_ns", "uuid", "foo", cadvisorReq) if stats != nil { t.Errorf("non-nil stats on error") } @@ -1367,7 +1357,7 @@ func TestGetContainerInfoWithNoContainers(t *testing.T) { kubelet.cadvisorClient = mockCadvisor kubelet.dockerClient = &errorTestingDockerClient{listContainersError: nil} - stats, err := kubelet.GetContainerInfo("qux", "", "foo", nil) + stats, err := kubelet.GetContainerInfo("qux_ns", "", "foo", nil) if err == nil { t.Errorf("Expected error from cadvisor client, got none") } @@ -1388,12 +1378,12 @@ func TestGetContainerInfoWithNoMatchingContainers(t *testing.T) { containerList := []docker.APIContainers{ { ID: "fakeId", - Names: []string{"/k8s_bar_qux_1234_42"}, + Names: []string{"/k8s_bar_qux_ns_1234_42"}, }, } kubelet.dockerClient = &errorTestingDockerClient{listContainersError: nil, containerList: containerList} - stats, err := kubelet.GetContainerInfo("qux", "", "foo", nil) + stats, err := kubelet.GetContainerInfo("qux_ns", "", "foo", nil) if err == nil { t.Errorf("Expected error from cadvisor client, got none") } @@ -1479,7 +1469,7 @@ func TestRunInContainer(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { ID: containerID, - Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + ".test_12345678_42"}, + Names: []string{"/k8s_" + containerName + "_" + podName + "_" + podNamespace + "_12345678_42"}, }, } @@ -1487,10 +1477,9 @@ func TestRunInContainer(t *testing.T) { _, err := kubelet.RunInContainer( GetPodFullName(&api.BoundPod{ ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: podName, - Namespace: podNamespace, - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: podName, + Namespace: podNamespace, }, }), "", @@ -1520,7 +1509,7 @@ func TestRunHandlerExec(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { ID: containerID, - Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + "_12345678_42"}, + Names: []string{"/k8s_" + containerName + "_" + podName + "_" + podNamespace + "_12345678_42"}, }, } @@ -1534,7 +1523,7 @@ func TestRunHandlerExec(t *testing.T) { }, }, } - err := kubelet.runHandler(podName+"."+podNamespace, "", &container, container.Lifecycle.PostStart) + err := kubelet.runHandler(podName+"_"+podNamespace, "", &container, container.Lifecycle.PostStart) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1576,7 +1565,7 @@ func TestRunHandlerHttp(t *testing.T) { }, }, } - err := kubelet.runHandler(podName+"."+podNamespace, "", &container, container.Lifecycle.PostStart) + err := kubelet.runHandler(podName+"_"+podNamespace, "", &container, container.Lifecycle.PostStart) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1624,16 +1613,15 @@ func TestSyncPodEventHandlerFails(t *testing.T) { dockerContainers := dockertools.DockerContainers{ "9876": &docker.APIContainers{ // pod infra container - Names: []string{"/k8s_POD_foo.new.test_12345678_42"}, + Names: []string{"/k8s_POD_foo_new_12345678_42"}, ID: "9876", }, } bound := api.BoundPod{ ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -1675,17 +1663,17 @@ func TestKubeletGarbageCollection(t *testing.T) { containers: []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "1876", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "2876", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "3876", }, }, @@ -1705,22 +1693,22 @@ func TestKubeletGarbageCollection(t *testing.T) { containers: []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "1876", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "2876", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "3876", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "4876", }, }, @@ -1747,7 +1735,7 @@ func TestKubeletGarbageCollection(t *testing.T) { containers: []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "1876", }, }, @@ -1757,32 +1745,32 @@ func TestKubeletGarbageCollection(t *testing.T) { containers: []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD_foo2.new.test_.beefbeef_40"}, + Names: []string{"/k8s_POD_foo2_new_.beefbeef_40"}, ID: "1706", }, { // pod infra container - Names: []string{"/k8s_POD_foo2.new.test_.beefbeef_40"}, + Names: []string{"/k8s_POD_foo2_new_.beefbeef_40"}, ID: "2706", }, { // pod infra container - Names: []string{"/k8s_POD_foo2.new.test_.beefbeef_40"}, + Names: []string{"/k8s_POD_foo2_new_.beefbeef_40"}, ID: "3706", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "1876", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "2876", }, { // pod infra container - Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"}, + Names: []string{"/k8s_POD_foo_new_.deadbeef_42"}, ID: "3876", }, }, @@ -1991,10 +1979,9 @@ func TestSyncPodsWithPullPolicy(t *testing.T) { err := kubelet.SyncPods([]api.BoundPod{ { ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -2790,16 +2777,15 @@ func TestExecInContainerNoSuchContainer(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { ID: "notfound", - Names: []string{"/k8s_notfound_" + podName + "." + podNamespace + ".test_12345678_42"}, + Names: []string{"/k8s_notfound_" + podName + "_" + podNamespace + "_12345678_42"}, }, } err := kubelet.ExecInContainer( GetPodFullName(&api.BoundPod{ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: podName, - Namespace: podNamespace, - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: podName, + Namespace: podNamespace, }}), "", containerID, @@ -2848,16 +2834,15 @@ func TestExecInContainer(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { ID: containerID, - Names: []string{"/k8s_" + containerID + "_" + podName + "." + podNamespace + ".test_12345678_42"}, + Names: []string{"/k8s_" + containerID + "_" + podName + "_" + podNamespace + "_12345678_42"}, }, } err := kubelet.ExecInContainer( GetPodFullName(&api.BoundPod{ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: podName, - Namespace: podNamespace, - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: podName, + Namespace: podNamespace, }}), "", containerID, @@ -2926,16 +2911,15 @@ func TestPortForwardNoSuchContainer(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { ID: "notfound", - Names: []string{"/k8s_notfound_" + podName + "." + podNamespace + ".test_12345678_42"}, + Names: []string{"/k8s_notfound_" + podName + "_" + podNamespace + "_12345678_42"}, }, } err := kubelet.PortForward( GetPodFullName(&api.BoundPod{ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: podName, - Namespace: podNamespace, - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: podName, + Namespace: podNamespace, }}), "", port, @@ -2966,20 +2950,19 @@ func TestPortForward(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { ID: infraContainerID, - Names: []string{"/k8s_" + kubelet.podInfraContainerImage + "_" + podName + "." + podNamespace + ".test_12345678_42"}, + Names: []string{"/k8s_" + kubelet.podInfraContainerImage + "_" + podName + "_" + podNamespace + "_12345678_42"}, }, { ID: containerID, - Names: []string{"/k8s_" + containerID + "_" + podName + "." + podNamespace + ".test_12345678_42"}, + Names: []string{"/k8s_" + containerID + "_" + podName + "_" + podNamespace + "_12345678_42"}, }, } err := kubelet.PortForward( GetPodFullName(&api.BoundPod{ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: podName, - Namespace: podNamespace, - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: podName, + Namespace: podNamespace, }}), "", port, diff --git a/pkg/kubelet/runonce_test.go b/pkg/kubelet/runonce_test.go index f64e6945bb..f20a607309 100644 --- a/pkg/kubelet/runonce_test.go +++ b/pkg/kubelet/runonce_test.go @@ -76,7 +76,7 @@ func TestRunOnce(t *testing.T) { } podContainers := []docker.APIContainers{ { - Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&api.Container{Name: "bar"}), 16) + "_foo.new.test_12345678_42"}, + Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&api.Container{Name: "bar"}), 16) + "_foo_new_12345678_42"}, ID: "1234", Status: "running", }, @@ -130,10 +130,9 @@ func TestRunOnce(t *testing.T) { results, err := kb.runOnce([]api.BoundPod{ { ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - Annotations: map[string]string{ConfigSourceAnnotationKey: "test"}, + UID: "12345678", + Name: "foo", + Namespace: "new", }, Spec: api.PodSpec{ Containers: []api.Container{ diff --git a/pkg/kubelet/server_test.go b/pkg/kubelet/server_test.go index 9816bed9fb..feb3fdac11 100644 --- a/pkg/kubelet/server_test.go +++ b/pkg/kubelet/server_test.go @@ -129,9 +129,6 @@ func newServerTest() *serverTestFramework { ObjectMeta: api.ObjectMeta{ Namespace: namespace, Name: name, - Annotations: map[string]string{ - ConfigSourceAnnotationKey: "etcd", - }, }, }, true }, @@ -157,6 +154,14 @@ func readResp(resp *http.Response) (string, error) { return string(body), err } +// A helper function to return the correct pod name. +func getPodName(name, namespace string) string { + if namespace == "" { + namespace = NamespaceDefault + } + return name + "_" + namespace +} + func TestPodStatus(t *testing.T) { fw := newServerTest() expected := api.PodStatus{ @@ -165,7 +170,7 @@ func TestPodStatus(t *testing.T) { }, } fw.fakeKubelet.statusFunc = func(name string) (api.PodStatus, error) { - if name == "goodpod.default.etcd" { + if name == "goodpod_default" { return expected, nil } return api.PodStatus{}, fmt.Errorf("bad pod %s", name) @@ -191,7 +196,7 @@ func TestContainerInfo(t *testing.T) { fw := newServerTest() expectedInfo := &info.ContainerInfo{} podID := "somepod" - expectedPodID := "somepod" + ".default.etcd" + expectedPodID := getPodName(podID, "") expectedContainerName := "goodcontainer" fw.fakeKubelet.containerInfoFunc = func(podID string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) { if podID != expectedPodID || containerName != expectedContainerName { @@ -220,7 +225,7 @@ func TestContainerInfoWithUidNamespace(t *testing.T) { expectedInfo := &info.ContainerInfo{} podID := "somepod" expectedNamespace := "custom" - expectedPodID := "somepod" + "." + expectedNamespace + ".etcd" + expectedPodID := getPodName(podID, expectedNamespace) expectedContainerName := "goodcontainer" expectedUid := "9b01b80f-8fb4-11e4-95ab-4200af06647" fw.fakeKubelet.containerInfoFunc = func(podID string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) { @@ -344,7 +349,7 @@ func TestServeRunInContainer(t *testing.T) { output := "foo bar" podNamespace := "other" podName := "foo" - expectedPodName := podName + "." + podNamespace + ".etcd" + expectedPodName := getPodName(podName, podNamespace) expectedContainerName := "baz" expectedCommand := "ls -a" fw.fakeKubelet.runFunc = func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) { @@ -384,7 +389,7 @@ func TestServeRunInContainerWithUID(t *testing.T) { output := "foo bar" podNamespace := "other" podName := "foo" - expectedPodName := podName + "." + podNamespace + ".etcd" + expectedPodName := getPodName(podName, podNamespace) expectedUID := "7e00838d_-_3523_-_11e4_-_8421_-_42010af0a720" expectedContainerName := "baz" expectedCommand := "ls -a" @@ -509,9 +514,6 @@ func setPodByNameFunc(fw *serverTestFramework, namespace, pod, container string) ObjectMeta: api.ObjectMeta{ Namespace: namespace, Name: pod, - Annotations: map[string]string{ - ConfigSourceAnnotationKey: "etcd", - }, }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -548,7 +550,7 @@ func TestContainerLogs(t *testing.T) { output := "foo bar" podNamespace := "other" podName := "foo" - expectedPodName := podName + ".other.etcd" + expectedPodName := getPodName(podName, podNamespace) expectedContainerName := "baz" expectedTail := "" expectedFollow := false @@ -575,7 +577,7 @@ func TestContainerLogsWithTail(t *testing.T) { output := "foo bar" podNamespace := "other" podName := "foo" - expectedPodName := podName + ".other.etcd" + expectedPodName := getPodName(podName, podNamespace) expectedContainerName := "baz" expectedTail := "5" expectedFollow := false @@ -602,7 +604,7 @@ func TestContainerLogsWithFollow(t *testing.T) { output := "foo bar" podNamespace := "other" podName := "foo" - expectedPodName := podName + ".other.etcd" + expectedPodName := getPodName(podName, podNamespace) expectedContainerName := "baz" expectedTail := "" expectedFollow := true @@ -693,7 +695,7 @@ func TestServeExecInContainer(t *testing.T) { podNamespace := "other" podName := "foo" - expectedPodName := podName + "." + podNamespace + ".etcd" + expectedPodName := getPodName(podName, podNamespace) expectedUid := "9b01b80f-8fb4-11e4-95ab-4200af06647" expectedContainerName := "baz" expectedCommand := "ls -a" @@ -955,7 +957,7 @@ func TestServePortForward(t *testing.T) { podNamespace := "other" podName := "foo" - expectedPodName := podName + "." + podNamespace + ".etcd" + expectedPodName := getPodName(podName, podNamespace) expectedUid := "9b01b80f-8fb4-11e4-95ab-4200af06647" for i, test := range tests { diff --git a/pkg/kubelet/types.go b/pkg/kubelet/types.go index 211e32a922..f7fafd8ba7 100644 --- a/pkg/kubelet/types.go +++ b/pkg/kubelet/types.go @@ -50,6 +50,8 @@ const ( ApiserverSource = "api" // Updates from all sources AllSource = "*" + + NamespaceDefault = api.NamespaceDefault ) // PodUpdate defines an operation sent on the channel. You can add or remove single services by @@ -69,5 +71,12 @@ type PodUpdate struct { // GetPodFullName returns a name that uniquely identifies a pod across all config sources. func GetPodFullName(pod *api.BoundPod) string { - return fmt.Sprintf("%s.%s.%s", pod.Name, pod.Namespace, pod.Annotations[ConfigSourceAnnotationKey]) + // Use underscore as the delimiter because it is not allowed in pod name + // (DNS subdomain format), while allowed in the container name format. + return fmt.Sprintf("%s_%s", pod.Name, pod.Namespace) +} + +// Build the pod full name from pod name and namespace. +func BuildPodFullName(name, namespace string) string { + return name + "_" + namespace }