mirror of
https://github.com/optim-enterprises-bv/kubernetes.git
synced 2025-11-02 03:08:15 +00:00
kube-proxy: internal config: refactor Healthz and Metrics Address
Refactor Healthz with Metrics Address for internal configuration of kube-proxy adhering to the v1alpha2 version specifications as detailed in https://kep.k8s.io/784. Signed-off-by: Daman Arora <aroradaman@gmail.com>
This commit is contained in:
@@ -19,7 +19,9 @@ package app
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -33,15 +35,14 @@ import (
|
||||
logsapi "k8s.io/component-base/logs/api/v1"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kube-proxy/config/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/cluster/ports"
|
||||
"k8s.io/kubernetes/pkg/kubelet/qos"
|
||||
kubeproxyconfig "k8s.io/kubernetes/pkg/proxy/apis/config"
|
||||
proxyconfigscheme "k8s.io/kubernetes/pkg/proxy/apis/config/scheme"
|
||||
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/config/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/proxy/apis/config/validation"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
"k8s.io/kubernetes/pkg/util/filesystem"
|
||||
utilflag "k8s.io/kubernetes/pkg/util/flag"
|
||||
netutils "k8s.io/utils/net"
|
||||
"k8s.io/utils/ptr"
|
||||
)
|
||||
|
||||
@@ -71,10 +72,6 @@ type Options struct {
|
||||
|
||||
// master is used to override the kubeconfig's URL to the apiserver.
|
||||
master string
|
||||
// healthzPort is the port to be used by the healthz server.
|
||||
healthzPort int32
|
||||
// metricsPort is the port to be used by the metrics server.
|
||||
metricsPort int32
|
||||
|
||||
// hostnameOverride, if set from the command line flag, takes precedence over the `HostnameOverride` value from the config file
|
||||
hostnameOverride string
|
||||
@@ -88,6 +85,8 @@ type Options struct {
|
||||
ipvsSyncPeriod time.Duration
|
||||
ipvsMinSyncPeriod time.Duration
|
||||
clusterCIDRs string
|
||||
healthzBindAddress string
|
||||
metricsBindAddress string
|
||||
}
|
||||
|
||||
// AddFlags adds flags to fs and binds them to options.
|
||||
@@ -111,8 +110,8 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
|
||||
|
||||
fs.StringVar(&o.hostnameOverride, "hostname-override", o.hostnameOverride, "If non-empty, will be used as the name of the Node that kube-proxy is running on. If unset, the node name is assumed to be the same as the node's hostname.")
|
||||
fs.Var(&utilflag.IPVar{Val: &o.config.BindAddress}, "bind-address", "Overrides kube-proxy's idea of what its node's primary IP is. Note that the name is a historical artifact, and kube-proxy does not actually bind any sockets to this IP. This parameter is ignored if a config file is specified by --config.")
|
||||
fs.Var(&utilflag.IPPortVar{Val: &o.config.HealthzBindAddress}, "healthz-bind-address", "The IP address and port for the health check server to serve on, defaulting to \"0.0.0.0:10256\". This parameter is ignored if a config file is specified by --config.")
|
||||
fs.Var(&utilflag.IPPortVar{Val: &o.config.MetricsBindAddress}, "metrics-bind-address", "The IP address and port for the metrics server to serve on, defaulting to \"127.0.0.1:10249\". (Set to \"0.0.0.0:10249\" / \"[::]:10249\" to bind on all interfaces.) Set empty to disable. This parameter is ignored if a config file is specified by --config.")
|
||||
fs.Var(&utilflag.IPPortVar{Val: &o.healthzBindAddress}, "healthz-bind-address", "The IP address and port for the health check server to serve on, defaulting to \"0.0.0.0:10256\". This parameter is ignored if a config file is specified by --config.")
|
||||
fs.Var(&utilflag.IPPortVar{Val: &o.metricsBindAddress}, "metrics-bind-address", "The IP address and port for the metrics server to serve on, defaulting to \"127.0.0.1:10249\". (Set to \"0.0.0.0:10249\" / \"[::]:10249\" to bind on all interfaces.) Set empty to disable. This parameter is ignored if a config file is specified by --config.")
|
||||
fs.BoolVar(&o.config.BindAddressHardFail, "bind-address-hard-fail", o.config.BindAddressHardFail, "If true kube-proxy will treat failure to bind to a port as fatal and exit")
|
||||
fs.BoolVar(&o.config.EnableProfiling, "profiling", o.config.EnableProfiling, "If true enables profiling via web interface on /debug/pprof handler. This parameter is ignored if a config file is specified by --config.")
|
||||
fs.StringVar(&o.config.ShowHiddenMetricsForVersion, "show-hidden-metrics-for-version", o.config.ShowHiddenMetricsForVersion,
|
||||
@@ -166,11 +165,6 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.DurationVar(&o.config.Linux.Conntrack.UDPStreamTimeout.Duration, "conntrack-udp-timeout-stream", o.config.Linux.Conntrack.UDPStreamTimeout.Duration, "Idle timeout for ASSURED UDP connections (0 to leave as-is)")
|
||||
fs.DurationVar(&o.config.ConfigSyncPeriod.Duration, "config-sync-period", o.config.ConfigSyncPeriod.Duration, "How often configuration from the apiserver is refreshed. Must be greater than 0.")
|
||||
|
||||
fs.Int32Var(&o.healthzPort, "healthz-port", o.healthzPort, "The port to bind the health check server. Use 0 to disable.")
|
||||
_ = fs.MarkDeprecated("healthz-port", "This flag is deprecated and will be removed in a future release. Please use --healthz-bind-address instead.")
|
||||
fs.Int32Var(&o.metricsPort, "metrics-port", o.metricsPort, "The port to bind the metrics server. Use 0 to disable.")
|
||||
_ = fs.MarkDeprecated("metrics-port", "This flag is deprecated and will be removed in a future release. Please use --metrics-bind-address instead.")
|
||||
|
||||
logsapi.AddFlags(&o.config.Logging, fs)
|
||||
}
|
||||
|
||||
@@ -189,21 +183,14 @@ func newKubeProxyConfiguration() *kubeproxyconfig.KubeProxyConfiguration {
|
||||
// NewOptions returns initialized Options
|
||||
func NewOptions() *Options {
|
||||
return &Options{
|
||||
config: newKubeProxyConfiguration(),
|
||||
healthzPort: ports.ProxyHealthzPort,
|
||||
metricsPort: ports.ProxyStatusPort,
|
||||
errCh: make(chan error),
|
||||
logger: klog.FromContext(context.Background()),
|
||||
config: newKubeProxyConfiguration(),
|
||||
errCh: make(chan error),
|
||||
logger: klog.FromContext(context.Background()),
|
||||
}
|
||||
}
|
||||
|
||||
// Complete completes all the required options.
|
||||
func (o *Options) Complete(fs *pflag.FlagSet) error {
|
||||
if len(o.ConfigFile) == 0 && len(o.WriteConfigTo) == 0 {
|
||||
o.config.HealthzBindAddress = addressFromDeprecatedFlags(o.config.HealthzBindAddress, o.healthzPort)
|
||||
o.config.MetricsBindAddress = addressFromDeprecatedFlags(o.config.MetricsBindAddress, o.metricsPort)
|
||||
}
|
||||
|
||||
// Load the config file here in Complete, so that Validate validates the fully-resolved config.
|
||||
if len(o.ConfigFile) > 0 {
|
||||
c, err := o.loadConfigFromFile(o.ConfigFile)
|
||||
@@ -328,6 +315,32 @@ func (o *Options) processV1Alpha1Flags(fs *pflag.FlagSet) {
|
||||
if fs.Changed("cluster-cidr") {
|
||||
o.config.DetectLocal.ClusterCIDRs = strings.Split(o.clusterCIDRs, ",")
|
||||
}
|
||||
if fs.Changed("healthz-bind-address") {
|
||||
host, port, _ := net.SplitHostPort(o.healthzBindAddress)
|
||||
ip := netutils.ParseIPSloppy(host)
|
||||
if ip.IsUnspecified() {
|
||||
o.config.HealthzBindAddresses = []string{fmt.Sprintf("%s/0", host)}
|
||||
} else if netutils.IsIPv4(ip) {
|
||||
o.config.HealthzBindAddresses = []string{fmt.Sprintf("%s/32", host)}
|
||||
} else {
|
||||
o.config.HealthzBindAddresses = []string{fmt.Sprintf("%s/128", host)}
|
||||
}
|
||||
intPort, _ := strconv.Atoi(port)
|
||||
o.config.HealthzBindPort = int32(intPort)
|
||||
}
|
||||
if fs.Changed("metrics-bind-address") {
|
||||
host, port, _ := net.SplitHostPort(o.metricsBindAddress)
|
||||
ip := netutils.ParseIPSloppy(host)
|
||||
if ip.IsUnspecified() {
|
||||
o.config.MetricsBindAddresses = []string{fmt.Sprintf("%s/0", host)}
|
||||
} else if netutils.IsIPv4(ip) {
|
||||
o.config.MetricsBindAddresses = []string{fmt.Sprintf("%s/32", host)}
|
||||
} else {
|
||||
o.config.MetricsBindAddresses = []string{fmt.Sprintf("%s/128", host)}
|
||||
}
|
||||
intPort, _ := strconv.Atoi(port)
|
||||
o.config.MetricsBindPort = int32(intPort)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate validates all the required options.
|
||||
@@ -416,17 +429,6 @@ func (o *Options) writeConfigFile() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// addressFromDeprecatedFlags returns server address from flags
|
||||
// passed on the command line based on the following rules:
|
||||
// 1. If port is 0, disable the server (e.g. set address to empty).
|
||||
// 2. Otherwise, set the port portion of the config accordingly.
|
||||
func addressFromDeprecatedFlags(addr string, port int32) string {
|
||||
if port == 0 {
|
||||
return ""
|
||||
}
|
||||
return proxyutil.AppendPortIfNeeded(addr, port)
|
||||
}
|
||||
|
||||
// newLenientSchemeAndCodecs returns a scheme that has only v1alpha1 registered into
|
||||
// it and a CodecFactory with strict decoding disabled.
|
||||
func newLenientSchemeAndCodecs() (*runtime.Scheme, *serializer.CodecFactory, error) {
|
||||
|
||||
@@ -89,94 +89,130 @@ nodePortAddresses:
|
||||
`
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
mode string
|
||||
bindAddress string
|
||||
clusterCIDR string
|
||||
healthzBindAddress string
|
||||
metricsBindAddress string
|
||||
extraConfig string
|
||||
name string
|
||||
mode string
|
||||
bindAddress string
|
||||
clusterCIDR string
|
||||
healthzBindAddress string
|
||||
metricsBindAddress string
|
||||
extraConfig string
|
||||
expectedHealthzBindAddresses []string
|
||||
expectedHealthzBindPort int32
|
||||
expectedMetricsBindAddresses []string
|
||||
expectedMetricsBindPort int32
|
||||
}{
|
||||
{
|
||||
name: "iptables mode, IPv4 all-zeros bind address",
|
||||
mode: "iptables",
|
||||
bindAddress: "0.0.0.0",
|
||||
clusterCIDR: "1.2.3.0/24",
|
||||
healthzBindAddress: "1.2.3.4:12345",
|
||||
metricsBindAddress: "2.3.4.5:23456",
|
||||
name: "iptables mode, IPv4 all-zeros bind address",
|
||||
mode: "iptables",
|
||||
bindAddress: "0.0.0.0",
|
||||
clusterCIDR: "1.2.3.0/24",
|
||||
healthzBindAddress: "1.2.3.4:12345",
|
||||
metricsBindAddress: "2.3.4.5:23456",
|
||||
expectedHealthzBindAddresses: []string{"1.2.3.4/32"},
|
||||
expectedHealthzBindPort: int32(12345),
|
||||
expectedMetricsBindAddresses: []string{"2.3.4.5/32"},
|
||||
expectedMetricsBindPort: int32(23456),
|
||||
},
|
||||
{
|
||||
name: "iptables mode, non-zeros IPv4 config",
|
||||
mode: "iptables",
|
||||
bindAddress: "9.8.7.6",
|
||||
clusterCIDR: "1.2.3.0/24",
|
||||
healthzBindAddress: "1.2.3.4:12345",
|
||||
metricsBindAddress: "2.3.4.5:23456",
|
||||
name: "iptables mode, non-zeros IPv4 config",
|
||||
mode: "iptables",
|
||||
bindAddress: "9.8.7.6",
|
||||
clusterCIDR: "1.2.3.0/24",
|
||||
healthzBindAddress: "1.2.3.4:12345",
|
||||
metricsBindAddress: "2.3.4.5:23456",
|
||||
expectedHealthzBindAddresses: []string{"1.2.3.4/32"},
|
||||
expectedHealthzBindPort: int32(12345),
|
||||
expectedMetricsBindAddresses: []string{"2.3.4.5/32"},
|
||||
expectedMetricsBindPort: int32(23456),
|
||||
},
|
||||
{
|
||||
// Test for 'bindAddress: "::"' (IPv6 all-zeros) in kube-proxy
|
||||
// config file. The user will need to put quotes around '::' since
|
||||
// 'bindAddress: ::' is invalid yaml syntax.
|
||||
name: "iptables mode, IPv6 \"::\" bind address",
|
||||
mode: "iptables",
|
||||
bindAddress: "\"::\"",
|
||||
clusterCIDR: "fd00:1::0/64",
|
||||
healthzBindAddress: "[fd00:1::5]:12345",
|
||||
metricsBindAddress: "[fd00:2::5]:23456",
|
||||
name: "iptables mode, IPv6 \"::\" bind address",
|
||||
mode: "iptables",
|
||||
bindAddress: "\"::\"",
|
||||
clusterCIDR: "fd00:1::0/64",
|
||||
healthzBindAddress: "[fd00:1::5]:12345",
|
||||
metricsBindAddress: "[fd00:2::5]:23456",
|
||||
expectedHealthzBindAddresses: []string{"fd00:1::5/128"},
|
||||
expectedHealthzBindPort: int32(12345),
|
||||
expectedMetricsBindAddresses: []string{"fd00:2::5/128"},
|
||||
expectedMetricsBindPort: int32(23456),
|
||||
},
|
||||
{
|
||||
// Test for 'bindAddress: "[::]"' (IPv6 all-zeros in brackets)
|
||||
// in kube-proxy config file. The user will need to use
|
||||
// surrounding quotes here since 'bindAddress: [::]' is invalid
|
||||
// yaml syntax.
|
||||
name: "iptables mode, IPv6 \"[::]\" bind address",
|
||||
mode: "iptables",
|
||||
bindAddress: "\"[::]\"",
|
||||
clusterCIDR: "fd00:1::0/64",
|
||||
healthzBindAddress: "[fd00:1::5]:12345",
|
||||
metricsBindAddress: "[fd00:2::5]:23456",
|
||||
name: "iptables mode, IPv6 \"[::]\" bind address",
|
||||
mode: "iptables",
|
||||
bindAddress: "\"[::]\"",
|
||||
clusterCIDR: "fd00:1::0/64",
|
||||
healthzBindAddress: "[fd00:1::5]:12345",
|
||||
metricsBindAddress: "[fd00:2::5]:23456",
|
||||
expectedHealthzBindAddresses: []string{"fd00:1::5/128"},
|
||||
expectedHealthzBindPort: int32(12345),
|
||||
expectedMetricsBindAddresses: []string{"fd00:2::5/128"},
|
||||
expectedMetricsBindPort: int32(23456),
|
||||
},
|
||||
{
|
||||
// Test for 'bindAddress: ::0' (another form of IPv6 all-zeros).
|
||||
// No surrounding quotes are required around '::0'.
|
||||
name: "iptables mode, IPv6 ::0 bind address",
|
||||
mode: "iptables",
|
||||
bindAddress: "::0",
|
||||
clusterCIDR: "fd00:1::0/64",
|
||||
healthzBindAddress: "[fd00:1::5]:12345",
|
||||
metricsBindAddress: "[fd00:2::5]:23456",
|
||||
name: "iptables mode, IPv6 ::0 bind address",
|
||||
mode: "iptables",
|
||||
bindAddress: "::0",
|
||||
clusterCIDR: "fd00:1::0/64",
|
||||
healthzBindAddress: "[fd00:1::5]:12345",
|
||||
metricsBindAddress: "[fd00:2::5]:23456",
|
||||
expectedHealthzBindAddresses: []string{"fd00:1::5/128"},
|
||||
expectedHealthzBindPort: int32(12345),
|
||||
expectedMetricsBindAddresses: []string{"fd00:2::5/128"},
|
||||
expectedMetricsBindPort: int32(23456),
|
||||
},
|
||||
{
|
||||
name: "ipvs mode, IPv6 config",
|
||||
mode: "ipvs",
|
||||
bindAddress: "2001:db8::1",
|
||||
clusterCIDR: "fd00:1::0/64",
|
||||
healthzBindAddress: "[fd00:1::5]:12345",
|
||||
metricsBindAddress: "[fd00:2::5]:23456",
|
||||
name: "ipvs mode, IPv6 config",
|
||||
mode: "ipvs",
|
||||
bindAddress: "2001:db8::1",
|
||||
clusterCIDR: "fd00:1::0/64",
|
||||
healthzBindAddress: "[fd00:1::5]:12345",
|
||||
metricsBindAddress: "[fd00:2::5]:23456",
|
||||
expectedHealthzBindAddresses: []string{"fd00:1::5/128"},
|
||||
expectedHealthzBindPort: int32(12345),
|
||||
expectedMetricsBindAddresses: []string{"fd00:2::5/128"},
|
||||
expectedMetricsBindPort: int32(23456),
|
||||
},
|
||||
{
|
||||
// Test for unknown field within config.
|
||||
// For v1alpha1 a lenient path is implemented and will throw a
|
||||
// strict decoding warning instead of failing to load
|
||||
name: "unknown field",
|
||||
mode: "iptables",
|
||||
bindAddress: "9.8.7.6",
|
||||
clusterCIDR: "1.2.3.0/24",
|
||||
healthzBindAddress: "1.2.3.4:12345",
|
||||
metricsBindAddress: "2.3.4.5:23456",
|
||||
extraConfig: "foo: bar",
|
||||
name: "unknown field",
|
||||
mode: "iptables",
|
||||
bindAddress: "9.8.7.6",
|
||||
clusterCIDR: "1.2.3.0/24",
|
||||
healthzBindAddress: "1.2.3.4:12345",
|
||||
metricsBindAddress: "2.3.4.5:23456",
|
||||
extraConfig: "foo: bar",
|
||||
expectedHealthzBindAddresses: []string{"1.2.3.4/32"},
|
||||
expectedHealthzBindPort: int32(12345),
|
||||
expectedMetricsBindAddresses: []string{"2.3.4.5/32"},
|
||||
expectedMetricsBindPort: int32(23456),
|
||||
},
|
||||
{
|
||||
// Test for duplicate field within config.
|
||||
// For v1alpha1 a lenient path is implemented and will throw a
|
||||
// strict decoding warning instead of failing to load
|
||||
name: "duplicate field",
|
||||
mode: "iptables",
|
||||
bindAddress: "9.8.7.6",
|
||||
clusterCIDR: "1.2.3.0/24",
|
||||
healthzBindAddress: "1.2.3.4:12345",
|
||||
metricsBindAddress: "2.3.4.5:23456",
|
||||
extraConfig: "bindAddress: 9.8.7.6",
|
||||
name: "duplicate field",
|
||||
mode: "iptables",
|
||||
bindAddress: "9.8.7.6",
|
||||
clusterCIDR: "1.2.3.0/24",
|
||||
healthzBindAddress: "1.2.3.4:12345",
|
||||
metricsBindAddress: "2.3.4.5:23456",
|
||||
extraConfig: "bindAddress: 9.8.7.6",
|
||||
expectedHealthzBindAddresses: []string{"1.2.3.4/32"},
|
||||
expectedHealthzBindPort: int32(12345),
|
||||
expectedMetricsBindAddresses: []string{"2.3.4.5/32"},
|
||||
expectedMetricsBindPort: int32(23456),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -209,9 +245,10 @@ nodePortAddresses:
|
||||
MasqueradeAll: true,
|
||||
OOMScoreAdj: ptr.To[int32](17),
|
||||
},
|
||||
FeatureGates: map[string]bool{},
|
||||
HealthzBindAddress: tc.healthzBindAddress,
|
||||
HostnameOverride: "foo",
|
||||
FeatureGates: map[string]bool{},
|
||||
HealthzBindAddresses: tc.expectedHealthzBindAddresses,
|
||||
HealthzBindPort: tc.expectedHealthzBindPort,
|
||||
HostnameOverride: "foo",
|
||||
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||
MasqueradeBit: ptr.To[int32](17),
|
||||
LocalhostNodePorts: ptr.To(true),
|
||||
@@ -222,10 +259,11 @@ nodePortAddresses:
|
||||
NFTables: kubeproxyconfig.KubeProxyNFTablesConfiguration{
|
||||
MasqueradeBit: ptr.To[int32](18),
|
||||
},
|
||||
MetricsBindAddress: tc.metricsBindAddress,
|
||||
Mode: kubeproxyconfig.ProxyMode(tc.mode),
|
||||
NodePortAddresses: []string{"10.20.30.40/16", "fd00:1::0/64"},
|
||||
DetectLocalMode: kubeproxyconfig.LocalModeClusterCIDR,
|
||||
MetricsBindAddresses: tc.expectedMetricsBindAddresses,
|
||||
MetricsBindPort: tc.expectedMetricsBindPort,
|
||||
Mode: kubeproxyconfig.ProxyMode(tc.mode),
|
||||
NodePortAddresses: []string{"10.20.30.40/16", "fd00:1::0/64"},
|
||||
DetectLocalMode: kubeproxyconfig.LocalModeClusterCIDR,
|
||||
DetectLocal: kubeproxyconfig.DetectLocalConfiguration{
|
||||
BridgeInterface: "cbr0",
|
||||
ClusterCIDRs: strings.Split(tc.clusterCIDR, ","),
|
||||
@@ -454,6 +492,36 @@ func TestProcessV1Alpha1Flags(t *testing.T) {
|
||||
return reflect.DeepEqual(config.DetectLocal.ClusterCIDRs, []string{"2002:0:0:1234::/64", "10.0.0.0/14"})
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "metrics and healthz address ipv4",
|
||||
flags: []string{
|
||||
"--healthz-bind-address=0.0.0.0:54321",
|
||||
"--metrics-bind-address=127.0.0.1:3306",
|
||||
},
|
||||
validate: func(config *kubeproxyconfig.KubeProxyConfiguration) bool {
|
||||
if reflect.DeepEqual(config.HealthzBindAddresses, []string{"0.0.0.0/0"}) &&
|
||||
reflect.DeepEqual(config.MetricsBindAddresses, []string{"127.0.0.1/32"}) &&
|
||||
config.HealthzBindPort == 54321 && config.MetricsBindPort == 3306 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "metrics and healthz address ipv6",
|
||||
flags: []string{
|
||||
"--healthz-bind-address=[fd00:4321::2]:9090",
|
||||
"--metrics-bind-address=[::1]:8080",
|
||||
},
|
||||
validate: func(config *kubeproxyconfig.KubeProxyConfiguration) bool {
|
||||
if reflect.DeepEqual(config.HealthzBindAddresses, []string{"fd00:4321::2/128"}) &&
|
||||
reflect.DeepEqual(config.MetricsBindAddresses, []string{"::1/128"}) &&
|
||||
config.HealthzBindPort == 9090 && config.MetricsBindPort == 8080 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@@ -592,71 +660,3 @@ kind: KubeProxyConfiguration
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddressFromDeprecatedFlags(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
healthzPort int32
|
||||
healthzBindAddress string
|
||||
metricsPort int32
|
||||
metricsBindAddress string
|
||||
expHealthz string
|
||||
expMetrics string
|
||||
}{
|
||||
{
|
||||
name: "IPv4 bind address",
|
||||
healthzBindAddress: "1.2.3.4",
|
||||
healthzPort: 12345,
|
||||
metricsBindAddress: "2.3.4.5",
|
||||
metricsPort: 23456,
|
||||
expHealthz: "1.2.3.4:12345",
|
||||
expMetrics: "2.3.4.5:23456",
|
||||
},
|
||||
{
|
||||
name: "IPv4 bind address has port",
|
||||
healthzBindAddress: "1.2.3.4:12345",
|
||||
healthzPort: 23456,
|
||||
metricsBindAddress: "2.3.4.5:12345",
|
||||
metricsPort: 23456,
|
||||
expHealthz: "1.2.3.4:12345",
|
||||
expMetrics: "2.3.4.5:12345",
|
||||
},
|
||||
{
|
||||
name: "IPv6 bind address",
|
||||
healthzBindAddress: "fd00:1::5",
|
||||
healthzPort: 12345,
|
||||
metricsBindAddress: "fd00:1::6",
|
||||
metricsPort: 23456,
|
||||
expHealthz: "[fd00:1::5]:12345",
|
||||
expMetrics: "[fd00:1::6]:23456",
|
||||
},
|
||||
{
|
||||
name: "IPv6 bind address has port",
|
||||
healthzBindAddress: "[fd00:1::5]:12345",
|
||||
healthzPort: 56789,
|
||||
metricsBindAddress: "[fd00:1::6]:56789",
|
||||
metricsPort: 12345,
|
||||
expHealthz: "[fd00:1::5]:12345",
|
||||
expMetrics: "[fd00:1::6]:56789",
|
||||
},
|
||||
{
|
||||
name: "Invalid IPv6 Config",
|
||||
healthzBindAddress: "[fd00:1::5]",
|
||||
healthzPort: 12345,
|
||||
metricsBindAddress: "[fd00:1::6]",
|
||||
metricsPort: 56789,
|
||||
expHealthz: "[fd00:1::5]",
|
||||
expMetrics: "[fd00:1::6]",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
gotHealthz := addressFromDeprecatedFlags(tc.healthzBindAddress, tc.healthzPort)
|
||||
gotMetrics := addressFromDeprecatedFlags(tc.metricsBindAddress, tc.metricsPort)
|
||||
|
||||
require.Equal(t, tc.expHealthz, gotHealthz)
|
||||
require.Equal(t, tc.expMetrics, gotMetrics)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -220,8 +221,8 @@ func newProxyServer(ctx context.Context, config *kubeproxyconfig.KubeProxyConfig
|
||||
Namespace: "",
|
||||
}
|
||||
|
||||
if len(config.HealthzBindAddress) > 0 {
|
||||
s.HealthzServer = healthcheck.NewProxierHealthServer(config.HealthzBindAddress, 2*config.SyncPeriod.Duration)
|
||||
if len(config.HealthzBindAddresses) > 0 {
|
||||
s.HealthzServer = healthcheck.NewProxierHealthServer(config.HealthzBindAddresses, config.HealthzBindPort, 2*config.SyncPeriod.Duration)
|
||||
}
|
||||
|
||||
err = s.platformSetup(ctx)
|
||||
@@ -312,7 +313,7 @@ func checkBadIPConfig(s *ProxyServer, dualStackSupported bool) (err error, fatal
|
||||
clusterType = fmt.Sprintf("%s-only", s.PrimaryIPFamily)
|
||||
}
|
||||
|
||||
if badCIDRs(s.Config.DetectLocal.ClusterCIDRs, badFamily) {
|
||||
if badCIDRs(s.Config.DetectLocal.ClusterCIDRs, badFamily, false) {
|
||||
errors = append(errors, fmt.Errorf("cluster is %s but clusterCIDRs contains only IPv%s addresses", clusterType, badFamily))
|
||||
if s.Config.DetectLocalMode == kubeproxyconfig.LocalModeClusterCIDR && !dualStackSupported {
|
||||
// This has always been a fatal error
|
||||
@@ -320,7 +321,7 @@ func checkBadIPConfig(s *ProxyServer, dualStackSupported bool) (err error, fatal
|
||||
}
|
||||
}
|
||||
|
||||
if badCIDRs(s.podCIDRs, badFamily) {
|
||||
if badCIDRs(s.podCIDRs, badFamily, false) {
|
||||
errors = append(errors, fmt.Errorf("cluster is %s but node.spec.podCIDRs contains only IPv%s addresses", clusterType, badFamily))
|
||||
if s.Config.DetectLocalMode == kubeproxyconfig.LocalModeNodeCIDR {
|
||||
// This has always been a fatal error
|
||||
@@ -335,15 +336,15 @@ func checkBadIPConfig(s *ProxyServer, dualStackSupported bool) (err error, fatal
|
||||
// In some cases, wrong-IP-family is only a problem when the secondary IP family
|
||||
// isn't present at all.
|
||||
if !dualStackSupported {
|
||||
if badCIDRs(s.Config.IPVS.ExcludeCIDRs, badFamily) {
|
||||
if badCIDRs(s.Config.IPVS.ExcludeCIDRs, badFamily, false) {
|
||||
errors = append(errors, fmt.Errorf("cluster is %s but ipvs.excludeCIDRs contains only IPv%s addresses", clusterType, badFamily))
|
||||
}
|
||||
|
||||
if badBindAddress(s.Config.HealthzBindAddress, badFamily) {
|
||||
errors = append(errors, fmt.Errorf("cluster is %s but healthzBindAddress is IPv%s", clusterType, badFamily))
|
||||
if badCIDRs(s.Config.HealthzBindAddresses, badFamily, true) {
|
||||
errors = append(errors, fmt.Errorf("cluster is %s but healthzBindAddresses doesn't contain IPv%s cidr", clusterType, badFamily))
|
||||
}
|
||||
if badBindAddress(s.Config.MetricsBindAddress, badFamily) {
|
||||
errors = append(errors, fmt.Errorf("cluster is %s but metricsBindAddress is IPv%s", clusterType, badFamily))
|
||||
if badCIDRs(s.Config.MetricsBindAddresses, badFamily, true) {
|
||||
errors = append(errors, fmt.Errorf("cluster is %s but metricsBindAddresses doesn't contain IPv%s cidr", clusterType, badFamily))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,30 +355,22 @@ func checkBadIPConfig(s *ProxyServer, dualStackSupported bool) (err error, fatal
|
||||
}
|
||||
|
||||
// badCIDRs returns true if cidrs is a non-empty list of CIDRs, all of wrongFamily.
|
||||
func badCIDRs(cidrs []string, wrongFamily netutils.IPFamily) bool {
|
||||
if len(cidrs) == 0 {
|
||||
// If allowUnspecified is false, unspecified addresses '0.0.0.0' and '::' will not be treated
|
||||
// as part of either family.
|
||||
func badCIDRs(cidrStrings []string, wrongFamily netutils.IPFamily, allowUnspecified bool) bool {
|
||||
if len(cidrStrings) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, cidr := range cidrs {
|
||||
if netutils.IPFamilyOfCIDRString(cidr) != wrongFamily {
|
||||
for _, cidrString := range cidrStrings {
|
||||
ip, cidr, _ := netutils.ParseCIDRSloppy(cidrString)
|
||||
maskSize, _ := cidr.Mask.Size()
|
||||
if netutils.IPFamilyOf(ip) != wrongFamily || (allowUnspecified && (ip.IsUnspecified() && maskSize == 0)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// badBindAddress returns true if bindAddress is an "IP:port" string where IP is a
|
||||
// non-zero IP of wrongFamily.
|
||||
func badBindAddress(bindAddress string, wrongFamily netutils.IPFamily) bool {
|
||||
if host, _, _ := net.SplitHostPort(bindAddress); host != "" {
|
||||
ip := netutils.ParseIPSloppy(host)
|
||||
if ip != nil && netutils.IPFamilyOf(ip) == wrongFamily && !ip.IsUnspecified() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// createClient creates a kube client from the given config and masterOverride.
|
||||
// TODO remove masterOverride when CLI flags are removed.
|
||||
func createClient(ctx context.Context, config componentbaseconfig.ClientConnectionConfiguration, masterOverride string) (clientset.Interface, error) {
|
||||
@@ -435,8 +428,9 @@ func serveHealthz(ctx context.Context, hz *healthcheck.ProxierHealthServer, errC
|
||||
go wait.Until(fn, 5*time.Second, ctx.Done())
|
||||
}
|
||||
|
||||
func serveMetrics(ctx context.Context, bindAddress string, proxyMode kubeproxyconfig.ProxyMode, enableProfiling bool, errCh chan error) {
|
||||
if len(bindAddress) == 0 {
|
||||
func serveMetrics(ctx context.Context, cidrStrings []string, port int32, proxyMode kubeproxyconfig.ProxyMode, enableProfiling bool, errCh chan error) {
|
||||
logger := klog.FromContext(ctx)
|
||||
if len(cidrStrings) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -458,6 +452,20 @@ func serveMetrics(ctx context.Context, bindAddress string, proxyMode kubeproxyco
|
||||
}
|
||||
|
||||
configz.InstallHandler(proxyMux)
|
||||
nodeIPs, err := proxyutil.FilterInterfaceAddrsByCIDRStrings(proxyutil.RealNetwork{}, cidrStrings)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get node IPs for metrics server")
|
||||
}
|
||||
if len(nodeIPs) == 0 {
|
||||
logger.Info("failed to get any node ip matching metricsBindAddresses", "metricsBindAddresses", cidrStrings)
|
||||
}
|
||||
var addrs []string
|
||||
for _, nodeIP := range nodeIPs {
|
||||
if nodeIP.IsLinkLocalUnicast() || nodeIP.IsLinkLocalMulticast() {
|
||||
continue
|
||||
}
|
||||
addrs = append(addrs, net.JoinHostPort(nodeIP.String(), strconv.Itoa(int(port))))
|
||||
}
|
||||
|
||||
fn := func() {
|
||||
var err error
|
||||
@@ -474,7 +482,7 @@ func serveMetrics(ctx context.Context, bindAddress string, proxyMode kubeproxyco
|
||||
}
|
||||
}()
|
||||
|
||||
listener, err := netutils.MultiListen(ctx, "tcp", bindAddress)
|
||||
listener, err := netutils.MultiListen(ctx, "tcp", addrs...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -526,7 +534,7 @@ func (s *ProxyServer) Run(ctx context.Context) error {
|
||||
serveHealthz(ctx, s.HealthzServer, healthzErrCh)
|
||||
|
||||
// Start up a metrics server if requested
|
||||
serveMetrics(ctx, s.Config.MetricsBindAddress, s.Config.Mode, s.Config.EnableProfiling, metricsErrCh)
|
||||
serveMetrics(ctx, s.Config.MetricsBindAddresses, s.Config.MetricsBindPort, s.Config.Mode, s.Config.EnableProfiling, metricsErrCh)
|
||||
|
||||
noProxyName, err := labels.NewRequirement(apis.LabelServiceProxyName, selection.DoesNotExist, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -551,7 +551,8 @@ func Test_checkBadIPConfig(t *testing.T) {
|
||||
name: "ok IPv4 metricsBindAddress",
|
||||
proxy: &ProxyServer{
|
||||
Config: &kubeproxyconfig.KubeProxyConfiguration{
|
||||
MetricsBindAddress: "10.0.0.1:9999",
|
||||
MetricsBindAddresses: []string{"10.0.0.0/24"},
|
||||
MetricsBindPort: 9999,
|
||||
},
|
||||
PrimaryIPFamily: v1.IPv4Protocol,
|
||||
},
|
||||
@@ -562,7 +563,8 @@ func Test_checkBadIPConfig(t *testing.T) {
|
||||
name: "ok IPv6 metricsBindAddress",
|
||||
proxy: &ProxyServer{
|
||||
Config: &kubeproxyconfig.KubeProxyConfiguration{
|
||||
MetricsBindAddress: "[fd01:2345::1]:9999",
|
||||
MetricsBindAddresses: []string{"fd01:2345::/64"},
|
||||
MetricsBindPort: 9999,
|
||||
},
|
||||
PrimaryIPFamily: v1.IPv6Protocol,
|
||||
},
|
||||
@@ -573,7 +575,8 @@ func Test_checkBadIPConfig(t *testing.T) {
|
||||
name: "ok unspecified wrong-family metricsBindAddress",
|
||||
proxy: &ProxyServer{
|
||||
Config: &kubeproxyconfig.KubeProxyConfiguration{
|
||||
MetricsBindAddress: "0.0.0.0:9999",
|
||||
MetricsBindAddresses: []string{"0.0.0.0/0"},
|
||||
MetricsBindPort: 9999,
|
||||
},
|
||||
PrimaryIPFamily: v1.IPv6Protocol,
|
||||
},
|
||||
@@ -584,7 +587,8 @@ func Test_checkBadIPConfig(t *testing.T) {
|
||||
name: "wrong family metricsBindAddress",
|
||||
proxy: &ProxyServer{
|
||||
Config: &kubeproxyconfig.KubeProxyConfiguration{
|
||||
MetricsBindAddress: "10.0.0.1:9999",
|
||||
MetricsBindAddresses: []string{"10.0.0.0/24"},
|
||||
MetricsBindPort: 9999,
|
||||
},
|
||||
PrimaryIPFamily: v1.IPv6Protocol,
|
||||
},
|
||||
|
||||
@@ -97,7 +97,7 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi.
|
||||
s.NodeIPs,
|
||||
s.Recorder,
|
||||
s.HealthzServer,
|
||||
config.HealthzBindAddress,
|
||||
int(config.HealthzBindPort),
|
||||
config.Winkernel,
|
||||
)
|
||||
} else {
|
||||
@@ -109,7 +109,7 @@ func (s *ProxyServer) createProxier(ctx context.Context, config *proxyconfigapi.
|
||||
s.NodeIPs[s.PrimaryIPFamily],
|
||||
s.Recorder,
|
||||
s.HealthzServer,
|
||||
config.HealthzBindAddress,
|
||||
int(config.HealthzBindPort),
|
||||
config.Winkernel,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user