2015-02-02 21:54:52 +00:00
/ *
2015-05-01 16:19:44 +00:00
Copyright 2014 The Kubernetes Authors All rights reserved .
2015-02-02 21:54:52 +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 21:55:35 +00:00
// Package app does all of the work necessary to configure and run a
// Kubernetes app process.
package app
2015-02-02 21:54:52 +00:00
import (
"net"
"net/http"
2015-03-30 19:00:21 +00:00
_ "net/http/pprof"
2015-02-02 21:54:52 +00:00
"strconv"
"time"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/client"
"k8s.io/kubernetes/pkg/client/clientcmd"
clientcmdapi "k8s.io/kubernetes/pkg/client/clientcmd/api"
2015-08-04 00:28:33 +00:00
"k8s.io/kubernetes/pkg/kubelet/qos"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/proxy"
"k8s.io/kubernetes/pkg/proxy/config"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/exec"
"k8s.io/kubernetes/pkg/util/iptables"
2015-08-04 00:28:33 +00:00
"k8s.io/kubernetes/pkg/util/oom"
2015-02-02 21:54:52 +00:00
"github.com/golang/glog"
"github.com/spf13/pflag"
)
// ProxyServer contains configures and runs a Kubernetes proxy server
type ProxyServer struct {
2015-03-26 06:49:20 +00:00
BindAddress util . IP
HealthzPort int
HealthzBindAddress util . IP
OOMScoreAdj int
2015-04-14 16:49:13 +00:00
ResourceContainer string
2015-04-17 07:18:07 +00:00
Master string
2015-04-17 06:42:54 +00:00
Kubeconfig string
2015-05-18 17:11:25 +00:00
PortRange util . PortRange
2015-02-02 21:54:52 +00:00
}
// NewProxyServer creates a new ProxyServer object with default parameters
func NewProxyServer ( ) * ProxyServer {
return & ProxyServer {
2015-03-26 06:49:20 +00:00
BindAddress : util . IP ( net . ParseIP ( "0.0.0.0" ) ) ,
HealthzPort : 10249 ,
HealthzBindAddress : util . IP ( net . ParseIP ( "127.0.0.1" ) ) ,
2015-08-04 00:28:33 +00:00
OOMScoreAdj : qos . KubeProxyOomScoreAdj ,
2015-04-14 16:49:13 +00:00
ResourceContainer : "/kube-proxy" ,
2015-02-02 21:54:52 +00:00
}
}
// AddFlags adds flags for a specific ProxyServer to the specified FlagSet
func ( s * ProxyServer ) AddFlags ( fs * pflag . FlagSet ) {
2015-04-24 06:10:33 +00:00
fs . Var ( & s . BindAddress , "bind-address" , "The IP address for the proxy server to serve on (set to 0.0.0.0 for all interfaces)" )
2015-04-17 07:18:07 +00:00
fs . StringVar ( & s . Master , "master" , s . Master , "The address of the Kubernetes API server (overrides any value in kubeconfig)" )
2015-04-24 06:10:33 +00:00
fs . IntVar ( & s . HealthzPort , "healthz-port" , s . HealthzPort , "The port to bind the health check server. Use 0 to disable." )
fs . Var ( & s . HealthzBindAddress , "healthz-bind-address" , "The IP address for the health check server to serve on, defaulting to 127.0.0.1 (set to 0.0.0.0 for all interfaces)" )
fs . IntVar ( & s . OOMScoreAdj , "oom-score-adj" , s . OOMScoreAdj , "The oom_score_adj value for kube-proxy process. Values must be within the range [-1000, 1000]" )
fs . StringVar ( & s . ResourceContainer , "resource-container" , s . ResourceContainer , "Absolute name of the resource-only container to create and run the Kube-proxy in (Default: /kube-proxy)." )
2015-05-12 03:44:13 +00:00
fs . StringVar ( & s . Kubeconfig , "kubeconfig" , s . Kubeconfig , "Path to kubeconfig file with authorization information (the master location is set by the master flag)." )
2015-05-18 17:11:25 +00:00
fs . Var ( & s . PortRange , "proxy-port-range" , "Range of host ports (beginPort-endPort, inclusive) that may be consumed in order to proxy service traffic. If unspecified (0-0) then ports will be randomly chosen." )
2015-02-02 21:54:52 +00:00
}
// Run runs the specified ProxyServer. This should never exit.
func ( s * ProxyServer ) Run ( _ [ ] string ) error {
2015-04-14 16:49:13 +00:00
// TODO(vmarmol): Use container config for this.
2015-08-04 00:28:33 +00:00
oomAdjuster := oom . NewOomAdjuster ( )
if err := oomAdjuster . ApplyOomScoreAdj ( 0 , s . OOMScoreAdj ) ; err != nil {
2015-05-14 20:03:30 +00:00
glog . V ( 2 ) . Info ( err )
2015-02-02 21:54:52 +00:00
}
2015-04-14 16:49:13 +00:00
// Run in its own container.
if err := util . RunInResourceContainer ( s . ResourceContainer ) ; err != nil {
glog . Warningf ( "Failed to start in resource-only container %q: %v" , s . ResourceContainer , err )
} else {
2015-05-14 20:03:30 +00:00
glog . V ( 2 ) . Infof ( "Running in resource-only container %q" , s . ResourceContainer )
2015-04-14 16:49:13 +00:00
}
2015-02-02 21:54:52 +00:00
serviceConfig := config . NewServiceConfig ( )
endpointsConfig := config . NewEndpointsConfig ( )
protocol := iptables . ProtocolIpv4
if net . IP ( s . BindAddress ) . To4 ( ) == nil {
protocol = iptables . ProtocolIpv6
}
loadBalancer := proxy . NewLoadBalancerRR ( )
2015-05-18 17:11:25 +00:00
proxier , err := proxy . NewProxier ( loadBalancer , net . IP ( s . BindAddress ) , iptables . New ( exec . New ( ) , protocol ) , s . PortRange )
2015-05-14 20:03:30 +00:00
if err != nil {
glog . Fatalf ( "Unable to create proxer: %v" , err )
2015-02-02 21:54:52 +00:00
}
// Wire proxier to handle changes to services
serviceConfig . RegisterHandler ( proxier )
// And wire loadBalancer to handle changes to endpoints to services
endpointsConfig . RegisterHandler ( loadBalancer )
// Note: RegisterHandler() calls need to happen before creation of Sources because sources
// only notify on changes, and the initial update (on process start) may be lost if no handlers
// are registered yet.
// define api config source
2015-04-17 07:18:07 +00:00
if s . Kubeconfig == "" && s . Master == "" {
glog . Warningf ( "Neither --kubeconfig nor --master was specified. Using default API client. This might not work." )
}
// This creates a client, first loading any specified kubeconfig
// file, and then overriding the Master flag, if non-empty.
kubeconfig , err := clientcmd . NewNonInteractiveDeferredLoadingClientConfig (
& clientcmd . ClientConfigLoadingRules { ExplicitPath : s . Kubeconfig } ,
& clientcmd . ConfigOverrides { ClusterInfo : clientcmdapi . Cluster { Server : s . Master } } ) . ClientConfig ( )
if err != nil {
return err
}
client , err := client . New ( kubeconfig )
if err != nil {
glog . Fatalf ( "Invalid API configuration: %v" , err )
2015-02-02 21:54:52 +00:00
}
2015-04-17 07:18:07 +00:00
config . NewSourceAPI (
2015-06-28 19:28:10 +00:00
client ,
2015-04-17 07:18:07 +00:00
30 * time . Second ,
serviceConfig . Channel ( "api" ) ,
endpointsConfig . Channel ( "api" ) ,
)
2015-02-02 21:54:52 +00:00
if s . HealthzPort > 0 {
go util . Forever ( func ( ) {
2015-03-26 06:49:20 +00:00
err := http . ListenAndServe ( s . HealthzBindAddress . String ( ) + ":" + strconv . Itoa ( s . HealthzPort ) , nil )
2015-02-02 21:54:52 +00:00
if err != nil {
glog . Errorf ( "Starting health server failed: %v" , err )
}
} , 5 * time . Second )
}
// Just loop forever for now...
proxier . SyncLoop ( )
return nil
}