Merge pull request #18541 from pravisankar/kubelet-nodeIP-option

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2016-01-03 11:45:16 -08:00
commit b494855ebf
5 changed files with 97 additions and 2 deletions

View File

@ -158,6 +158,7 @@ type KubeletServer struct {
// Pull images one at a time.
SerializeImagePulls bool
ExperimentalFlannelOverlay bool
NodeIP net.IP
}
// bootstrapping interface for kubelet, targets the initialization protocol
@ -349,6 +350,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
fs.IntVar(&s.KubeAPIBurst, "kube-api-burst", s.KubeAPIBurst, "Burst to use while talking with kubernetes apiserver")
fs.BoolVar(&s.SerializeImagePulls, "serialize-image-pulls", s.SerializeImagePulls, "Pull images one at a time. We recommend *not* changing the default value on nodes that run docker daemon with version < 1.9 or an Aufs storage backend. Issue #10959 has more details. [default=true]")
fs.BoolVar(&s.ExperimentalFlannelOverlay, "experimental-flannel-overlay", s.ExperimentalFlannelOverlay, "Experimental support for starting the kubelet with the default overlay network (flannel). Assumes flanneld is already running in client mode. [default=false]")
fs.IPVar(&s.NodeIP, "node-ip", s.NodeIP, "IP address of the node. If set, kubelet will use this IP address for the node")
}
// UnsecuredKubeletConfig returns a KubeletConfig suitable for being run, or an error if the server setup
@ -488,6 +490,7 @@ func (s *KubeletServer) UnsecuredKubeletConfig() (*KubeletConfig, error) {
VolumePlugins: ProbeVolumePlugins(s.VolumePluginDir),
ExperimentalFlannelOverlay: s.ExperimentalFlannelOverlay,
NodeIP: s.NodeIP,
}, nil
}
@ -964,6 +967,7 @@ type KubeletConfig struct {
VolumePlugins []volume.VolumePlugin
ExperimentalFlannelOverlay bool
NodeIP net.IP
}
func CreateAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.PodConfig, err error) {
@ -1047,6 +1051,7 @@ func CreateAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.Pod
kc.SerializeImagePulls,
kc.ContainerManager,
kc.ExperimentalFlannelOverlay,
kc.NodeIP,
)
if err != nil {

View File

@ -113,6 +113,7 @@ kubelet
--minimum-container-ttl-duration=1m0s: Minimum age for a finished container before it is garbage collected. Examples: '300ms', '10s' or '2h45m'
--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-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

View File

@ -221,6 +221,7 @@ namespace-sync-period
network-plugin
network-plugin-dir
node-instance-group
node-ip
node-monitor-grace-period
node-monitor-period
node-label

View File

@ -197,6 +197,7 @@ func NewMainKubelet(
serializeImagePulls bool,
containerManager cm.ContainerManager,
flannelExperimentalOverlay bool,
nodeIP net.IP,
) (*Kubelet, error) {
if rootDirectory == "" {
@ -313,10 +314,17 @@ func NewMainKubelet(
containerManager: containerManager,
flannelExperimentalOverlay: flannelExperimentalOverlay,
flannelHelper: NewFlannelHelper(),
nodeIP: nodeIP,
}
if klet.flannelExperimentalOverlay {
glog.Infof("Flannel is in charge of podCIDR and overlay networking.")
}
if klet.nodeIP != nil {
if err := klet.validateNodeIP(); err != nil {
return nil, err
}
glog.Infof("Using node IP: %q", klet.nodeIP.String())
}
if plug, err := network.InitNetworkPlugin(networkPlugins, networkPluginName, &networkHost{klet}); err != nil {
return nil, err
} else {
@ -643,6 +651,42 @@ type Kubelet struct {
// on the fly if we're confident the dbus connetions it opens doesn't
// put the system under duress.
flannelHelper *FlannelHelper
// If non-nil, use this IP address for the node
nodeIP net.IP
}
// Validate given node IP belongs to the current host
func (kl *Kubelet) validateNodeIP() error {
if kl.nodeIP == nil {
return nil
}
// Honor IP limitations set in setNodeStatus()
if kl.nodeIP.IsLoopback() {
return fmt.Errorf("nodeIP can't be loopback address")
}
if kl.nodeIP.To4() == nil {
return fmt.Errorf("nodeIP must be IPv4 address")
}
addrs, err := net.InterfaceAddrs()
if err != nil {
return err
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
if ip != nil && ip.Equal(kl.nodeIP) {
return nil
}
}
return fmt.Errorf("Node IP: %q not found in the host's network interfaces", kl.nodeIP.String())
}
func (kl *Kubelet) allSourcesReady() bool {
@ -2663,8 +2707,12 @@ func (kl *Kubelet) setNodeAddress(node *api.Node) error {
}
node.Status.Addresses = nodeAddresses
} else {
addr := net.ParseIP(kl.hostname)
if addr != nil {
if kl.nodeIP != nil {
node.Status.Addresses = []api.NodeAddress{
{Type: api.NodeLegacyHostIP, Address: kl.nodeIP.String()},
{Type: api.NodeInternalIP, Address: kl.nodeIP.String()},
}
} else if addr := net.ParseIP(kl.hostname); addr != nil {
node.Status.Addresses = []api.NodeAddress{
{Type: api.NodeLegacyHostIP, Address: addr.String()},
{Type: api.NodeInternalIP, Address: addr.String()},

View File

@ -787,6 +787,46 @@ func TestGetContainerInfoWithNoContainers(t *testing.T) {
mockCadvisor.AssertExpectations(t)
}
func TestNodeIPParam(t *testing.T) {
testKubelet := newTestKubelet(t)
kubelet := testKubelet.kubelet
tests := []struct {
nodeIP string
success bool
testName string
}{
{
nodeIP: "",
success: true,
testName: "IP not set",
},
{
nodeIP: "127.0.0.1",
success: false,
testName: "loopback address",
},
{
nodeIP: "FE80::0202:B3FF:FE1E:8329",
success: false,
testName: "IPv6 address",
},
{
nodeIP: "1.2.3.4",
success: false,
testName: "IPv4 address that doesn't belong to host",
},
}
for _, test := range tests {
kubelet.nodeIP = net.ParseIP(test.nodeIP)
err := kubelet.validateNodeIP()
if err != nil && test.success {
t.Errorf("Test: %s, expected no error but got: %v", test.testName, err)
} else if err == nil && !test.success {
t.Errorf("Test: %s, expected an error", test.testName)
}
}
}
func TestGetContainerInfoWithNoMatchingContainers(t *testing.T) {
testKubelet := newTestKubelet(t)
fakeRuntime := testKubelet.fakeRuntime