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 6 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.HookCheckLXD(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.HookCheckLXD(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.HookCheckLXD(true),
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
Run: func(cmd *cobra.Command, args []string) {
// configure logging
log.Configure(log.Options{
Expand Down
99 changes: 99 additions & 0 deletions src/k8s/cmd/util/hooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
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"}

// HookCheckLXD checks ownership of dirs required for k8s to run.
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
// HookCheckLXD if verbose true prints out list of potenital issues.
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
// If potential issue found pops up warning for user.
func HookCheckLXD(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
if lxd, err := inLXDContainer(); lxd {
Copy link
Contributor

Choose a reason for hiding this comment

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

this should first check if any err is returned and only if there is no error check for the lxd value

errMsgs := VerifyPaths()
if len(errMsgs) > 0 {
if verbose {
cmd.PrintErrln("Warning: When validating required resources potential issues found:")
for _, errMsg := range errMsgs {
cmd.PrintErrln("\t", errMsg)
}
}
cmd.PrintErrln("The lxc profile for Canonical Kubernetes might be missing.")
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())
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

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
}

// inLXDContainer checks if k8s runs in lxd container if so returns link to documentation
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
func inLXDContainer() (bool, error) {
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