mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			273 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
| Copyright 2014 Google Inc. All rights reserved.
 | |
| 
 | |
| Licensed under the Apache License, Version 2.0 (the "License");
 | |
| you may not use this file except in compliance with the License.
 | |
| You may obtain a copy of the License at
 | |
| 
 | |
|     http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| Unless required by applicable law or agreed to in writing, software
 | |
| distributed under the License is distributed on an "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| See the License for the specific language governing permissions and
 | |
| limitations under the License.
 | |
| */
 | |
| 
 | |
| package standalone
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"math"
 | |
| 	"net"
 | |
| 	"net/http"
 | |
| 	"os"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | |
| 	minionControllerPkg "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/controller"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/config"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/resources"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/service"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler"
 | |
| 	"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler/factory"
 | |
| 
 | |
| 	"github.com/golang/glog"
 | |
| )
 | |
| 
 | |
| type delegateHandler struct {
 | |
| 	delegate http.Handler
 | |
| }
 | |
| 
 | |
| func (h *delegateHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | |
| 	if h.delegate != nil {
 | |
| 		h.delegate.ServeHTTP(w, req)
 | |
| 		return
 | |
| 	}
 | |
| 	w.WriteHeader(http.StatusNotFound)
 | |
| }
 | |
| 
 | |
| // Get a docker endpoint, either from the string passed in, or $DOCKER_HOST environment variables
 | |
| func GetDockerEndpoint(dockerEndpoint string) string {
 | |
| 	var endpoint string
 | |
| 	if len(dockerEndpoint) > 0 {
 | |
| 		endpoint = dockerEndpoint
 | |
| 	} else if len(os.Getenv("DOCKER_HOST")) > 0 {
 | |
| 		endpoint = os.Getenv("DOCKER_HOST")
 | |
| 	} else {
 | |
| 		endpoint = "unix:///var/run/docker.sock"
 | |
| 	}
 | |
| 	glog.Infof("Connecting to docker on %s", endpoint)
 | |
| 
 | |
| 	return endpoint
 | |
| }
 | |
| 
 | |
| // RunApiServer starts an API server in a go routine.
 | |
