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

Make rootless settings configurable #6498

Merged
merged 4 commits into from
Nov 21, 2022
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
6 changes: 5 additions & 1 deletion pkg/agent/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,11 @@ func Run(ctx context.Context, cfg cmds.Agent) error {
}

if cfg.Rootless && !cfg.RootlessAlreadyUnshared {
if err := rootless.Rootless(cfg.DataDir); err != nil {
dualNode, err := utilsnet.IsDualStackIPStrings(cfg.NodeIP)
if err != nil {
return err
}
if err := rootless.Rootless(cfg.DataDir, dualNode); err != nil {
return err
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ func Run(ctx *cli.Context) error {
return err
}

if os.Getuid() != 0 && runtime.GOOS != "windows" {
return fmt.Errorf("agent must be ran as root")
if runtime.GOOS != "windows" && os.Getuid() != 0 && !cmds.AgentConfig.Rootless {
return fmt.Errorf("agent must be run as root, or with --rootless")
}

if cmds.AgentConfig.TokenFile != "" {
Expand Down
8 changes: 6 additions & 2 deletions pkg/cli/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
}

if !cfg.DisableAgent && os.Getuid() != 0 && !cfg.Rootless {
return fmt.Errorf("must run as root unless --disable-agent is specified")
return fmt.Errorf("server must run as root, or with --rootless and/or --disable-agent")
}

if cfg.Rootless {
Expand All @@ -81,7 +81,11 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
}
cfg.DataDir = dataDir
if !cfg.DisableAgent {
if err := rootless.Rootless(dataDir); err != nil {
dualNode, err := utilsnet.IsDualStackIPStrings(cmds.AgentConfig.NodeIP)
if err != nil {
return err
}
if err := rootless.Rootless(dataDir, dualNode); err != nil {
return err
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/rootless/mounts.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//go:build !windows
// +build !windows

package rootless

Expand Down
99 changes: 99 additions & 0 deletions pkg/rootless/portdriver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//go:build !windows
// +build !windows

package rootless

import (
"io"
"path"
"strings"

"github.com/rootless-containers/rootlesskit/pkg/port"
portbuiltin "github.com/rootless-containers/rootlesskit/pkg/port/builtin"
portslirp4netns "github.com/rootless-containers/rootlesskit/pkg/port/slirp4netns"
"github.com/sirupsen/logrus"
)

type logrusDebugWriter struct {
}

func (w *logrusDebugWriter) Write(p []byte) (int, error) {
s := strings.TrimSuffix(string(p), "\n")
logrus.Debug(s)
return len(p), nil
}

type portDriver interface {
NewParentDriver() (port.ParentDriver, error)
NewChildDriver() port.ChildDriver
LogWriter() io.Writer
SetStateDir(string)
APISocketPath() string
}

type builtinDriver struct {
logWriter io.Writer
stateDir string
}

func (b *builtinDriver) NewParentDriver() (port.ParentDriver, error) {
return portbuiltin.NewParentDriver(b.logWriter, b.stateDir)
}

func (b *builtinDriver) NewChildDriver() port.ChildDriver {
return portbuiltin.NewChildDriver(b.logWriter)
}

func (b *builtinDriver) LogWriter() io.Writer {
return b.logWriter
}

func (b *builtinDriver) SetStateDir(stateDir string) {
b.stateDir = stateDir
}

func (b *builtinDriver) APISocketPath() string {
return ""
}

type slirp4netnsDriver struct {
logWriter io.Writer
stateDir string
}

func (s *slirp4netnsDriver) NewParentDriver() (port.ParentDriver, error) {
return portslirp4netns.NewParentDriver(s.logWriter, s.APISocketPath())
}

func (s *slirp4netnsDriver) NewChildDriver() port.ChildDriver {
return portslirp4netns.NewChildDriver()
}

func (s *slirp4netnsDriver) LogWriter() io.Writer {
return s.logWriter
}

func (s *slirp4netnsDriver) SetStateDir(stateDir string) {
s.stateDir = stateDir
}

func (s *slirp4netnsDriver) APISocketPath() string {
if s.stateDir != "" {
return path.Join(s.stateDir, ".s4nn.sock")
}
return ""
}

func getDriver(driverName string) portDriver {
logWriter := &logrusDebugWriter{}

if driverName == "slirp4netns" {
return &slirp4netnsDriver{logWriter: logWriter}
}

if driverName != "" && driverName != "builtin" {
logrus.Warnf("Unsupported port driver %s, using default builtin", driverName)
}

return &builtinDriver{logWriter: logWriter}
}
74 changes: 51 additions & 23 deletions pkg/rootless/rootless.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/rootless-containers/rootlesskit/pkg/copyup/tmpfssymlink"
"github.com/rootless-containers/rootlesskit/pkg/network/slirp4netns"
"github.com/rootless-containers/rootlesskit/pkg/parent"
portbuiltin "github.com/rootless-containers/rootlesskit/pkg/port/builtin"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
Expand All @@ -27,20 +26,28 @@ var (
childEnv = "_K3S_ROOTLESS_SOCK"
evacuateCgroup2Env = "_K3S_ROOTLESS_EVACUATE_CGROUP2" // boolean
Sock = ""

mtuEnv = "K3S_ROOTLESS_MTU"
cidrEnv = "K3S_ROOTLESS_CIDR"
enableIPv6Env = "K3S_ROOTLESS_ENABLE_IPV6"
portDriverEnv = "K3S_ROOTLESS_PORT_DRIVER"
disableLoopbackEnv = "K3S_ROOTLESS_DISABLE_HOST_LOOPBACK"
)

func Rootless(stateDir string) error {
func Rootless(stateDir string, enableIPv6 bool) error {
defer func() {
os.Unsetenv(pipeFD)
os.Unsetenv(childEnv)
}()

hasFD := os.Getenv(pipeFD) != ""
hasChildEnv := os.Getenv(childEnv) != ""
rootlessDir := filepath.Join(stateDir, "rootless")
driver := getDriver(strings.ToLower(os.Getenv(portDriverEnv)))

if hasFD {
logrus.Debug("Running rootless child")
childOpt, err := createChildOpt()
childOpt, err := createChildOpt(driver)
if err != nil {
logrus.Fatal(err)
}
Expand All @@ -59,7 +66,7 @@ func Rootless(stateDir string) error {
if err := validateSysctl(); err != nil {
logrus.Fatal(err)
}
parentOpt, err := createParentOpt(filepath.Join(stateDir, "rootless"))
parentOpt, err := createParentOpt(driver, rootlessDir, enableIPv6)
if err != nil {
logrus.Fatal(err)
}
Expand Down Expand Up @@ -120,7 +127,7 @@ func parseCIDR(s string) (*net.IPNet, error) {
return ipnet, nil
}

func createParentOpt(stateDir string) (*parent.Opt, error) {
func createParentOpt(driver portDriver, stateDir string, enableIPv6 bool) (*parent.Opt, error) {
if err := os.MkdirAll(stateDir, 0755); err != nil {
return nil, errors.Wrapf(err, "failed to mkdir %s", stateDir)
}
Expand All @@ -130,6 +137,8 @@ func createParentOpt(stateDir string) (*parent.Opt, error) {
return nil, err
}

driver.SetStateDir(stateDir)

opt := &parent.Opt{
StateDir: stateDir,
CreatePIDNS: true,
Expand All @@ -143,33 +152,61 @@ func createParentOpt(stateDir string) (*parent.Opt, error) {
return nil, err
}
if selfCgroup2 := selfCgroupMap[""]; selfCgroup2 == "" {
logrus.Warnf("enabling cgroup2 is highly recommended, see https://rootlesscontaine.rs/getting-started/common/cgroup2/")
logrus.Warnf("Enabling cgroup2 is highly recommended, see https://rootlesscontaine.rs/getting-started/common/cgroup2/")
} else {
selfCgroup2Dir := filepath.Join("/sys/fs/cgroup", selfCgroup2)
if unix.Access(selfCgroup2Dir, unix.W_OK) == nil {
opt.EvacuateCgroup2 = "k3s_evac"
} else {
logrus.Warn("cannot set cgroup2 evacuation, make sure to run k3s as a systemd unit")
logrus.Warn("Cannot set cgroup2 evacuation, make sure to run k3s as a systemd unit")
}
}

mtu := 0
ipnet, err := parseCIDR("10.41.0.0/16")
if val := os.Getenv(mtuEnv); val != "" {
if v, err := strconv.ParseInt(val, 10, 0); err != nil {
logrus.Warn("Failed to parse rootless mtu value; using default")
} else {
mtu = int(v)
}
}

disableHostLoopback := true
if val := os.Getenv(disableLoopbackEnv); val != "" {
if v, err := strconv.ParseBool(val); err != nil {
logrus.Warn("Failed to parse rootless disable-host-loopback value; using default")
} else {
disableHostLoopback = v
}
}

if val := os.Getenv(enableIPv6Env); val != "" {
if v, err := strconv.ParseBool(val); err != nil {
logrus.Warn("Failed to parse rootless enable-ipv6 value; using default")
} else {
enableIPv6 = v
}
}

cidr := "10.41.0.0/16"
if val := os.Getenv(cidrEnv); val != "" {
cidr = val
}

ipnet, err := parseCIDR(cidr)
if err != nil {
return nil, err
}
disableHostLoopback := true
binary := "slirp4netns"
if _, err := exec.LookPath(binary); err != nil {
return nil, err
}
debugWriter := &logrusDebugWriter{}
opt.NetworkDriver, err = slirp4netns.NewParentDriver(debugWriter, binary, mtu, ipnet, "tap0", disableHostLoopback, "", false, false, false)
opt.NetworkDriver, err = slirp4netns.NewParentDriver(driver.LogWriter(), binary, mtu, ipnet, "tap0", disableHostLoopback, driver.APISocketPath(), false, false, enableIPv6)
if err != nil {
return nil, err
}

opt.PortDriver, err = portbuiltin.NewParentDriver(debugWriter, stateDir)
opt.PortDriver, err = driver.NewParentDriver()
if err != nil {
return nil, err
}
Expand All @@ -179,21 +216,12 @@ func createParentOpt(stateDir string) (*parent.Opt, error) {
return opt, nil
}

type logrusDebugWriter struct {
}

func (w *logrusDebugWriter) Write(p []byte) (int, error) {
s := strings.TrimSuffix(string(p), "\n")
logrus.Debug(s)
return len(p), nil
}

func createChildOpt() (*child.Opt, error) {
func createChildOpt(driver portDriver) (*child.Opt, error) {
opt := &child.Opt{}
opt.TargetCmd = os.Args
opt.PipeFDEnvKey = pipeFD
opt.NetworkDriver = slirp4netns.NewChildDriver()
opt.PortDriver = portbuiltin.NewChildDriver(&logrusDebugWriter{})
opt.PortDriver = driver.NewChildDriver()
opt.CopyUpDirs = []string{"/etc", "/var/run", "/run", "/var/lib"}
opt.CopyUpDriver = tmpfssymlink.NewChildDriver()
opt.MountProcfs = true
Expand Down
4 changes: 2 additions & 2 deletions pkg/rootless/rootless_windows.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package rootless

func Rootless(stateDir string) error {
panic("Rootless not supported on windows")
func Rootless(stateDir string, enableIPv6 bool) error {
panic("Rootless is not supported on windows")
}