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

Warnings that k8s service may not work #657

Merged
merged 11 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion src/k8s/cmd/k8s/k8s_bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func newBootstrapCmd(env cmdutil.ExecutionEnvironment) *cobra.Command {
Use: "bootstrap",
Short: "Bootstrap a new Kubernetes cluster",
Long: "Generate certificates, configure service arguments and start the Kubernetes services.",
PreRun: chainPreRunHooks(hookRequireRoot(env), hookInitializeFormatter(env, &opts.outputFormat)),
PreRun: chainPreRunHooks(hookRequireRoot(env), hookInitializeFormatter(env, &opts.outputFormat), cmdutil.HookVerifyResources(false)),
Run: func(cmd *cobra.Command, args []string) {
if opts.interactive && opts.configFile != "" {
cmd.PrintErrln("Error: --interactive and --file flags cannot be set at the same time.")
Expand Down
2 changes: 1 addition & 1 deletion src/k8s/cmd/k8s/k8s_join_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func newJoinClusterCmd(env cmdutil.ExecutionEnvironment) *cobra.Command {
cmd := &cobra.Command{
Use: "join-cluster <join-token>",
Short: "Join a cluster using the provided token",
PreRun: chainPreRunHooks(hookRequireRoot(env), hookInitializeFormatter(env, &opts.outputFormat)),
PreRun: chainPreRunHooks(hookRequireRoot(env), hookInitializeFormatter(env, &opts.outputFormat), cmdutil.HookVerifyResources(false)),
Args: cmdutil.ExactArgs(env, 1),
Run: func(cmd *cobra.Command, args []string) {
token := args[0]
Expand Down
5 changes: 3 additions & 2 deletions src/k8s/cmd/k8sd/k8sd.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ func addCommands(root *cobra.Command, group *cobra.Group, commands ...*cobra.Com

func NewRootCmd(env cmdutil.ExecutionEnvironment) *cobra.Command {
cmd := &cobra.Command{
Use: "k8sd",
Short: "Canonical Kubernetes orchestrator and clustering daemon",
Use: "k8sd",
Short: "Canonical Kubernetes orchestrator and clustering daemon",
PreRun: cmdutil.HookVerifyResources(true),
Run: func(cmd *cobra.Command, args []string) {
// configure logging
log.Configure(log.Options{
Expand Down
102 changes: 102 additions & 0 deletions src/k8s/cmd/util/hooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package cmdutil

import (
"fmt"
"os"
"strings"
"syscall"

"github.com/spf13/cobra"
)

const initialProcesEnvironmentVariables = "/proc/1/environ"
Copy link
Contributor

Choose a reason for hiding this comment

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

Process

Copy link
Contributor

Choose a reason for hiding this comment

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

also add a short comment please


// paths to validate if root in the owner
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
var pathsOwnershipCheck = []string{"/sys", "/proc", "/dev/kmsg"}

// HookVerifyResources checks ownership of dirs required for k8s to run.
// HookVerifyResources if verbose true prints out list of potenital issues.
// If potential issue found pops up warning for user.
func HookVerifyResources(verbose bool) func(*cobra.Command, []string) {
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
return func(cmd *cobra.Command, args []string) {
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
errMsgs := VerifyPaths()

// printing report
if len(errMsgs) > 0 {
if verbose {
cmd.PrintErrln("Warning: When validating required resources potential issues found:")
for _, errMsg := range errMsgs {
cmd.PrintErrln("\t", errMsg)
}
}
if lxd, err := validateLXD(); lxd {
cmd.PrintErrln("The lxc profile for MicroK8s might be missing.")
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
cmd.PrintErrln("For running k8s inside LXD container refer to " +
"https://documentation.ubuntu.com/canonical-kubernetes/latest/snap/howto/install/lxd/")
} else if err != nil {
cmd.PrintErrf(err.Error())

}
}
}
}

func VerifyPaths() []string {
Copy link
Contributor

Choose a reason for hiding this comment

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

does this need to be public?

var errMsg []string
// check ownership of required dirs
for _, pathToCheck := range pathsOwnershipCheck {
if err := validateRootOwnership(pathToCheck); err != nil {
errMsg = append(errMsg, err.Error())
}
}
return errMsg
}

func getOwnership(path string) (int, int, error) {
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
info, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return 0, 0, fmt.Errorf("%s do not exist", path)
} else {
return 0, 0, err
}
}
if stat, ok := info.Sys().(*syscall.Stat_t); ok {
return int(stat.Uid), int(stat.Gid), nil
} else {
return 0, 0, fmt.Errorf("cannot access %s", path)
}
}

// validateRootOwnership checks if given path owner root and root group.
func validateRootOwnership(path string) error {
UID, GID, err := getOwnership(path)
if err != nil {
return err
}
if UID != 0 {
return fmt.Errorf("owner of %s is user with UID %d expected 0", path, UID)
}
if GID != 0 {
return fmt.Errorf("owner of %s is group with GID %d expected 0", path, GID)
}
return nil
}

// validateLXD checks if k8s runs in lxd container if so returns link to documentation
func validateLXD() (bool, error) {
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
dat, err := os.ReadFile(initialProcesEnvironmentVariables)
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
// if permission to file is missing we still want to display info about lxd
if os.IsPermission(err) {
return true, err
}
return false, err
}
env := string(dat)
if strings.Contains(env, "container=lxc") {

maci3jka marked this conversation as resolved.
Show resolved Hide resolved
return true, nil
}
return false, nil
}
Loading