Merge pull request #19498 from pwittrock/nodelabels

Node labels: Remove node-labels-file command line option.  Change --n…
This commit is contained in:
Mike Danese 2016-01-12 15:12:57 -08:00
commit bf763bba95
6 changed files with 49 additions and 236 deletions

View File

@ -84,8 +84,7 @@ type KubeletServer struct {
NetworkPluginDir string
NetworkPluginName string
VolumePluginDir string
NodeLabels []string
NodeLabelsFile string
NodeLabels string
NodeStatusUpdateFrequency time.Duration
OOMScoreAdj int
PodCIDR string
@ -165,8 +164,7 @@ func NewKubeletServer() *KubeletServer {
NetworkPluginDir: "/usr/libexec/kubernetes/kubelet-plugins/net/exec/",
NetworkPluginName: "",
VolumePluginDir: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/",
NodeLabels: []string{},
NodeLabelsFile: "",
NodeLabels: "",
NodeStatusUpdateFrequency: 10 * time.Second,
OOMScoreAdj: qos.KubeletOOMScoreAdj,
PodInfraContainerImage: kubetypes.PodInfraContainerImage,
@ -241,8 +239,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.MasterServiceNamespace, "master-service-namespace", s.MasterServiceNamespace, "The namespace from which the kubernetes master services should be injected into pods")
fs.IPVar(&s.ClusterDNS, "cluster-dns", s.ClusterDNS, "IP address for a cluster DNS server. If set, kubelet will configure all containers to use this for DNS resolution in addition to the host's DNS servers")
fs.DurationVar(&s.StreamingConnectionIdleTimeout, "streaming-connection-idle-timeout", s.StreamingConnectionIdleTimeout, "Maximum time a streaming connection can be idle before the connection is automatically closed. Example: '5m'")
fs.StringSliceVar(&s.NodeLabels, "node-label", []string{}, "add labels when registering the node in the cluster, the flag can be used multiple times (key=value)")
fs.StringVar(&s.NodeLabelsFile, "node-labels-file", "", "the path to a yaml or json file containing a series of key pair labels to apply on node registration")
fs.StringVar(&s.NodeLabels, "node-labels", s.NodeLabels, "<Warning: Alpha feature> Labels to add when registering the node in the cluster. Labels must be specified as a json map of key:value pairs.")
fs.DurationVar(&s.NodeStatusUpdateFrequency, "node-status-update-frequency", s.NodeStatusUpdateFrequency, "Specifies how often kubelet posts node status to master. Note: be cautious when changing the constant, it must work with nodeMonitorGracePeriod in nodecontroller. Default: 10s")
fs.IntVar(&s.ImageGCHighThresholdPercent, "image-gc-high-threshold", s.ImageGCHighThresholdPercent, "The percent of disk usage after which image garbage collection is always run. Default: 90%")
fs.IntVar(&s.ImageGCLowThresholdPercent, "image-gc-low-threshold", s.ImageGCLowThresholdPercent, "The percent of disk usage before which image garbage collection is never run. Lowest disk usage to garbage collect to. Default: 80%")

View File

@ -215,7 +215,6 @@ func UnsecuredKubeletConfig(s *options.KubeletServer) (*KubeletConfig, error) {
NetworkPluginName: s.NetworkPluginName,
NetworkPlugins: ProbeNetworkPlugins(s.NetworkPluginDir),
NodeLabels: s.NodeLabels,
NodeLabelsFile: s.NodeLabelsFile,
NodeStatusUpdateFrequency: s.NodeStatusUpdateFrequency,
OOMAdjuster: oom.NewOOMAdjuster(),
OSInterface: kubecontainer.RealOS{},
@ -692,8 +691,7 @@ type KubeletConfig struct {
NetworkPluginName string
NetworkPlugins []network.NetworkPlugin
NodeName string
NodeLabels []string
NodeLabelsFile string
NodeLabels string
NodeStatusUpdateFrequency time.Duration
OOMAdjuster *oom.OOMAdjuster
OSInterface kubecontainer.OSInterface
@ -783,7 +781,6 @@ func CreateAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.Pod
kc.DiskSpacePolicy,
kc.Cloud,
kc.NodeLabels,
kc.NodeLabelsFile,
kc.NodeStatusUpdateFrequency,
kc.ResourceContainer,
kc.OSInterface,

View File

@ -114,8 +114,7 @@ kubelet
--network-plugin="": <Warning: Alpha feature> The name of the network plugin to be invoked for various events in kubelet/pod lifecycle
--network-plugin-dir="/usr/libexec/kubernetes/kubelet-plugins/net/exec/": <Warning: Alpha feature> The full path of the directory in which to search for network plugins
--node-ip=<nil>: IP address of the node. If set, kubelet will use this IP address for the node
--node-label=[]: add labels when registering the node in the cluster, the flag can be used multiple times (key=value)
--node-labels-file="": the path to a yaml or json file containing a series of key pair labels to apply on node registration
--node-labels="": <Warning: Alpha feature> Labels to add when registering the node in the cluster. Labels must be specified as a json map of key:value pairs.
--node-status-update-frequency=10s: Specifies how often kubelet posts node status to master. Note: be cautious when changing the constant, it must work with nodeMonitorGracePeriod in nodecontroller. Default: 10s
--oom-score-adj=-999: The oom-score-adj value for kubelet process. Values must be within the range [-1000, 1000]
--outofdisk-transition-frequency=5m0s: Duration for which the kubelet has to wait before transitioning out of out-of-disk node condition status. Default: 5m0s
@ -144,7 +143,7 @@ kubelet
--volume-plugin-dir="/usr/libexec/kubernetes/kubelet-plugins/volume/exec/": <Warning: Alpha feature> The full path of the directory in which to search for additional third party volume plugins
```
###### Auto generated by spf13/cobra on 29-Dec-2015
###### Auto generated by spf13/cobra on 11-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->

View File

@ -225,8 +225,7 @@ no-headers
no-suggestions
node-instance-group
node-ip
node-label
node-labels-file
node-labels
node-monitor-grace-period
node-monitor-period
node-name

View File

@ -17,7 +17,6 @@ limitations under the License.
package kubelet
import (
"bufio"
"bytes"
"errors"
"fmt"
@ -33,6 +32,7 @@ import (
"sync"
"time"
"encoding/json"
"github.com/golang/glog"
cadvisorapi "github.com/google/cadvisor/info/v1"
"k8s.io/kubernetes/pkg/api"
@ -168,8 +168,7 @@ func NewMainKubelet(
imageGCPolicy ImageGCPolicy,
diskSpacePolicy DiskSpacePolicy,
cloud cloudprovider.Interface,
nodeLabels []string,
nodeLabelsFile string,
nodeLabels string,
nodeStatusUpdateFrequency time.Duration,
resourceContainer string,
osInterface kubecontainer.OSInterface,
@ -292,7 +291,6 @@ func NewMainKubelet(
cloud: cloud,
nodeRef: nodeRef,
nodeLabels: nodeLabels,
nodeLabelsFile: nodeLabelsFile,
nodeStatusUpdateFrequency: nodeStatusUpdateFrequency,
resourceContainer: resourceContainer,
os: osInterface,
@ -512,10 +510,7 @@ type Kubelet struct {
nodeInfo predicates.NodeInfo
// a list of node labels to register
nodeLabels []string
// the path to a yaml or json file container series of node labels
nodeLabelsFile string
nodeLabels string
// Last timestamp when runtime responded on ping.
// Mutex is used to protect this value.
@ -1025,77 +1020,23 @@ func (kl *Kubelet) initialNodeStatus() (*api.Node, error) {
return node, nil
}
// getNodeLabels is just a wrapper method for the two below, not to duplicate above
// getNodeLabels extracts the node labels specified on the command line
func (kl *Kubelet) getNodeLabels() (map[string]string, error) {
var err error
labels := make(map[string]string, 0)
if kl.nodeLabelsFile != "" {
labels, err = kl.retrieveNodeLabelsFile(kl.nodeLabelsFile)
if err != nil {
return labels, err
}
}
// step: apply the command line label - permitted to override those from file
if len(kl.nodeLabels) > 0 {
nl, err := kl.retrieveNodeLabels(kl.nodeLabels)
if err != nil {
return labels, err
}
for k, v := range nl {
if vl, found := labels[k]; found {
glog.Warningf("the --node-label %s=%s option will overwrite %s from node-labels-file", k, v, vl)
}
labels[k] = v
}
}
if kl.nodeLabels == "" {
return labels, nil
}
// retrieveNodeLabels extracts the node labels specified on the command line
func (kl *Kubelet) retrieveNodeLabels(labels []string) (map[string]string, error) {
nodeLabels := make(map[string]string, 0)
for _, label := range labels {
items := strings.Split(label, "=")
if len(items) != 2 {
return nodeLabels, fmt.Errorf("--node-label %s, should be in the form key=pair", label)
}
nodeLabels[strings.TrimSpace(items[0])] = strings.TrimSpace(items[1])
}
rawLabels := make(map[string]json.Number, 0)
return nodeLabels, nil
}
// retrieveNodeLabelsFile reads in and parses the yaml or json node labels file
func (kl *Kubelet) retrieveNodeLabelsFile(path string) (map[string]string, error) {
labels := make(map[string]string, 0)
kps := make(map[string]interface{}, 0)
fd, err := os.Open(path)
err := yaml.NewYAMLOrJSONDecoder(strings.NewReader(kl.nodeLabels), 12).Decode(&rawLabels)
if err != nil {
return nil, err
}
defer fd.Close()
err = yaml.NewYAMLOrJSONDecoder(bufio.NewReader(fd), 12).Decode(&kps)
if err != nil {
return nil, fmt.Errorf("the --node-labels-file %s content is invalid, %s", path, err)
return nil, fmt.Errorf("the --node-labels content '%s' is invalid, %s", kl.nodeLabels, err)
}
for k, v := range kps {
// we ONLY accept key=value pairs, no complex types
switch v.(type) {
case string:
labels[k] = v.(string)
case float64:
labels[k] = fmt.Sprintf("%d", v.(float64))
default:
return nil, fmt.Errorf("--node-labels-file only supports key:string, not complex values e.g arrays, maps")
// Parse the labels
for k, v := range rawLabels {
labels[k] = v.String()
}
}
return labels, nil
}

View File

@ -3702,40 +3702,41 @@ func TestGetNodeLabels(t *testing.T) {
testCases := []struct {
Expecting map[string]string
LabelOptions []string
FileContent string
NodeLabels string
Ok bool
}{
{
Expecting: map[string]string{"key1": "value1", "key2": "2", "key3": "3.3"},
NodeLabels: `---
key1: value1
key2: 2
key3: 3.3`,
Ok: true,
Expecting: map[string]string{"key1": "pair1", "key2": "pair2", "key3": "pair3", "key4": "pair4", "key5": "pair5"},
LabelOptions: []string{"key5=pair5"},
FileContent: `---
key1: pair1
key2: pair2
key3: pair3
key4: pair4
`,
}, {
},
{
Expecting: nil,
NodeLabels: `---
key11: value11
key12: 12
key13: 13.3
key14:
nested_key: nested_value`,
Ok: false,
},
{
Expecting: map[string]string{"key21": "value21", "key22": "22", "key23": "23.3"},
NodeLabels: `{"key21": "value21", "key22": "22", "key23": "23.3"}`,
Ok: true,
Expecting: map[string]string{"key1": "pair1", "key2": "override"},
LabelOptions: []string{"key2=override"},
FileContent: `---
key1: pair1
key2: pair2
`,
},
{
Expecting: nil,
NodeLabels: `{"key31": "value31", "key32": "32", "key33": "33.3", "key34": {"nested_key": "nested_value"}}`,
Ok: false,
},
}
for i, test := range testCases {
fd := createTestNodeLabelFile(t, test.FileContent)
defer func(f *os.File) {
os.Remove(f.Name())
}(fd)
kubelet.nodeLabels = test.LabelOptions
kubelet.nodeLabelsFile = fd.Name()
kubelet.nodeLabels = test.NodeLabels
list, err := kubelet.getNodeLabels()
if test.Ok && err != nil {
t.Errorf("test case %d should not have failed, error: %s", i, err)
@ -3746,127 +3747,6 @@ key2: pair2
}
}
func TestRetrieveNodeLabels(t *testing.T) {
kubelet := newTestKubelet(t).kubelet
testCases := []struct {
Expecting map[string]string
LabelOptions []string
Ok bool
}{
{
Expecting: map[string]string{"key1": "pair1", "key2": "pair2", "key3": "pair3", "key4": "pair4"},
LabelOptions: []string{"key1=pair1", "key2=pair2", "key3=pair3", "key4=pair4"},
Ok: true,
},
{
Expecting: map[string]string{"key1": "pair1"},
LabelOptions: []string{"key1=pair1", "key2paiwdsr2"},
},
}
for i, test := range testCases {
list, err := kubelet.retrieveNodeLabels(test.LabelOptions)
if test.Ok && err != nil {
t.Errorf("test case %d should not have failed, error: %s", i, err)
}
if !reflect.DeepEqual(test.Expecting, list) {
t.Errorf("test case %d are not the same, %v ~ %v", i, list, test.Expecting)
}
}
}
func TestRetrieveNodeLabelsFile(t *testing.T) {
kubelet := newTestKubelet(t).kubelet
testCases := []struct {
Expecting map[string]string
Ok bool
FileContent string
}{
{
Expecting: map[string]string{"key1": "pair1", "key2": "pair2", "key3": "pair3", "key4": "pair4"},
Ok: true,
FileContent: `---
key1: pair1
key2: pair2
key3: pair3
key4: pair4`,
}, {
FileContent: `---
key1: pair1
hash_map:
key2: pair2
`,
}, {
Expecting: map[string]string{"key1": "pair1", "key2": "pair2"},
Ok: true,
FileContent: `
key1: pair1
key2: pair2
`,
}, {
FileContent: `---
key1: pair1
bad_key_pair
`,
}, {
Expecting: nil,
FileContent: `{
"key1": "pair1",
"key2": "pair2",
"key3": "pair3",
"key4": {
"some_key": "some_value"
}
}`,
}, {
FileContent: "",
}, {
Expecting: map[string]string{"key1": "pair1", "key2": "pair2", "key3": "pair3", "key4": "pair4"},
Ok: true,
FileContent: `---
key1: pair1
key2: pair2
key3: pair3
key4: pair4
`,
},
}
for i, test := range testCases {
fd := createTestNodeLabelFile(t, test.FileContent)
defer func(f *os.File) {
os.Remove(f.Name())
}(fd)
labels, err := kubelet.retrieveNodeLabelsFile(fd.Name())
if test.Ok && err != nil {
t.Errorf("test case %d should not have returned an error, %s", i, err)
continue
}
if test.Expecting != nil && !reflect.DeepEqual(test.Expecting, labels) {
t.Errorf("test case %d not as expected, got: %#v, expecting: %#v", i, labels, test.Expecting)
}
}
}
func createTestNodeLabelFile(t *testing.T, content string) *os.File {
f, err := ioutil.TempFile("", "node_label_file")
if err != nil {
t.Fatalf("unexpected error creating node_label_file: %v", err)
}
f.Close()
if err := ioutil.WriteFile(f.Name(), []byte(content), 0700); err != nil {
t.Fatalf("unexpected error writing node label file: %v", err)
}
return f
}
func TestMakePortMappings(t *testing.T) {
tests := []struct {
container *api.Container