Unverified Commit 574492ae authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #53553 from bsteciuk/kubeadm-windows

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Kubeadm - Added initial support for Windows worker nodes to join cluster using kubeadm **What this PR does / why we need it**: This PR adds initial support for adding a Windows worker node to a Kubernetes cluster with kubeadm. Also adds Windows build of kubeadm to node build targets. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes https://github.com/kubernetes/kubeadm/issues/364 **Special notes for your reviewer**: Depends on #53730 **Release note**: ```release-note kubeadm: Add support for adding a Windows node ```
parents fcf9b1f7 44fbec29
......@@ -111,6 +111,7 @@ release_filegroup(
name = "node-targets",
srcs = [
"//cmd/kube-proxy",
"//cmd/kubeadm",
"//cmd/kubelet",
],
)
......@@ -125,7 +126,6 @@ release_filegroup(
"//cmd/hyperkube",
"//cmd/kube-apiserver",
"//cmd/kube-controller-manager",
"//cmd/kubeadm",
"//plugin/cmd/kube-scheduler",
"//vendor/k8s.io/kube-aggregator",
],
......
......@@ -9,13 +9,19 @@ go_library(
name = "go_default_library",
srcs = [
"defaults.go",
"defaults_unix.go",
"doc.go",
"register.go",
"types.go",
"zz_generated.conversion.go",
"zz_generated.deepcopy.go",
"zz_generated.defaults.go",
] + select({
"@io_bazel_rules_go//go/platform:windows_amd64": [
"defaults_windows.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1",
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
......
......@@ -36,8 +36,6 @@ const (
DefaultAPIBindPort = 6443
// DefaultAuthorizationModes defines default authorization modes
DefaultAuthorizationModes = "Node,RBAC"
// DefaultCACertPath defines default location of CA certificate
DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
// DefaultCertificatesDir defines default certificate directory
DefaultCertificatesDir = "/etc/kubernetes/pki"
// DefaultImageRepository defines default image registry
......
// +build !windows
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
// DefaultCACertPath defines default location of CA certificate on Linux
const DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
// +build windows
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
// DefaultCACertPath defines default location of CA certificate on Windows
const DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt"
......@@ -10,8 +10,14 @@ go_library(
name = "go_default_library",
srcs = [
"checks.go",
"checks_unix.go",
"utils.go",
] + select({
"@io_bazel_rules_go//go/platform:windows_amd64": [
"checks_windows.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/preflight",
deps = [
"//cmd/kube-apiserver/app/options:go_default_library",
......
......@@ -28,6 +28,7 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"time"
......@@ -166,18 +167,8 @@ func (poc PortOpenCheck) Check() (warnings, errors []error) {
return nil, errors
}
// IsRootCheck verifies user is root
type IsRootCheck struct{}
// Check validates if an user has root privileges.
func (irc IsRootCheck) Check() (warnings, errors []error) {
errors = []error{}
if os.Getuid() != 0 {
errors = append(errors, fmt.Errorf("user is not running as root"))
}
return nil, errors
}
// IsPrivilegedUserCheck verifies user is privileged (linux - root, windows - Administrator)
type IsPrivilegedUserCheck struct{}
// DirAvailableCheck checks if the given directory either does not exist, or is empty.
type DirAvailableCheck struct {
......@@ -438,12 +429,16 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
var errs []error
var warns []error
// All the validators we'd like to run:
// All the common validators we'd like to run:
var validators = []system.Validator{
&system.OSValidator{Reporter: reporter},
&system.KernelValidator{Reporter: reporter},
&system.CgroupsValidator{Reporter: reporter},
&system.DockerValidator{Reporter: reporter},
&system.DockerValidator{Reporter: reporter}}
if runtime.GOOS == "linux" {
//add linux validators
validators = append(validators,
&system.OSValidator{Reporter: reporter},
&system.CgroupsValidator{Reporter: reporter})
}
// Run all validators
......@@ -691,7 +686,7 @@ func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
checks := []Checker{
KubernetesVersionCheck{KubernetesVersion: cfg.KubernetesVersion, KubeadmVersion: kubeadmversion.Get().GitVersion},
SystemVerificationCheck{},
IsRootCheck{},
IsPrivilegedUserCheck{},
HostnameCheck{nodeName: cfg.NodeName},
KubeletVersionCheck{},
ServiceCheck{Service: "kubelet", CheckIfActive: false},
......@@ -774,7 +769,7 @@ func RunJoinNodeChecks(cfg *kubeadmapi.NodeConfiguration) error {
checks := []Checker{
SystemVerificationCheck{},
IsRootCheck{},
IsPrivilegedUserCheck{},
HostnameCheck{cfg.NodeName},
KubeletVersionCheck{},
ServiceCheck{Service: "kubelet", CheckIfActive: false},
......@@ -783,6 +778,10 @@ func RunJoinNodeChecks(cfg *kubeadmapi.NodeConfiguration) error {
DirAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName)},
FileAvailableCheck{Path: cfg.CACertPath},
FileAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)},
}
//non-windows checks
if runtime.GOOS == "linux" {
checks = append(checks,
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
SwapCheck{},
InPathCheck{executable: "ip", mandatory: true},
......@@ -793,7 +792,7 @@ func RunJoinNodeChecks(cfg *kubeadmapi.NodeConfiguration) error {
InPathCheck{executable: "ethtool", mandatory: false},
InPathCheck{executable: "socat", mandatory: false},
InPathCheck{executable: "tc", mandatory: false},
InPathCheck{executable: "touch", mandatory: false},
InPathCheck{executable: "touch", mandatory: false})
}
if len(cfg.DiscoveryTokenAPIServers) > 0 {
......@@ -808,10 +807,10 @@ func RunJoinNodeChecks(cfg *kubeadmapi.NodeConfiguration) error {
return RunChecks(checks, os.Stderr)
}
// RunRootCheckOnly initializes cheks slice of structs and call RunChecks
// RunRootCheckOnly initializes checks slice of structs and call RunChecks
func RunRootCheckOnly() error {
checks := []Checker{
IsRootCheck{},
IsPrivilegedUserCheck{},
}
return RunChecks(checks, os.Stderr)
......
// +build !windows
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package preflight
import (
"fmt"
"os"
)
// Check validates if an user has elevated (root) privileges.
func (ipuc IsPrivilegedUserCheck) Check() (warnings, errors []error) {
errors = []error{}
if os.Getuid() != 0 {
errors = append(errors, fmt.Errorf("user is not running as root"))
}
return nil, errors
}
// +build windows
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package preflight
import (
"fmt"
"os/exec"
"strings"
)
// Check validates if an user has elevated (administrator) privileges.
func (ipuc IsPrivilegedUserCheck) Check() (warnings, errors []error) {
errors = []error{}
// The "Well-known SID" of Administrator group is S-1-5-32-544
// The following powershell will return "True" if run as an administrator, "False" otherwise
// See https://msdn.microsoft.com/en-us/library/cc980032.aspx
args := []string{"[bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match \"S-1-5-32-544\")"}
isAdmin, err := exec.Command("powershell", args...).Output()
if err != nil {
errors = append(errors, fmt.Errorf("unable to determine if user is running as administrator: %s", err))
} else if strings.EqualFold(strings.TrimSpace(string(isAdmin)), "false") {
errors = append(errors, fmt.Errorf("user is not running as administrator"))
}
return nil, errors
}
......@@ -44,6 +44,7 @@ readonly KUBE_SERVER_BINARIES=("${KUBE_SERVER_TARGETS[@]##*/}")
kube::golang::node_targets() {
local targets=(
cmd/kube-proxy
cmd/kubeadm
cmd/kubelet
)
echo "${targets[@]}"
......
......@@ -43,13 +43,13 @@ type SystemdInitSystem struct{}
func (sysd SystemdInitSystem) ServiceStart(service string) error {
args := []string{"start", service}
_, err := exec.Command("systemctl", args...).Output()
err := exec.Command("systemctl", args...).Run()
return err
}
func (sysd SystemdInitSystem) ServiceStop(service string) error {
args := []string{"stop", service}
_, err := exec.Command("systemctl", args...).Output()
err := exec.Command("systemctl", args...).Run()
return err
}
......@@ -65,7 +65,7 @@ func (sysd SystemdInitSystem) ServiceExists(service string) bool {
func (sysd SystemdInitSystem) ServiceIsEnabled(service string) bool {
args := []string{"is-enabled", service}
_, err := exec.Command("systemctl", args...).Output()
err := exec.Command("systemctl", args...).Run()
if err != nil {
return false
}
......@@ -86,7 +86,52 @@ func (sysd SystemdInitSystem) ServiceIsActive(service string) bool {
return false
}
// getInitSystem returns an InitSystem for the current system, or nil
// WindowsInitSystem is the windows implementation of InitSystem
type WindowsInitSystem struct{}
func (sysd WindowsInitSystem) ServiceStart(service string) error {
args := []string{"Start-Service", service}
err := exec.Command("powershell", args...).Run()
return err
}
func (sysd WindowsInitSystem) ServiceStop(service string) error {
args := []string{"Stop-Service", service}
err := exec.Command("powershell", args...).Run()
return err
}
func (sysd WindowsInitSystem) ServiceExists(service string) bool {
args := []string{"Get-Service", service}
err := exec.Command("powershell", args...).Run()
if err != nil {
return false
}
return true
}
func (sysd WindowsInitSystem) ServiceIsEnabled(service string) bool {
args := []string{"Get-Service", service + "| select -property starttype"}
outBytes, _ := exec.Command("powershell", args...).Output()
output := strings.TrimSpace(string(outBytes))
if strings.Contains(output, "Automatic") {
return true
}
return false
}
func (sysd WindowsInitSystem) ServiceIsActive(service string) bool {
args := []string{"Get-Service", service + "| select -property status"}
outBytes, _ := exec.Command("powershell", args...).Output()
output := strings.TrimSpace(string(outBytes))
if strings.Contains(output, "Running") {
return true
}
return false
}
// GetInitSystem returns an InitSystem for the current system, or nil
// if we cannot detect a supported init system for pre-flight checks.
// This indicates we will skip init system checks, not an error.
func GetInitSystem() (InitSystem, error) {
......@@ -95,5 +140,9 @@ func GetInitSystem() (InitSystem, error) {
if err == nil {
return &SystemdInitSystem{}, nil
}
_, err = exec.LookPath("wininit.exe")
if err == nil {
return &WindowsInitSystem{}, nil
}
return nil, fmt.Errorf("no supported init system detected, skipping checking for services")
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment