Skip to content

Commit

Permalink
Merge pull request kubernetes#5775 from smarterclayton/fix_mac_hostname
Browse files Browse the repository at this point in the history
Kubelet config sources should use the provided hostname, not lookup os.Hostname()
  • Loading branch information
thockin committed Mar 23, 2015
2 parents b46276e + d020ca0 commit df67250
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 89 deletions.
32 changes: 23 additions & 9 deletions cmd/integration/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ func startComponents(manifestURL, apiVersion string) (string, string) {
scheduler.New(schedulerConfig).Run()

endpoints := service.NewEndpointController(cl)
go util.Forever(func() { endpoints.SyncServiceEndpoints() }, time.Second*10)
// ensure the service endpoints are sync'd several times within the window that the integration tests wait
go util.Forever(func() { endpoints.SyncServiceEndpoints() }, time.Second*4)

controllerManager := replicationControllerPkg.NewReplicationManager(cl)

Expand All @@ -222,13 +223,17 @@ func startComponents(manifestURL, apiVersion string) (string, string) {
testRootDir := makeTempDirOrDie("kubelet_integ_1.", "")
configFilePath := makeTempDirOrDie("config", testRootDir)
glog.Infof("Using %s as root dir for kubelet #1", testRootDir)
kubeletapp.SimpleRunKubelet(cl, &fakeDocker1, machineList[0], testRootDir, manifestURL, "127.0.0.1", 10250, api.NamespaceDefault, empty_dir.ProbeVolumePlugins(), nil, cadvisorInterface, configFilePath)
kcfg := kubeletapp.SimpleKubelet(cl, &fakeDocker1, machineList[0], testRootDir, manifestURL, "127.0.0.1", 10250, api.NamespaceDefault, empty_dir.ProbeVolumePlugins(), nil, cadvisorInterface, configFilePath)
kcfg.PodStatusUpdateFrequency = 1 * time.Second
kubeletapp.RunKubelet(kcfg)
// Kubelet (machine)
// Create a second kubelet so that the guestbook example's two redis slaves both
// have a place they can schedule.
testRootDir = makeTempDirOrDie("kubelet_integ_2.", "")
glog.Infof("Using %s as root dir for kubelet #2", testRootDir)
kubeletapp.SimpleRunKubelet(cl, &fakeDocker2, machineList[1], testRootDir, "", "127.0.0.1", 10251, api.NamespaceDefault, empty_dir.ProbeVolumePlugins(), nil, cadvisorInterface, "")
kcfg = kubeletapp.SimpleKubelet(cl, &fakeDocker2, machineList[1], testRootDir, "", "127.0.0.1", 10251, api.NamespaceDefault, empty_dir.ProbeVolumePlugins(), nil, cadvisorInterface, "")
kcfg.PodStatusUpdateFrequency = 1 * time.Second
kubeletapp.RunKubelet(kcfg)
return apiServer.URL, configFilePath
}

Expand Down Expand Up @@ -273,7 +278,9 @@ func endpointsSet(c *client.Client, serviceNamespace, serviceID string, endpoint
glog.Infof("Error on creating endpoints: %v", err)
return false, nil
}
glog.Infof("endpoints: %v", endpoints.Endpoints)
for _, e := range endpoints.Endpoints {
glog.Infof("%s/%s endpoint: %s:%d %#v", serviceNamespace, serviceID, e.IP, e.Port, e.TargetRef)
}
return len(endpoints.Endpoints) == endpointCount, nil
}
}
Expand All @@ -295,6 +302,9 @@ func podNotFound(c *client.Client, podNamespace string, podID string) wait.Condi
func podRunning(c *client.Client, podNamespace string, podID string) wait.ConditionFunc {
return func() (bool, error) {
pod, err := c.Pods(podNamespace).Get(podID)
if apierrors.IsNotFound(err) {
return false, nil
}
if err != nil {
return false, err
}
Expand All @@ -317,11 +327,15 @@ containers:
ioutil.WriteFile(manifestFile.Name(), []byte(manifest), 0600)

// Wait for the mirror pod to be created.
hostname, _ := os.Hostname()
podName := fmt.Sprintf("static-pod-%s", hostname)
podName := "static-pod-localhost"
namespace := kubelet.NamespaceDefault
if err := wait.Poll(time.Second, time.Second*30,
if err := wait.Poll(time.Second, time.Minute*2,
podRunning(c, namespace, podName)); err != nil {
if pods, err := c.Pods(namespace).List(labels.Everything()); err == nil {
for _, pod := range pods.Items {
glog.Infof("pod found: %s/%s", namespace, pod.Name)
}
}
glog.Fatalf("FAILED: mirror pod has not been created or is not running: %v", err)
}
// Delete the mirror pod, and wait for it to be recreated.
Expand Down Expand Up @@ -709,7 +723,7 @@ func runServiceTest(client *client.Client) {
glog.Fatalf("Failed to create service: %v, %v", svc3, err)
}

if err := wait.Poll(time.Second, time.Second*20, endpointsSet(client, svc1.Namespace, svc1.Name, 1)); err != nil {
if err := wait.Poll(time.Second, time.Second*30, endpointsSet(client, svc1.Namespace, svc1.Name, 1)); err != nil {
glog.Fatalf("FAILED: unexpected endpoints: %v", err)
}
// A second service with the same port.
Expand All @@ -728,7 +742,7 @@ func runServiceTest(client *client.Client) {
if err != nil {
glog.Fatalf("Failed to create service: %v, %v", svc2, err)
}
if err := wait.Poll(time.Second, time.Second*20, endpointsSet(client, svc2.Namespace, svc2.Name, 1)); err != nil {
if err := wait.Poll(time.Second, time.Second*30, endpointsSet(client, svc2.Namespace, svc2.Name, 1)); err != nil {
glog.Fatalf("FAILED: unexpected endpoints: %v", err)
}

Expand Down
10 changes: 5 additions & 5 deletions cmd/kubelet/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,15 +262,15 @@ func (s *KubeletServer) createAPIServerClient() (*client.Client, error) {

// SimpleRunKubelet is a simple way to start a Kubelet talking to dockerEndpoint, using an API Client.
// Under the hood it calls RunKubelet (below)
func SimpleRunKubelet(client *client.Client,
func SimpleKubelet(client *client.Client,
dockerClient dockertools.DockerInterface,
hostname, rootDir, manifestURL, address string,
port uint,
masterServiceNamespace string,
volumePlugins []volume.VolumePlugin,
tlsOptions *kubelet.TLSOptions,
cadvisorInterface cadvisor.Interface,
configFilePath string) {
configFilePath string) *KubeletConfig {

imageGCPolicy := kubelet.ImageGCPolicy{
HighThresholdPercent: 90,
Expand Down Expand Up @@ -302,7 +302,7 @@ func SimpleRunKubelet(client *client.Client,
ConfigFile: configFilePath,
ImageGCPolicy: imageGCPolicy,
}
RunKubelet(&kcfg)
return &kcfg
}

// RunKubelet is responsible for setting up and running a kubelet. It is used in three different applications:
Expand Down Expand Up @@ -358,13 +358,13 @@ func makePodSourceConfig(kc *KubeletConfig) *config.PodConfig {
// define file config source
if kc.ConfigFile != "" {
glog.Infof("Adding manifest file: %v", kc.ConfigFile)
config.NewSourceFile(kc.ConfigFile, kc.FileCheckFrequency, cfg.Channel(kubelet.FileSource))
config.NewSourceFile(kc.ConfigFile, kc.Hostname, kc.FileCheckFrequency, cfg.Channel(kubelet.FileSource))
}

// define url config source
if kc.ManifestURL != "" {
glog.Infof("Adding manifest url: %v", kc.ManifestURL)
config.NewSourceURL(kc.ManifestURL, kc.HTTPCheckFrequency, cfg.Channel(kubelet.HTTPSource))
config.NewSourceURL(kc.ManifestURL, kc.Hostname, kc.HTTPCheckFrequency, cfg.Channel(kubelet.HTTPSource))
}
if kc.KubeClient != nil {
glog.Infof("Watching apiserver")
Expand Down
3 changes: 2 additions & 1 deletion cmd/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ func startComponents(etcdClient tools.EtcdClient, cl *client.Client, addr net.IP
if err != nil {
glog.Fatalf("Failed to create cAdvisor: %v", err)
}
kubeletapp.SimpleRunKubelet(cl, dockerClient, machineList[0], "/tmp/kubernetes", "", "127.0.0.1", 10250, *masterServiceNamespace, kubeletapp.ProbeVolumePlugins(), nil, cadvisorInterface, "")
kcfg := kubeletapp.SimpleKubelet(cl, dockerClient, machineList[0], "/tmp/kubernetes", "", "127.0.0.1", 10250, *masterServiceNamespace, kubeletapp.ProbeVolumePlugins(), nil, cadvisorInterface, "")
kubeletapp.RunKubelet(kcfg)
}

func newApiClient(addr net.IP, port int) *client.Client {
Expand Down
2 changes: 0 additions & 2 deletions pkg/kubelet/config/apiserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)

const hostname string = "mcaa1"

type fakePodLW struct {
listResp runtime.Object
watchResp watch.Interface
Expand Down
29 changes: 12 additions & 17 deletions pkg/kubelet/config/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import (
"crypto/md5"
"encoding/hex"
"fmt"
"os"
"strings"

"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
Expand All @@ -35,15 +33,10 @@ import (
"github.com/golang/glog"
)

func applyDefaults(pod *api.Pod, source string, isFile bool) error {
func applyDefaults(pod *api.Pod, source string, isFile bool, hostname string) error {
if len(pod.UID) == 0 {
hasher := md5.New()
if isFile {
hostname, err := os.Hostname() // TODO: kubelet name would be better
if err != nil {
return err
}
hostname = strings.ToLower(hostname)
fmt.Fprintf(hasher, "host:%s", hostname)
fmt.Fprintf(hasher, "file:%s", source)
} else {
Expand All @@ -60,7 +53,7 @@ func applyDefaults(pod *api.Pod, source string, isFile bool) error {
if len(pod.Name) == 0 {
pod.Name = string(pod.UID)
}
if pod.Name, err = GeneratePodName(pod.Name); err != nil {
if pod.Name, err = GeneratePodName(pod.Name, hostname); err != nil {
return err
}
glog.V(5).Infof("Generated Name %q for UID %q from URL %s", pod.Name, pod.UID, source)
Expand All @@ -76,7 +69,9 @@ func applyDefaults(pod *api.Pod, source string, isFile bool) error {
return nil
}

func tryDecodeSinglePod(data []byte, source string, isFile bool) (parsed bool, pod api.Pod, err error) {
type defaultFunc func(pod *api.Pod) error

func tryDecodeSinglePod(data []byte, defaultFn defaultFunc) (parsed bool, pod api.Pod, err error) {
obj, err := api.Scheme.Decode(data)
if err != nil {
return false, pod, err
Expand All @@ -88,7 +83,7 @@ func tryDecodeSinglePod(data []byte, source string, isFile bool) (parsed bool, p
}
newPod := obj.(*api.Pod)
// Apply default values and validate the pod.
if err = applyDefaults(newPod, source, isFile); err != nil {
if err = defaultFn(newPod); err != nil {
return true, pod, err
}
if errs := validation.ValidatePod(newPod); len(errs) > 0 {
Expand All @@ -98,7 +93,7 @@ func tryDecodeSinglePod(data []byte, source string, isFile bool) (parsed bool, p
return true, *newPod, nil
}

func tryDecodePodList(data []byte, source string, isFile bool) (parsed bool, pods api.PodList, err error) {
func tryDecodePodList(data []byte, defaultFn defaultFunc) (parsed bool, pods api.PodList, err error) {
obj, err := api.Scheme.Decode(data)
if err != nil {
return false, pods, err
Expand All @@ -112,7 +107,7 @@ func tryDecodePodList(data []byte, source string, isFile bool) (parsed bool, pod
// Apply default values and validate pods.
for i := range newPods.Items {
newPod := &newPods.Items[i]
if err = applyDefaults(newPod, source, isFile); err != nil {
if err = defaultFn(newPod); err != nil {
return true, pods, err
}
if errs := validation.ValidatePod(newPod); len(errs) > 0 {
Expand All @@ -123,7 +118,7 @@ func tryDecodePodList(data []byte, source string, isFile bool) (parsed bool, pod
return true, *newPods, err
}

func tryDecodeSingleManifest(data []byte, source string, isFile bool) (parsed bool, manifest v1beta1.ContainerManifest, pod api.Pod, err error) {
func tryDecodeSingleManifest(data []byte, defaultFn defaultFunc) (parsed bool, manifest v1beta1.ContainerManifest, pod api.Pod, err error) {
// TODO: should be api.Scheme.Decode
// This is awful. DecodeInto() expects to find an APIObject, which
// Manifest is not. We keep reading manifest for now for compat, but
Expand All @@ -149,14 +144,14 @@ func tryDecodeSingleManifest(data []byte, source string, isFile bool) (parsed bo
if err = api.Scheme.Convert(&newManifest, &pod); err != nil {
return true, manifest, pod, err
}
if err = applyDefaults(&pod, source, isFile); err != nil {
if err := defaultFn(&pod); err != nil {
return true, manifest, pod, err
}
// Success.
return true, manifest, pod, nil
}

func tryDecodeManifestList(data []byte, source string, isFile bool) (parsed bool, manifests []v1beta1.ContainerManifest, pods api.PodList, err error) {
func tryDecodeManifestList(data []byte, defaultFn defaultFunc) (parsed bool, manifests []v1beta1.ContainerManifest, pods api.PodList, err error) {
// TODO: should be api.Scheme.Decode
// See the comment in tryDecodeSingle().
if err = yaml.Unmarshal(data, &manifests); err != nil {
Expand All @@ -179,7 +174,7 @@ func tryDecodeManifestList(data []byte, source string, isFile bool) (parsed bool
}
for i := range pods.Items {
pod := &pods.Items[i]
if err = applyDefaults(pod, source, isFile); err != nil {
if err := defaultFn(pod); err != nil {
return true, manifests, pods, err
}
}
Expand Down
9 changes: 1 addition & 8 deletions pkg/kubelet/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ package config

import (
"fmt"
"os"
"reflect"
"strings"
"sync"

"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
Expand Down Expand Up @@ -363,11 +361,6 @@ func bestPodIdentString(pod *api.Pod) 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
}
hostname = strings.ToLower(hostname)
func GeneratePodName(name, hostname string) (string, error) {
return fmt.Sprintf("%s-%s", name, hostname), nil
}
34 changes: 22 additions & 12 deletions pkg/kubelet/config/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ import (
)

type sourceFile struct {
path string
updates chan<- interface{}
path string
hostname string
updates chan<- interface{}
}

func NewSourceFile(path string, period time.Duration, updates chan<- interface{}) {
func NewSourceFile(path string, hostname string, period time.Duration, updates chan<- interface{}) {
config := &sourceFile{
path: path,
updates: updates,
path: path,
hostname: hostname,
updates: updates,
}
glog.V(1).Infof("Watching path %q", path)
go util.Forever(config.run, period)
Expand All @@ -52,6 +54,10 @@ func (s *sourceFile) run() {
}
}

func (s *sourceFile) applyDefaults(pod *api.Pod, source string) error {
return applyDefaults(pod, source, true, s.hostname)
}

func (s *sourceFile) extractFromPath() error {
path := s.path
statInfo, err := os.Stat(path)
Expand All @@ -66,14 +72,14 @@ func (s *sourceFile) extractFromPath() error {

switch {
case statInfo.Mode().IsDir():
pods, err := extractFromDir(path)
pods, err := s.extractFromDir(path)
if err != nil {
return err
}
s.updates <- kubelet.PodUpdate{pods, kubelet.SET, kubelet.FileSource}

case statInfo.Mode().IsRegular():
pod, err := extractFromFile(path)
pod, err := s.extractFromFile(path)
if err != nil {
return err
}
Expand All @@ -89,7 +95,7 @@ func (s *sourceFile) extractFromPath() error {
// Get as many pod configs as we can from a directory. Return an error iff something
// prevented us from reading anything at all. Do not return an error if only some files
// were problematic.
func extractFromDir(name string) ([]api.Pod, error) {
func (s *sourceFile) extractFromDir(name string) ([]api.Pod, error) {
dirents, err := filepath.Glob(filepath.Join(name, "[^.]*"))
if err != nil {
return nil, fmt.Errorf("glob failed: %v", err)
Expand All @@ -112,7 +118,7 @@ func extractFromDir(name string) ([]api.Pod, error) {
case statInfo.Mode().IsDir():
glog.V(1).Infof("Not recursing into config path %q", path)
case statInfo.Mode().IsRegular():
pod, err := extractFromFile(path)
pod, err := s.extractFromFile(path)
if err != nil {
glog.V(1).Infof("Can't process config file %q: %v", path, err)
} else {
Expand All @@ -125,7 +131,7 @@ func extractFromDir(name string) ([]api.Pod, error) {
return pods, nil
}

func extractFromFile(filename string) (pod api.Pod, err error) {
func (s *sourceFile) extractFromFile(filename string) (pod api.Pod, err error) {
glog.V(3).Infof("Reading config file %q", filename)
file, err := os.Open(filename)
if err != nil {
Expand All @@ -138,7 +144,11 @@ func extractFromFile(filename string) (pod api.Pod, err error) {
return pod, err
}

parsed, _, pod, manifestErr := tryDecodeSingleManifest(data, filename, true)
defaultFn := func(pod *api.Pod) error {
return s.applyDefaults(pod, filename)
}

parsed, _, pod, manifestErr := tryDecodeSingleManifest(data, defaultFn)
if parsed {
if manifestErr != nil {
// It parsed but could not be used.
Expand All @@ -147,7 +157,7 @@ func extractFromFile(filename string) (pod api.Pod, err error) {
return pod, nil
}

parsed, pod, podErr := tryDecodeSinglePod(data, filename, true)
parsed, pod, podErr := tryDecodeSinglePod(data, defaultFn)
if parsed {
if podErr != nil {
return pod, podErr
Expand Down
Loading

0 comments on commit df67250

Please sign in to comment.