Merge pull request #35843 from bulletRush/feature/pre-hostname-check

Automatic merge from submit-queue

[kubeadm] pre-flight check hostname to ensure kubelet can launch static pods li…

<!--  Thanks for sending a pull request!  Here are some tips for you:
1. If this is your first time, read our contributor guidelines https://github.com/kubernetes/kubernetes/blob/master/CONTRIBUTING.md and developer guide https://github.com/kubernetes/kubernetes/blob/master/docs/devel/development.md
2. If you want *faster* PR reviews, read how: https://github.com/kubernetes/kubernetes/blob/master/docs/devel/faster_reviews.md
3. Follow the instructions for writing a release note: https://github.com/kubernetes/kubernetes/blob/master/docs/devel/pull-requests.md#release-notes
-->

**What this PR does / why we need it**: pre-flight check hostname to ensure kubelet can launch static pods like kube-apiserver/kube-controller-manager

**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # 

**Special notes for your reviewer**:

# what is the influence of this issue?

kubelet will not create api server and kcm pod if your hostname is uncorrect. It complain the config files in "/etc/kubernetes/manifests" are invlid.

# how to reproduce this issue?

change your hostname by `hostnamectl set-hostname vm_81_12_centos`. then run `kubeadm init`. you will get this error log from kubelet:

```log
Oct 27 11:12:57 vm_81_12_centos kubelet: I1027 11:12:57.279458    2695 file.go:123] Can't process config file "/etc/kubernetes/manifests/kube-controller-manager.json": invalid pod: [metadata.name: Invalid value: "kube-controller-manager-vm_81_12_centos": must match the regex [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* (e.g. 'example.com') spec.nodeName: Invalid value: "vm_81_12_centos": must match the regex [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* (e.g. 'example.com')]
```

# where the error comes from in the code?

`pkg/kubelet/config/file.go:144 sourceFile:extractFromDir`

```go
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)
	}

	pods := make([]*api.Pod, 0)
	if len(dirents) == 0 {
		return pods, nil
	}

	sort.Strings(dirents)
	for _, path := range dirents {
		statInfo, err := os.Stat(path)
		if err != nil {
			glog.V(1).Infof("Can't get metadata for %q: %v", path, err)
			continue
		}

		switch {
		case statInfo.Mode().IsDir():
			glog.V(1).Infof("Not recursing into config path %q", path)
		case statInfo.Mode().IsRegular():
			pod, err := s.extractFromFile(path)
			if err != nil {
-->				glog.V(1).Infof("Can't process config file %q: %v", path, err)
			} else {
				pods = append(pods, pod)
			}
		default:
			glog.V(1).Infof("Config path %q is not a directory or file: %v", path, statInfo.Mode())
		}
	}
	return pods, nil
}
```

# how to fix it?

1. change hostname by `hostnamectl set-hostname <right host name>` or
2. add `hostnameOverride` config. If hostnameOverride is set, then kubelet will use this value instead of system hostname.

**Release note**:
<!--  Steps to write your release note:
1. Use the release-note-* labels to set the release note state (if you have access) 
2. Enter your extended release note in the below block; leaving it blank means using the PR title as the release note. If no release note is required, just write `NONE`. 
-->
```release-note
```

…ke kube-apiserver/kube-controller-manager and so on.
pull/6/head
Kubernetes Submit Queue 2016-10-30 09:56:25 -07:00 committed by GitHub
commit b4f8d88d51
2 changed files with 19 additions and 0 deletions

View File

@ -16,6 +16,8 @@ go_library(
tags = ["automanaged"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//pkg/api/validation:go_default_library",
"//pkg/util/initsystem:go_default_library",
"//pkg/util/node:go_default_library",
],
)

View File

@ -25,7 +25,9 @@ import (
"os/exec"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/util/initsystem"
"k8s.io/kubernetes/pkg/util/node"
)
type PreFlightError struct {
@ -170,10 +172,24 @@ func (ipc InPathCheck) Check() (warnings, errors []error) {
return nil, nil
}
// HostnameCheck checks if hostname match dns sub domain regex.
// If hostname doesn't match this regex, kubelet will not launch static pods like kube-apiserver/kube-controller-manager and so on.
type HostnameCheck struct{}
func (hc HostnameCheck) Check() (warnings, errors []error) {
errors = []error{}
hostname := node.GetHostname("")
for _, msg := range validation.ValidateNodeName(hostname, false) {
errors = append(errors, fmt.Errorf("hostname \"%s\" %s", hostname, msg))
}
return nil, errors
}
func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
// TODO: Some of these ports should come from kubeadm config eventually:
checks := []PreFlightCheck{
IsRootCheck{root: true},
HostnameCheck{},
ServiceCheck{Service: "kubelet"},
ServiceCheck{Service: "docker"},
PortOpenCheck{port: int(cfg.API.BindPort)},
@ -207,6 +223,7 @@ func RunJoinNodeChecks() error {
// TODO: Some of these ports should come from kubeadm config eventually:
checks := []PreFlightCheck{
IsRootCheck{root: true},
HostnameCheck{},
ServiceCheck{Service: "docker"},
ServiceCheck{Service: "kubelet"},
PortOpenCheck{port: 10250},