2015-01-30 17:04:39 +00:00
/ *
2015-05-01 16:19:44 +00:00
Copyright 2014 The Kubernetes Authors All rights reserved .
2015-01-30 17:04:39 +00:00
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 .
* /
2015-02-07 22:13:22 +00:00
// Package app does all of the work necessary to create a Kubernetes
2015-01-30 17:04:39 +00:00
// APIServer by binding together the API, master and APIServer infrastructure.
// It can be configured and called directly or via the hyperkube framework.
2015-02-07 22:13:22 +00:00
package app
2015-01-30 17:04:39 +00:00
import (
"crypto/tls"
"net"
"net/http"
2015-03-25 04:39:19 +00:00
"os"
2015-04-19 08:40:08 +00:00
"path"
2015-04-21 00:36:41 +00:00
"regexp"
2015-01-30 17:04:39 +00:00
"strconv"
"strings"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
2015-06-05 14:33:34 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports"
2015-01-30 17:04:39 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
2015-04-27 08:10:12 +00:00
forked "github.com/GoogleCloudPlatform/kubernetes/third_party/forked/coreos/go-etcd/etcd"
2015-05-24 22:15:19 +00:00
systemd "github.com/coreos/go-systemd/daemon"
2015-01-30 17:04:39 +00:00
"github.com/coreos/go-etcd/etcd"
"github.com/golang/glog"
"github.com/spf13/pflag"
)
2015-05-12 02:41:13 +00:00
const (
// Maximum duration before timing out read/write requests
// Set to a value larger than the timeouts in each watch server.
ReadWriteTimeout = time . Minute * 60
2015-06-16 17:50:40 +00:00
//TODO: This can be tightened up. It still matches objects named watch or proxy.
defaultLongRunningRequestRE = "(/|^)((watch|proxy)(/|$)|(logs|portforward|exec)/?$)"
2015-05-12 02:41:13 +00:00
)
2015-01-30 17:04:39 +00:00
// APIServer runs a kubernetes api server.
type APIServer struct {
2015-04-07 18:49:08 +00:00
InsecureBindAddress util . IP
InsecurePort int
BindAddress util . IP
2015-05-20 21:05:23 +00:00
AdvertiseAddress util . IP
2015-04-07 18:49:08 +00:00
SecurePort int
ExternalHost string
2015-01-30 17:04:39 +00:00
APIRate float32
APIBurst int
TLSCertFile string
TLSPrivateKeyFile string
2015-04-19 08:40:08 +00:00
CertDirectory string
2015-01-30 17:04:39 +00:00
APIPrefix string
StorageVersion string
CloudProvider string
CloudConfigFile string
EventTTL time . Duration
2015-04-06 23:34:42 +00:00
BasicAuthFile string
2015-03-30 21:24:22 +00:00
ClientCAFile string
2015-01-30 17:04:39 +00:00
TokenAuthFile string
2015-05-01 16:02:38 +00:00
ServiceAccountKeyFile string
ServiceAccountLookup bool
2015-01-30 17:04:39 +00:00
AuthorizationMode string
AuthorizationPolicyFile string
AdmissionControl string
AdmissionControlConfigFile string
EtcdServerList util . StringList
EtcdConfigFile string
2015-03-11 17:10:09 +00:00
EtcdPathPrefix string
2015-01-30 17:04:39 +00:00
CorsAllowedOriginList util . StringList
AllowPrivileged bool
2015-05-23 20:41:11 +00:00
ServiceClusterIPRange util . IPNet // TODO: make this a list
ServiceNodePortRange util . PortRange
2015-01-30 17:04:39 +00:00
EnableLogsSupport bool
MasterServiceNamespace string
RuntimeConfig util . ConfigurationMap
KubeletConfig client . KubeletConfig
2015-02-13 22:58:42 +00:00
ClusterName string
2015-03-13 15:44:11 +00:00
EnableProfiling bool
2015-03-31 04:41:10 +00:00
MaxRequestsInFlight int
2015-05-27 01:39:42 +00:00
MinRequestTimeout int
2015-03-31 04:41:10 +00:00
LongRunningRequestRE string
2015-05-28 04:38:21 +00:00
SSHUser string
SSHKeyfile string
2015-01-30 17:04:39 +00:00
}
// NewAPIServer creates a new APIServer object with default parameters
func NewAPIServer ( ) * APIServer {
s := APIServer {
2015-04-07 18:49:08 +00:00
InsecurePort : 8080 ,
InsecureBindAddress : util . IP ( net . ParseIP ( "127.0.0.1" ) ) ,
BindAddress : util . IP ( net . ParseIP ( "0.0.0.0" ) ) ,
SecurePort : 6443 ,
2015-01-30 17:04:39 +00:00
APIRate : 10.0 ,
APIBurst : 200 ,
APIPrefix : "/api" ,
2015-03-11 18:30:31 +00:00
EventTTL : 1 * time . Hour ,
2015-01-30 17:04:39 +00:00
AuthorizationMode : "AlwaysAllow" ,
AdmissionControl : "AlwaysAdmit" ,
2015-03-11 17:10:09 +00:00
EtcdPathPrefix : master . DefaultEtcdPathPrefix ,
2015-01-30 17:04:39 +00:00
EnableLogsSupport : true ,
MasterServiceNamespace : api . NamespaceDefault ,
2015-02-13 22:58:42 +00:00
ClusterName : "kubernetes" ,
2015-04-19 08:40:08 +00:00
CertDirectory : "/var/run/kubernetes" ,
2015-01-30 17:04:39 +00:00
RuntimeConfig : make ( util . ConfigurationMap ) ,
KubeletConfig : client . KubeletConfig {
2015-06-05 14:33:34 +00:00
Port : ports . KubeletPort ,
2015-04-01 23:19:17 +00:00
EnableHttps : true ,
2015-03-19 01:11:39 +00:00
HTTPTimeout : time . Duration ( 5 ) * time . Second ,
2015-01-30 17:04:39 +00:00
} ,
}
return & s
}
// AddFlags adds flags for a specific APIServer to the specified FlagSet
func ( s * APIServer ) AddFlags ( fs * pflag . FlagSet ) {
// Note: the weird ""+ in below lines seems to be the only way to get gofmt to
// arrange these text blocks sensibly. Grrr.
2015-04-24 06:10:33 +00:00
fs . IntVar ( & s . InsecurePort , "insecure-port" , s . InsecurePort , "" +
2015-04-07 18:49:08 +00:00
"The port on which to serve unsecured, unauthenticated access. Default 8080. It is assumed " +
"that firewall rules are set up such that this port is not reachable from outside of " +
"the cluster and that port 443 on the cluster's public address is proxied to this " +
2015-01-30 17:04:39 +00:00
"port. This is performed by nginx in the default setup." )
2015-04-24 06:10:33 +00:00
fs . IntVar ( & s . InsecurePort , "port" , s . InsecurePort , "DEPRECATED: see --insecure-port instead" )
fs . Var ( & s . InsecureBindAddress , "insecure-bind-address" , "" +
"The IP address on which to serve the --insecure-port (set to 0.0.0.0 for all interfaces). " +
2015-04-07 18:49:08 +00:00
"Defaults to localhost." )
2015-04-24 06:10:33 +00:00
fs . Var ( & s . InsecureBindAddress , "address" , "DEPRECATED: see --insecure-bind-address instead" )
fs . Var ( & s . BindAddress , "bind-address" , "" +
2015-05-20 21:05:23 +00:00
"The IP address on which to serve the --read-only-port and --secure-port ports. The " +
"associated interface(s) must be reachable by the rest of the cluster, and by CLI/web " +
"clients. If blank, all interfaces will be used (0.0.0.0)." )
fs . Var ( & s . AdvertiseAddress , "advertise-address" , "" +
"The IP address on which to advertise the apiserver to members of the cluster. This " +
2015-05-22 06:12:57 +00:00
"address must be reachable by the rest of the cluster. If blank, the --bind-address " +
"will be used. If --bind-address is unspecified, the host's default interface will " +
"be used." )
2015-04-24 06:10:33 +00:00
fs . Var ( & s . BindAddress , "public-address-override" , "DEPRECATED: see --bind-address instead" )
fs . IntVar ( & s . SecurePort , "secure-port" , s . SecurePort , "" +
2015-04-07 18:49:08 +00:00
"The port on which to serve HTTPS with authentication and authorization. If 0, " +
"don't serve HTTPS at all." )
2015-04-24 06:10:33 +00:00
fs . Float32Var ( & s . APIRate , "api-rate" , s . APIRate , "API rate limit as QPS for the read only port" )
fs . IntVar ( & s . APIBurst , "api-burst" , s . APIBurst , "API burst amount for the read only port" )
fs . StringVar ( & s . TLSCertFile , "tls-cert-file" , s . TLSCertFile , "" +
2015-01-30 17:04:39 +00:00
"File containing x509 Certificate for HTTPS. (CA cert, if any, concatenated after server cert). " +
2015-04-24 06:10:33 +00:00
"If HTTPS serving is enabled, and --tls-cert-file and --tls-private-key-file are not provided, " +
2015-01-30 17:04:39 +00:00
"a self-signed certificate and key are generated for the public address and saved to /var/run/kubernetes." )
2015-04-24 06:10:33 +00:00
fs . StringVar ( & s . TLSPrivateKeyFile , "tls-private-key-file" , s . TLSPrivateKeyFile , "File containing x509 private key matching --tls-cert-file." )
fs . StringVar ( & s . CertDirectory , "cert-dir" , s . CertDirectory , "The directory where the TLS certs are located (by default /var/run/kubernetes). " +
"If --tls-cert-file and --tls-private-key-file are provided, this flag will be ignored." )
fs . StringVar ( & s . APIPrefix , "api-prefix" , s . APIPrefix , "The prefix for API requests on the server. Default '/api'." )
fs . StringVar ( & s . StorageVersion , "storage-version" , s . StorageVersion , "The version to store resources with. Defaults to server preferred" )
fs . StringVar ( & s . CloudProvider , "cloud-provider" , s . CloudProvider , "The provider for cloud services. Empty string for no provider." )
fs . StringVar ( & s . CloudConfigFile , "cloud-config" , s . CloudConfigFile , "The path to the cloud provider configuration file. Empty string for no configuration file." )
fs . DurationVar ( & s . EventTTL , "event-ttl" , s . EventTTL , "Amount of time to retain events. Default 1 hour." )
2015-04-06 23:34:42 +00:00
fs . StringVar ( & s . BasicAuthFile , "basic-auth-file" , s . BasicAuthFile , "If set, the file that will be used to admit requests to the secure port of the API server via http basic authentication." )
2015-04-24 06:10:33 +00:00
fs . StringVar ( & s . ClientCAFile , "client-ca-file" , s . ClientCAFile , "If set, any request presenting a client certificate signed by one of the authorities in the client-ca-file is authenticated with an identity corresponding to the CommonName of the client certificate." )
fs . StringVar ( & s . TokenAuthFile , "token-auth-file" , s . TokenAuthFile , "If set, the file that will be used to secure the secure port of the API server via token authentication." )
2015-05-01 16:02:38 +00:00
fs . StringVar ( & s . ServiceAccountKeyFile , "service-account-key-file" , s . ServiceAccountKeyFile , "File containing PEM-encoded x509 RSA private or public key, used to verify ServiceAccount tokens. If unspecified, --tls-private-key-file is used." )
fs . BoolVar ( & s . ServiceAccountLookup , "service-account-lookup" , s . ServiceAccountLookup , "If true, validate ServiceAccount tokens exist in etcd as part of authentication." )
2015-04-24 06:10:33 +00:00
fs . StringVar ( & s . AuthorizationMode , "authorization-mode" , s . AuthorizationMode , "Selects how to do authorization on the secure port. One of: " + strings . Join ( apiserver . AuthorizationModeChoices , "," ) )
fs . StringVar ( & s . AuthorizationPolicyFile , "authorization-policy-file" , s . AuthorizationPolicyFile , "File with authorization policy in csv format, used with --authorization-mode=ABAC, on the secure port." )
fs . StringVar ( & s . AdmissionControl , "admission-control" , s . AdmissionControl , "Ordered list of plug-ins to do admission control of resources into cluster. Comma-delimited list of: " + strings . Join ( admission . GetPlugins ( ) , ", " ) )
fs . StringVar ( & s . AdmissionControlConfigFile , "admission-control-config-file" , s . AdmissionControlConfigFile , "File with admission control configuration." )
fs . Var ( & s . EtcdServerList , "etcd-servers" , "List of etcd servers to watch (http://ip:port), comma separated. Mutually exclusive with -etcd-config" )
fs . StringVar ( & s . EtcdConfigFile , "etcd-config" , s . EtcdConfigFile , "The config file for the etcd client. Mutually exclusive with -etcd-servers." )
fs . StringVar ( & s . EtcdPathPrefix , "etcd-prefix" , s . EtcdPathPrefix , "The prefix for all resource paths in etcd." )
fs . Var ( & s . CorsAllowedOriginList , "cors-allowed-origins" , "List of allowed origins for CORS, comma separated. An allowed origin can be a regular expression to support subdomain matching. If this list is empty CORS will not be enabled." )
fs . BoolVar ( & s . AllowPrivileged , "allow-privileged" , s . AllowPrivileged , "If true, allow privileged containers." )
2015-05-24 04:59:46 +00:00
fs . Var ( & s . ServiceClusterIPRange , "service-cluster-ip-range" , "A CIDR notation IP range from which to assign service cluster IPs. This must not overlap with any IP ranges assigned to nodes for pods." )
fs . Var ( & s . ServiceClusterIPRange , "portal-net" , "Deprecated: see --service-cluster-ip-range instead." )
fs . MarkDeprecated ( "portal-net" , "see --service-cluster-ip-range instead." )
fs . Var ( & s . ServiceNodePortRange , "service-node-port-range" , "A port range to reserve for services with NodePort visibility. Example: '30000-32767'. Inclusive at both ends of the range." )
fs . Var ( & s . ServiceNodePortRange , "service-node-ports" , "Deprecated: see --service-node-port-range instead." )
fs . MarkDeprecated ( "service-node-ports" , "see --service-node-port-range instead." )
2015-04-24 06:10:33 +00:00
fs . StringVar ( & s . MasterServiceNamespace , "master-service-namespace" , s . MasterServiceNamespace , "The namespace from which the kubernetes master services should be injected into pods" )
2015-05-05 23:53:22 +00:00
fs . Var ( & s . RuntimeConfig , "runtime-config" , "A set of key=value pairs that describe runtime configuration that may be passed to the apiserver. api/<version> key can be used to turn on/off specific api versions. api/all and api/legacy are special keys to control all and legacy api versions respectively." )
2015-01-30 17:04:39 +00:00
client . BindKubeletClientConfigFlags ( fs , & s . KubeletConfig )
2015-04-24 06:10:33 +00:00
fs . StringVar ( & s . ClusterName , "cluster-name" , s . ClusterName , "The instance prefix for the cluster" )
2015-04-09 15:52:37 +00:00
fs . BoolVar ( & s . EnableProfiling , "profiling" , true , "Enable profiling via web interface host:port/debug/pprof/" )
2015-04-24 06:10:33 +00:00
fs . StringVar ( & s . ExternalHost , "external-hostname" , "" , "The hostname to use when generating externalized URLs for this master (e.g. Swagger API Docs.)" )
fs . IntVar ( & s . MaxRequestsInFlight , "max-requests-inflight" , 400 , "The maximum number of requests in flight at a given time. When the server exceeds this, it rejects requests. Zero for no limit." )
2015-05-28 22:50:39 +00:00
fs . IntVar ( & s . MinRequestTimeout , "min-request-timeout" , 1800 , "An optional field indicating the minimum number of seconds a handler must keep a request open before timing it out. Currently only honored by the watch request handler, which picks a randomized value above this number as the connection timeout, to spread out load." )
2015-06-16 17:50:40 +00:00
fs . StringVar ( & s . LongRunningRequestRE , "long-running-request-regexp" , defaultLongRunningRequestRE , "A regular expression matching long running requests which should be excluded from maximum inflight request handling." )
2015-05-28 04:38:21 +00:00
fs . StringVar ( & s . SSHUser , "ssh-user" , "" , "If non-empty, use secure SSH proxy to the nodes, using this user name" )
fs . StringVar ( & s . SSHKeyfile , "ssh-keyfile" , "" , "If non-empty, use secure SSH proxy to the nodes, using this user keyfile" )
2015-01-30 17:04:39 +00:00
}
// TODO: Longer term we should read this from some config store, rather than a flag.
2015-05-23 20:41:11 +00:00
func ( s * APIServer ) verifyClusterIPFlags ( ) {
if s . ServiceClusterIPRange . IP == nil {
glog . Fatal ( "No --service-cluster-ip-range specified" )
2015-01-30 17:04:39 +00:00
}
}
2015-03-11 17:10:09 +00:00
func newEtcd ( etcdConfigFile string , etcdServerList util . StringList , storageVersion string , pathPrefix string ) ( helper tools . EtcdHelper , err error ) {
2015-07-20 14:12:24 +00:00
var client tools . EtcdClient
2015-01-30 17:04:39 +00:00
if etcdConfigFile != "" {
client , err = etcd . NewClientFromFile ( etcdConfigFile )
if err != nil {
return helper , err
}
} else {
2015-04-27 08:10:12 +00:00
etcdClient := etcd . NewClient ( etcdServerList )
transport := & http . Transport {
Dial : forked . Dial ,
TLSClientConfig : & tls . Config {
InsecureSkipVerify : true ,
} ,
MaxIdleConnsPerHost : 500 ,
}
etcdClient . SetTransport ( transport )
client = etcdClient
2015-01-30 17:04:39 +00:00
}
2015-03-11 17:10:09 +00:00
return master . NewEtcdHelper ( client , storageVersion , pathPrefix )
2015-01-30 17:04:39 +00:00
}
// Run runs the specified APIServer. This should never exit.
func ( s * APIServer ) Run ( _ [ ] string ) error {
2015-05-23 20:41:11 +00:00
s . verifyClusterIPFlags ( )
2015-01-30 17:04:39 +00:00
2015-05-22 06:12:57 +00:00
// If advertise-address is not specified, use bind-address. If bind-address
// is also unset (or 0.0.0.0), setDefaults() in pkg/master/master.go will
// do the right thing and use the host's default interface.
if s . AdvertiseAddress == nil || net . IP ( s . AdvertiseAddress ) . IsUnspecified ( ) {
s . AdvertiseAddress = s . BindAddress
}
2015-01-30 17:04:39 +00:00
if ( s . EtcdConfigFile != "" && len ( s . EtcdServerList ) != 0 ) || ( s . EtcdConfigFile == "" && len ( s . EtcdServerList ) == 0 ) {
2015-04-24 06:10:33 +00:00
glog . Fatalf ( "specify either --etcd-servers or --etcd-config" )
2015-01-30 17:04:39 +00:00
}
capabilities . Initialize ( capabilities . Capabilities {
AllowPrivileged : s . AllowPrivileged ,
2015-03-24 23:09:16 +00:00
// TODO(vmarmol): Implement support for HostNetworkSources.
HostNetworkSources : [ ] string { } ,
2015-01-30 17:04:39 +00:00
} )
2015-07-01 18:41:49 +00:00
cloud , err := cloudprovider . InitCloudProvider ( s . CloudProvider , s . CloudConfigFile )
if err != nil {
glog . Fatalf ( "Cloud provider could not be initialized: %v" , err )
}
2015-01-30 17:04:39 +00:00
kubeletClient , err := client . NewKubeletClient ( & s . KubeletConfig )
if err != nil {
glog . Fatalf ( "Failure to start kubelet client: %v" , err )
}
2015-05-05 23:53:22 +00:00
// "api/all=false" allows users to selectively enable specific api versions.
disableAllAPIs := false
allAPIFlagValue , ok := s . RuntimeConfig [ "api/all" ]
if ok && allAPIFlagValue == "false" {
disableAllAPIs = true
2015-03-27 21:19:03 +00:00
}
2015-01-30 17:04:39 +00:00
2015-05-05 23:53:22 +00:00
// "api/legacy=false" allows users to disable legacy api versions.
2015-05-11 23:09:25 +00:00
disableLegacyAPIs := false
legacyAPIFlagValue , ok := s . RuntimeConfig [ "api/legacy" ]
if ok && legacyAPIFlagValue == "false" {
disableLegacyAPIs = true
}
2015-05-22 15:20:27 +00:00
_ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable.
2015-05-05 23:53:22 +00:00
2015-06-04 18:37:44 +00:00
// "api/v1={true|false} allows users to enable/disable v1 API.
// This takes preference over api/all and api/legacy, if specified.
disableV1 := disableAllAPIs
disableV1 = ! s . getRuntimeConfigValue ( "api/v1" , ! disableV1 )
2015-05-05 23:53:22 +00:00
2015-01-30 17:04:39 +00:00
// TODO: expose same flags as client.BindClientConfigFlags but for a server
clientConfig := & client . Config {
2015-04-07 18:49:08 +00:00
Host : net . JoinHostPort ( s . InsecureBindAddress . String ( ) , strconv . Itoa ( s . InsecurePort ) ) ,
2015-01-30 17:04:39 +00:00
Version : s . StorageVersion ,
}
client , err := client . New ( clientConfig )
if err != nil {
glog . Fatalf ( "Invalid server address: %v" , err )
}
2015-03-11 17:10:09 +00:00
helper , err := newEtcd ( s . EtcdConfigFile , s . EtcdServerList , s . StorageVersion , s . EtcdPathPrefix )
2015-01-30 17:04:39 +00:00
if err != nil {
glog . Fatalf ( "Invalid storage version or misconfigured etcd: %v" , err )
}
2015-05-23 20:41:11 +00:00
n := net . IPNet ( s . ServiceClusterIPRange )
2015-01-30 17:04:39 +00:00
2015-05-01 16:02:38 +00:00
// Default to the private server key for service account token signing
if s . ServiceAccountKeyFile == "" && s . TLSPrivateKeyFile != "" {
2015-06-17 03:02:54 +00:00
if apiserver . IsValidServiceAccountKeyFile ( s . TLSPrivateKeyFile ) {
s . ServiceAccountKeyFile = s . TLSPrivateKeyFile
} else {
glog . Warning ( "no RSA key provided, service account token authentication disabled" )
}
2015-05-01 16:02:38 +00:00
}
2015-05-17 03:29:18 +00:00
authenticator , err := apiserver . NewAuthenticator ( s . BasicAuthFile , s . ClientCAFile , s . TokenAuthFile , s . ServiceAccountKeyFile , s . ServiceAccountLookup , helper )
2015-01-30 17:04:39 +00:00
if err != nil {
glog . Fatalf ( "Invalid Authentication Config: %v" , err )
}
authorizer , err := apiserver . NewAuthorizerFromAuthorizationConfig ( s . AuthorizationMode , s . AuthorizationPolicyFile )
if err != nil {
glog . Fatalf ( "Invalid Authorization Config: %v" , err )
}
admissionControlPluginNames := strings . Split ( s . AdmissionControl , "," )
admissionController := admission . NewFromPlugins ( client , admissionControlPluginNames , s . AdmissionControlConfigFile )
2015-03-25 04:39:19 +00:00
if len ( s . ExternalHost ) == 0 {
// TODO: extend for other providers
if s . CloudProvider == "gce" {
instances , supported := cloud . Instances ( )
if ! supported {
glog . Fatalf ( "gce cloud provider has no instances. this shouldn't happen. exiting." )
}
name , err := os . Hostname ( )
if err != nil {
glog . Fatalf ( "failed to get hostname: %v" , err )
}
addrs , err := instances . NodeAddresses ( name )
if err != nil {
glog . Warningf ( "unable to obtain external host address from cloud provider: %v" , err )
} else {
for _ , addr := range addrs {
if addr . Type == api . NodeExternalIP {
s . ExternalHost = addr . Address
}
}
}
}
}
2015-05-28 18:45:08 +00:00
var installSSH master . InstallSSHKey
2015-06-04 18:58:38 +00:00
if cloud != nil {
if instances , supported := cloud . Instances ( ) ; supported {
installSSH = instances . AddSSHKeyToAllInstances
}
2015-05-28 18:45:08 +00:00
}
2015-01-30 17:04:39 +00:00
config := & master . Config {
EtcdHelper : helper ,
EventTTL : s . EventTTL ,
KubeletClient : kubeletClient ,
2015-05-23 20:41:11 +00:00
ServiceClusterIPRange : & n ,
2015-05-03 22:44:05 +00:00
EnableCoreControllers : true ,
2015-01-30 17:04:39 +00:00
EnableLogsSupport : s . EnableLogsSupport ,
EnableUISupport : true ,
EnableSwaggerSupport : true ,
2015-03-13 15:44:11 +00:00
EnableProfiling : s . EnableProfiling ,
2015-01-30 23:53:04 +00:00
EnableIndex : true ,
2015-01-30 17:04:39 +00:00
APIPrefix : s . APIPrefix ,
CorsAllowedOriginList : s . CorsAllowedOriginList ,
2015-02-07 00:33:28 +00:00
ReadWritePort : s . SecurePort ,
2015-05-20 21:05:23 +00:00
PublicAddress : net . IP ( s . AdvertiseAddress ) ,
2015-01-30 17:04:39 +00:00
Authenticator : authenticator ,
2015-04-28 05:24:26 +00:00
SupportsBasicAuth : len ( s . BasicAuthFile ) > 0 ,
2015-01-30 17:04:39 +00:00
Authorizer : authorizer ,
AdmissionControl : admissionController ,
2015-06-04 18:37:44 +00:00
DisableV1 : disableV1 ,
2015-01-30 17:04:39 +00:00
MasterServiceNamespace : s . MasterServiceNamespace ,
2015-02-13 22:58:42 +00:00
ClusterName : s . ClusterName ,
2015-03-25 04:39:19 +00:00
ExternalHost : s . ExternalHost ,
2015-05-27 01:39:42 +00:00
MinRequestTimeout : s . MinRequestTimeout ,
2015-05-28 04:38:21 +00:00
SSHUser : s . SSHUser ,
SSHKeyfile : s . SSHKeyfile ,
2015-05-28 18:45:08 +00:00
InstallSSHKey : installSSH ,
2015-06-06 18:40:13 +00:00
ServiceNodePortRange : s . ServiceNodePortRange ,
2015-01-30 17:04:39 +00:00
}
m := master . New ( config )
2015-05-06 21:54:54 +00:00
// We serve on 2 ports. See docs/accessing_the_api.md
2015-01-30 17:04:39 +00:00
secureLocation := ""
if s . SecurePort != 0 {
2015-04-07 18:49:08 +00:00
secureLocation = net . JoinHostPort ( s . BindAddress . String ( ) , strconv . Itoa ( s . SecurePort ) )
2015-01-30 17:04:39 +00:00
}
2015-04-07 18:49:08 +00:00
insecureLocation := net . JoinHostPort ( s . InsecureBindAddress . String ( ) , strconv . Itoa ( s . InsecurePort ) )
2015-01-30 17:04:39 +00:00
// See the flag commentary to understand our assumptions when opening the read-only and read-write ports.
2015-03-31 04:41:10 +00:00
var sem chan bool
if s . MaxRequestsInFlight > 0 {
sem = make ( chan bool , s . MaxRequestsInFlight )
}
longRunningRE := regexp . MustCompile ( s . LongRunningRequestRE )
2015-01-30 17:04:39 +00:00
if secureLocation != "" {
secureServer := & http . Server {
Addr : secureLocation ,
2015-03-31 04:41:10 +00:00
Handler : apiserver . MaxInFlightLimit ( sem , longRunningRE , apiserver . RecoverPanics ( m . Handler ) ) ,
2015-05-12 02:41:13 +00:00
ReadTimeout : ReadWriteTimeout ,
WriteTimeout : ReadWriteTimeout ,
2015-01-30 17:04:39 +00:00
MaxHeaderBytes : 1 << 20 ,
TLSConfig : & tls . Config {
// Change default from SSLv3 to TLSv1.0 (because of POODLE vulnerability)
MinVersion : tls . VersionTLS10 ,
} ,
}
2015-03-30 21:24:22 +00:00
if len ( s . ClientCAFile ) > 0 {
clientCAs , err := util . CertPoolFromFile ( s . ClientCAFile )
if err != nil {
glog . Fatalf ( "unable to load client CA file: %v" , err )
}
// Populate PeerCertificates in requests, but don't reject connections without certificates
// This allows certificates to be validated by authenticators, while still allowing other auth types
secureServer . TLSConfig . ClientAuth = tls . RequestClientCert
// Specify allowed CAs for client certificates
secureServer . TLSConfig . ClientCAs = clientCAs
}
2015-01-30 17:04:39 +00:00
glog . Infof ( "Serving securely on %s" , secureLocation )
go func ( ) {
defer util . HandleCrash ( )
for {
if s . TLSCertFile == "" && s . TLSPrivateKeyFile == "" {
2015-04-19 08:40:08 +00:00
s . TLSCertFile = path . Join ( s . CertDirectory , "apiserver.crt" )
s . TLSPrivateKeyFile = path . Join ( s . CertDirectory , "apiserver.key" )
2015-05-20 21:05:23 +00:00
// TODO (cjcullen): Is PublicAddress the right address to sign a cert with?
2015-07-03 17:21:29 +00:00
alternateIPs := [ ] net . IP { config . ServiceReadWriteIP }
alternateDNS := [ ] string { "kubernetes.default.svc" , "kubernetes.default" , "kubernetes" }
// It would be nice to set a fqdn subject alt name, but only the kubelets know, the apiserver is clueless
// alternateDNS = append(alternateDNS, "kubernetes.default.svc.CLUSTER.DNS.NAME")
if err := util . GenerateSelfSignedCert ( config . PublicAddress . String ( ) , s . TLSCertFile , s . TLSPrivateKeyFile , alternateIPs , alternateDNS ) ; err != nil {
2015-01-30 17:04:39 +00:00
glog . Errorf ( "Unable to generate self signed cert: %v" , err )
} else {
glog . Infof ( "Using self-signed cert (%s, %s)" , s . TLSCertFile , s . TLSPrivateKeyFile )
}
}
2015-05-26 23:21:08 +00:00
// err == systemd.SdNotifyNoSocket when not running on a systemd system
if err := systemd . SdNotify ( "READY=1\n" ) ; err != nil && err != systemd . SdNotifyNoSocket {
glog . Errorf ( "Unable to send systemd daemon sucessful start message: %v\n" , err )
}
2015-01-30 17:04:39 +00:00
if err := secureServer . ListenAndServeTLS ( s . TLSCertFile , s . TLSPrivateKeyFile ) ; err != nil {
glog . Errorf ( "Unable to listen for secure (%v); will try again." , err )
}
time . Sleep ( 15 * time . Second )
}
} ( )
}
http := & http . Server {
2015-04-07 18:49:08 +00:00
Addr : insecureLocation ,
2015-01-30 17:04:39 +00:00
Handler : apiserver . RecoverPanics ( m . InsecureHandler ) ,
2015-05-12 02:41:13 +00:00
ReadTimeout : ReadWriteTimeout ,
WriteTimeout : ReadWriteTimeout ,
2015-01-30 17:04:39 +00:00
MaxHeaderBytes : 1 << 20 ,
}
2015-05-24 22:15:19 +00:00
if secureLocation == "" {
2015-05-26 23:21:08 +00:00
// err == systemd.SdNotifyNoSocket when not running on a systemd system
if err := systemd . SdNotify ( "READY=1\n" ) ; err != nil && err != systemd . SdNotifyNoSocket {
glog . Errorf ( "Unable to send systemd daemon sucessful start message: %v\n" , err )
}
2015-05-24 22:15:19 +00:00
}
2015-04-07 18:49:08 +00:00
glog . Infof ( "Serving insecurely on %s" , insecureLocation )
2015-01-30 17:04:39 +00:00
glog . Fatal ( http . ListenAndServe ( ) )
return nil
}
2015-05-05 23:53:22 +00:00
func ( s * APIServer ) getRuntimeConfigValue ( apiKey string , defaultValue bool ) bool {
flagValue , ok := s . RuntimeConfig [ apiKey ]
if ok {
if flagValue == "" {
return true
}
boolValue , err := strconv . ParseBool ( flagValue )
if err != nil {
glog . Fatalf ( "Invalid value of %s: %s" , apiKey , flagValue )
}
return boolValue
}
return defaultValue
}