mirror of https://github.com/k3s-io/k3s
Properly handle operation as init process
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>pull/4119/head
parent
c948305076
commit
38ddda587a
|
@ -23,9 +23,16 @@ func Run(ctx *cli.Context) error {
|
||||||
// database credentials or other secrets.
|
// database credentials or other secrets.
|
||||||
gspt.SetProcTitle(os.Args[0] + " agent")
|
gspt.SetProcTitle(os.Args[0] + " agent")
|
||||||
|
|
||||||
|
// Do init stuff if pid 1.
|
||||||
|
// This must be done before InitLogging as that may reexec in order to capture log output
|
||||||
|
if err := cmds.HandleInit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := cmds.InitLogging(); err != nil {
|
if err := cmds.InitLogging(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getuid() != 0 && runtime.GOOS != "windows" {
|
if os.Getuid() != 0 && runtime.GOOS != "windows" {
|
||||||
return fmt.Errorf("agent must be ran as root")
|
return fmt.Errorf("agent must be ran as root")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
// +build !linux !cgo
|
||||||
|
|
||||||
|
package cmds
|
||||||
|
|
||||||
|
func HandleInit() error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
// +build linux,cgo
|
||||||
|
|
||||||
|
package cmds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/erikdubbelboer/gspt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/rancher/k3s/pkg/version"
|
||||||
|
"github.com/rootless-containers/rootlesskit/pkg/parent/cgrouputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleInit takes care of things that need to be done when running as process 1, usually in a
|
||||||
|
// Docker container. This includes evacuating the root cgroup and reaping child pids.
|
||||||
|
func HandleInit() error {
|
||||||
|
if os.Getpid() != 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The root cgroup has to be empty to enable subtree_control, so evacuate it by placing
|
||||||
|
// ourselves in the init cgroup.
|
||||||
|
if err := cgrouputil.EvacuateCgroup2("init"); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to evacuate root cgroup")
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to get working directory for init process")
|
||||||
|
}
|
||||||
|
|
||||||
|
go reapChildren()
|
||||||
|
|
||||||
|
// fork the main process to do work so that this init process can handle reaping pids
|
||||||
|
// without interfering with any other exec's that the rest of the codebase may do.
|
||||||
|
var wstatus syscall.WaitStatus
|
||||||
|
pattrs := &syscall.ProcAttr{
|
||||||
|
Dir: pwd,
|
||||||
|
Env: os.Environ(),
|
||||||
|
Sys: &syscall.SysProcAttr{Setsid: true},
|
||||||
|
Files: []uintptr{
|
||||||
|
uintptr(syscall.Stdin),
|
||||||
|
uintptr(syscall.Stdout),
|
||||||
|
uintptr(syscall.Stderr),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pid, err := syscall.ForkExec(os.Args[0], os.Args, pattrs)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to fork/exec "+version.Program)
|
||||||
|
}
|
||||||
|
|
||||||
|
gspt.SetProcTitle(os.Args[0] + " init")
|
||||||
|
// wait for main process to exit, and return its status when it does
|
||||||
|
_, err = syscall.Wait4(pid, &wstatus, 0, nil)
|
||||||
|
for err == syscall.EINTR {
|
||||||
|
_, err = syscall.Wait4(pid, &wstatus, 0, nil)
|
||||||
|
}
|
||||||
|
os.Exit(wstatus.ExitStatus())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//reapChildren calls Wait4 whenever SIGCHLD is received
|
||||||
|
func reapChildren() {
|
||||||
|
sigs := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigs, syscall.SIGCHLD)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-sigs:
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
var wstatus syscall.WaitStatus
|
||||||
|
_, err := syscall.Wait4(-1, &wstatus, 0, nil)
|
||||||
|
for err == syscall.EINTR {
|
||||||
|
_, err = syscall.Wait4(-1, &wstatus, 0, nil)
|
||||||
|
}
|
||||||
|
if err == nil || err == syscall.ECHILD {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,16 +38,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(app *cli.Context) error {
|
func Run(app *cli.Context) error {
|
||||||
if err := cmds.InitLogging(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return run(app, &cmds.ServerConfig, server.CustomControllers{}, server.CustomControllers{})
|
return run(app, &cmds.ServerConfig, server.CustomControllers{}, server.CustomControllers{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunWithControllers(app *cli.Context, leaderControllers server.CustomControllers, controllers server.CustomControllers) error {
|
func RunWithControllers(app *cli.Context, leaderControllers server.CustomControllers, controllers server.CustomControllers) error {
|
||||||
if err := cmds.InitLogging(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return run(app, &cmds.ServerConfig, leaderControllers, controllers)
|
return run(app, &cmds.ServerConfig, leaderControllers, controllers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +54,16 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
|
||||||
// database credentials or other secrets.
|
// database credentials or other secrets.
|
||||||
gspt.SetProcTitle(os.Args[0] + " server")
|
gspt.SetProcTitle(os.Args[0] + " server")
|
||||||
|
|
||||||
|
// Do init stuff if pid 1.
|
||||||
|
// This must be done before InitLogging as that may reexec in order to capture log output
|
||||||
|
if err := cmds.HandleInit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cmds.InitLogging(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if !cfg.DisableAgent && os.Getuid() != 0 && !cfg.Rootless {
|
if !cfg.DisableAgent && os.Getuid() != 0 && !cfg.Rootless {
|
||||||
return fmt.Errorf("must run as root unless --disable-agent is specified")
|
return fmt.Errorf("must run as root unless --disable-agent is specified")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue