Skip to content

Commit

Permalink
Warnings that k8s service may not work (#657)
Browse files Browse the repository at this point in the history
Warnings that k8s service may not work (#657)
KU-1475
  • Loading branch information
maci3jka authored and evilnick committed Sep 18, 2024
1 parent f1d1254 commit f55f6f8
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 2 deletions.
35 changes: 35 additions & 0 deletions src/k8s/cmd/k8s/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package k8s

import (
cmdutil "github.com/canonical/k8s/cmd/util"

"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -34,3 +35,37 @@ func hookInitializeFormatter(env cmdutil.ExecutionEnvironment, format *string) f
}
}
}

// hookCheckLXD verifies the ownership of directories needed for Kubernetes to function.
// If a potential issue is detected, it displays a warning to the user.
func hookCheckLXD() func(*cobra.Command, []string) {
return func(cmd *cobra.Command, args []string) {
// pathsOwnershipCheck paths to validate root is the owner
var pathsOwnershipCheck = []string{"/sys", "/proc", "/dev/kmsg"}
inLXD, err := cmdutil.InLXDContainer()
if err != nil {
cmd.PrintErrf("Failed to check if running inside LXD container: %s", err.Error())
return
}
if inLXD {
var errMsgs []string
for _, pathToCheck := range pathsOwnershipCheck {
if err = cmdutil.ValidateRootOwnership(pathToCheck); err != nil {
errMsgs = append(errMsgs, err.Error())
}
}
if len(errMsgs) > 0 {
if debug, _ := cmd.Flags().GetBool("debug"); debug {
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/")
}
}
return
}
}
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), hookCheckLXD()),
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), hookCheckLXD()),
Args: cmdutil.ExactArgs(env, 1),
Run: func(cmd *cobra.Command, args []string) {
token := args[0]
Expand Down
56 changes: 56 additions & 0 deletions src/k8s/cmd/util/hooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package cmdutil

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

// getFileOwnerAndGroup retrieves the UID and GID of a file.
func getFileOwnerAndGroup(filePath string) (uid, gid uint32, err error) {
// Get file info using os.Stat
fileInfo, err := os.Stat(filePath)
if err != nil {
return 0, 0, fmt.Errorf("error getting file info: %w", err)
}
// Convert the fileInfo.Sys() to syscall.Stat_t to access UID and GID
stat, ok := fileInfo.Sys().(*syscall.Stat_t)
if !ok {
return 0, 0, fmt.Errorf("failed to cast to syscall.Stat_t")
}
// Return the UID and GID
return stat.Uid, stat.Gid, nil
}

// ValidateRootOwnership checks if the specified path is owned by the root user and root group.
func ValidateRootOwnership(path string) (err error) {
UID, GID, err := getFileOwnerAndGroup(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 a lxd container.
func InLXDContainer() (isLXD bool, err error) {
initialProcessEnvironmentVariables := "/proc/1/environ"
content, err := os.ReadFile(initialProcessEnvironmentVariables)
if err != nil {
// if the permission to file is missing we still want to display info about lxd
if os.IsPermission(err) {
return true, fmt.Errorf("cannnot access %s to check if runing in LXD container: %w", initialProcessEnvironmentVariables, err)
}
return false, fmt.Errorf("cannnot read %s to check if runing in LXD container: %w", initialProcessEnvironmentVariables, err)
}
if strings.Contains(string(content), "container=lxc") {
return true, nil
}
return false, nil
}

0 comments on commit f55f6f8

Please sign in to comment.