@@ -5,15 +5,20 @@ import (
5
5
"fmt"
6
6
"io"
7
7
"os"
8
+ "os/exec"
8
9
"path/filepath"
9
10
"strings"
11
+ "syscall"
10
12
11
13
"github.com/coreos/go-systemd/daemon"
12
14
"github.com/golang/glog"
13
15
"github.com/spf13/cobra"
14
16
15
17
kerrors "k8s.io/apimachinery/pkg/api/errors"
18
+ utilruntime "k8s.io/apimachinery/pkg/util/runtime"
19
+ "k8s.io/apimachinery/pkg/util/sets"
16
20
"k8s.io/apimachinery/pkg/util/wait"
21
+ kubeletoptions "k8s.io/kubernetes/cmd/kubelet/app/options"
17
22
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
18
23
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
19
24
@@ -328,12 +333,85 @@ func (o NodeOptions) IsRunFromConfig() bool {
328
333
return (len (o .ConfigFile ) > 0 )
329
334
}
330
335
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
+
331
397
func StartNode (nodeConfig configapi.NodeConfig , components * utilflags.ComponentFlag ) error {
332
398
server , proxyConfig , err := nodeoptions .Build (nodeConfig )
333
399
if err != nil {
334
400
return err
335
401
}
336
402
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
+
337
415
networkConfig , err := network .New (nodeConfig , server .ClusterDomain , proxyConfig , components .Enabled (ComponentProxy ), components .Enabled (ComponentDNS ) && len (nodeConfig .DNSBindAddress ) > 0 )
338
416
if err != nil {
339
417
return err
0 commit comments