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 (
2015-08-20 17:01:37 +00:00
"errors"
2015-02-02 21:54:52 +00:00
"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-09 18:07:36 +00:00
"k8s.io/kubernetes/pkg/api"
2015-09-03 21:43:19 +00:00
"k8s.io/kubernetes/pkg/client/record"
2015-09-21 10:05:22 +00:00
kubeclient "k8s.io/kubernetes/pkg/client/unversioned"
2015-08-13 19:01:50 +00:00
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
2015-08-04 00:28:33 +00:00
"k8s.io/kubernetes/pkg/kubelet/qos"
2015-08-11 02:47:13 +00:00
"k8s.io/kubernetes/pkg/proxy"
2015-09-21 10:05:22 +00:00
proxyconfig "k8s.io/kubernetes/pkg/proxy/config"
2015-08-11 02:47:13 +00:00
"k8s.io/kubernetes/pkg/proxy/iptables"
2015-08-08 00:07:15 +00:00
"k8s.io/kubernetes/pkg/proxy/userspace"
2015-08-09 18:07:36 +00:00
"k8s.io/kubernetes/pkg/types"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/util"
2015-08-14 16:36:15 +00:00
utildbus "k8s.io/kubernetes/pkg/util/dbus"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/util/exec"
2015-08-11 02:47:13 +00:00
utiliptables "k8s.io/kubernetes/pkg/util/iptables"
2015-08-09 18:07:36 +00:00
nodeutil "k8s.io/kubernetes/pkg/util/node"
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"
2015-10-12 14:33:39 +00:00
"github.com/spf13/cobra"
2015-02-02 21:54:52 +00:00
"github.com/spf13/pflag"
)
2015-09-21 10:05:22 +00:00
// ProxyServerConfig contains configures and runs a Kubernetes proxy server
type ProxyServerConfig struct {
2015-09-21 21:25:57 +00:00
BindAddress net . IP
HealthzPort int
HealthzBindAddress net . IP
OOMScoreAdj int
ResourceContainer string
Master string
Kubeconfig string
PortRange util . PortRange
HostnameOverride string
ProxyMode string
2015-10-15 01:48:35 +00:00
IptablesSyncPeriod time . Duration
ConfigSyncPeriod time . Duration
2015-09-01 13:35:38 +00:00
NodeRef * api . ObjectReference // Reference to this node.
2015-09-21 21:25:57 +00:00
MasqueradeAll bool
CleanupAndExit bool
2015-10-20 12:33:48 +00:00
KubeAPIQPS float32
KubeAPIBurst int
2015-10-16 21:52:58 +00:00
UDPIdleTimeout time . Duration
2015-02-02 21:54:52 +00:00
}
2015-09-21 10:05:22 +00:00
type ProxyServer struct {
2015-09-01 13:35:38 +00:00
Client * kubeclient . Client
2015-10-01 22:22:32 +00:00
Config * ProxyServerConfig
IptInterface utiliptables . Interface
Proxier proxy . ProxyProvider
2015-09-01 13:35:38 +00:00
Broadcaster record . EventBroadcaster
2015-10-01 22:22:32 +00:00
Recorder record . EventRecorder
2015-02-02 21:54:52 +00:00
}
// AddFlags adds flags for a specific ProxyServer to the specified FlagSet
2015-09-21 10:05:22 +00:00
func ( s * ProxyServerConfig ) AddFlags ( fs * pflag . FlagSet ) {
2015-08-05 19:42:13 +00:00
fs . IPVar ( & s . BindAddress , "bind-address" , s . BindAddress , "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." )
2015-08-05 19:42:13 +00:00
fs . IPVar ( & s . HealthzBindAddress , "healthz-bind-address" , s . HealthzBindAddress , "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)" )
2015-08-13 23:52:01 +00:00
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]" )
2015-04-24 06:10:33 +00:00
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-11-21 21:39:35 +00:00
fs . MarkDeprecated ( "resource-container" , "This feature will be removed in a later release." )
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-08-09 18:07:36 +00:00
fs . StringVar ( & s . HostnameOverride , "hostname-override" , s . HostnameOverride , "If non-empty, will use this string as identification instead of the actual hostname." )
2015-10-27 06:08:37 +00:00
fs . StringVar ( & s . ProxyMode , "proxy-mode" , "" , "Which proxy mode to use: 'userspace' (older) or 'iptables' (faster). If blank, look at the Node object on the Kubernetes API and respect the '" + experimentalProxyModeAnnotation + "' annotation if provided. Otherwise use the best-available proxy (currently iptables). If the iptables proxy is selected, regardless of how, but the system's kernel or iptables versions are insufficient, this always falls back to the userspace proxy." )
2015-10-15 01:48:35 +00:00
fs . DurationVar ( & s . IptablesSyncPeriod , "iptables-sync-period" , s . IptablesSyncPeriod , "How often iptables rules are refreshed (e.g. '5s', '1m', '2h22m'). Must be greater than 0." )
fs . DurationVar ( & s . ConfigSyncPeriod , "config-sync-period" , s . ConfigSyncPeriod , "How often configuration from the apiserver is refreshed. Must be greater than 0." )
2015-08-20 18:39:01 +00:00
fs . BoolVar ( & s . MasqueradeAll , "masquerade-all" , false , "If using the pure iptables proxy, SNAT everything" )
2015-08-20 17:01:37 +00:00
fs . BoolVar ( & s . CleanupAndExit , "cleanup-iptables" , false , "If true cleanup iptables rules and exit." )
2015-10-20 12:33:48 +00:00
fs . Float32Var ( & s . KubeAPIQPS , "kube-api-qps" , s . KubeAPIQPS , "QPS to use while talking with kubernetes apiserver" )
fs . IntVar ( & s . KubeAPIBurst , "kube-api-burst" , s . KubeAPIBurst , "Burst to use while talking with kubernetes apiserver" )
2015-10-16 21:52:58 +00:00
fs . DurationVar ( & s . UDPIdleTimeout , "udp-timeout" , s . UDPIdleTimeout , "How long an idle UDP connection will be kept open (e.g. '250ms', '2s'). Must be greater than 0. Only applicable for proxy-mode=userspace" )
2015-02-02 21:54:52 +00:00
}
2015-09-21 21:25:57 +00:00
const (
proxyModeUserspace = "userspace"
proxyModeIptables = "iptables"
experimentalProxyModeAnnotation = "net.experimental.kubernetes.io/proxy-mode"
2015-10-09 23:52:23 +00:00
betaProxyModeAnnotation = "net.beta.kubernetes.io/proxy-mode"
2015-09-21 21:25:57 +00:00
)
func checkKnownProxyMode ( proxyMode string ) bool {
switch proxyMode {
case "" , proxyModeUserspace , proxyModeIptables :
return true
}
return false
}
2015-09-21 10:05:22 +00:00
func NewProxyConfig ( ) * ProxyServerConfig {
return & ProxyServerConfig {
BindAddress : net . ParseIP ( "0.0.0.0" ) ,
HealthzPort : 10249 ,
HealthzBindAddress : net . ParseIP ( "127.0.0.1" ) ,
2015-09-28 08:00:43 +00:00
OOMScoreAdj : qos . KubeProxyOOMScoreAdj ,
2015-09-21 10:05:22 +00:00
ResourceContainer : "/kube-proxy" ,
2015-10-15 01:48:35 +00:00
IptablesSyncPeriod : 30 * time . Second ,
ConfigSyncPeriod : 15 * time . Minute ,
2015-10-20 12:33:48 +00:00
KubeAPIQPS : 5.0 ,
KubeAPIBurst : 10 ,
2015-10-16 21:52:58 +00:00
UDPIdleTimeout : 250 * time . Millisecond ,
2015-09-21 10:05:22 +00:00
}
}
func NewProxyServer (
2015-09-01 13:35:38 +00:00
client * kubeclient . Client ,
2015-09-21 10:05:22 +00:00
config * ProxyServerConfig ,
iptInterface utiliptables . Interface ,
proxier proxy . ProxyProvider ,
2015-09-01 13:35:38 +00:00
broadcaster record . EventBroadcaster ,
2015-09-21 10:05:22 +00:00
recorder record . EventRecorder ,
) ( * ProxyServer , error ) {
return & ProxyServer {
2015-09-01 13:35:38 +00:00
Client : client ,
2015-10-01 22:22:32 +00:00
Config : config ,
IptInterface : iptInterface ,
Proxier : proxier ,
2015-09-01 13:35:38 +00:00
Broadcaster : broadcaster ,
2015-10-01 22:22:32 +00:00
Recorder : recorder ,
2015-09-21 10:05:22 +00:00
} , nil
}
2015-10-12 14:33:39 +00:00
// NewProxyCommand creates a *cobra.Command object with default parameters
func NewProxyCommand ( ) * cobra . Command {
s := NewProxyConfig ( )
s . AddFlags ( pflag . CommandLine )
cmd := & cobra . Command {
Use : "kube-proxy" ,
Long : ` The Kubernetes network proxy runs on each node . This
reflects services as defined in the Kubernetes API on each node and can do simple
TCP , UDP stream forwarding or round robin TCP , UDP forwarding across a set of backends .
Service cluster ips and ports are currently found through Docker - links - compatible
environment variables specifying ports opened by the service proxy . There is an optional
addon that provides cluster DNS for these cluster IPs . The user must create a service
with the apiserver API to configure the proxy . ` ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
} ,
}
return cmd
}
2015-09-21 10:05:22 +00:00
// NewProxyServerDefault creates a new ProxyServer object with default parameters.
func NewProxyServerDefault ( config * ProxyServerConfig ) ( * ProxyServer , error ) {
2015-08-20 17:01:37 +00:00
protocol := utiliptables . ProtocolIpv4
2015-09-21 10:05:22 +00:00
if config . BindAddress . To4 ( ) == nil {
2015-08-20 17:01:37 +00:00
protocol = utiliptables . ProtocolIpv6
}
2015-09-29 02:08:38 +00:00
// Create a iptables utils.
execer := exec . New ( )
dbus := utildbus . New ( )
iptInterface := utiliptables . New ( execer , dbus , protocol )
2015-09-21 10:05:22 +00:00
// We ommit creation of pretty much everything if we run in cleanup mode
if config . CleanupAndExit {
return & ProxyServer {
2015-10-01 03:13:13 +00:00
Config : config ,
2015-09-29 02:08:38 +00:00
IptInterface : iptInterface ,
2015-09-21 10:05:22 +00:00
} , nil
2015-08-20 17:01:37 +00:00
}
2015-04-14 16:49:13 +00:00
// TODO(vmarmol): Use container config for this.
2015-09-28 08:00:43 +00:00
var oomAdjuster * oom . OOMAdjuster
2015-09-21 10:05:22 +00:00
if config . OOMScoreAdj != 0 {
2015-09-29 02:08:38 +00:00
oomAdjuster = oom . NewOOMAdjuster ( )
2015-09-28 08:00:43 +00:00
if err := oomAdjuster . ApplyOOMScoreAdj ( 0 , config . OOMScoreAdj ) ; err != nil {
2015-09-21 10:05:22 +00:00
glog . V ( 2 ) . Info ( err )
}
2015-02-02 21:54:52 +00:00
}
2015-09-21 10:05:22 +00:00
if config . ResourceContainer != "" {
// Run in its own container.
if err := util . RunInResourceContainer ( config . ResourceContainer ) ; err != nil {
glog . Warningf ( "Failed to start in resource-only container %q: %v" , config . ResourceContainer , err )
} else {
glog . V ( 2 ) . Infof ( "Running in resource-only container %q" , config . ResourceContainer )
}
2015-04-14 16:49:13 +00:00
}
2015-09-21 10:05:22 +00:00
// Create a Kube Client
2015-08-09 18:07:36 +00:00
// define api config source
2015-09-21 10:05:22 +00:00
if config . Kubeconfig == "" && config . Master == "" {
2015-08-09 18:07:36 +00:00
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 (
2015-09-21 10:05:22 +00:00
& clientcmd . ClientConfigLoadingRules { ExplicitPath : config . Kubeconfig } ,
& clientcmd . ConfigOverrides { ClusterInfo : clientcmdapi . Cluster { Server : config . Master } } ) . ClientConfig ( )
2015-08-09 18:07:36 +00:00
if err != nil {
2015-09-21 10:05:22 +00:00
return nil , err
2015-08-09 18:07:36 +00:00
}
2015-10-12 15:56:15 +00:00
// Override kubeconfig qps/burst settings from flags
2015-10-20 12:33:48 +00:00
kubeconfig . QPS = config . KubeAPIQPS
kubeconfig . Burst = config . KubeAPIBurst
2015-10-12 15:56:15 +00:00
2015-09-21 10:05:22 +00:00
client , err := kubeclient . New ( kubeconfig )
2015-08-09 18:07:36 +00:00
if err != nil {
glog . Fatalf ( "Invalid API configuration: %v" , err )
}
2015-09-21 10:05:22 +00:00
// Create event recorder
hostname := nodeutil . GetHostname ( config . HostnameOverride )
2015-08-09 18:07:36 +00:00
eventBroadcaster := record . NewBroadcaster ( )
2015-09-21 10:05:22 +00:00
recorder := eventBroadcaster . NewRecorder ( api . EventSource { Component : "kube-proxy" , Host : hostname } )
2015-08-09 18:07:36 +00:00
2015-09-21 10:05:22 +00:00
var proxier proxy . ProxyProvider
var endpointsHandler proxyconfig . EndpointsConfigHandler
2015-09-21 21:25:57 +00:00
2015-10-27 06:08:37 +00:00
proxyMode := getProxyMode ( config . ProxyMode , client . Nodes ( ) , hostname , iptInterface )
if proxyMode == proxyModeIptables {
2015-08-11 02:47:13 +00:00
glog . V ( 2 ) . Info ( "Using iptables Proxier." )
2015-10-15 01:48:35 +00:00
proxierIptables , err := iptables . NewProxier ( iptInterface , execer , config . IptablesSyncPeriod , config . MasqueradeAll )
2015-08-11 02:47:13 +00:00
if err != nil {
glog . Fatalf ( "Unable to create proxier: %v" , err )
}
proxier = proxierIptables
endpointsHandler = proxierIptables
2015-08-20 17:01:37 +00:00
// No turning back. Remove artifacts that might still exist from the userspace Proxier.
glog . V ( 2 ) . Info ( "Tearing down userspace rules. Errors here are acceptable." )
2015-09-21 10:05:22 +00:00
userspace . CleanupLeftovers ( iptInterface )
2015-08-11 02:47:13 +00:00
} else {
glog . V ( 2 ) . Info ( "Using userspace Proxier." )
// This is a proxy.LoadBalancer which NewProxier needs but has methods we don't need for
// our config.EndpointsConfigHandler.
loadBalancer := userspace . NewLoadBalancerRR ( )
// set EndpointsConfigHandler to our loadBalancer
endpointsHandler = loadBalancer
2015-10-16 21:52:58 +00:00
proxierUserspace , err := userspace . NewProxier ( loadBalancer , config . BindAddress , iptInterface , config . PortRange , config . IptablesSyncPeriod , config . UDPIdleTimeout )
2015-08-11 02:47:13 +00:00
if err != nil {
2015-09-08 18:03:45 +00:00
glog . Fatalf ( "Unable to create proxier: %v" , err )
2015-08-11 02:47:13 +00:00
}
proxier = proxierUserspace
2015-08-20 17:01:37 +00:00
// Remove artifacts from the pure-iptables Proxier.
glog . V ( 2 ) . Info ( "Tearing down pure-iptables proxy rules. Errors here are acceptable." )
2015-09-21 10:05:22 +00:00
iptables . CleanupLeftovers ( iptInterface )
2015-02-02 21:54:52 +00:00
}
2015-09-21 10:05:22 +00:00
iptInterface . AddReloadFunc ( proxier . Sync )
2015-02-02 21:54:52 +00:00
2015-09-21 10:05:22 +00:00
// Create configs (i.e. Watches for Services and Endpoints)
2015-02-02 21:54:52 +00:00
// 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.
2015-09-21 10:05:22 +00:00
serviceConfig := proxyconfig . NewServiceConfig ( )
serviceConfig . RegisterHandler ( proxier )
2015-02-02 21:54:52 +00:00
2015-09-21 10:05:22 +00:00
endpointsConfig := proxyconfig . NewEndpointsConfig ( )
endpointsConfig . RegisterHandler ( endpointsHandler )
proxyconfig . NewSourceAPI (
2015-06-28 19:28:10 +00:00
client ,
2015-10-15 01:48:35 +00:00
config . ConfigSyncPeriod ,
2015-04-17 07:18:07 +00:00
serviceConfig . Channel ( "api" ) ,
endpointsConfig . Channel ( "api" ) ,
)
2015-09-01 13:35:38 +00:00
config . NodeRef = & api . ObjectReference {
2015-09-21 10:05:22 +00:00
Kind : "Node" ,
Name : hostname ,
UID : types . UID ( hostname ) ,
Namespace : "" ,
}
2015-09-01 13:35:38 +00:00
return NewProxyServer ( client , config , iptInterface , proxier , eventBroadcaster , recorder )
2015-09-21 10:05:22 +00:00
}
// Run runs the specified ProxyServer. This should never exit (unless CleanupAndExit is set).
func ( s * ProxyServer ) Run ( _ [ ] string ) error {
// remove iptables rules and exit
if s . Config . CleanupAndExit {
encounteredError := userspace . CleanupLeftovers ( s . IptInterface )
encounteredError = iptables . CleanupLeftovers ( s . IptInterface ) || encounteredError
if encounteredError {
return errors . New ( "Encountered an error while tearing down rules." )
}
return nil
}
2015-09-01 13:35:38 +00:00
s . Broadcaster . StartRecordingToSink ( s . Client . Events ( "" ) )
2015-09-21 10:05:22 +00:00
// Birth Cry after the birth is successful
s . birthCry ( )
// Start up Healthz service if requested
if s . Config . HealthzPort > 0 {
2015-08-24 01:59:15 +00:00
go util . Until ( func ( ) {
2015-09-21 10:05:22 +00:00
err := http . ListenAndServe ( s . Config . HealthzBindAddress . String ( ) + ":" + strconv . Itoa ( s . Config . HealthzPort ) , nil )
2015-02-02 21:54:52 +00:00
if err != nil {
glog . Errorf ( "Starting health server failed: %v" , err )
}
2015-08-24 01:59:15 +00:00
} , 5 * time . Second , util . NeverStop )
2015-02-02 21:54:52 +00:00
}
// Just loop forever for now...
2015-09-21 10:05:22 +00:00
s . Proxier . SyncLoop ( )
2015-02-02 21:54:52 +00:00
return nil
}
2015-08-09 18:07:36 +00:00
2015-09-21 21:25:57 +00:00
type nodeGetter interface {
Get ( hostname string ) ( * api . Node , error )
}
2015-10-27 06:08:37 +00:00
func getProxyMode ( proxyMode string , client nodeGetter , hostname string , iptver iptables . IptablesVersioner ) string {
if proxyMode == proxyModeUserspace {
return proxyModeUserspace
} else if proxyMode == proxyModeIptables {
return tryIptablesProxy ( iptver )
2015-09-21 21:25:57 +00:00
} else if proxyMode != "" {
2015-10-27 06:08:37 +00:00
glog . V ( 1 ) . Infof ( "Flag proxy-mode=%q unknown, assuming iptables proxy" , proxyMode )
return tryIptablesProxy ( iptver )
2015-09-21 21:25:57 +00:00
}
// proxyMode == "" - choose the best option.
if client == nil {
2015-10-27 06:08:37 +00:00
glog . Errorf ( "nodeGetter is nil: assuming iptables proxy" )
return tryIptablesProxy ( iptver )
2015-09-21 21:25:57 +00:00
}
node , err := client . Get ( hostname )
if err != nil {
2015-10-27 06:08:37 +00:00
glog . Errorf ( "Can't get Node %q, assuming iptables proxy: %v" , hostname , err )
return tryIptablesProxy ( iptver )
2015-09-21 21:25:57 +00:00
}
if node == nil {
2015-10-27 06:08:37 +00:00
glog . Errorf ( "Got nil Node %q, assuming iptables proxy: %v" , hostname )
return tryIptablesProxy ( iptver )
2015-09-21 21:25:57 +00:00
}
2015-10-09 23:52:23 +00:00
proxyMode , found := node . Annotations [ betaProxyModeAnnotation ]
2015-09-21 21:25:57 +00:00
if found {
2015-10-09 23:52:23 +00:00
glog . V ( 1 ) . Infof ( "Found beta annotation %q = %q" , betaProxyModeAnnotation , proxyMode )
} else {
// We already published some information about this annotation with the "experimental" name, so we will respect it.
proxyMode , found = node . Annotations [ experimentalProxyModeAnnotation ]
if found {
glog . V ( 1 ) . Infof ( "Found experimental annotation %q = %q" , experimentalProxyModeAnnotation , proxyMode )
}
2015-09-21 21:25:57 +00:00
}
2015-10-27 06:08:37 +00:00
if proxyMode == proxyModeUserspace {
glog . V ( 1 ) . Infof ( "Annotation demands userspace proxy" )
return proxyModeUserspace
2015-09-21 21:25:57 +00:00
}
2015-10-27 06:08:37 +00:00
return tryIptablesProxy ( iptver )
}
func tryIptablesProxy ( iptver iptables . IptablesVersioner ) string {
var err error
// guaranteed false on error, error only necessary for debugging
useIptablesProxy , err := iptables . CanUseIptablesProxier ( iptver )
if err != nil {
glog . Errorf ( "Can't determine whether to use iptables proxy, using userspace proxier: %v" , err )
return proxyModeUserspace
}
if useIptablesProxy {
return proxyModeIptables
}
// Fallback.
glog . V ( 1 ) . Infof ( "Can't use iptables proxy, using userspace proxier: %v" , err )
return proxyModeUserspace
2015-09-21 21:25:57 +00:00
}
2015-08-09 18:07:36 +00:00
func ( s * ProxyServer ) birthCry ( ) {
2015-09-01 13:35:38 +00:00
s . Recorder . Eventf ( s . Config . NodeRef , "Starting" , "Starting kube-proxy." )
2015-08-09 18:07:36 +00:00
}