Skip to content

Commit e7bff7e

Browse files
Instead of launching kubelet directly, exec
If the only component running on the node is the kubelet, exec with the necessary args instead of running the code in the current process.
1 parent 7f2236d commit e7bff7e

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

pkg/cmd/server/kubernetes/node/options/options.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,7 @@ func buildKubeProxyConfig(options configapi.NodeConfig) (*componentconfig.KubePr
201201

202202
return proxyconfig, nil
203203
}
204+
205+
func ToFlags(config *kubeletoptions.KubeletServer) []string {
206+
return cmdflags.AsArgs(config.AddFlags, kubeletoptions.NewKubeletServer().AddFlags)
207+
}

pkg/cmd/server/start/start_node.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@ import (
55
"fmt"
66
"io"
77
"os"
8+
"os/exec"
89
"path/filepath"
910
"strings"
11+
"syscall"
1012

1113
"github.com/coreos/go-systemd/daemon"
1214
"github.com/golang/glog"
1315
"github.com/spf13/cobra"
1416

1517
kerrors "k8s.io/apimachinery/pkg/api/errors"
18+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
19+
"k8s.io/apimachinery/pkg/util/sets"
1620
"k8s.io/apimachinery/pkg/util/wait"
21+
kubeletoptions "k8s.io/kubernetes/cmd/kubelet/app/options"
1722
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
1823
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
1924

@@ -328,12 +333,85 @@ func (o NodeOptions) IsRunFromConfig() bool {
328333
return (len(o.ConfigFile) > 0)
329334
}
330335

336+
// execKubelet attempts to call execve() for the kubelet with the configuration defined
337+
// in server passed as flags. If the binary is not the same as the current file and
338+
// the environment variable OPENSHIFT_ALLOW_UNSUPPORTED_KUBELET is unset, the method
339+
// will return an error. The returned boolean indicates whether fallback to in-process
340+
// is allowed.
341+
func execKubelet(server *kubeletoptions.KubeletServer) (bool, error) {
342+
// verify the Kubelet binary to use
343+
path := "kubelet"
344+
requireSameBinary := true
345+
if newPath := os.Getenv("OPENSHIFT_ALLOW_UNSUPPORTED_KUBELET"); len(newPath) > 0 {
346+
requireSameBinary = false
347+
path = newPath
348+
}
349+
kubeletPath, err := exec.LookPath(path)
350+
if err != nil {
351+
return requireSameBinary, err
352+
}
353+
kubeletFile, err := os.Stat(kubeletPath)
354+
if err != nil {
355+
return requireSameBinary, err
356+
}
357+
thisPath, err := exec.LookPath(os.Args[0])
358+
if err != nil {
359+
return true, err
360+
}
361+
thisFile, err := os.Stat(thisPath)
362+
if err != nil {
363+
return true, err
364+
}
365+
if !os.SameFile(thisFile, kubeletFile) {
366+
if requireSameBinary {
367+
return true, fmt.Errorf("binary at %q is not the same file as %q, cannot execute", thisPath, kubeletPath)
368+
}
369+
glog.Warningf("UNSUPPORTED: Executing a different Kubelet than the current binary is not supported: %s", kubeletPath)
370+
}
371+
372+
// convert current settings to flags
373+
args := nodeoptions.ToFlags(server)
374+
args = append([]string{kubeletPath}, args...)
375+
for i := glog.Level(10); i > 0; i-- {
376+
if glog.V(i) {
377+
args = append(args, fmt.Sprintf("--v=%d", i))
378+
break
379+
}
380+
}
381+
for i, s := range os.Args {
382+
if s == "--vmodule" {
383+
if i+1 < len(os.Args) {
384+
args = append(args, fmt.Sprintf("--vmodule=", os.Args[i+1]))
385+
break
386+
}
387+
}
388+
if strings.HasPrefix(s, "--vmodule=") {
389+
args = append(args, s)
390+
break
391+
}
392+
}
393+
glog.V(3).Infof("Exec %s %s", kubeletPath, strings.Join(args, " "))
394+
return false, syscall.Exec(kubeletPath, args, os.Environ())
395+
}
396+
331397
func StartNode(nodeConfig configapi.NodeConfig, components *utilflags.ComponentFlag) error {
332398
server, proxyConfig, err := nodeoptions.Build(nodeConfig)
333399
if err != nil {
334400
return err
335401
}
336402

403+
// as a step towards decomposing OpenShift into Kubernetes components, perform an execve
404+
// to launch the Kubelet instead of loading in-process
405+
if components.Calculated().Equal(sets.NewString(ComponentKubelet)) {
406+
ok, err := execKubelet(server)
407+
if !ok {
408+
return err
409+
}
410+
if err != nil {
411+
utilruntime.HandleError(fmt.Errorf("Unable to call exec on kubelet, continuing with normal startup: %v", err))
412+
}
413+
}
414+
337415
networkConfig, err := network.New(nodeConfig, server.ClusterDomain, proxyConfig, components.Enabled(ComponentProxy), components.Enabled(ComponentDNS) && len(nodeConfig.DNSBindAddress) > 0)
338416
if err != nil {
339417
return err

pkg/cmd/util/flags/flags.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,33 @@ func Resolve(args map[string][]string, fn func(*pflag.FlagSet)) []error {
3636
return Apply(args, fs)
3737
}
3838

39+
func AsArgs(fn, defaultFn func(*pflag.FlagSet)) []string {
40+
fs := pflag.NewFlagSet("extended", pflag.ContinueOnError)
41+
fn(fs)
42+
defaults := pflag.NewFlagSet("defaults", pflag.ContinueOnError)
43+
defaultFn(defaults)
44+
var args []string
45+
fs.VisitAll(func(flag *pflag.Flag) {
46+
defaultFlag := defaults.Lookup(flag.Name)
47+
s := flag.Value.String()
48+
defaultValue := defaultFlag.Value.String()
49+
if s == defaultValue {
50+
return
51+
}
52+
if values, err := fs.GetStringSlice(flag.Name); err == nil {
53+
for _, s := range values {
54+
args = append(args, fmt.Sprintf("--%s=%s", flag.Name, s))
55+
}
56+
} else {
57+
if len(s) == 0 {
58+
s = defaultValue
59+
}
60+
args = append(args, fmt.Sprintf("--%s=%s", flag.Name, s))
61+
}
62+
})
63+
return args
64+
}
65+
3966
// ComponentFlag represents a set of enabled components used in a command line.
4067
type ComponentFlag struct {
4168
enabled string

0 commit comments

Comments
 (0)