| func RunApiServer(cl *client.Client, etcdClient tools.EtcdClient, addr string, port int) {
 | |
| 	handler := delegateHandler{}
 | |
| 
 | |
| 	helper, err := master.NewEtcdHelper(etcdClient, "")
 | |
| 	if err != nil {
 | |
| 		glog.Fatalf("Unable to get etcd helper: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Create a master and install handlers into mux.
 | |
| 	m := master.New(&master.Config{
 | |
| 		Client:     cl,
 | |
| 		EtcdHelper: helper,
 | |
| 		KubeletClient: &client.HTTPKubeletClient{
 | |
| 			Client: http.DefaultClient,
 | |
| 			Port:   10250,
 | |
| 		},
 | |
| 		EnableLogsSupport: false,
 | |
| 		APIPrefix:         "/api",
 | |
| 		Authorizer:        apiserver.NewAlwaysAllowAuthorizer(),
 | |
| 
 | |
| 		ReadWritePort: port,
 | |
| 		ReadOnlyPort:  port,
 | |
| 		PublicAddress: addr,
 | |
| 	})
 | |
| 
 | |
| 	handler.delegate = m.InsecureHandler
 | |
| 
 | |
| 	go http.ListenAndServe(fmt.Sprintf("%s:%d", addr, port), &handler)
 | |
| }
 | |
| 
 | |
| // RunScheduler starts up a scheduler in it's own goroutine
 | |
| func RunScheduler(cl *client.Client) {
 | |
| 	// Scheduler
 | |
| 	schedulerConfigFactory := factory.NewConfigFactory(cl)
 | |
| 	schedulerConfig, err := schedulerConfigFactory.Create(nil, nil)
 | |
| 	if err != nil {
 | |
| 		glog.Fatal("Couldn't create scheduler config: %v", err)
 | |
| 	}
 | |
| 	scheduler.New(schedulerConfig).Run()
 | |
| }
 | |
| 
 | |
| // RunControllerManager starts a controller
 | |
| func RunControllerManager(machineList []string, cl *client.Client, nodeMilliCPU, nodeMemory int64) {
 | |
| 	if int64(int(nodeMilliCPU)) != nodeMilliCPU {
 | |
| 		glog.Warningf("node_milli_cpu is too big for platform. Clamping: %d -> %d",
 | |
| 			nodeMilliCPU, math.MaxInt32)
 | |
| 		nodeMilliCPU = math.MaxInt32
 | |
| 	}
 | |
| 
 | |
| 	if int64(int(nodeMemory)) != nodeMemory {
 | |
| 		glog.Warningf("node_memory is too big for platform. Clamping: %d -> %d",
 | |
| 			nodeMemory, math.MaxInt32)
 | |
| 		nodeMemory = math.MaxInt32
 | |
| 	}
 | |
| 
 | |
| 	nodeResources := &api.NodeResources{
 | |
| 		Capacity: api.ResourceList{
 | |
| 			resources.CPU:    util.NewIntOrStringFromInt(int(nodeMilliCPU)),
 | |
| 			resources.Memory: util.NewIntOrStringFromInt(int(nodeMemory)),
 | |
| 		},
 | |
| 	}
 | |
| 	minionController := minionControllerPkg.NewMinionController(nil, "", machineList, nodeResources, cl)
 | |
| 	minionController.Run(10 * time.Second)
 | |
| 
 | |
| 	endpoints := service.NewEndpointController(cl)
 | |
| 	go util.Forever(func() { endpoints.SyncServiceEndpoints() }, time.Second*10)
 | |
| 
 | |
| 	controllerManager := controller.NewReplicationManager(cl)
 | |
| 	controllerManager.Run(10 * time.Second)
 | |
| }
 | |
| 
 | |
| // SimpleRunKubelet is a simple way to start a Kubelet talking to dockerEndpoint, using an etcdClient.
 | |
| // Under the hood it calls RunKubelet (below)
 | |
| func SimpleRunKubelet(etcdClient tools.EtcdClient, dockerClient dockertools.DockerInterface, hostname, rootDir, manifestURL, address string, port uint) {
 | |
| 	kcfg := KubeletConfig{
 | |
| 		EtcdClient:            etcdClient,
 | |
| 		DockerClient:          dockerClient,
 | |
| 		HostnameOverride:      hostname,
 | |
| 		RootDirectory:         rootDir,
 | |
| 		ManifestURL:           manifestURL,
 | |
| 		NetworkContainerImage: kubelet.NetworkContainerImage,
 | |
| 		Port:                    port,
 | |
| 		Address:                 util.IP(net.ParseIP(address)),
 | |
| 		EnableServer:            true,
 | |
| 		EnableDebuggingHandlers: true,
 | |
| 	}
 | |
| 	RunKubelet(&kcfg)
 | |
| }
 | |
| 
 | |
| // RunKubelet is responsible for setting up and running a kubelet.  It is used in three different applications:
 | |
| //   1 Integration tests
 | |
| //   2 Kubelet binary
 | |
| //   3 Standalone 'kubernetes' binary
 | |
| // Eventually, #2 will be replaced with instances of #3
 | |
| func RunKubelet(kcfg *KubeletConfig) {
 | |
| 	kubelet.SetupEventSending(kcfg.AuthPath, kcfg.ApiServerList)
 | |
| 	kubelet.SetupLogging()
 | |
| 	kubelet.SetupCapabilities(kcfg.AllowPrivileged)
 | |
| 
 | |
| 	kcfg.Hostname = kubelet.GetHostname(kcfg.HostnameOverride)
 | |
| 	if len(kcfg.RootDirectory) > 0 {
 | |
| 		kubelet.SetupRootDirectoryOrDie(kcfg.RootDirectory)
 | |
| 	}
 | |
| 
 | |
| 	cfg := makePodSourceConfig(kcfg)
 | |
| 	k := createAndInitKubelet(kcfg)
 | |
| 	// process pods and exit.
 | |
| 	if kcfg.Runonce {
 | |
| 		if _, err := k.RunOnce(cfg.Updates()); err != nil {
 | |
| 			glog.Errorf("--runonce failed: %v", err)
 | |
| 		}
 | |
| 	} else {
 | |
| 		startKubelet(k, cfg, kcfg)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func startKubelet(k *kubelet.Kubelet, cfg *config.PodConfig, kc *KubeletConfig) {
 | |
| 	// start the kubelet
 | |
| 	go util.Forever(func() { k.Run(cfg.Updates()) }, 0)
 | |
| 
 | |
| 	// start the kubelet server
 | |
| 	if kc.EnableServer {
 | |
| 		go util.Forever(func() {
 | |
| 			kubelet.ListenAndServeKubeletServer(k, cfg.Channel("http"), net.IP(kc.Address), kc.Port, kc.EnableDebuggingHandlers)
 | |
| 		}, 0)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func makePodSourceConfig(kc *KubeletConfig) *config.PodConfig {
 | |
| 	// source of all configuration
 | |
| 	cfg := config.NewPodConfig(config.PodConfigNotificationSnapshotAndUpdates)
 | |
| 
 | |
| 	// define file config source
 | |
| 	if kc.ConfigFile != "" {
 | |
| 		config.NewSourceFile(kc.ConfigFile, kc.FileCheckFrequency, cfg.Channel("file"))
 | |
| 	}
 | |
| 
 | |
| 	// define url config source
 | |
| 	if kc.ManifestURL != "" {
 | |
| 		config.NewSourceURL(kc.ManifestURL, kc.HttpCheckFrequency, cfg.Channel("http"))
 | |
| 	}
 | |
| 
 | |
| 	if kc.EtcdClient != nil {
 | |
| 		glog.Infof("Watching for etcd configs at %v", kc.EtcdClient.GetCluster())
 | |
| 		config.NewSourceEtcd(config.EtcdKeyForHost(kc.Hostname), kc.EtcdClient, cfg.Channel("etcd"))
 | |
| 	}
 | |
| 	return cfg
 | |
| }
 | |
| 
 | |
| type KubeletConfig struct {
 | |
| 	EtcdClient              tools.EtcdClient
 | |
| 	DockerClient            dockertools.DockerInterface
 | |
| 	Address                 util.IP
 | |
| 	AuthPath                string
 | |
| 	ApiServerList           util.StringList
 | |
| 	AllowPrivileged         bool
 | |
| 	HostnameOverride        string
 | |
| 	RootDirectory           string
 | |
| 	ConfigFile              string
 | |
| 	ManifestURL             string
 | |
| 	FileCheckFrequency      time.Duration
 | |
| 	HttpCheckFrequency      time.Duration
 | |
| 	Hostname                string
 | |
| 	NetworkContainerImage   string
 | |
| 	SyncFrequency           time.Duration
 | |
| 	RegistryPullQPS         float64
 | |
| 	RegistryBurst           int
 | |
| 	MinimumGCAge            time.Duration
 | |
| 	MaxContainerCount       int
 | |
| 	EnableServer            bool
 | |
| 	EnableDebuggingHandlers bool
 | |
| 	Port                    uint
 | |
| 	Runonce                 bool
 | |
| }
 | |
| 
 | |
| func createAndInitKubelet(kc *KubeletConfig) *kubelet.Kubelet {
 | |
| 	// TODO: block until all sources have delivered at least one update to the channel, or break the sync loop
 | |
| 	// up into "per source" synchronizations
 | |
| 
 | |
| 	k := kubelet.NewMainKubelet(
 | |
| 		kc.Hostname,
 | |
| 		kc.DockerClient,
 | |
| 		kc.EtcdClient,
 | |
| 		kc.RootDirectory,
 | |
| 		kc.NetworkContainerImage,
 | |
| 		kc.SyncFrequency,
 | |
| 		float32(kc.RegistryPullQPS),
 | |
| 		kc.RegistryBurst,
 | |
| 		kc.MinimumGCAge,
 | |
| 		kc.MaxContainerCount)
 | |
| 
 | |
| 	k.BirthCry()
 | |
| 
 | |
| 	go kubelet.GarbageCollectLoop(k)
 | |
| 	go kubelet.MonitorCAdvisor(k)
 | |
| 	kubelet.InitHealthChecking(k)
 | |
| 
 | |
| 	return k
 | |
| }
 |