2014-06-06 23:40:48 +00:00
/ *
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 .
* /
2014-06-23 18:32:11 +00:00
2014-06-06 23:40:48 +00:00
// The kubelet binary is responsible for maintaining a set of containers on a particular host VM.
2014-06-24 04:14:15 +00:00
// It syncs data from both configuration file(s) as well as from a quorum of etcd servers.
2014-06-06 23:40:48 +00:00
// It then queries Docker to see what is currently running. It synchronizes the configuration data,
// with the running set of containers by starting or stopping Docker containers.
package main
import (
"flag"
"math/rand"
2014-07-15 20:24:41 +00:00
"net/http"
2014-06-27 23:07:30 +00:00
"os"
2014-06-12 02:04:14 +00:00
"os/exec"
2014-07-19 00:13:34 +00:00
"path"
2014-07-15 20:24:41 +00:00
"strings"
2014-06-06 23:40:48 +00:00
"time"
2014-09-16 14:04:12 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities"
2014-08-13 04:33:56 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/health"
2014-07-15 13:54:23 +00:00
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/healthz"
2014-06-06 23:40:48 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
2014-07-15 20:24:41 +00:00
kconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/config"
2014-09-12 13:45:39 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
2014-07-22 21:40:59 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
2014-06-25 03:51:57 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
2014-08-30 06:19:32 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/version/verflag"
2014-06-06 23:40:48 +00:00
"github.com/coreos/go-etcd/etcd"
"github.com/fsouza/go-dockerclient"
2014-06-25 03:51:57 +00:00
"github.com/golang/glog"
2014-07-15 20:24:41 +00:00
"github.com/google/cadvisor/client"
2014-06-06 23:40:48 +00:00
)
2014-07-19 00:13:34 +00:00
const defaultRootDir = "/var/lib/kubelet"
2014-06-06 23:40:48 +00:00
var (
2014-06-24 04:14:15 +00:00
config = flag . String ( "config" , "" , "Path to the config file or directory of files" )
2014-06-11 06:29:35 +00:00
syncFrequency = flag . Duration ( "sync_frequency" , 10 * time . Second , "Max period between synchronizing running containers and config" )
2014-06-24 04:14:15 +00:00
fileCheckFrequency = flag . Duration ( "file_check_frequency" , 20 * time . Second , "Duration between checking config files for new data" )
2014-06-11 06:29:35 +00:00
httpCheckFrequency = flag . Duration ( "http_check_frequency" , 20 * time . Second , "Duration between checking http for new data" )
2014-07-08 06:30:18 +00:00
manifestURL = flag . String ( "manifest_url" , "" , "URL for accessing the container manifest" )
2014-08-07 00:28:41 +00:00
enableServer = flag . Bool ( "enable_server" , true , "Enable the info server" )
address = flag . String ( "address" , "127.0.0.1" , "The address for the info server to serve on (set to 0.0.0.0 or \"\" for all interfaces)" )
2014-09-12 13:45:39 +00:00
port = flag . Uint ( "port" , master . KubeletPort , "The port for the info server to serve on" )
2014-06-15 17:24:36 +00:00
hostnameOverride = flag . String ( "hostname_override" , "" , "If non-empty, will use this string as identification instead of the actual hostname." )
2014-06-27 23:07:30 +00:00
dockerEndpoint = flag . String ( "docker_endpoint" , "" , "If non-empty, use this for the docker endpoint to communicate with" )
2014-07-20 14:48:47 +00:00
etcdServerList util . StringList
2014-07-19 00:13:34 +00:00
rootDirectory = flag . String ( "root_dir" , defaultRootDir , "Directory path for managing kubelet files (volume mounts,etc)." )
2014-09-16 14:04:12 +00:00
allowPrivileged = flag . Bool ( "allow_privileged" , false , "If true, allow containers to request privileged mode. [default=false]" )
2014-09-26 04:24:44 +00:00
registryPullQPS = flag . Float64 ( "registry_qps" , 0.0 , "If > 0, limit registry pull QPS to this value. If 0, unlimited. [default=0.0]" )
registryBurst = flag . Int ( "registry_burst" , 10 , "Maximum size of a bursty pulls, temporarily allows pulls to burst to this number, while still not exceeding registry_qps. Only used if --registry_qps > 0" )
2014-06-06 23:40:48 +00:00
)
2014-07-20 14:48:47 +00:00
func init ( ) {
flag . Var ( & etcdServerList , "etcd_servers" , "List of etcd servers to watch (http://ip:port), comma separated" )
}
2014-07-20 04:33:06 +00:00
func getDockerEndpoint ( ) string {
2014-06-27 23:07:30 +00:00
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 )
2014-06-06 23:40:48 +00:00
2014-07-20 04:33:06 +00:00
return endpoint
}
func getHostname ( ) string {
2014-06-15 17:24:36 +00:00
hostname := [ ] byte ( * hostnameOverride )
if string ( hostname ) == "" {
2014-06-24 04:14:15 +00:00
// Note: We use exec here instead of os.Hostname() because we
// want the FQDN, and this is the easiest way to get it.
2014-07-20 04:33:06 +00:00
fqdn , err := exec . Command ( "hostname" , "-f" ) . Output ( )
2014-06-15 17:24:36 +00:00
if err != nil {
2014-06-25 03:51:57 +00:00
glog . Fatalf ( "Couldn't determine hostname: %v" , err )
2014-06-15 17:24:36 +00:00
}
2014-07-20 04:33:06 +00:00
hostname = fqdn
}
2014-07-15 20:24:41 +00:00
return strings . TrimSpace ( string ( hostname ) )
2014-07-20 04:33:06 +00:00
}
func main ( ) {
flag . Parse ( )
util . InitLogs ( )
defer util . FlushLogs ( )
rand . Seed ( time . Now ( ) . UTC ( ) . UnixNano ( ) )
2014-08-01 05:55:44 +00:00
verflag . PrintAndExitIfRequested ( )
2014-07-30 22:21:34 +00:00
2014-07-20 04:33:06 +00:00
etcd . SetLogger ( util . NewLogger ( "etcd " ) )
2014-09-16 22:18:33 +00:00
capabilities . Initialize ( capabilities . Capabilities {
2014-09-16 14:04:12 +00:00
AllowPrivileged : * allowPrivileged ,
} )
2014-07-20 04:33:06 +00:00
dockerClient , err := docker . NewClient ( getDockerEndpoint ( ) )
if err != nil {
glog . Fatal ( "Couldn't connect to docker." )
2014-06-12 01:57:15 +00:00
}
2014-07-31 20:14:00 +00:00
cadvisorClient , err := cadvisor . NewClient ( "http://127.0.0.1:4194" )
2014-07-15 20:24:41 +00:00
if err != nil {
glog . Errorf ( "Error on creating cadvisor client: %v" , err )
}
hostname := getHostname ( )
2014-07-19 00:13:34 +00:00
if * rootDirectory == "" {
glog . Fatal ( "Invalid root directory path." )
}
* rootDirectory = path . Clean ( * rootDirectory )
os . MkdirAll ( * rootDirectory , 0750 )
2014-07-15 20:24:41 +00:00
// source of all configuration
cfg := kconfig . NewPodConfig ( kconfig . PodConfigNotificationSnapshotAndUpdates )
// define file config source
if * config != "" {
kconfig . NewSourceFile ( * config , * fileCheckFrequency , cfg . Channel ( "file" ) )
}
// define url config source
if * manifestURL != "" {
kconfig . NewSourceURL ( * manifestURL , * httpCheckFrequency , cfg . Channel ( "http" ) )
2014-06-06 23:40:48 +00:00
}
2014-07-15 20:24:41 +00:00
// define etcd config source and initialize etcd client
2014-07-22 21:40:59 +00:00
var etcdClient tools . EtcdClient
2014-07-15 20:24:41 +00:00
if len ( etcdServerList ) > 0 {
glog . Infof ( "Watching for etcd configs at %v" , etcdServerList )
2014-07-22 21:40:59 +00:00
etcdClient = etcd . NewClient ( etcdServerList )
2014-08-19 03:45:37 +00:00
kconfig . NewSourceEtcd ( kconfig . EtcdKeyForHost ( hostname ) , etcdClient , cfg . Channel ( "etcd" ) )
2014-07-15 20:24:41 +00:00
}
// TODO: block until all sources have delivered at least one update to the channel, or break the sync loop
// up into "per source" synchronizations
2014-07-22 21:40:59 +00:00
k := kubelet . NewMainKubelet (
getHostname ( ) ,
dockerClient ,
cadvisorClient ,
2014-07-19 00:13:34 +00:00
etcdClient ,
2014-08-06 20:12:19 +00:00
* rootDirectory ,
2014-09-26 04:24:44 +00:00
* syncFrequency ,
float32 ( * registryPullQPS ) ,
* registryBurst )
2014-07-22 21:40:59 +00:00
2014-08-13 04:33:56 +00:00
health . AddHealthChecker ( "exec" , health . NewExecHealthChecker ( k ) )
health . AddHealthChecker ( "http" , health . NewHTTPHealthChecker ( & http . Client { } ) )
health . AddHealthChecker ( "tcp" , & health . TCPHealthChecker { } )
2014-07-15 20:24:41 +00:00
// start the kubelet
go util . Forever ( func ( ) { k . Run ( cfg . Updates ( ) ) } , 0 )
// start the kubelet server
2014-08-07 00:28:41 +00:00
if * enableServer {
2014-07-15 20:24:41 +00:00
go util . Forever ( func ( ) {
2014-08-20 18:24:51 +00:00
kubelet . ListenAndServeKubeletServer ( k , cfg . Channel ( "http" ) , * address , * port )
2014-07-15 20:24:41 +00:00
} , 0 )
}
// runs forever
select { }
2014-06-06 23:40:48 +00:00
}