Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kubeadm: Add a preflight check that the control-plane node has at least 1700MB of RAM #93275

Merged
merged 2 commits into from
Sep 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/kubeadm/app/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,10 @@ const (
// ControlPlaneNumCPU is the number of CPUs required on control-plane
ControlPlaneNumCPU = 2

// ControlPlaneMem is the number of megabytes of memory required on the control-plane
// Below that amount of RAM running a stable control plane would be difficult.
ControlPlaneMem = 1700

// KubeadmCertsSecret specifies in what Secret in the kube-system namespace the certificates should be stored
KubeadmCertsSecret = "kubeadm-certs"

Expand Down
13 changes: 13 additions & 0 deletions cmd/kubeadm/app/preflight/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,16 @@ func (ncc NumCPUCheck) Check() (warnings, errorList []error) {
return warnings, errorList
}

// MemCheck checks if the number of megabytes of memory is not less than required
type MemCheck struct {
Mem uint64
}

// Name returns the label for memory
func (MemCheck) Name() string {
return "Mem"
}

// RunInitNodeChecks executes all individual, applicable to control-plane node checks.
// The boolean flag 'isSecondaryControlPlane' controls whether we are running checks in a --join-control-plane scenario.
// The boolean flag 'downloadCerts' controls whether we should skip checks on certificates because we are downloading them.
Expand All @@ -884,6 +894,9 @@ func RunInitNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.InitConfigura
manifestsDir := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName)
checks := []Checker{
NumCPUCheck{NumCPU: kubeadmconstants.ControlPlaneNumCPU},
// Linux only
// TODO: support other OS, if control-plane is supported on it.
MemCheck{Mem: kubeadmconstants.ControlPlaneMem},
KubernetesVersionCheck{KubernetesVersion: cfg.KubernetesVersion, KubeadmVersion: kubeadmversion.Get().GitVersion},
FirewalldCheck{ports: []int{int(cfg.LocalAPIEndpoint.BindPort), kubeadmconstants.KubeletPort}},
PortOpenCheck{port: int(cfg.LocalAPIEndpoint.BindPort)},
Expand Down
6 changes: 6 additions & 0 deletions cmd/kubeadm/app/preflight/checks_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,9 @@ package preflight
func (idsc IsDockerSystemdCheck) Check() (warnings, errorList []error) {
return nil, nil
}

// Check number of memory required by kubeadm
// No-op for Darwin (MacOS).
func (mc MemCheck) Check() (warnings, errorList []error) {
return nil, nil
}
18 changes: 18 additions & 0 deletions cmd/kubeadm/app/preflight/checks_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ limitations under the License.
package preflight

import (
"syscall"

"github.com/pkg/errors"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/utils/exec"
Expand All @@ -40,3 +42,19 @@ func (idsc IsDockerSystemdCheck) Check() (warnings, errorList []error) {
}
return nil, nil
}

// Check number of memory required by kubeadm
func (mc MemCheck) Check() (warnings, errorList []error) {
info := syscall.Sysinfo_t{}
err := syscall.Sysinfo(&info)
if err != nil {
errorList = append(errorList, errors.Wrapf(err, "failed to get system info"))
}

// Totalram returns bytes; convert to MB
actual := uint64(info.Totalram) / 1024 / 1024
if actual < mc.Mem {
errorList = append(errorList, errors.Errorf("the system RAM (%d MB) is less than the minimum %d MB", actual, mc.Mem))
}
return warnings, errorList
}
27 changes: 27 additions & 0 deletions cmd/kubeadm/app/preflight/checks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"bytes"
"fmt"
"io/ioutil"
"runtime"
"strings"
"testing"

Expand Down Expand Up @@ -849,3 +850,29 @@ func TestNumCPUCheck(t *testing.T) {
})
}
}

func TestMemCheck(t *testing.T) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test will ONLY pass on Linux. should we remove? @neolit123 @rosti

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can skip it if the GOOS != "linux"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// skip this test, if OS in not Linux, since it will ONLY pass on Linux.
if runtime.GOOS != "linux" {
t.Skip("unsupported OS for memory check test ")
}

var tests = []struct {
minimum uint64
expectedErrors int
}{
{0, 0},
{9999999999999999, 1},
}

for _, rt := range tests {
t.Run(fmt.Sprintf("MemoryCheck{%d}", rt.minimum), func(t *testing.T) {
warnings, errors := MemCheck{Mem: rt.minimum}.Check()
if len(warnings) > 0 {
t.Errorf("expected 0 warnings but got %d: %q", len(warnings), warnings)
} else if len(errors) != rt.expectedErrors {
t.Errorf("expected %d error(s) but got %d: %q", rt.expectedErrors, len(errors), errors)
}
})
}
}
6 changes: 6 additions & 0 deletions cmd/kubeadm/app/preflight/checks_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,9 @@ func (ipuc IsPrivilegedUserCheck) Check() (warnings, errorList []error) {
func (idsc IsDockerSystemdCheck) Check() (warnings, errorList []error) {
return nil, nil
}

// Check number of memory required by kubeadm
// No-op for Windows.
func (mc MemCheck) Check() (warnings, errorList []error) {
return nil, nil
}