Add kube-proxy config file support

Add support for configuring kube-proxy via a config file instead of
command line flags.
pull/6/head
Andy Goldstein 2017-04-26 09:41:44 -04:00
parent 07424af12b
commit 43cb024402
21 changed files with 837 additions and 555 deletions

View File

@ -50,7 +50,6 @@ go_library(
"//cmd/kube-controller-manager/app:go_default_library", "//cmd/kube-controller-manager/app:go_default_library",
"//cmd/kube-controller-manager/app/options:go_default_library", "//cmd/kube-controller-manager/app/options:go_default_library",
"//cmd/kube-proxy/app:go_default_library", "//cmd/kube-proxy/app:go_default_library",
"//cmd/kube-proxy/app/options:go_default_library",
"//cmd/kubelet/app:go_default_library", "//cmd/kubelet/app:go_default_library",
"//cmd/kubelet/app/options:go_default_library", "//cmd/kubelet/app/options:go_default_library",
"//federation/cmd/federation-apiserver/app:go_default_library", "//federation/cmd/federation-apiserver/app:go_default_library",

View File

@ -17,39 +17,37 @@ limitations under the License.
package main package main
import ( import (
"flag"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/kubernetes/cmd/kube-proxy/app" "k8s.io/kubernetes/cmd/kube-proxy/app"
"k8s.io/kubernetes/cmd/kube-proxy/app/options"
) )
func init() {
healthz.DefaultHealthz()
}
// NewKubeProxy creates a new hyperkube Server object that includes the // NewKubeProxy creates a new hyperkube Server object that includes the
// description and flags. // description and flags.
func NewKubeProxy() *Server { func NewKubeProxy() *Server {
config := options.NewProxyConfig() healthz.DefaultHealthz()
command := app.NewProxyCommand()
hks := Server{ hks := Server{
name: "proxy", name: "proxy",
AlternativeName: "kube-proxy", AlternativeName: "kube-proxy",
SimpleUsage: "proxy", SimpleUsage: "proxy",
Long: `The Kubernetes proxy server is responsible for taking traffic directed at Long: command.Long,
services and forwarding it to the appropriate pods. It generally runs on
nodes next to the Kubelet and proxies traffic from local pods to remote pods.
It is also used when handling incoming external traffic.`,
} }
config.AddFlags(hks.Flags()) serverFlags := hks.Flags()
serverFlags.AddFlagSet(command.Flags())
hks.Run = func(_ *Server, _ []string) error { // FIXME this is here because hyperkube does its own flag parsing, and we need
s, err := app.NewProxyServerDefault(config) // the command to know about the go flag set. Remove this once hyperkube is
if err != nil { // refactored to use cobra throughout.
return err command.Flags().AddGoFlagSet(flag.CommandLine)
}
return s.Run() hks.Run = func(_ *Server, args []string) error {
command.SetArgs(args)
return command.Execute()
} }
return &hks return &hks

View File

@ -27,7 +27,6 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//cmd/kube-proxy/app:go_default_library", "//cmd/kube-proxy/app:go_default_library",
"//cmd/kube-proxy/app/options:go_default_library",
"//pkg/client/metrics/prometheus:go_default_library", "//pkg/client/metrics/prometheus:go_default_library",
"//pkg/version/prometheus:go_default_library", "//pkg/version/prometheus:go_default_library",
"//pkg/version/verflag:go_default_library", "//pkg/version/verflag:go_default_library",

View File

@ -16,10 +16,13 @@ go_library(
], ],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//cmd/kube-proxy/app/options:go_default_library",
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/apis/componentconfig:go_default_library",
"//pkg/apis/componentconfig/v1alpha1:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library",
"//pkg/kubelet/qos:go_default_library",
"//pkg/proxy:go_default_library", "//pkg/proxy:go_default_library",
"//pkg/proxy/config:go_default_library", "//pkg/proxy/config:go_default_library",
"//pkg/proxy/iptables:go_default_library", "//pkg/proxy/iptables:go_default_library",
@ -42,10 +45,13 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//vendor/k8s.io/client-go/pkg/api/v1:go_default_library", "//vendor/k8s.io/client-go/pkg/api/v1:go_default_library",
"//vendor/k8s.io/client-go/pkg/util:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
"//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/client-go/tools/record:go_default_library",
@ -58,7 +64,6 @@ go_test(
library = ":go_default_library", library = ":go_default_library",
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//cmd/kube-proxy/app/options:go_default_library",
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/apis/componentconfig:go_default_library", "//pkg/apis/componentconfig:go_default_library",
"//pkg/util/iptables:go_default_library", "//pkg/util/iptables:go_default_library",
@ -76,9 +81,6 @@ filegroup(
filegroup( filegroup(
name = "all-srcs", name = "all-srcs",
srcs = [ srcs = [":package-srcs"],
":package-srcs",
"//cmd/kube-proxy/app/options:all-srcs",
],
tags = ["automanaged"], tags = ["automanaged"],
) )

View File

@ -1,38 +0,0 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["options.go"],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/apis/componentconfig:go_default_library",
"//pkg/apis/componentconfig/v1alpha1:go_default_library",
"//pkg/features:go_default_library",
"//pkg/kubelet/qos:go_default_library",
"//pkg/util:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/client-go/pkg/api/v1:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -1,105 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
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 options contains flags for initializing a proxy.
package options
import (
_ "net/http/pprof"
"time"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientv1 "k8s.io/client-go/pkg/api/v1"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/componentconfig"
"k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1"
_ "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubelet/qos"
"k8s.io/kubernetes/pkg/util"
// add the kubernetes feature gates
_ "k8s.io/kubernetes/pkg/features"
"github.com/spf13/pflag"
)
// ProxyServerConfig configures and runs a Kubernetes proxy server
type ProxyServerConfig struct {
componentconfig.KubeProxyConfiguration
ResourceContainer string
ContentType string
KubeAPIQPS float32
KubeAPIBurst int32
ConfigSyncPeriod time.Duration
CleanupAndExit bool
NodeRef *clientv1.ObjectReference
Master string
Kubeconfig string
}
func NewProxyConfig() *ProxyServerConfig {
versioned := &v1alpha1.KubeProxyConfiguration{}
api.Scheme.Default(versioned)
cfg := componentconfig.KubeProxyConfiguration{}
api.Scheme.Convert(versioned, &cfg, nil)
return &ProxyServerConfig{
KubeProxyConfiguration: cfg,
ContentType: "application/vnd.kubernetes.protobuf",
KubeAPIQPS: 5.0,
KubeAPIBurst: 10,
ConfigSyncPeriod: 15 * time.Minute,
}
}
// AddFlags adds flags for a specific ProxyServer to the specified FlagSet
func (s *ProxyServerConfig) AddFlags(fs *pflag.FlagSet) {
fs.Var(componentconfig.IPVar{Val: &s.BindAddress}, "bind-address", "The IP address for the proxy server to serve on (set to 0.0.0.0 for all interfaces)")
fs.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
fs.Int32Var(&s.HealthzPort, "healthz-port", s.HealthzPort, "The port to bind the health check server. Use 0 to disable.")
fs.Var(componentconfig.IPVar{Val: &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.Int32Var(s.OOMScoreAdj, "oom-score-adj", util.Int32PtrDerefOr(s.OOMScoreAdj, int32(qos.KubeProxyOOMScoreAdj)), "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).")
fs.MarkDeprecated("resource-container", "This feature will be removed in a later release.")
fs.StringVar(&s.Kubeconfig, "kubeconfig", s.Kubeconfig, "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
fs.Var(componentconfig.PortRangeVar{Val: &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.")
fs.StringVar(&s.HostnameOverride, "hostname-override", s.HostnameOverride, "If non-empty, will use this string as identification instead of the actual hostname.")
fs.Var(&s.Mode, "proxy-mode", "Which proxy mode to use: 'userspace' (older) or 'iptables' (faster). If blank, 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.")
fs.Int32Var(s.IPTablesMasqueradeBit, "iptables-masquerade-bit", util.Int32PtrDerefOr(s.IPTablesMasqueradeBit, 14), "If using the pure iptables proxy, the bit of the fwmark space to mark packets requiring SNAT with. Must be within the range [0, 31].")
fs.DurationVar(&s.IPTablesSyncPeriod.Duration, "iptables-sync-period", s.IPTablesSyncPeriod.Duration, "The maximum interval of how often iptables rules are refreshed (e.g. '5s', '1m', '2h22m'). Must be greater than 0.")
fs.DurationVar(&s.IPTablesMinSyncPeriod.Duration, "iptables-min-sync-period", s.IPTablesMinSyncPeriod.Duration, "The minimum interval of how often the iptables rules can be refreshed as endpoints and services change (e.g. '5s', '1m', '2h22m').")
fs.DurationVar(&s.ConfigSyncPeriod, "config-sync-period", s.ConfigSyncPeriod, "How often configuration from the apiserver is refreshed. Must be greater than 0.")
fs.BoolVar(&s.MasqueradeAll, "masquerade-all", s.MasqueradeAll, "If using the pure iptables proxy, SNAT everything")
fs.StringVar(&s.ClusterCIDR, "cluster-cidr", s.ClusterCIDR, "The CIDR range of pods in the cluster. It is used to bridge traffic coming from outside of the cluster. If not provided, no off-cluster bridging will be performed.")
fs.BoolVar(&s.CleanupAndExit, "cleanup-iptables", s.CleanupAndExit, "If true cleanup iptables rules and exit.")
fs.StringVar(&s.ContentType, "kube-api-content-type", s.ContentType, "Content type of requests sent to apiserver.")
fs.Float32Var(&s.KubeAPIQPS, "kube-api-qps", s.KubeAPIQPS, "QPS to use while talking with kubernetes apiserver")
fs.Int32Var(&s.KubeAPIBurst, "kube-api-burst", s.KubeAPIBurst, "Burst to use while talking with kubernetes apiserver")
fs.DurationVar(&s.UDPIdleTimeout.Duration, "udp-timeout", s.UDPIdleTimeout.Duration, "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")
fs.Int32Var(&s.ConntrackMax, "conntrack-max", s.ConntrackMax,
"Maximum number of NAT connections to track (0 to leave as-is). This overrides conntrack-max-per-core and conntrack-min.")
fs.MarkDeprecated("conntrack-max", "This feature will be removed in a later release.")
fs.Int32Var(&s.ConntrackMaxPerCore, "conntrack-max-per-core", s.ConntrackMaxPerCore,
"Maximum number of NAT connections to track per CPU core (0 to leave the limit as-is and ignore conntrack-min).")
fs.Int32Var(&s.ConntrackMin, "conntrack-min", s.ConntrackMin,
"Minimum number of conntrack entries to allocate, regardless of conntrack-max-per-core (set conntrack-max-per-core=0 to leave the limit as-is).")
fs.DurationVar(&s.ConntrackTCPEstablishedTimeout.Duration, "conntrack-tcp-timeout-established", s.ConntrackTCPEstablishedTimeout.Duration, "Idle timeout for established TCP connections (0 to leave as-is)")
fs.DurationVar(
&s.ConntrackTCPCloseWaitTimeout.Duration, "conntrack-tcp-timeout-close-wait",
s.ConntrackTCPCloseWaitTimeout.Duration,
"NAT timeout for TCP connections in the CLOSE_WAIT state")
utilfeature.DefaultFeatureGate.AddFlag(fs)
}

View File

@ -21,27 +21,34 @@ package app
import ( import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"net" "net"
"net/http" "net/http"
_ "net/http/pprof" _ "net/http/pprof"
"runtime" "runtime"
"strconv" "strings"
"time" "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilnet "k8s.io/apimachinery/pkg/util/net" utilnet "k8s.io/apimachinery/pkg/util/net"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientgoclientset "k8s.io/client-go/kubernetes" clientgoclientset "k8s.io/client-go/kubernetes"
v1core "k8s.io/client-go/kubernetes/typed/core/v1" v1core "k8s.io/client-go/kubernetes/typed/core/v1"
clientv1 "k8s.io/client-go/pkg/api/v1" clientv1 "k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/pkg/util"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
"k8s.io/kubernetes/cmd/kube-proxy/app/options"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/componentconfig"
"k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubelet/qos"
"k8s.io/kubernetes/pkg/proxy" "k8s.io/kubernetes/pkg/proxy"
proxyconfig "k8s.io/kubernetes/pkg/proxy/config" proxyconfig "k8s.io/kubernetes/pkg/proxy/config"
"k8s.io/kubernetes/pkg/proxy/iptables" "k8s.io/kubernetes/pkg/proxy/iptables"
@ -63,23 +70,12 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
type ProxyServer struct {
Client clientset.Interface
EventClient v1core.EventsGetter
Config *options.ProxyServerConfig
IptInterface utiliptables.Interface
Proxier proxy.ProxyProvider
Broadcaster record.EventBroadcaster
Recorder record.EventRecorder
Conntracker Conntracker // if nil, ignored
ProxyMode string
}
const ( const (
proxyModeUserspace = "userspace" proxyModeUserspace = "userspace"
proxyModeIPTables = "iptables" proxyModeIPTables = "iptables"
) )
// checkKnownProxyMode returns true if proxyMode is valid.
func checkKnownProxyMode(proxyMode string) bool { func checkKnownProxyMode(proxyMode string) bool {
switch proxyMode { switch proxyMode {
case "", proxyModeUserspace, proxyModeIPTables: case "", proxyModeUserspace, proxyModeIPTables:
@ -88,34 +84,174 @@ func checkKnownProxyMode(proxyMode string) bool {
return false return false
} }
func NewProxyServer( // Options contains everything necessary to create and run a proxy server.
client clientset.Interface, type Options struct {
eventClient v1core.EventsGetter, // ConfigFile is the location of the proxy server's configuration file.
config *options.ProxyServerConfig, ConfigFile string
iptInterface utiliptables.Interface, // CleanupAndExit, when true, makes the proxy server clean up iptables rules, then exit.
proxier proxy.ProxyProvider, CleanupAndExit bool
broadcaster record.EventBroadcaster,
recorder record.EventRecorder, // config is the proxy server's configuration object.
conntracker Conntracker, config *componentconfig.KubeProxyConfiguration
proxyMode string,
) (*ProxyServer, error) { // The fields below here are placeholders for flags that can't be directly mapped into
return &ProxyServer{ // componentconfig.KubeProxyConfiguration.
Client: client, //
EventClient: eventClient, // TODO remove these fields once the deprecated flags are removed.
Config: config,
IptInterface: iptInterface, // master is used to override the kubeconfig's URL to the apiserver.
Proxier: proxier, master string
Broadcaster: broadcaster, // healthzPort is the port to be used by the healthz server.
Recorder: recorder, healthzPort int32
Conntracker: conntracker, }
ProxyMode: proxyMode,
}, nil // AddFlags adds flags to fs and binds them to options.
func AddFlags(options *Options, fs *pflag.FlagSet) {
fs.StringVar(&options.ConfigFile, "config", options.ConfigFile, "The path to the configuration file.")
fs.BoolVar(&options.CleanupAndExit, "cleanup-iptables", options.CleanupAndExit, "If true cleanup iptables rules and exit.")
// All flags below here are deprecated and will eventually be removed.
fs.Var(componentconfig.IPVar{Val: &options.config.BindAddress}, "bind-address", "The IP address for the proxy server to serve on (set to 0.0.0.0 for all interfaces)")
fs.StringVar(&options.master, "master", options.master, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
fs.Int32Var(&options.healthzPort, "healthz-port", options.healthzPort, "The port to bind the health check server. Use 0 to disable.")
fs.Var(componentconfig.IPVar{Val: &options.config.HealthzBindAddress}, "healthz-bind-address", "The IP address and port for the health check server to serve on (set to 0.0.0.0 for all interfaces)")
fs.Int32Var(options.config.OOMScoreAdj, "oom-score-adj", util.Int32PtrDerefOr(options.config.OOMScoreAdj, int32(qos.KubeProxyOOMScoreAdj)), "The oom-score-adj value for kube-proxy process. Values must be within the range [-1000, 1000]")
fs.StringVar(&options.config.ResourceContainer, "resource-container", options.config.ResourceContainer, "Absolute name of the resource-only container to create and run the Kube-proxy in (Default: /kube-proxy).")
fs.MarkDeprecated("resource-container", "This feature will be removed in a later release.")
fs.StringVar(&options.config.ClientConnection.KubeConfigFile, "kubeconfig", options.config.ClientConnection.KubeConfigFile, "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
fs.Var(componentconfig.PortRangeVar{Val: &options.config.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.")
fs.StringVar(&options.config.HostnameOverride, "hostname-override", options.config.HostnameOverride, "If non-empty, will use this string as identification instead of the actual hostname.")
fs.Var(&options.config.Mode, "proxy-mode", "Which proxy mode to use: 'userspace' (older) or 'iptables' (faster). If blank, 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.")
fs.Int32Var(options.config.IPTables.MasqueradeBit, "iptables-masquerade-bit", util.Int32PtrDerefOr(options.config.IPTables.MasqueradeBit, 14), "If using the pure iptables proxy, the bit of the fwmark space to mark packets requiring SNAT with. Must be within the range [0, 31].")
fs.DurationVar(&options.config.IPTables.SyncPeriod.Duration, "iptables-sync-period", options.config.IPTables.SyncPeriod.Duration, "The maximum interval of how often iptables rules are refreshed (e.g. '5s', '1m', '2h22m'). Must be greater than 0.")
fs.DurationVar(&options.config.IPTables.MinSyncPeriod.Duration, "iptables-min-sync-period", options.config.IPTables.MinSyncPeriod.Duration, "The minimum interval of how often the iptables rules can be refreshed as endpoints and services change (e.g. '5s', '1m', '2h22m').")
fs.DurationVar(&options.config.ConfigSyncPeriod.Duration, "config-sync-period", options.config.ConfigSyncPeriod.Duration, "How often configuration from the apiserver is refreshed. Must be greater than 0.")
fs.BoolVar(&options.config.IPTables.MasqueradeAll, "masquerade-all", options.config.IPTables.MasqueradeAll, "If using the pure iptables proxy, SNAT everything")
fs.StringVar(&options.config.ClusterCIDR, "cluster-cidr", options.config.ClusterCIDR, "The CIDR range of pods in the cluster. It is used to bridge traffic coming from outside of the cluster. If not provided, no off-cluster bridging will be performed.")
fs.StringVar(&options.config.ClientConnection.ContentType, "kube-api-content-type", options.config.ClientConnection.ContentType, "Content type of requests sent to apiserver.")
fs.Float32Var(&options.config.ClientConnection.QPS, "kube-api-qps", options.config.ClientConnection.QPS, "QPS to use while talking with kubernetes apiserver")
fs.IntVar(&options.config.ClientConnection.Burst, "kube-api-burst", options.config.ClientConnection.Burst, "Burst to use while talking with kubernetes apiserver")
fs.DurationVar(&options.config.UDPIdleTimeout.Duration, "udp-timeout", options.config.UDPIdleTimeout.Duration, "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")
fs.Int32Var(&options.config.Conntrack.Max, "conntrack-max", options.config.Conntrack.Max,
"Maximum number of NAT connections to track (0 to leave as-is). This overrides conntrack-max-per-core and conntrack-min.")
fs.MarkDeprecated("conntrack-max", "This feature will be removed in a later release.")
fs.Int32Var(&options.config.Conntrack.MaxPerCore, "conntrack-max-per-core", options.config.Conntrack.MaxPerCore,
"Maximum number of NAT connections to track per CPU core (0 to leave the limit as-is and ignore conntrack-min).")
fs.Int32Var(&options.config.Conntrack.Min, "conntrack-min", options.config.Conntrack.Min,
"Minimum number of conntrack entries to allocate, regardless of conntrack-max-per-core (set conntrack-max-per-core=0 to leave the limit as-is).")
fs.DurationVar(&options.config.Conntrack.TCPEstablishedTimeout.Duration, "conntrack-tcp-timeout-established", options.config.Conntrack.TCPEstablishedTimeout.Duration, "Idle timeout for established TCP connections (0 to leave as-is)")
fs.DurationVar(
&options.config.Conntrack.TCPCloseWaitTimeout.Duration, "conntrack-tcp-timeout-close-wait",
options.config.Conntrack.TCPCloseWaitTimeout.Duration,
"NAT timeout for TCP connections in the CLOSE_WAIT state")
utilfeature.DefaultFeatureGate.AddFlag(fs)
}
// Complete completes all the required options.
func (o Options) Complete() error {
if len(o.ConfigFile) == 0 {
glog.Warning("WARNING: all flags other than --config and --cleanup-iptables are deprecated. Please begin using a config file ASAP.")
o.applyDeprecatedHealthzPortToConfig()
}
return nil
}
// Validate validates all the required options.
func (o Options) Validate(args []string) error {
if len(args) != 0 {
return errors.New("no arguments are supported")
}
return nil
}
func (o Options) Run() error {
config := o.config
if len(o.ConfigFile) > 0 {
if c, err := loadConfigFromFile(o.ConfigFile); err != nil {
return err
} else {
config = c
// Make sure we apply the feature gate settings in the config file.
utilfeature.DefaultFeatureGate.Set(config.FeatureGates)
}
}
proxyServer, err := NewProxyServer(config, o.CleanupAndExit, o.master)
if err != nil {
return err
}
return proxyServer.Run()
}
// applyDeprecatedHealthzPortToConfig sets o.config.HealthzBindAddress from
// flags passed on the command line based on the following rules:
//
// 1. If --healthz-port is 0, disable the healthz server.
// 2. Otherwise, use the value of --healthz-port for the port portion of
// o.config.HealthzBindAddress
func (o Options) applyDeprecatedHealthzPortToConfig() {
if o.healthzPort == 0 {
o.config.HealthzBindAddress = ""
return
}
index := strings.Index(o.config.HealthzBindAddress, ":")
if index != -1 {
o.config.HealthzBindAddress = o.config.HealthzBindAddress[0:index]
}
o.config.HealthzBindAddress = fmt.Sprintf("%s:%d", o.config.HealthzBindAddress, o.healthzPort)
}
// loadConfigFromFile loads the contents of file and decodes it as a
// KubeProxyConfiguration object.
func loadConfigFromFile(file string) (*componentconfig.KubeProxyConfiguration, error) {
data, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
configObj, gvk, err := api.Codecs.UniversalDecoder().Decode(data, nil, nil)
if err != nil {
return nil, err
}
config, ok := configObj.(*componentconfig.KubeProxyConfiguration)
if !ok {
return nil, fmt.Errorf("got unexpected config type: %v", gvk)
}
return config, nil
}
func applyDefaults(in *componentconfig.KubeProxyConfiguration) (*componentconfig.KubeProxyConfiguration, error) {
external, err := api.Scheme.ConvertToVersion(in, v1alpha1.SchemeGroupVersion)
if err != nil {
return nil, err
}
api.Scheme.Default(external)
internal, err := api.Scheme.ConvertToVersion(external, componentconfig.SchemeGroupVersion)
if err != nil {
return nil, err
}
out := internal.(*componentconfig.KubeProxyConfiguration)
return out, nil
} }
// NewProxyCommand creates a *cobra.Command object with default parameters // NewProxyCommand creates a *cobra.Command object with default parameters
func NewProxyCommand() *cobra.Command { func NewProxyCommand() *cobra.Command {
s := options.NewProxyConfig() opts := Options{
s.AddFlags(pflag.CommandLine) config: new(componentconfig.KubeProxyConfiguration),
healthzPort: 10249,
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "kube-proxy", Use: "kube-proxy",
Long: `The Kubernetes network proxy runs on each node. This Long: `The Kubernetes network proxy runs on each node. This
@ -126,19 +262,98 @@ environment variables specifying ports opened by the service proxy. There is an
addon that provides cluster DNS for these cluster IPs. The user must create a service addon that provides cluster DNS for these cluster IPs. The user must create a service
with the apiserver API to configure the proxy.`, with the apiserver API to configure the proxy.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(opts.Complete())
cmdutil.CheckErr(opts.Validate(args))
cmdutil.CheckErr(opts.Run())
}, },
} }
var err error
opts.config, err = applyDefaults(opts.config)
if err != nil {
glog.Fatalf("unable to create flag defaults: %v", err)
}
flags := cmd.Flags()
AddFlags(&opts, flags)
cmd.MarkFlagFilename("config", "yaml", "yml", "json")
return cmd return cmd
} }
// NewProxyServerDefault creates a new ProxyServer object with default parameters. // ProxyServer represents all the parameters required to start the Kubernetes proxy server. All
func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, error) { // fields are required.
if c, err := configz.New("componentconfig"); err == nil { type ProxyServer struct {
c.Set(config.KubeProxyConfiguration) Client clientset.Interface
} else { EventClient v1core.EventsGetter
glog.Errorf("unable to register configz: %s", err) IptInterface utiliptables.Interface
Proxier proxy.ProxyProvider
Broadcaster record.EventBroadcaster
Recorder record.EventRecorder
ConntrackConfiguration componentconfig.KubeProxyConntrackConfiguration
Conntracker Conntracker // if nil, ignored
ProxyMode string
NodeRef *clientv1.ObjectReference
CleanupAndExit bool
HealthzBindAddress string
OOMScoreAdj *int32
ResourceContainer string
ConfigSyncPeriod time.Duration
ServiceEventHandler proxyconfig.ServiceHandler
// TODO: Migrate all handlers to ServiceHandler types and
// get rid of this one.
ServiceHandler proxyconfig.ServiceConfigHandler
EndpointsEventHandler proxyconfig.EndpointsHandler
} }
// createClients creates a kube client and an event client from the given config and masterOverride.
// TODO remove masterOverride when CLI flags are removed.
func createClients(config componentconfig.ClientConnectionConfiguration, masterOverride string) (clientset.Interface, v1core.EventsGetter, error) {
if len(config.KubeConfigFile) == 0 && len(masterOverride) == 0 {
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: config.KubeConfigFile},
&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterOverride}}).ClientConfig()
if err != nil {
return nil, nil, err
}
kubeConfig.AcceptContentTypes = config.AcceptContentTypes
kubeConfig.ContentType = config.ContentType
kubeConfig.QPS = config.QPS
//TODO make config struct use int instead of int32?
kubeConfig.Burst = int(config.Burst)
client, err := clientset.NewForConfig(kubeConfig)
if err != nil {
return nil, nil, err
}
eventClient, err := clientgoclientset.NewForConfig(kubeConfig)
if err != nil {
return nil, nil, err
}
return client, eventClient, nil
}
// NewProxyServer returns a new ProxyServer.
func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndExit bool, master string) (*ProxyServer, error) {
if config == nil {
return nil, errors.New("config is required")
}
if c, err := configz.New("componentconfig"); err == nil {
c.Set(config)
} else {
return nil, fmt.Errorf("unable to register configz: %s", err)
}
protocol := utiliptables.ProtocolIpv4 protocol := utiliptables.ProtocolIpv4
if net.ParseIP(config.BindAddress).To4() == nil { if net.ParseIP(config.BindAddress).To4() == nil {
protocol = utiliptables.ProtocolIpv6 protocol = utiliptables.ProtocolIpv6
@ -159,56 +374,11 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err
} }
// We omit creation of pretty much everything if we run in cleanup mode // We omit creation of pretty much everything if we run in cleanup mode
if config.CleanupAndExit { if cleanupAndExit {
return &ProxyServer{ return &ProxyServer{IptInterface: iptInterface}, nil
Config: config,
IptInterface: iptInterface,
}, nil
} }
// TODO(vmarmol): Use container config for this. client, eventClient, err := createClients(config.ClientConnection, master)
var oomAdjuster *oom.OOMAdjuster
if config.OOMScoreAdj != nil {
oomAdjuster = oom.NewOOMAdjuster()
if err := oomAdjuster.ApplyOOMScoreAdj(0, int(*config.OOMScoreAdj)); err != nil {
glog.V(2).Info(err)
}
}
if config.ResourceContainer != "" {
// Run in its own container.
if err := resourcecontainer.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)
}
}
// Create a Kube Client
// define api config source
if config.Kubeconfig == "" && config.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: config.Kubeconfig},
&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: config.Master}}).ClientConfig()
if err != nil {
return nil, err
}
kubeconfig.ContentType = config.ContentType
// Override kubeconfig qps/burst settings from flags
kubeconfig.QPS = config.KubeAPIQPS
kubeconfig.Burst = int(config.KubeAPIBurst)
client, err := clientset.NewForConfig(kubeconfig)
if err != nil {
glog.Fatalf("Invalid API configuration: %v", err)
}
eventClient, err := clientgoclientset.NewForConfig(kubeconfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -228,31 +398,34 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err
proxyMode := getProxyMode(string(config.Mode), iptInterface, iptables.LinuxKernelCompatTester{}) proxyMode := getProxyMode(string(config.Mode), iptInterface, iptables.LinuxKernelCompatTester{})
if proxyMode == proxyModeIPTables { if proxyMode == proxyModeIPTables {
glog.V(0).Info("Using iptables Proxier.") glog.V(0).Info("Using iptables Proxier.")
if config.IPTablesMasqueradeBit == nil { if config.IPTables.MasqueradeBit == nil {
// IPTablesMasqueradeBit must be specified or defaulted. // MasqueradeBit must be specified or defaulted.
return nil, fmt.Errorf("Unable to read IPTablesMasqueradeBit from config") return nil, fmt.Errorf("unable to read IPTables MasqueradeBit from config")
} }
// TODO this has side effects that should only happen when Run() is invoked.
proxierIPTables, err := iptables.NewProxier( proxierIPTables, err := iptables.NewProxier(
iptInterface, iptInterface,
utilsysctl.New(), utilsysctl.New(),
execer, execer,
config.IPTablesSyncPeriod.Duration, config.IPTables.SyncPeriod.Duration,
config.IPTablesMinSyncPeriod.Duration, config.IPTables.MinSyncPeriod.Duration,
config.MasqueradeAll, config.IPTables.MasqueradeAll,
int(*config.IPTablesMasqueradeBit), int(*config.IPTables.MasqueradeBit),
config.ClusterCIDR, config.ClusterCIDR,
hostname, hostname,
getNodeIP(client, hostname), getNodeIP(client, hostname),
recorder, recorder,
) )
if err != nil { if err != nil {
glog.Fatalf("Unable to create proxier: %v", err) return nil, fmt.Errorf("unable to create proxier: %v", err)
} }
proxier = proxierIPTables proxier = proxierIPTables
serviceEventHandler = proxierIPTables serviceEventHandler = proxierIPTables
endpointsEventHandler = proxierIPTables endpointsEventHandler = proxierIPTables
// No turning back. Remove artifacts that might still exist from the userspace Proxier. // No turning back. Remove artifacts that might still exist from the userspace Proxier.
glog.V(0).Info("Tearing down userspace rules.") glog.V(0).Info("Tearing down userspace rules.")
// TODO this has side effects that should only happen when Run() is invoked.
userspace.CleanupLeftovers(iptInterface) userspace.CleanupLeftovers(iptInterface)
} else { } else {
glog.V(0).Info("Using userspace Proxier.") glog.V(0).Info("Using userspace Proxier.")
@ -268,11 +441,11 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err
netshInterface, netshInterface,
*utilnet.ParsePortRangeOrDie(config.PortRange), *utilnet.ParsePortRangeOrDie(config.PortRange),
// TODO @pires replace below with default values, if applicable // TODO @pires replace below with default values, if applicable
config.IPTablesSyncPeriod.Duration, config.IPTables.SyncPeriod.Duration,
config.UDPIdleTimeout.Duration, config.UDPIdleTimeout.Duration,
) )
if err != nil { if err != nil {
glog.Fatalf("Unable to create proxier: %v", err) return nil, fmt.Errorf("unable to create proxier: %v", err)
} }
serviceHandler = proxierUserspace serviceHandler = proxierUserspace
proxier = proxierUserspace proxier = proxierUserspace
@ -282,18 +455,20 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err
loadBalancer := userspace.NewLoadBalancerRR() loadBalancer := userspace.NewLoadBalancerRR()
// set EndpointsConfigHandler to our loadBalancer // set EndpointsConfigHandler to our loadBalancer
endpointsEventHandler = loadBalancer endpointsEventHandler = loadBalancer
// TODO this has side effects that should only happen when Run() is invoked.
proxierUserspace, err := userspace.NewProxier( proxierUserspace, err := userspace.NewProxier(
loadBalancer, loadBalancer,
net.ParseIP(config.BindAddress), net.ParseIP(config.BindAddress),
iptInterface, iptInterface,
execer, execer,
*utilnet.ParsePortRangeOrDie(config.PortRange), *utilnet.ParsePortRangeOrDie(config.PortRange),
config.IPTablesSyncPeriod.Duration, config.IPTables.SyncPeriod.Duration,
config.IPTablesMinSyncPeriod.Duration, config.IPTables.MinSyncPeriod.Duration,
config.UDPIdleTimeout.Duration, config.UDPIdleTimeout.Duration,
) )
if err != nil { if err != nil {
glog.Fatalf("Unable to create proxier: %v", err) return nil, fmt.Errorf("unable to create proxier: %v", err)
} }
serviceHandler = proxierUserspace serviceHandler = proxierUserspace
proxier = proxierUserspace proxier = proxierUserspace
@ -301,6 +476,7 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err
// Remove artifacts from the pure-iptables Proxier, if not on Windows. // Remove artifacts from the pure-iptables Proxier, if not on Windows.
if runtime.GOOS != "windows" { if runtime.GOOS != "windows" {
glog.V(0).Info("Tearing down pure-iptables proxy rules.") glog.V(0).Info("Tearing down pure-iptables proxy rules.")
// TODO this has side effects that should only happen when Run() is invoked.
iptables.CleanupLeftovers(iptInterface) iptables.CleanupLeftovers(iptInterface)
} }
} }
@ -310,73 +486,84 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err
iptInterface.AddReloadFunc(proxier.Sync) iptInterface.AddReloadFunc(proxier.Sync)
} }
informerFactory := informers.NewSharedInformerFactory(client, config.ConfigSyncPeriod) nodeRef := &clientv1.ObjectReference{
// Create configs (i.e. Watches for Services and Endpoints)
// 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.
serviceConfig := proxyconfig.NewServiceConfig(informerFactory.Core().InternalVersion().Services(), config.ConfigSyncPeriod)
if serviceHandler != nil {
serviceConfig.RegisterHandler(serviceHandler)
}
if serviceEventHandler != nil {
serviceConfig.RegisterEventHandler(serviceEventHandler)
}
go serviceConfig.Run(wait.NeverStop)
endpointsConfig := proxyconfig.NewEndpointsConfig(informerFactory.Core().InternalVersion().Endpoints(), config.ConfigSyncPeriod)
endpointsConfig.RegisterEventHandler(endpointsEventHandler)
go endpointsConfig.Run(wait.NeverStop)
// This has to start after the calls to NewServiceConfig and NewEndpointsConfig because those
// functions must configure their shared informer event handlers first.
go informerFactory.Start(wait.NeverStop)
config.NodeRef = &clientv1.ObjectReference{
Kind: "Node", Kind: "Node",
Name: hostname, Name: hostname,
UID: types.UID(hostname), UID: types.UID(hostname),
Namespace: "", Namespace: "",
} }
conntracker := realConntracker{} return &ProxyServer{
Client: client,
return NewProxyServer(client, eventClient, config, iptInterface, proxier, eventBroadcaster, recorder, conntracker, proxyMode) EventClient: eventClient,
IptInterface: iptInterface,
Proxier: proxier,
Broadcaster: eventBroadcaster,
Recorder: recorder,
ConntrackConfiguration: config.Conntrack,
Conntracker: &realConntracker{},
ProxyMode: proxyMode,
NodeRef: nodeRef,
HealthzBindAddress: config.HealthzBindAddress,
OOMScoreAdj: config.OOMScoreAdj,
ResourceContainer: config.ResourceContainer,
ConfigSyncPeriod: config.ConfigSyncPeriod.Duration,
ServiceEventHandler: serviceEventHandler,
ServiceHandler: serviceHandler,
EndpointsEventHandler: endpointsEventHandler,
}, nil
} }
// Run runs the specified ProxyServer. This should never exit (unless CleanupAndExit is set). // Run runs the specified ProxyServer. This should never exit (unless CleanupAndExit is set).
func (s *ProxyServer) Run() error { func (s *ProxyServer) Run() error {
// remove iptables rules and exit // remove iptables rules and exit
if s.Config.CleanupAndExit { if s.CleanupAndExit {
encounteredError := userspace.CleanupLeftovers(s.IptInterface) encounteredError := userspace.CleanupLeftovers(s.IptInterface)
encounteredError = iptables.CleanupLeftovers(s.IptInterface) || encounteredError encounteredError = iptables.CleanupLeftovers(s.IptInterface) || encounteredError
if encounteredError { if encounteredError {
return errors.New("Encountered an error while tearing down rules.") return errors.New("encountered an error while tearing down rules.")
} }
return nil return nil
} }
// TODO(vmarmol): Use container config for this.
var oomAdjuster *oom.OOMAdjuster
if s.OOMScoreAdj != nil {
oomAdjuster = oom.NewOOMAdjuster()
if err := oomAdjuster.ApplyOOMScoreAdj(0, int(*s.OOMScoreAdj)); err != nil {
glog.V(2).Info(err)
}
}
if len(s.ResourceContainer) != 0 {
// Run in its own container.
if err := resourcecontainer.RunInResourceContainer(s.ResourceContainer); err != nil {
glog.Warningf("Failed to start in resource-only container %q: %v", s.ResourceContainer, err)
} else {
glog.V(2).Infof("Running in resource-only container %q", s.ResourceContainer)
}
}
s.Broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: s.EventClient.Events("")}) s.Broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: s.EventClient.Events("")})
// Start up a webserver if requested // Start up a webserver if requested
if s.Config.HealthzPort > 0 { if len(s.HealthzBindAddress) > 0 {
http.HandleFunc("/proxyMode", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/proxyMode", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s", s.ProxyMode) fmt.Fprintf(w, "%s", s.ProxyMode)
}) })
http.Handle("/metrics", prometheus.Handler()) http.Handle("/metrics", prometheus.Handler())
configz.InstallHandler(http.DefaultServeMux) configz.InstallHandler(http.DefaultServeMux)
go wait.Until(func() { go wait.Until(func() {
err := http.ListenAndServe(s.Config.HealthzBindAddress+":"+strconv.Itoa(int(s.Config.HealthzPort)), nil) err := http.ListenAndServe(s.HealthzBindAddress, nil)
if err != nil { if err != nil {
glog.Errorf("Starting health server failed: %v", err) utilruntime.HandleError(fmt.Errorf("starting health server failed: %v", err))
} }
}, 5*time.Second, wait.NeverStop) }, 5*time.Second, wait.NeverStop)
} }
// Tune conntrack, if requested // Tune conntrack, if requested
if s.Conntracker != nil && runtime.GOOS != "windows" { if s.Conntracker != nil && runtime.GOOS != "windows" {
max, err := getConntrackMax(s.Config) max, err := getConntrackMax(s.ConntrackConfiguration)
if err != nil { if err != nil {
return err return err
} }
@ -394,25 +581,48 @@ func (s *ProxyServer) Run() error {
// TODO(random-liu): Remove this when the docker bug is fixed. // TODO(random-liu): Remove this when the docker bug is fixed.
const message = "DOCKER RESTART NEEDED (docker issue #24000): /sys is read-only: " + const message = "DOCKER RESTART NEEDED (docker issue #24000): /sys is read-only: " +
"cannot modify conntrack limits, problems may arise later." "cannot modify conntrack limits, problems may arise later."
s.Recorder.Eventf(s.Config.NodeRef, api.EventTypeWarning, err.Error(), message) s.Recorder.Eventf(s.NodeRef, api.EventTypeWarning, err.Error(), message)
} }
} }
if s.Config.ConntrackTCPEstablishedTimeout.Duration > 0 { if s.ConntrackConfiguration.TCPEstablishedTimeout.Duration > 0 {
timeout := int(s.Config.ConntrackTCPEstablishedTimeout.Duration / time.Second) timeout := int(s.ConntrackConfiguration.TCPEstablishedTimeout.Duration / time.Second)
if err := s.Conntracker.SetTCPEstablishedTimeout(timeout); err != nil { if err := s.Conntracker.SetTCPEstablishedTimeout(timeout); err != nil {
return err return err
} }
} }
if s.Config.ConntrackTCPCloseWaitTimeout.Duration > 0 { if s.ConntrackConfiguration.TCPCloseWaitTimeout.Duration > 0 {
timeout := int(s.Config.ConntrackTCPCloseWaitTimeout.Duration / time.Second) timeout := int(s.ConntrackConfiguration.TCPCloseWaitTimeout.Duration / time.Second)
if err := s.Conntracker.SetTCPCloseWaitTimeout(timeout); err != nil { if err := s.Conntracker.SetTCPCloseWaitTimeout(timeout); err != nil {
return err return err
} }
} }
} }
informerFactory := informers.NewSharedInformerFactory(s.Client, s.ConfigSyncPeriod)
// Create configs (i.e. Watches for Services and Endpoints)
// 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.
serviceConfig := proxyconfig.NewServiceConfig(informerFactory.Core().InternalVersion().Services(), s.ConfigSyncPeriod)
if s.ServiceHandler != nil {
serviceConfig.RegisterHandler(s.ServiceHandler)
}
if s.ServiceEventHandler != nil {
serviceConfig.RegisterEventHandler(s.ServiceEventHandler)
}
go serviceConfig.Run(wait.NeverStop)
endpointsConfig := proxyconfig.NewEndpointsConfig(informerFactory.Core().InternalVersion().Endpoints(), s.ConfigSyncPeriod)
endpointsConfig.RegisterEventHandler(s.EndpointsEventHandler)
go endpointsConfig.Run(wait.NeverStop)
// This has to start after the calls to NewServiceConfig and NewEndpointsConfig because those
// functions must configure their shared informer event handlers first.
go informerFactory.Start(wait.NeverStop)
// Birth Cry after the birth is successful // Birth Cry after the birth is successful
s.birthCry() s.birthCry()
@ -421,17 +631,17 @@ func (s *ProxyServer) Run() error {
return nil return nil
} }
func getConntrackMax(config *options.ProxyServerConfig) (int, error) { func getConntrackMax(config componentconfig.KubeProxyConntrackConfiguration) (int, error) {
if config.ConntrackMax > 0 { if config.Max > 0 {
if config.ConntrackMaxPerCore > 0 { if config.MaxPerCore > 0 {
return -1, fmt.Errorf("invalid config: Conntrack Max and Conntrack MaxPerCore are mutually exclusive") return -1, fmt.Errorf("invalid config: Conntrack Max and Conntrack MaxPerCore are mutually exclusive")
} }
glog.V(3).Infof("getConntrackMax: using absolute conntrack-max (deprecated)") glog.V(3).Infof("getConntrackMax: using absolute conntrack-max (deprecated)")
return int(config.ConntrackMax), nil return int(config.Max), nil
} }
if config.ConntrackMaxPerCore > 0 { if config.MaxPerCore > 0 {
floor := int(config.ConntrackMin) floor := int(config.Min)
scaled := int(config.ConntrackMaxPerCore) * runtime.NumCPU() scaled := int(config.MaxPerCore) * runtime.NumCPU()
if scaled > floor { if scaled > floor {
glog.V(3).Infof("getConntrackMax: using scaled conntrack-max-per-core") glog.V(3).Infof("getConntrackMax: using scaled conntrack-max-per-core")
return scaled, nil return scaled, nil
@ -447,7 +657,7 @@ func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, kcompat i
return proxyModeUserspace return proxyModeUserspace
} }
if proxyMode != "" && proxyMode != proxyModeIPTables { if len(proxyMode) > 0 && proxyMode != proxyModeIPTables {
glog.Warningf("Flag proxy-mode=%q unknown, assuming iptables proxy", proxyMode) glog.Warningf("Flag proxy-mode=%q unknown, assuming iptables proxy", proxyMode)
} }
@ -458,7 +668,7 @@ func tryIPTablesProxy(iptver iptables.IPTablesVersioner, kcompat iptables.Kernel
// guaranteed false on error, error only necessary for debugging // guaranteed false on error, error only necessary for debugging
useIPTablesProxy, err := iptables.CanUseIPTablesProxier(iptver, kcompat) useIPTablesProxy, err := iptables.CanUseIPTablesProxier(iptver, kcompat)
if err != nil { if err != nil {
glog.Errorf("Can't determine whether to use iptables proxy, using userspace proxier: %v", err) utilruntime.HandleError(fmt.Errorf("can't determine whether to use iptables proxy, using userspace proxier: %v", err))
return proxyModeUserspace return proxyModeUserspace
} }
if useIPTablesProxy { if useIPTablesProxy {
@ -470,7 +680,7 @@ func tryIPTablesProxy(iptver iptables.IPTablesVersioner, kcompat iptables.Kernel
} }
func (s *ProxyServer) birthCry() { func (s *ProxyServer) birthCry() {
s.Recorder.Eventf(s.Config.NodeRef, api.EventTypeNormal, "Starting", "Starting kube-proxy.") s.Recorder.Eventf(s.NodeRef, api.EventTypeNormal, "Starting", "Starting kube-proxy.")
} }
func getNodeIP(client clientset.Interface, hostname string) net.IP { func getNodeIP(client clientset.Interface, hostname string) net.IP {

View File

@ -25,7 +25,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/cmd/kube-proxy/app/options"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/apis/componentconfig"
"k8s.io/kubernetes/pkg/util/iptables" "k8s.io/kubernetes/pkg/util/iptables"
@ -131,77 +130,68 @@ func Test_getProxyMode(t *testing.T) {
} }
} }
// This test verifies that Proxy Server does not crash that means // This test verifies that Proxy Server does not crash when CleanupAndExit is true.
// Config and iptinterface are not nil when CleanupAndExit is true.
// To avoid proxy crash: https://github.com/kubernetes/kubernetes/pull/14736
func TestProxyServerWithCleanupAndExit(t *testing.T) { func TestProxyServerWithCleanupAndExit(t *testing.T) {
// creates default config options := Options{
config := options.NewProxyConfig() config: &componentconfig.KubeProxyConfiguration{
BindAddress: "0.0.0.0",
},
CleanupAndExit: true,
}
// sets CleanupAndExit manually proxyserver, err := NewProxyServer(options.config, options.CleanupAndExit, options.master)
config.CleanupAndExit = true
// creates new proxy server
proxyserver, err := NewProxyServerDefault(config)
// verifies that nothing is nill except error
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, proxyserver) assert.NotNil(t, proxyserver)
assert.NotNil(t, proxyserver.Config)
assert.NotNil(t, proxyserver.IptInterface) assert.NotNil(t, proxyserver.IptInterface)
} }
func TestGetConntrackMax(t *testing.T) { func TestGetConntrackMax(t *testing.T) {
ncores := runtime.NumCPU() ncores := runtime.NumCPU()
testCases := []struct { testCases := []struct {
config componentconfig.KubeProxyConfiguration min int32
max int32
maxPerCore int32
expected int expected int
err string err string
}{ }{
{ {
config: componentconfig.KubeProxyConfiguration{},
expected: 0, expected: 0,
}, },
{ {
config: componentconfig.KubeProxyConfiguration{ max: 12345,
ConntrackMax: 12345,
},
expected: 12345, expected: 12345,
}, },
{ {
config: componentconfig.KubeProxyConfiguration{ max: 12345,
ConntrackMax: 12345, maxPerCore: 67890,
ConntrackMaxPerCore: 67890,
},
expected: -1, expected: -1,
err: "mutually exclusive", err: "mutually exclusive",
}, },
{ {
config: componentconfig.KubeProxyConfiguration{ maxPerCore: 67890, // use this if Max is 0
ConntrackMaxPerCore: 67890, // use this if Max is 0 min: 1, // avoid 0 default
ConntrackMin: 1, // avoid 0 default
},
expected: 67890 * ncores, expected: 67890 * ncores,
}, },
{ {
config: componentconfig.KubeProxyConfiguration{ maxPerCore: 1, // ensure that Min is considered
ConntrackMaxPerCore: 1, // ensure that Min is considered min: 123456,
ConntrackMin: 123456,
},
expected: 123456, expected: 123456,
}, },
{ {
config: componentconfig.KubeProxyConfiguration{ maxPerCore: 0, // leave system setting
ConntrackMaxPerCore: 0, // leave system setting min: 123456,
ConntrackMin: 123456,
},
expected: 0, expected: 0,
}, },
} }
for i, tc := range testCases { for i, tc := range testCases {
cfg := options.ProxyServerConfig{KubeProxyConfiguration: tc.config} cfg := componentconfig.KubeProxyConntrackConfiguration{
x, e := getConntrackMax(&cfg) Min: tc.min,
Max: tc.max,
MaxPerCore: tc.maxPerCore,
}
x, e := getConntrackMax(cfg)
if e != nil { if e != nil {
if tc.err == "" { if tc.err == "" {
t.Errorf("[%d] unexpected error: %v", i, e) t.Errorf("[%d] unexpected error: %v", i, e)

View File

@ -17,43 +17,37 @@ limitations under the License.
package main package main
import ( import (
"fmt" goflag "flag"
"os" "os"
"github.com/spf13/pflag"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/apiserver/pkg/util/flag" utilflag "k8s.io/apiserver/pkg/util/flag"
"k8s.io/apiserver/pkg/util/logs" "k8s.io/apiserver/pkg/util/logs"
"k8s.io/kubernetes/cmd/kube-proxy/app" "k8s.io/kubernetes/cmd/kube-proxy/app"
"k8s.io/kubernetes/cmd/kube-proxy/app/options"
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration _ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
_ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration _ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration
"k8s.io/kubernetes/pkg/version/verflag" "k8s.io/kubernetes/pkg/version/verflag"
"github.com/spf13/pflag"
) )
func init() {
healthz.DefaultHealthz()
}
func main() { func main() {
config := options.NewProxyConfig() healthz.DefaultHealthz()
config.AddFlags(pflag.CommandLine)
flag.InitFlags() command := app.NewProxyCommand()
// TODO: once we switch everything over to Cobra commands, we can go back to calling
// utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the
// normalize func and add the go flag set by hand.
pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc)
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
// utilflag.InitFlags()
logs.InitLogs() logs.InitLogs()
defer logs.FlushLogs() defer logs.FlushLogs()
verflag.PrintAndExitIfRequested() verflag.PrintAndExitIfRequested()
s, err := app.NewProxyServerDefault(config) if err := command.Execute(); err != nil {
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
if err = s.Run(); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1) os.Exit(1)
} }
} }

View File

@ -22,13 +22,11 @@ go_library(
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library", "//pkg/client/clientset_generated/clientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/client/metrics/prometheus:go_default_library", "//pkg/client/metrics/prometheus:go_default_library",
"//pkg/kubelet/cadvisor/testing:go_default_library", "//pkg/kubelet/cadvisor/testing:go_default_library",
"//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/cm:go_default_library",
"//pkg/kubelet/dockertools:go_default_library", "//pkg/kubelet/dockertools:go_default_library",
"//pkg/kubemark:go_default_library", "//pkg/kubemark:go_default_library",
"//pkg/proxy/config:go_default_library",
"//pkg/util/iptables/testing:go_default_library", "//pkg/util/iptables/testing:go_default_library",
"//pkg/version/prometheus:go_default_library", "//pkg/version/prometheus:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",

View File

@ -30,13 +30,11 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset" "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration _ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing" cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing"
"k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/pkg/kubelet/cm"
"k8s.io/kubernetes/pkg/kubelet/dockertools" "k8s.io/kubernetes/pkg/kubelet/dockertools"
"k8s.io/kubernetes/pkg/kubemark" "k8s.io/kubernetes/pkg/kubemark"
proxyconfig "k8s.io/kubernetes/pkg/proxy/config"
fakeiptables "k8s.io/kubernetes/pkg/util/iptables/testing" fakeiptables "k8s.io/kubernetes/pkg/util/iptables/testing"
_ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration _ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration
@ -138,13 +136,6 @@ func main() {
iptInterface := fakeiptables.NewFake() iptInterface := fakeiptables.NewFake()
informerFactory := informers.NewSharedInformerFactory(internalClientset, configResyncPeriod)
serviceConfig := proxyconfig.NewServiceConfig(informerFactory.Core().InternalVersion().Services(), configResyncPeriod)
serviceConfig.RegisterHandler(&kubemark.FakeProxyHandler{})
endpointsConfig := proxyconfig.NewEndpointsConfig(informerFactory.Core().InternalVersion().Endpoints(), configResyncPeriod)
endpointsConfig.RegisterEventHandler(&kubemark.FakeProxyHandler{})
eventClient, err := clientgoclientset.NewForConfig(clientConfig) eventClient, err := clientgoclientset.NewForConfig(clientConfig)
if err != nil { if err != nil {
glog.Fatalf("Failed to create API Server client: %v", err) glog.Fatalf("Failed to create API Server client: %v", err)
@ -154,9 +145,6 @@ func main() {
config.NodeName, config.NodeName,
internalClientset, internalClientset,
eventClient, eventClient,
endpointsConfig,
serviceConfig,
informerFactory,
iptInterface, iptInterface,
eventBroadcaster, eventBroadcaster,
recorder, recorder,

View File

@ -689,12 +689,20 @@ function start_kubelet {
function start_kubeproxy { function start_kubeproxy {
PROXY_LOG=${LOG_DIR}/kube-proxy.log PROXY_LOG=${LOG_DIR}/kube-proxy.log
cat <<EOF > /tmp/kube-proxy.yaml
apiVersion: componentconfig/v1alpha1
kind: KubeProxyConfiguration
clientConnection:
kubeconfig: ${CERT_DIR}/kube-proxy.kubeconfig
hostnameOverride: ${HOSTNAME_OVERRIDE}
featureGates: ${FEATURE_GATES}
EOF
sudo "${GO_OUT}/hyperkube" proxy \ sudo "${GO_OUT}/hyperkube" proxy \
--v=${LOG_LEVEL} \ --config=/tmp/kube-proxy.yaml \
--hostname-override="${HOSTNAME_OVERRIDE}" \ --master="https://${API_HOST}:${API_SECURE_PORT}" >"${PROXY_LOG}" \
--feature-gates="${FEATURE_GATES}" \ --v=${LOG_LEVEL} 2>&1 &
--kubeconfig "$CERT_DIR"/kube-proxy.kubeconfig \
--master="https://${API_HOST}:${API_SECURE_PORT}" >"${PROXY_LOG}" 2>&1 &
PROXY_PID=$! PROXY_PID=$!
SCHEDULER_LOG=${LOG_DIR}/kube-scheduler.log SCHEDULER_LOG=${LOG_DIR}/kube-scheduler.log

View File

@ -25,39 +25,90 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
) )
// ClientConnectionConfiguration contains details for constructing a client.
type ClientConnectionConfiguration struct {
// kubeConfigFile is the path to a kubeconfig file.
KubeConfigFile string
// acceptContentTypes defines the Accept header sent by clients when connecting to a server, overriding the
// default value of 'application/json'. This field will control all connections to the server used by a particular
// client.
AcceptContentTypes string
// contentType is the content type used when sending data to the server from this client.
ContentType string
// qps controls the number of queries per second allowed for this connection.
QPS float32
// burst allows extra queries to accumulate when a client is exceeding its rate.
Burst int
}
// KubeProxyIPTablesConfiguration contains iptables-related configuration
// details for the Kubernetes proxy server.
type KubeProxyIPTablesConfiguration struct {
// masqueradeBit is the bit of the iptables fwmark space to use for SNAT if using
// the pure iptables proxy mode. Values must be within the range [0, 31].
MasqueradeBit *int32
// masqueradeAll tells kube-proxy to SNAT everything if using the pure iptables proxy mode.
MasqueradeAll bool
// syncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m',
// '2h22m'). Must be greater than 0.
SyncPeriod metav1.Duration
// minSyncPeriod is the minimum period that iptables rules are refreshed (e.g. '5s', '1m',
// '2h22m').
MinSyncPeriod metav1.Duration
}
// KubeProxyConntrackConfiguration contains conntrack settings for
// the Kubernetes proxy server.
type KubeProxyConntrackConfiguration struct {
// max is the maximum number of NAT connections to track (0 to
// leave as-is). This takes precedence over conntrackMaxPerCore and conntrackMin.
Max int32
// maxPerCore is the maximum number of NAT connections to track
// per CPU core (0 to leave the limit as-is and ignore conntrackMin).
MaxPerCore int32
// min is the minimum value of connect-tracking records to allocate,
// regardless of conntrackMaxPerCore (set conntrackMaxPerCore=0 to leave the limit as-is).
Min int32
// tcpEstablishedTimeout is how long an idle TCP connection will be kept open
// (e.g. '2s'). Must be greater than 0.
TCPEstablishedTimeout metav1.Duration
// tcpCloseWaitTimeout is how long an idle conntrack entry
// in CLOSE_WAIT state will remain in the conntrack
// table. (e.g. '60s'). Must be greater than 0 to set.
TCPCloseWaitTimeout metav1.Duration
}
// KubeProxyConfiguration contains everything necessary to configure the
// Kubernetes proxy server.
type KubeProxyConfiguration struct { type KubeProxyConfiguration struct {
metav1.TypeMeta metav1.TypeMeta
// featureGates is a comma-separated list of key=value pairs that control
// which alpha/beta features are enabled.
//
// TODO this really should be a map but that requires refactoring all
// components to use config files because local-up-cluster.sh only supports
// the --feature-gates flag right now, which is comma-separated key=value
// pairs.
FeatureGates string
// bindAddress is the IP address for the proxy server to serve on (set to 0.0.0.0 // bindAddress is the IP address for the proxy server to serve on (set to 0.0.0.0
// for all interfaces) // for all interfaces)
BindAddress string BindAddress string
// healthzBindAddress is the IP address and port for the health check server to serve on,
// defaulting to 127.0.0.1:10249 (set to 0.0.0.0 for all interfaces)
HealthzBindAddress string
// clusterCIDR is the CIDR range of the pods in the cluster. It is used to // clusterCIDR is the CIDR range of the pods in the cluster. It is used to
// bridge traffic coming from outside of the cluster. If not provided, // bridge traffic coming from outside of the cluster. If not provided,
// no off-cluster bridging will be performed. // no off-cluster bridging will be performed.
ClusterCIDR string ClusterCIDR string
// healthzBindAddress is 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)
HealthzBindAddress string
// healthzPort is the port to bind the health check server. Use 0 to disable.
HealthzPort int32
// hostnameOverride, if non-empty, will be used as the identity instead of the actual hostname. // hostnameOverride, if non-empty, will be used as the identity instead of the actual hostname.
HostnameOverride string HostnameOverride string
// iptablesMasqueradeBit is the bit of the iptables fwmark space to use for SNAT if using // clientConnection specifies the kubeconfig file and client connection settings for the proxy
// the pure iptables proxy mode. Values must be within the range [0, 31]. // server to use when communicating with the apiserver.
IPTablesMasqueradeBit *int32 ClientConnection ClientConnectionConfiguration
// iptablesSyncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m', // iptables contains iptables-related configuration options.
// '2h22m'). Must be greater than 0. IPTables KubeProxyIPTablesConfiguration
IPTablesSyncPeriod metav1.Duration
// iptablesMinSyncPeriod is the minimum period that iptables rules are refreshed (e.g. '5s', '1m',
// '2h22m').
IPTablesMinSyncPeriod metav1.Duration
// kubeconfigPath is the path to the kubeconfig file with authorization information (the
// master location is set by the master flag).
KubeconfigPath string
// masqueradeAll tells kube-proxy to SNAT everything if using the pure iptables proxy mode.
MasqueradeAll bool
// master is the address of the Kubernetes API server (overrides any value in kubeconfig)
Master string
// oomScoreAdj is the oom-score-adj value for kube-proxy process. Values must be within // oomScoreAdj is the oom-score-adj value for kube-proxy process. Values must be within
// the range [-1000, 1000] // the range [-1000, 1000]
OOMScoreAdj *int32 OOMScoreAdj *int32
@ -72,22 +123,11 @@ type KubeProxyConfiguration struct {
// udpIdleTimeout is how long an idle UDP connection will be kept open (e.g. '250ms', '2s'). // udpIdleTimeout is how long an idle UDP connection will be kept open (e.g. '250ms', '2s').
// Must be greater than 0. Only applicable for proxyMode=userspace. // Must be greater than 0. Only applicable for proxyMode=userspace.
UDPIdleTimeout metav1.Duration UDPIdleTimeout metav1.Duration
// conntrackMax is the maximum number of NAT connections to track (0 to // conntrack contains conntrack-related configuration options.
// leave as-is). This takes precedence over conntrackMaxPerCore and conntrackMin. Conntrack KubeProxyConntrackConfiguration
ConntrackMax int32 // configSyncPeriod is how often configuration from the apiserver is refreshed. Must be greater
// conntrackMaxPerCore is the maximum number of NAT connections to track // than 0.
// per CPU core (0 to leave the limit as-is and ignore conntrackMin). ConfigSyncPeriod metav1.Duration
ConntrackMaxPerCore int32
// conntrackMin is the minimum value of connect-tracking records to allocate,
// regardless of conntrackMaxPerCore (set conntrackMaxPerCore=0 to leave the limit as-is).
ConntrackMin int32
// conntrackTCPEstablishedTimeout is how long an idle TCP connection will be kept open
// (e.g. '2s'). Must be greater than 0.
ConntrackTCPEstablishedTimeout metav1.Duration
// conntrackTCPCloseWaitTimeout is how long an idle conntrack entry
// in CLOSE_WAIT state will remain in the conntrack
// table. (e.g. '60s'). Must be greater than 0 to set.
ConntrackTCPCloseWaitTimeout metav1.Duration
} }
// Currently two modes of proxying are available: 'userspace' (older, stable) or 'iptables' // Currently two modes of proxying are available: 'userspace' (older, stable) or 'iptables'

View File

@ -19,6 +19,7 @@ package v1alpha1
import ( import (
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"time" "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -59,14 +60,13 @@ func addDefaultingFuncs(scheme *kruntime.Scheme) error {
} }
func SetDefaults_KubeProxyConfiguration(obj *KubeProxyConfiguration) { func SetDefaults_KubeProxyConfiguration(obj *KubeProxyConfiguration) {
if obj.BindAddress == "" { if len(obj.BindAddress) == 0 {
obj.BindAddress = "0.0.0.0" obj.BindAddress = "0.0.0.0"
} }
if obj.HealthzPort == 0 { if len(obj.HealthzBindAddress) == 0 {
obj.HealthzPort = 10249 obj.HealthzBindAddress = "127.0.0.1:10249"
} } else if !strings.Contains(obj.HealthzBindAddress, ":") {
if obj.HealthzBindAddress == "" { obj.HealthzBindAddress = ":10249"
obj.HealthzBindAddress = "127.0.0.1"
} }
if obj.OOMScoreAdj == nil { if obj.OOMScoreAdj == nil {
temp := int32(qos.KubeProxyOOMScoreAdj) temp := int32(qos.KubeProxyOOMScoreAdj)
@ -75,31 +75,31 @@ func SetDefaults_KubeProxyConfiguration(obj *KubeProxyConfiguration) {
if obj.ResourceContainer == "" { if obj.ResourceContainer == "" {
obj.ResourceContainer = "/kube-proxy" obj.ResourceContainer = "/kube-proxy"
} }
if obj.IPTablesSyncPeriod.Duration == 0 { if obj.IPTables.SyncPeriod.Duration == 0 {
obj.IPTablesSyncPeriod = metav1.Duration{Duration: 30 * time.Second} obj.IPTables.SyncPeriod = metav1.Duration{Duration: 30 * time.Second}
} }
zero := metav1.Duration{} zero := metav1.Duration{}
if obj.UDPIdleTimeout == zero { if obj.UDPIdleTimeout == zero {
obj.UDPIdleTimeout = metav1.Duration{Duration: 250 * time.Millisecond} obj.UDPIdleTimeout = metav1.Duration{Duration: 250 * time.Millisecond}
} }
// If ConntrackMax is set, respect it. // If ConntrackMax is set, respect it.
if obj.ConntrackMax == 0 { if obj.Conntrack.Max == 0 {
// If ConntrackMax is *not* set, use per-core scaling. // If ConntrackMax is *not* set, use per-core scaling.
if obj.ConntrackMaxPerCore == 0 { if obj.Conntrack.MaxPerCore == 0 {
obj.ConntrackMaxPerCore = 32 * 1024 obj.Conntrack.MaxPerCore = 32 * 1024
} }
if obj.ConntrackMin == 0 { if obj.Conntrack.Min == 0 {
obj.ConntrackMin = 128 * 1024 obj.Conntrack.Min = 128 * 1024
} }
} }
if obj.IPTablesMasqueradeBit == nil { if obj.IPTables.MasqueradeBit == nil {
temp := int32(14) temp := int32(14)
obj.IPTablesMasqueradeBit = &temp obj.IPTables.MasqueradeBit = &temp
} }
if obj.ConntrackTCPEstablishedTimeout == zero { if obj.Conntrack.TCPEstablishedTimeout == zero {
obj.ConntrackTCPEstablishedTimeout = metav1.Duration{Duration: 24 * time.Hour} // 1 day (1/5 default) obj.Conntrack.TCPEstablishedTimeout = metav1.Duration{Duration: 24 * time.Hour} // 1 day (1/5 default)
} }
if obj.ConntrackTCPCloseWaitTimeout == zero { if obj.Conntrack.TCPCloseWaitTimeout == zero {
// See https://github.com/kubernetes/kubernetes/issues/32551. // See https://github.com/kubernetes/kubernetes/issues/32551.
// //
// CLOSE_WAIT conntrack state occurs when the the Linux kernel // CLOSE_WAIT conntrack state occurs when the the Linux kernel
@ -120,7 +120,20 @@ func SetDefaults_KubeProxyConfiguration(obj *KubeProxyConfiguration) {
// //
// We set CLOSE_WAIT to one hour by default to better match // We set CLOSE_WAIT to one hour by default to better match
// typical server timeouts. // typical server timeouts.
obj.ConntrackTCPCloseWaitTimeout = metav1.Duration{Duration: 1 * time.Hour} obj.Conntrack.TCPCloseWaitTimeout = metav1.Duration{Duration: 1 * time.Hour}
}
if obj.ConfigSyncPeriod.Duration == 0 {
obj.ConfigSyncPeriod.Duration = 15 * time.Minute
}
if len(obj.ClientConnection.ContentType) == 0 {
obj.ClientConnection.ContentType = "application/vnd.kubernetes.protobuf"
}
if obj.ClientConnection.QPS == 0.0 {
obj.ClientConnection.QPS = 5.0
}
if obj.ClientConnection.Burst == 0 {
obj.ClientConnection.Burst = 10
} }
} }

View File

@ -21,39 +21,90 @@ import (
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
) )
// ClientConnectionConfiguration contains details for constructing a client.
type ClientConnectionConfiguration struct {
// kubeConfigFile is the path to a kubeconfig file.
KubeConfigFile string `json:"kubeconfig"`
// acceptContentTypes defines the Accept header sent by clients when connecting to a server, overriding the
// default value of 'application/json'. This field will control all connections to the server used by a particular
// client.
AcceptContentTypes string `json:"acceptContentTypes"`
// contentType is the content type used when sending data to the server from this client.
ContentType string `json:"contentType"`
// cps controls the number of queries per second allowed for this connection.
QPS float32 `json:"qps"`
// burst allows extra queries to accumulate when a client is exceeding its rate.
Burst int `json:"burst"`
}
// KubeProxyIPTablesConfiguration contains iptables-related configuration
// details for the Kubernetes proxy server.
type KubeProxyIPTablesConfiguration struct {
// masqueradeBit is the bit of the iptables fwmark space to use for SNAT if using
// the pure iptables proxy mode. Values must be within the range [0, 31].
MasqueradeBit *int32 `json:"masqueradeBit"`
// masqueradeAll tells kube-proxy to SNAT everything if using the pure iptables proxy mode.
MasqueradeAll bool `json:"masqueradeAll"`
// syncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m',
// '2h22m'). Must be greater than 0.
SyncPeriod metav1.Duration `json:"syncPeriod"`
// minSyncPeriod is the minimum period that iptables rules are refreshed (e.g. '5s', '1m',
// '2h22m').
MinSyncPeriod metav1.Duration `json:"minSyncPeriod"`
}
// KubeProxyConntrackConfiguration contains conntrack settings for
// the Kubernetes proxy server.
type KubeProxyConntrackConfiguration struct {
// max is the maximum number of NAT connections to track (0 to
// leave as-is). This takes precedence over conntrackMaxPerCore and conntrackMin.
Max int32 `json:"max"`
// maxPerCore is the maximum number of NAT connections to track
// per CPU core (0 to leave the limit as-is and ignore conntrackMin).
MaxPerCore int32 `json:"maxPerCore"`
// min is the minimum value of connect-tracking records to allocate,
// regardless of conntrackMaxPerCore (set conntrackMaxPerCore=0 to leave the limit as-is).
Min int32 `json:"min"`
// tcpEstablishedTimeout is how long an idle TCP connection will be kept open
// (e.g. '2s'). Must be greater than 0.
TCPEstablishedTimeout metav1.Duration `json:"tcpEstablishedTimeout"`
// tcpCloseWaitTimeout is how long an idle conntrack entry
// in CLOSE_WAIT state will remain in the conntrack
// table. (e.g. '60s'). Must be greater than 0 to set.
TCPCloseWaitTimeout metav1.Duration `json:"tcpCloseWaitTimeout"`
}
// KubeProxyConfiguration contains everything necessary to configure the
// Kubernetes proxy server.
type KubeProxyConfiguration struct { type KubeProxyConfiguration struct {
metav1.TypeMeta `json:",inline"` metav1.TypeMeta `json:",inline"`
// featureGates is a comma-separated list of key=value pairs that control
// which alpha/beta features are enabled.
//
// TODO this really should be a map but that requires refactoring all
// components to use config files because local-up-cluster.sh only supports
// the --feature-gates flag right now, which is comma-separated key=value
// pairs.
FeatureGates string `json:"featureGates"`
// bindAddress is the IP address for the proxy server to serve on (set to 0.0.0.0 // bindAddress is the IP address for the proxy server to serve on (set to 0.0.0.0
// for all interfaces) // for all interfaces)
BindAddress string `json:"bindAddress"` BindAddress string `json:"bindAddress"`
// healthzBindAddress is the IP address and port for the health check server to serve on,
// defaulting to 127.0.0.1:10249 (set to 0.0.0.0 for all interfaces)
HealthzBindAddress string `json:"healthzBindAddress"`
// clusterCIDR is the CIDR range of the pods in the cluster. It is used to // clusterCIDR is the CIDR range of the pods in the cluster. It is used to
// bridge traffic coming from outside of the cluster. If not provided, // bridge traffic coming from outside of the cluster. If not provided,
// no off-cluster bridging will be performed. // no off-cluster bridging will be performed.
ClusterCIDR string `json:"clusterCIDR"` ClusterCIDR string `json:"clusterCIDR"`
// healthzBindAddress is 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)
HealthzBindAddress string `json:"healthzBindAddress"`
// healthzPort is the port to bind the health check server. Use 0 to disable.
HealthzPort int32 `json:"healthzPort"`
// hostnameOverride, if non-empty, will be used as the identity instead of the actual hostname. // hostnameOverride, if non-empty, will be used as the identity instead of the actual hostname.
HostnameOverride string `json:"hostnameOverride"` HostnameOverride string `json:"hostnameOverride"`
// iptablesMasqueradeBit is the bit of the iptables fwmark space to use for SNAT if using // clientConnection specifies the kubeconfig file and client connection settings for the proxy
// the pure iptables proxy mode. Values must be within the range [0, 31]. // server to use when communicating with the apiserver.
IPTablesMasqueradeBit *int32 `json:"iptablesMasqueradeBit"` ClientConnection ClientConnectionConfiguration `json:"clientConnection"`
// iptablesSyncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m', // iptables contains iptables-related configuration options.
// '2h22m'). Must be greater than 0. IPTables KubeProxyIPTablesConfiguration `json:"iptables"`
IPTablesSyncPeriod metav1.Duration `json:"iptablesSyncPeriodSeconds"`
// iptablesMinSyncPeriod is the minimum period that iptables rules are refreshed (e.g. '5s', '1m',
// '2h22m').
IPTablesMinSyncPeriod metav1.Duration `json:"iptablesMinSyncPeriodSeconds"`
// kubeconfigPath is the path to the kubeconfig file with authorization information (the
// master location is set by the master flag).
KubeconfigPath string `json:"kubeconfigPath"`
// masqueradeAll tells kube-proxy to SNAT everything if using the pure iptables proxy mode.
MasqueradeAll bool `json:"masqueradeAll"`
// master is the address of the Kubernetes API server (overrides any value in kubeconfig)
Master string `json:"master"`
// oomScoreAdj is the oom-score-adj value for kube-proxy process. Values must be within // oomScoreAdj is the oom-score-adj value for kube-proxy process. Values must be within
// the range [-1000, 1000] // the range [-1000, 1000]
OOMScoreAdj *int32 `json:"oomScoreAdj"` OOMScoreAdj *int32 `json:"oomScoreAdj"`
@ -68,22 +119,11 @@ type KubeProxyConfiguration struct {
// udpIdleTimeout is how long an idle UDP connection will be kept open (e.g. '250ms', '2s'). // udpIdleTimeout is how long an idle UDP connection will be kept open (e.g. '250ms', '2s').
// Must be greater than 0. Only applicable for proxyMode=userspace. // Must be greater than 0. Only applicable for proxyMode=userspace.
UDPIdleTimeout metav1.Duration `json:"udpTimeoutMilliseconds"` UDPIdleTimeout metav1.Duration `json:"udpTimeoutMilliseconds"`
// conntrackMax is the maximum number of NAT connections to track (0 to // conntrack contains conntrack-related configuration options.
// leave as-is). This takes precedence over conntrackMaxPerCore and conntrackMin. Conntrack KubeProxyConntrackConfiguration `json:"conntrack"`
ConntrackMax int32 `json:"conntrackMax"` // configSyncPeriod is how often configuration from the apiserver is refreshed. Must be greater
// conntrackMaxPerCore is the maximum number of NAT connections to track // than 0.
// per CPU core (0 to leave the limit as-is and ignore conntrackMin). ConfigSyncPeriod metav1.Duration `json:"configSyncPeriod"`
ConntrackMaxPerCore int32 `json:"conntrackMaxPerCore"`
// conntrackMin is the minimum value of connect-tracking records to allocate,
// regardless of conntrackMaxPerCore (set conntrackMaxPerCore=0 to leave the limit as-is).
ConntrackMin int32 `json:"conntrackMin"`
// conntrackTCPEstablishedTimeout is how long an idle TCP connection
// will be kept open (e.g. '2s'). Must be greater than 0.
ConntrackTCPEstablishedTimeout metav1.Duration `json:"conntrackTCPEstablishedTimeout"`
// conntrackTCPCloseWaitTimeout is how long an idle conntrack entry
// in CLOSE_WAIT state will remain in the conntrack
// table. (e.g. '60s'). Must be greater than 0 to set.
ConntrackTCPCloseWaitTimeout metav1.Duration `json:"conntrackTCPCloseWaitTimeout"`
} }
// Currently two modes of proxying are available: 'userspace' (older, stable) or 'iptables' // Currently two modes of proxying are available: 'userspace' (older, stable) or 'iptables'

View File

@ -38,8 +38,14 @@ func init() {
// Public to allow building arbitrary schemes. // Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error { func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs( return scheme.AddGeneratedConversionFuncs(
Convert_v1alpha1_ClientConnectionConfiguration_To_componentconfig_ClientConnectionConfiguration,
Convert_componentconfig_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration,
Convert_v1alpha1_KubeProxyConfiguration_To_componentconfig_KubeProxyConfiguration, Convert_v1alpha1_KubeProxyConfiguration_To_componentconfig_KubeProxyConfiguration,
Convert_componentconfig_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfiguration, Convert_componentconfig_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfiguration,
Convert_v1alpha1_KubeProxyConntrackConfiguration_To_componentconfig_KubeProxyConntrackConfiguration,
Convert_componentconfig_KubeProxyConntrackConfiguration_To_v1alpha1_KubeProxyConntrackConfiguration,
Convert_v1alpha1_KubeProxyIPTablesConfiguration_To_componentconfig_KubeProxyIPTablesConfiguration,
Convert_componentconfig_KubeProxyIPTablesConfiguration_To_v1alpha1_KubeProxyIPTablesConfiguration,
Convert_v1alpha1_KubeSchedulerConfiguration_To_componentconfig_KubeSchedulerConfiguration, Convert_v1alpha1_KubeSchedulerConfiguration_To_componentconfig_KubeSchedulerConfiguration,
Convert_componentconfig_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration, Convert_componentconfig_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration,
Convert_v1alpha1_KubeletAnonymousAuthentication_To_componentconfig_KubeletAnonymousAuthentication, Convert_v1alpha1_KubeletAnonymousAuthentication_To_componentconfig_KubeletAnonymousAuthentication,
@ -61,28 +67,55 @@ func RegisterConversions(scheme *runtime.Scheme) error {
) )
} }
func autoConvert_v1alpha1_ClientConnectionConfiguration_To_componentconfig_ClientConnectionConfiguration(in *ClientConnectionConfiguration, out *componentconfig.ClientConnectionConfiguration, s conversion.Scope) error {
out.KubeConfigFile = in.KubeConfigFile
out.AcceptContentTypes = in.AcceptContentTypes
out.ContentType = in.ContentType
out.QPS = in.QPS
out.Burst = in.Burst
return nil
}
// Convert_v1alpha1_ClientConnectionConfiguration_To_componentconfig_ClientConnectionConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_ClientConnectionConfiguration_To_componentconfig_ClientConnectionConfiguration(in *ClientConnectionConfiguration, out *componentconfig.ClientConnectionConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_ClientConnectionConfiguration_To_componentconfig_ClientConnectionConfiguration(in, out, s)
}
func autoConvert_componentconfig_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(in *componentconfig.ClientConnectionConfiguration, out *ClientConnectionConfiguration, s conversion.Scope) error {
out.KubeConfigFile = in.KubeConfigFile
out.AcceptContentTypes = in.AcceptContentTypes
out.ContentType = in.ContentType
out.QPS = in.QPS
out.Burst = in.Burst
return nil
}
// Convert_componentconfig_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration is an autogenerated conversion function.
func Convert_componentconfig_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(in *componentconfig.ClientConnectionConfiguration, out *ClientConnectionConfiguration, s conversion.Scope) error {
return autoConvert_componentconfig_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(in, out, s)
}
func autoConvert_v1alpha1_KubeProxyConfiguration_To_componentconfig_KubeProxyConfiguration(in *KubeProxyConfiguration, out *componentconfig.KubeProxyConfiguration, s conversion.Scope) error { func autoConvert_v1alpha1_KubeProxyConfiguration_To_componentconfig_KubeProxyConfiguration(in *KubeProxyConfiguration, out *componentconfig.KubeProxyConfiguration, s conversion.Scope) error {
out.FeatureGates = in.FeatureGates
out.BindAddress = in.BindAddress out.BindAddress = in.BindAddress
out.ClusterCIDR = in.ClusterCIDR
out.HealthzBindAddress = in.HealthzBindAddress out.HealthzBindAddress = in.HealthzBindAddress
out.HealthzPort = in.HealthzPort out.ClusterCIDR = in.ClusterCIDR
out.HostnameOverride = in.HostnameOverride out.HostnameOverride = in.HostnameOverride
out.IPTablesMasqueradeBit = (*int32)(unsafe.Pointer(in.IPTablesMasqueradeBit)) if err := Convert_v1alpha1_ClientConnectionConfiguration_To_componentconfig_ClientConnectionConfiguration(&in.ClientConnection, &out.ClientConnection, s); err != nil {
out.IPTablesSyncPeriod = in.IPTablesSyncPeriod return err
out.IPTablesMinSyncPeriod = in.IPTablesMinSyncPeriod }
out.KubeconfigPath = in.KubeconfigPath if err := Convert_v1alpha1_KubeProxyIPTablesConfiguration_To_componentconfig_KubeProxyIPTablesConfiguration(&in.IPTables, &out.IPTables, s); err != nil {
out.MasqueradeAll = in.MasqueradeAll return err
out.Master = in.Master }
out.OOMScoreAdj = (*int32)(unsafe.Pointer(in.OOMScoreAdj)) out.OOMScoreAdj = (*int32)(unsafe.Pointer(in.OOMScoreAdj))
out.Mode = componentconfig.ProxyMode(in.Mode) out.Mode = componentconfig.ProxyMode(in.Mode)
out.PortRange = in.PortRange out.PortRange = in.PortRange
out.ResourceContainer = in.ResourceContainer out.ResourceContainer = in.ResourceContainer
out.UDPIdleTimeout = in.UDPIdleTimeout out.UDPIdleTimeout = in.UDPIdleTimeout
out.ConntrackMax = in.ConntrackMax if err := Convert_v1alpha1_KubeProxyConntrackConfiguration_To_componentconfig_KubeProxyConntrackConfiguration(&in.Conntrack, &out.Conntrack, s); err != nil {
out.ConntrackMaxPerCore = in.ConntrackMaxPerCore return err
out.ConntrackMin = in.ConntrackMin }
out.ConntrackTCPEstablishedTimeout = in.ConntrackTCPEstablishedTimeout out.ConfigSyncPeriod = in.ConfigSyncPeriod
out.ConntrackTCPCloseWaitTimeout = in.ConntrackTCPCloseWaitTimeout
return nil return nil
} }
@ -92,27 +125,26 @@ func Convert_v1alpha1_KubeProxyConfiguration_To_componentconfig_KubeProxyConfigu
} }
func autoConvert_componentconfig_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfiguration(in *componentconfig.KubeProxyConfiguration, out *KubeProxyConfiguration, s conversion.Scope) error { func autoConvert_componentconfig_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfiguration(in *componentconfig.KubeProxyConfiguration, out *KubeProxyConfiguration, s conversion.Scope) error {
out.FeatureGates = in.FeatureGates
out.BindAddress = in.BindAddress out.BindAddress = in.BindAddress
out.ClusterCIDR = in.ClusterCIDR
out.HealthzBindAddress = in.HealthzBindAddress out.HealthzBindAddress = in.HealthzBindAddress
out.HealthzPort = in.HealthzPort out.ClusterCIDR = in.ClusterCIDR
out.HostnameOverride = in.HostnameOverride out.HostnameOverride = in.HostnameOverride
out.IPTablesMasqueradeBit = (*int32)(unsafe.Pointer(in.IPTablesMasqueradeBit)) if err := Convert_componentconfig_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(&in.ClientConnection, &out.ClientConnection, s); err != nil {
out.IPTablesSyncPeriod = in.IPTablesSyncPeriod return err
out.IPTablesMinSyncPeriod = in.IPTablesMinSyncPeriod }
out.KubeconfigPath = in.KubeconfigPath if err := Convert_componentconfig_KubeProxyIPTablesConfiguration_To_v1alpha1_KubeProxyIPTablesConfiguration(&in.IPTables, &out.IPTables, s); err != nil {
out.MasqueradeAll = in.MasqueradeAll return err
out.Master = in.Master }
out.OOMScoreAdj = (*int32)(unsafe.Pointer(in.OOMScoreAdj)) out.OOMScoreAdj = (*int32)(unsafe.Pointer(in.OOMScoreAdj))
out.Mode = ProxyMode(in.Mode) out.Mode = ProxyMode(in.Mode)
out.PortRange = in.PortRange out.PortRange = in.PortRange
out.ResourceContainer = in.ResourceContainer out.ResourceContainer = in.ResourceContainer
out.UDPIdleTimeout = in.UDPIdleTimeout out.UDPIdleTimeout = in.UDPIdleTimeout
out.ConntrackMax = in.ConntrackMax if err := Convert_componentconfig_KubeProxyConntrackConfiguration_To_v1alpha1_KubeProxyConntrackConfiguration(&in.Conntrack, &out.Conntrack, s); err != nil {
out.ConntrackMaxPerCore = in.ConntrackMaxPerCore return err
out.ConntrackMin = in.ConntrackMin }
out.ConntrackTCPEstablishedTimeout = in.ConntrackTCPEstablishedTimeout out.ConfigSyncPeriod = in.ConfigSyncPeriod
out.ConntrackTCPCloseWaitTimeout = in.ConntrackTCPCloseWaitTimeout
return nil return nil
} }
@ -121,6 +153,60 @@ func Convert_componentconfig_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfigu
return autoConvert_componentconfig_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfiguration(in, out, s) return autoConvert_componentconfig_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfiguration(in, out, s)
} }
func autoConvert_v1alpha1_KubeProxyConntrackConfiguration_To_componentconfig_KubeProxyConntrackConfiguration(in *KubeProxyConntrackConfiguration, out *componentconfig.KubeProxyConntrackConfiguration, s conversion.Scope) error {
out.Max = in.Max
out.MaxPerCore = in.MaxPerCore
out.Min = in.Min
out.TCPEstablishedTimeout = in.TCPEstablishedTimeout
out.TCPCloseWaitTimeout = in.TCPCloseWaitTimeout
return nil
}
// Convert_v1alpha1_KubeProxyConntrackConfiguration_To_componentconfig_KubeProxyConntrackConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_KubeProxyConntrackConfiguration_To_componentconfig_KubeProxyConntrackConfiguration(in *KubeProxyConntrackConfiguration, out *componentconfig.KubeProxyConntrackConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeProxyConntrackConfiguration_To_componentconfig_KubeProxyConntrackConfiguration(in, out, s)
}
func autoConvert_componentconfig_KubeProxyConntrackConfiguration_To_v1alpha1_KubeProxyConntrackConfiguration(in *componentconfig.KubeProxyConntrackConfiguration, out *KubeProxyConntrackConfiguration, s conversion.Scope) error {
out.Max = in.Max
out.MaxPerCore = in.MaxPerCore
out.Min = in.Min
out.TCPEstablishedTimeout = in.TCPEstablishedTimeout
out.TCPCloseWaitTimeout = in.TCPCloseWaitTimeout
return nil
}
// Convert_componentconfig_KubeProxyConntrackConfiguration_To_v1alpha1_KubeProxyConntrackConfiguration is an autogenerated conversion function.
func Convert_componentconfig_KubeProxyConntrackConfiguration_To_v1alpha1_KubeProxyConntrackConfiguration(in *componentconfig.KubeProxyConntrackConfiguration, out *KubeProxyConntrackConfiguration, s conversion.Scope) error {
return autoConvert_componentconfig_KubeProxyConntrackConfiguration_To_v1alpha1_KubeProxyConntrackConfiguration(in, out, s)
}
func autoConvert_v1alpha1_KubeProxyIPTablesConfiguration_To_componentconfig_KubeProxyIPTablesConfiguration(in *KubeProxyIPTablesConfiguration, out *componentconfig.KubeProxyIPTablesConfiguration, s conversion.Scope) error {
out.MasqueradeBit = (*int32)(unsafe.Pointer(in.MasqueradeBit))
out.MasqueradeAll = in.MasqueradeAll
out.SyncPeriod = in.SyncPeriod
out.MinSyncPeriod = in.MinSyncPeriod
return nil
}
// Convert_v1alpha1_KubeProxyIPTablesConfiguration_To_componentconfig_KubeProxyIPTablesConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_KubeProxyIPTablesConfiguration_To_componentconfig_KubeProxyIPTablesConfiguration(in *KubeProxyIPTablesConfiguration, out *componentconfig.KubeProxyIPTablesConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeProxyIPTablesConfiguration_To_componentconfig_KubeProxyIPTablesConfiguration(in, out, s)
}
func autoConvert_componentconfig_KubeProxyIPTablesConfiguration_To_v1alpha1_KubeProxyIPTablesConfiguration(in *componentconfig.KubeProxyIPTablesConfiguration, out *KubeProxyIPTablesConfiguration, s conversion.Scope) error {
out.MasqueradeBit = (*int32)(unsafe.Pointer(in.MasqueradeBit))
out.MasqueradeAll = in.MasqueradeAll
out.SyncPeriod = in.SyncPeriod
out.MinSyncPeriod = in.MinSyncPeriod
return nil
}
// Convert_componentconfig_KubeProxyIPTablesConfiguration_To_v1alpha1_KubeProxyIPTablesConfiguration is an autogenerated conversion function.
func Convert_componentconfig_KubeProxyIPTablesConfiguration_To_v1alpha1_KubeProxyIPTablesConfiguration(in *componentconfig.KubeProxyIPTablesConfiguration, out *KubeProxyIPTablesConfiguration, s conversion.Scope) error {
return autoConvert_componentconfig_KubeProxyIPTablesConfiguration_To_v1alpha1_KubeProxyIPTablesConfiguration(in, out, s)
}
func autoConvert_v1alpha1_KubeSchedulerConfiguration_To_componentconfig_KubeSchedulerConfiguration(in *KubeSchedulerConfiguration, out *componentconfig.KubeSchedulerConfiguration, s conversion.Scope) error { func autoConvert_v1alpha1_KubeSchedulerConfiguration_To_componentconfig_KubeSchedulerConfiguration(in *KubeSchedulerConfiguration, out *componentconfig.KubeSchedulerConfiguration, s conversion.Scope) error {
out.Port = int32(in.Port) out.Port = int32(in.Port)
out.Address = in.Address out.Address = in.Address

View File

@ -35,7 +35,10 @@ func init() {
// to allow building arbitrary schemes. // to allow building arbitrary schemes.
func RegisterDeepCopies(scheme *runtime.Scheme) error { func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs( return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ClientConnectionConfiguration, InType: reflect.TypeOf(&ClientConnectionConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeProxyConfiguration, InType: reflect.TypeOf(&KubeProxyConfiguration{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeProxyConfiguration, InType: reflect.TypeOf(&KubeProxyConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeProxyConntrackConfiguration, InType: reflect.TypeOf(&KubeProxyConntrackConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeProxyIPTablesConfiguration, InType: reflect.TypeOf(&KubeProxyIPTablesConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeSchedulerConfiguration, InType: reflect.TypeOf(&KubeSchedulerConfiguration{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeSchedulerConfiguration, InType: reflect.TypeOf(&KubeSchedulerConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletAnonymousAuthentication, InType: reflect.TypeOf(&KubeletAnonymousAuthentication{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletAnonymousAuthentication, InType: reflect.TypeOf(&KubeletAnonymousAuthentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletAuthentication, InType: reflect.TypeOf(&KubeletAuthentication{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletAuthentication, InType: reflect.TypeOf(&KubeletAuthentication{})},
@ -48,15 +51,22 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
) )
} }
func DeepCopy_v1alpha1_ClientConnectionConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ClientConnectionConfiguration)
out := out.(*ClientConnectionConfiguration)
*out = *in
return nil
}
}
func DeepCopy_v1alpha1_KubeProxyConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error { func DeepCopy_v1alpha1_KubeProxyConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{ {
in := in.(*KubeProxyConfiguration) in := in.(*KubeProxyConfiguration)
out := out.(*KubeProxyConfiguration) out := out.(*KubeProxyConfiguration)
*out = *in *out = *in
if in.IPTablesMasqueradeBit != nil { if err := DeepCopy_v1alpha1_KubeProxyIPTablesConfiguration(&in.IPTables, &out.IPTables, c); err != nil {
in, out := &in.IPTablesMasqueradeBit, &out.IPTablesMasqueradeBit return err
*out = new(int32)
**out = **in
} }
if in.OOMScoreAdj != nil { if in.OOMScoreAdj != nil {
in, out := &in.OOMScoreAdj, &out.OOMScoreAdj in, out := &in.OOMScoreAdj, &out.OOMScoreAdj
@ -67,6 +77,29 @@ func DeepCopy_v1alpha1_KubeProxyConfiguration(in interface{}, out interface{}, c
} }
} }
func DeepCopy_v1alpha1_KubeProxyConntrackConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeProxyConntrackConfiguration)
out := out.(*KubeProxyConntrackConfiguration)
*out = *in
return nil
}
}
func DeepCopy_v1alpha1_KubeProxyIPTablesConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeProxyIPTablesConfiguration)
out := out.(*KubeProxyIPTablesConfiguration)
*out = *in
if in.MasqueradeBit != nil {
in, out := &in.MasqueradeBit, &out.MasqueradeBit
*out = new(int32)
**out = **in
}
return nil
}
}
func DeepCopy_v1alpha1_KubeSchedulerConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error { func DeepCopy_v1alpha1_KubeSchedulerConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{ {
in := in.(*KubeSchedulerConfiguration) in := in.(*KubeSchedulerConfiguration)

View File

@ -35,9 +35,12 @@ func init() {
// to allow building arbitrary schemes. // to allow building arbitrary schemes.
func RegisterDeepCopies(scheme *runtime.Scheme) error { func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs( return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_ClientConnectionConfiguration, InType: reflect.TypeOf(&ClientConnectionConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_IPVar, InType: reflect.TypeOf(&IPVar{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_IPVar, InType: reflect.TypeOf(&IPVar{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeControllerManagerConfiguration, InType: reflect.TypeOf(&KubeControllerManagerConfiguration{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeControllerManagerConfiguration, InType: reflect.TypeOf(&KubeControllerManagerConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeProxyConfiguration, InType: reflect.TypeOf(&KubeProxyConfiguration{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeProxyConfiguration, InType: reflect.TypeOf(&KubeProxyConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeProxyConntrackConfiguration, InType: reflect.TypeOf(&KubeProxyConntrackConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeProxyIPTablesConfiguration, InType: reflect.TypeOf(&KubeProxyIPTablesConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeSchedulerConfiguration, InType: reflect.TypeOf(&KubeSchedulerConfiguration{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeSchedulerConfiguration, InType: reflect.TypeOf(&KubeSchedulerConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletAnonymousAuthentication, InType: reflect.TypeOf(&KubeletAnonymousAuthentication{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletAnonymousAuthentication, InType: reflect.TypeOf(&KubeletAnonymousAuthentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletAuthentication, InType: reflect.TypeOf(&KubeletAuthentication{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletAuthentication, InType: reflect.TypeOf(&KubeletAuthentication{})},
@ -53,6 +56,15 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
) )
} }
func DeepCopy_componentconfig_ClientConnectionConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ClientConnectionConfiguration)
out := out.(*ClientConnectionConfiguration)
*out = *in
return nil
}
}
func DeepCopy_componentconfig_IPVar(in interface{}, out interface{}, c *conversion.Cloner) error { func DeepCopy_componentconfig_IPVar(in interface{}, out interface{}, c *conversion.Cloner) error {
{ {
in := in.(*IPVar) in := in.(*IPVar)
@ -86,10 +98,8 @@ func DeepCopy_componentconfig_KubeProxyConfiguration(in interface{}, out interfa
in := in.(*KubeProxyConfiguration) in := in.(*KubeProxyConfiguration)
out := out.(*KubeProxyConfiguration) out := out.(*KubeProxyConfiguration)
*out = *in *out = *in
if in.IPTablesMasqueradeBit != nil { if err := DeepCopy_componentconfig_KubeProxyIPTablesConfiguration(&in.IPTables, &out.IPTables, c); err != nil {
in, out := &in.IPTablesMasqueradeBit, &out.IPTablesMasqueradeBit return err
*out = new(int32)
**out = **in
} }
if in.OOMScoreAdj != nil { if in.OOMScoreAdj != nil {
in, out := &in.OOMScoreAdj, &out.OOMScoreAdj in, out := &in.OOMScoreAdj, &out.OOMScoreAdj
@ -100,6 +110,29 @@ func DeepCopy_componentconfig_KubeProxyConfiguration(in interface{}, out interfa
} }
} }
func DeepCopy_componentconfig_KubeProxyConntrackConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeProxyConntrackConfiguration)
out := out.(*KubeProxyConntrackConfiguration)
*out = *in
return nil
}
}
func DeepCopy_componentconfig_KubeProxyIPTablesConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeProxyIPTablesConfiguration)
out := out.(*KubeProxyIPTablesConfiguration)
*out = *in
if in.MasqueradeBit != nil {
in, out := &in.MasqueradeBit, &out.MasqueradeBit
*out = new(int32)
**out = **in
}
return nil
}
}
func DeepCopy_componentconfig_KubeSchedulerConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error { func DeepCopy_componentconfig_KubeSchedulerConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{ {
in := in.(*KubeSchedulerConfiguration) in := in.(*KubeSchedulerConfiguration)

View File

@ -16,7 +16,6 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//cmd/kube-proxy/app:go_default_library", "//cmd/kube-proxy/app:go_default_library",
"//cmd/kube-proxy/app/options:go_default_library",
"//cmd/kubelet/app:go_default_library", "//cmd/kubelet/app:go_default_library",
"//cmd/kubelet/app/options:go_default_library", "//cmd/kubelet/app/options:go_default_library",
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
@ -24,14 +23,12 @@ go_library(
"//pkg/apis/componentconfig/v1alpha1:go_default_library", "//pkg/apis/componentconfig/v1alpha1:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library", "//pkg/client/clientset_generated/clientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/kubelet:go_default_library", "//pkg/kubelet:go_default_library",
"//pkg/kubelet/cadvisor:go_default_library", "//pkg/kubelet/cadvisor:go_default_library",
"//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/cm:go_default_library",
"//pkg/kubelet/container/testing:go_default_library", "//pkg/kubelet/container/testing:go_default_library",
"//pkg/kubelet/dockertools:go_default_library", "//pkg/kubelet/dockertools:go_default_library",
"//pkg/kubelet/types:go_default_library", "//pkg/kubelet/types:go_default_library",
"//pkg/proxy/config:go_default_library",
"//pkg/util:go_default_library", "//pkg/util:go_default_library",
"//pkg/util/io:go_default_library", "//pkg/util/io:go_default_library",
"//pkg/util/iptables:go_default_library", "//pkg/util/iptables:go_default_library",
@ -43,7 +40,6 @@ go_library(
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//vendor/k8s.io/client-go/pkg/api/v1:go_default_library", "//vendor/k8s.io/client-go/pkg/api/v1:go_default_library",
"//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/client-go/tools/record:go_default_library",

View File

@ -17,17 +17,15 @@ limitations under the License.
package kubemark package kubemark
import ( import (
"time"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
v1core "k8s.io/client-go/kubernetes/typed/core/v1" v1core "k8s.io/client-go/kubernetes/typed/core/v1"
clientv1 "k8s.io/client-go/pkg/api/v1" clientv1 "k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
proxyapp "k8s.io/kubernetes/cmd/kube-proxy/app" proxyapp "k8s.io/kubernetes/cmd/kube-proxy/app"
"k8s.io/kubernetes/cmd/kube-proxy/app/options"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
proxyconfig "k8s.io/kubernetes/pkg/proxy/config"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
utiliptables "k8s.io/kubernetes/pkg/util/iptables" utiliptables "k8s.io/kubernetes/pkg/util/iptables"
@ -58,34 +56,32 @@ func NewHollowProxyOrDie(
nodeName string, nodeName string,
client clientset.Interface, client clientset.Interface,
eventClient v1core.EventsGetter, eventClient v1core.EventsGetter,
endpointsConfig *proxyconfig.EndpointsConfig,
serviceConfig *proxyconfig.ServiceConfig,
informerFactory informers.SharedInformerFactory,
iptInterface utiliptables.Interface, iptInterface utiliptables.Interface,
broadcaster record.EventBroadcaster, broadcaster record.EventBroadcaster,
recorder record.EventRecorder, recorder record.EventRecorder,
) *HollowProxy { ) *HollowProxy {
// Create and start Hollow Proxy // Create and start Hollow Proxy
config := options.NewProxyConfig() nodeRef := &clientv1.ObjectReference{
config.OOMScoreAdj = util.Int32Ptr(0)
config.ResourceContainer = ""
config.NodeRef = &clientv1.ObjectReference{
Kind: "Node", Kind: "Node",
Name: nodeName, Name: nodeName,
UID: types.UID(nodeName), UID: types.UID(nodeName),
Namespace: "", Namespace: "",
} }
go endpointsConfig.Run(wait.NeverStop)
go serviceConfig.Run(wait.NeverStop)
go informerFactory.Start(wait.NeverStop)
hollowProxy, err := proxyapp.NewProxyServer(client, eventClient, config, iptInterface, &FakeProxier{}, broadcaster, recorder, nil, "fake")
if err != nil {
glog.Fatalf("Error while creating ProxyServer: %v\n", err)
}
return &HollowProxy{ return &HollowProxy{
ProxyServer: hollowProxy, ProxyServer: &proxyapp.ProxyServer{
Client: client,
EventClient: eventClient,
IptInterface: iptInterface,
Proxier: &FakeProxier{},
Broadcaster: broadcaster,
Recorder: recorder,
ProxyMode: "fake",
NodeRef: nodeRef,
OOMScoreAdj: util.Int32Ptr(0),
ResourceContainer: "",
ConfigSyncPeriod: 30 * time.Second,
},
} }
} }

View File

@ -152,6 +152,8 @@ func New(exec utilexec.Interface, dbus utildbus.Interface, protocol Protocol) In
waitFlag: getIPTablesWaitFlag(vstring), waitFlag: getIPTablesWaitFlag(vstring),
restoreWaitFlag: getIPTablesRestoreWaitFlag(exec), restoreWaitFlag: getIPTablesRestoreWaitFlag(exec),
} }
// TODO this needs to be moved to a separate Start() or Run() function so that New() has zero side
// effects.
runner.connectToFirewallD() runner.connectToFirewallD()
return runner return runner
} }