mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 23:15:14 +00:00
Add a dummy nftables kube-proxy backend which is just a copy of iptables
This commit is contained in:
parent
3631efd85c
commit
a70653143e
@ -553,6 +553,7 @@ API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,V
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,VolumeConfiguration,FlexVolumePluginDir
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,VolumeConfiguration,PersistentVolumeRecyclerConfiguration
|
||||
API rule violation: names_match,k8s.io/kube-proxy/config/v1alpha1,KubeProxyConfiguration,IPTables
|
||||
API rule violation: names_match,k8s.io/kube-proxy/config/v1alpha1,KubeProxyConfiguration,NFTables
|
||||
API rule violation: names_match,k8s.io/kubelet/config/v1beta1,KubeletConfiguration,IPTablesDropBit
|
||||
API rule violation: names_match,k8s.io/kubelet/config/v1beta1,KubeletConfiguration,IPTablesMasqueradeBit
|
||||
API rule violation: names_match,k8s.io/kubelet/config/v1beta1,KubeletConfiguration,ResolverConfig
|
||||
|
@ -50,6 +50,7 @@ import (
|
||||
utilipset "k8s.io/kubernetes/pkg/proxy/ipvs/ipset"
|
||||
utilipvs "k8s.io/kubernetes/pkg/proxy/ipvs/util"
|
||||
proxymetrics "k8s.io/kubernetes/pkg/proxy/metrics"
|
||||
"k8s.io/kubernetes/pkg/proxy/nftables"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
proxyutiliptables "k8s.io/kubernetes/pkg/proxy/util/iptables"
|
||||
utiliptables "k8s.io/kubernetes/pkg/util/iptables"
|
||||
@ -282,6 +283,67 @@ func (s *ProxyServer) createProxier(config *proxyconfigapi.KubeProxyConfiguratio
|
||||
initOnly,
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create proxier: %v", err)
|
||||
}
|
||||
} else if config.Mode == proxyconfigapi.ProxyModeNFTables {
|
||||
klog.InfoS("Using nftables Proxier")
|
||||
|
||||
if dualStack {
|
||||
// Always ordered to match []ipt
|
||||
var localDetectors [2]proxyutiliptables.LocalTrafficDetector
|
||||
localDetectors, err = getDualStackLocalDetectorTuple(config.DetectLocalMode, config, s.podCIDRs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create proxier: %v", err)
|
||||
}
|
||||
|
||||
// TODO this has side effects that should only happen when Run() is invoked.
|
||||
proxier, err = nftables.NewDualStackProxier(
|
||||
ipt,
|
||||
utilsysctl.New(),
|
||||
execer,
|
||||
config.NFTables.SyncPeriod.Duration,
|
||||
config.NFTables.MinSyncPeriod.Duration,
|
||||
config.NFTables.MasqueradeAll,
|
||||
*config.NFTables.LocalhostNodePorts,
|
||||
int(*config.NFTables.MasqueradeBit),
|
||||
localDetectors,
|
||||
s.Hostname,
|
||||
s.NodeIPs,
|
||||
s.Recorder,
|
||||
s.HealthzServer,
|
||||
config.NodePortAddresses,
|
||||
initOnly,
|
||||
)
|
||||
} else {
|
||||
// Create a single-stack proxier if and only if the node does not support dual-stack (i.e, no iptables support).
|
||||
var localDetector proxyutiliptables.LocalTrafficDetector
|
||||
localDetector, err = getLocalDetector(s.PrimaryIPFamily, config.DetectLocalMode, config, s.podCIDRs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create proxier: %v", err)
|
||||
}
|
||||
|
||||
// TODO this has side effects that should only happen when Run() is invoked.
|
||||
proxier, err = nftables.NewProxier(
|
||||
s.PrimaryIPFamily,
|
||||
iptInterface,
|
||||
utilsysctl.New(),
|
||||
execer,
|
||||
config.NFTables.SyncPeriod.Duration,
|
||||
config.NFTables.MinSyncPeriod.Duration,
|
||||
config.NFTables.MasqueradeAll,
|
||||
*config.NFTables.LocalhostNodePorts,
|
||||
int(*config.NFTables.MasqueradeBit),
|
||||
localDetector,
|
||||
s.Hostname,
|
||||
s.NodeIPs[s.PrimaryIPFamily],
|
||||
s.Recorder,
|
||||
s.HealthzServer,
|
||||
config.NodePortAddresses,
|
||||
initOnly,
|
||||
)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create proxier: %v", err)
|
||||
}
|
||||
@ -492,6 +554,7 @@ func cleanupAndExit() error {
|
||||
for _, ipt := range ipts {
|
||||
encounteredError = iptables.CleanupLeftovers(ipt) || encounteredError
|
||||
encounteredError = ipvs.CleanupLeftovers(ipvsInterface, ipt, ipsetInterface) || encounteredError
|
||||
encounteredError = nftables.CleanupLeftovers(ipt) || encounteredError
|
||||
}
|
||||
if encounteredError {
|
||||
return errors.New("encountered an error while tearing down rules")
|
||||
|
@ -74,6 +74,12 @@ ipvs:
|
||||
excludeCIDRs:
|
||||
- "10.20.30.40/16"
|
||||
- "fd00:1::0/64"
|
||||
nftables:
|
||||
masqueradeAll: true
|
||||
masqueradeBit: 18
|
||||
minSyncPeriod: 10s
|
||||
syncPeriod: 60s
|
||||
localhostNodePorts: false
|
||||
kind: KubeProxyConfiguration
|
||||
metricsBindAddress: "%s"
|
||||
mode: "%s"
|
||||
@ -218,6 +224,13 @@ nodePortAddresses:
|
||||
SyncPeriod: metav1.Duration{Duration: 60 * time.Second},
|
||||
ExcludeCIDRs: []string{"10.20.30.40/16", "fd00:1::0/64"},
|
||||
},
|
||||
NFTables: kubeproxyconfig.KubeProxyNFTablesConfiguration{
|
||||
MasqueradeAll: true,
|
||||
MasqueradeBit: ptr.To[int32](18),
|
||||
LocalhostNodePorts: ptr.To(false),
|
||||
MinSyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||
SyncPeriod: metav1.Duration{Duration: 60 * time.Second},
|
||||
},
|
||||
MetricsBindAddress: tc.metricsBindAddress,
|
||||
Mode: kubeproxyconfig.ProxyMode(tc.mode),
|
||||
OOMScoreAdj: ptr.To[int32](17),
|
||||
|
@ -564,6 +564,13 @@ const (
|
||||
// Robust VolumeManager reconstruction after kubelet restart.
|
||||
NewVolumeManagerReconstruction featuregate.Feature = "NewVolumeManagerReconstruction"
|
||||
|
||||
// owner: @danwinship
|
||||
// kep: https://kep.k8s.io/3866
|
||||
// alpha: v1.29
|
||||
//
|
||||
// Allows running kube-proxy with `--mode nftables`.
|
||||
NFTablesProxyMode featuregate.Feature = "NFTablesProxyMode"
|
||||
|
||||
// owner: @aravindhp @LorbusChris
|
||||
// kep: http://kep.k8s.io/2271
|
||||
// alpha: v1.27
|
||||
@ -1103,6 +1110,8 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
|
||||
NewVolumeManagerReconstruction: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
||||
NFTablesProxyMode: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
NodeLogQuery: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
NodeOutOfServiceVolumeDetach: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.31
|
||||
|
62
pkg/generated/openapi/zz_generated.openapi.go
generated
62
pkg/generated/openapi/zz_generated.openapi.go
generated
@ -1095,6 +1095,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
||||
"k8s.io/kube-proxy/config/v1alpha1.KubeProxyConntrackConfiguration": schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyConntrackConfiguration(ref),
|
||||
"k8s.io/kube-proxy/config/v1alpha1.KubeProxyIPTablesConfiguration": schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyIPTablesConfiguration(ref),
|
||||
"k8s.io/kube-proxy/config/v1alpha1.KubeProxyIPVSConfiguration": schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyIPVSConfiguration(ref),
|
||||
"k8s.io/kube-proxy/config/v1alpha1.KubeProxyNFTablesConfiguration": schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyNFTablesConfiguration(ref),
|
||||
"k8s.io/kube-proxy/config/v1alpha1.KubeProxyWinkernelConfiguration": schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyWinkernelConfiguration(ref),
|
||||
"k8s.io/kube-scheduler/config/v1.DefaultPreemptionArgs": schema_k8sio_kube_scheduler_config_v1_DefaultPreemptionArgs(ref),
|
||||
"k8s.io/kube-scheduler/config/v1.Extender": schema_k8sio_kube_scheduler_config_v1_Extender(ref),
|
||||
@ -54415,6 +54416,13 @@ func schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyConfiguration(ref common.R
|
||||
Ref: ref("k8s.io/kube-proxy/config/v1alpha1.KubeProxyIPVSConfiguration"),
|
||||
},
|
||||
},
|
||||
"nftables": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "nftables contains nftables-related configuration options.",
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/kube-proxy/config/v1alpha1.KubeProxyNFTablesConfiguration"),
|
||||
},
|
||||
},
|
||||
"winkernel": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "winkernel contains winkernel-related configuration options.",
|
||||
@ -54489,11 +54497,11 @@ func schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyConfiguration(ref common.R
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"clientConnection", "hostnameOverride", "bindAddress", "healthzBindAddress", "metricsBindAddress", "bindAddressHardFail", "enableProfiling", "showHiddenMetricsForVersion", "mode", "iptables", "ipvs", "winkernel", "detectLocalMode", "detectLocal", "clusterCIDR", "nodePortAddresses", "oomScoreAdj", "conntrack", "configSyncPeriod", "portRange"},
|
||||
Required: []string{"clientConnection", "hostnameOverride", "bindAddress", "healthzBindAddress", "metricsBindAddress", "bindAddressHardFail", "enableProfiling", "showHiddenMetricsForVersion", "mode", "iptables", "ipvs", "nftables", "winkernel", "detectLocalMode", "detectLocal", "clusterCIDR", "nodePortAddresses", "oomScoreAdj", "conntrack", "configSyncPeriod", "portRange"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.Duration", "k8s.io/component-base/config/v1alpha1.ClientConnectionConfiguration", "k8s.io/component-base/logs/api/v1.LoggingConfiguration", "k8s.io/kube-proxy/config/v1alpha1.DetectLocalConfiguration", "k8s.io/kube-proxy/config/v1alpha1.KubeProxyConntrackConfiguration", "k8s.io/kube-proxy/config/v1alpha1.KubeProxyIPTablesConfiguration", "k8s.io/kube-proxy/config/v1alpha1.KubeProxyIPVSConfiguration", "k8s.io/kube-proxy/config/v1alpha1.KubeProxyWinkernelConfiguration"},
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.Duration", "k8s.io/component-base/config/v1alpha1.ClientConnectionConfiguration", "k8s.io/component-base/logs/api/v1.LoggingConfiguration", "k8s.io/kube-proxy/config/v1alpha1.DetectLocalConfiguration", "k8s.io/kube-proxy/config/v1alpha1.KubeProxyConntrackConfiguration", "k8s.io/kube-proxy/config/v1alpha1.KubeProxyIPTablesConfiguration", "k8s.io/kube-proxy/config/v1alpha1.KubeProxyIPVSConfiguration", "k8s.io/kube-proxy/config/v1alpha1.KubeProxyNFTablesConfiguration", "k8s.io/kube-proxy/config/v1alpha1.KubeProxyWinkernelConfiguration"},
|
||||
}
|
||||
}
|
||||
|
||||
@ -54686,6 +54694,56 @@ func schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyIPVSConfiguration(ref comm
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyNFTablesConfiguration(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "KubeProxyNFTablesConfiguration contains nftables-related configuration details for the Kubernetes proxy server.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"masqueradeBit": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "masqueradeBit is the bit of the iptables fwmark space to use for SNAT if using the nftables proxy mode. Values must be within the range [0, 31].",
|
||||
Type: []string{"integer"},
|
||||
Format: "int32",
|
||||
},
|
||||
},
|
||||
"masqueradeAll": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "masqueradeAll tells kube-proxy to SNAT all traffic sent to Service cluster IPs, when using the nftables mode. This may be required with some CNI plugins.",
|
||||
Default: false,
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"localhostNodePorts": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "localhostNodePorts, if false, tells kube-proxy to disable the legacy behavior of allowing NodePort services to be accessed via localhost. FIXME: remove.",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"syncPeriod": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "syncPeriod is an interval (e.g. '5s', '1m', '2h22m') indicating how frequently various re-synchronizing and cleanup operations are performed. Must be greater than 0.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
|
||||
},
|
||||
},
|
||||
"minSyncPeriod": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "minSyncPeriod is the minimum period between iptables rule resyncs (e.g. '5s', '1m', '2h22m'). A value of 0 means every Service or EndpointSlice change will result in an immediate iptables resync.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"masqueradeBit", "masqueradeAll", "localhostNodePorts", "syncPeriod", "minSyncPeriod"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.Duration"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyWinkernelConfiguration(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
|
@ -43,6 +43,8 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
obj.HealthzBindAddress = fmt.Sprintf("%d.%d.%d.%d:%d", c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(65536))
|
||||
obj.IPTables.MasqueradeBit = ptr.To(c.Int31())
|
||||
obj.IPTables.LocalhostNodePorts = ptr.To(c.RandBool())
|
||||
obj.NFTables.MasqueradeBit = ptr.To(c.Int31())
|
||||
obj.NFTables.LocalhostNodePorts = ptr.To(c.RandBool())
|
||||
obj.MetricsBindAddress = fmt.Sprintf("%d.%d.%d.%d:%d", c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(65536))
|
||||
obj.OOMScoreAdj = ptr.To(c.Int31())
|
||||
obj.ClientConnection.ContentType = "bar"
|
||||
|
@ -49,6 +49,12 @@ logging:
|
||||
verbosity: 0
|
||||
metricsBindAddress: 127.0.0.1:10249
|
||||
mode: ""
|
||||
nftables:
|
||||
localhostNodePorts: true
|
||||
masqueradeAll: false
|
||||
masqueradeBit: 14
|
||||
minSyncPeriod: 1s
|
||||
syncPeriod: 30s
|
||||
nodePortAddresses: null
|
||||
oomScoreAdj: -999
|
||||
portRange: ""
|
||||
|
@ -49,6 +49,12 @@ logging:
|
||||
verbosity: 0
|
||||
metricsBindAddress: 127.0.0.1:10249
|
||||
mode: ""
|
||||
nftables:
|
||||
localhostNodePorts: true
|
||||
masqueradeAll: false
|
||||
masqueradeBit: 14
|
||||
minSyncPeriod: 1s
|
||||
syncPeriod: 30s
|
||||
nodePortAddresses: null
|
||||
oomScoreAdj: -999
|
||||
portRange: ""
|
||||
|
@ -81,6 +81,28 @@ type KubeProxyIPVSConfiguration struct {
|
||||
UDPTimeout metav1.Duration
|
||||
}
|
||||
|
||||
// KubeProxyNFTablesConfiguration contains nftables-related configuration
|
||||
// details for the Kubernetes proxy server.
|
||||
type KubeProxyNFTablesConfiguration struct {
|
||||
// masqueradeBit is the bit of the iptables fwmark space to use for SNAT if using
|
||||
// the nftables proxy mode. Values must be within the range [0, 31].
|
||||
MasqueradeBit *int32
|
||||
// masqueradeAll tells kube-proxy to SNAT all traffic sent to Service cluster IPs,
|
||||
// when using the nftables mode. This may be required with some CNI plugins.
|
||||
MasqueradeAll bool
|
||||
// localhostNodePorts, if false, tells kube-proxy to disable the legacy behavior
|
||||
// of allowing NodePort services to be accessed via localhost. FIXME: remove.
|
||||
LocalhostNodePorts *bool
|
||||
// syncPeriod is an interval (e.g. '5s', '1m', '2h22m') indicating how frequently
|
||||
// various re-synchronizing and cleanup operations are performed. Must be greater
|
||||
// than 0.
|
||||
SyncPeriod metav1.Duration
|
||||
// minSyncPeriod is the minimum period between iptables rule resyncs (e.g. '5s',
|
||||
// '1m', '2h22m'). A value of 0 means every Service or EndpointSlice change will
|
||||
// result in an immediate iptables resync.
|
||||
MinSyncPeriod metav1.Duration
|
||||
}
|
||||
|
||||
// KubeProxyConntrackConfiguration contains conntrack settings for
|
||||
// the Kubernetes proxy server.
|
||||
type KubeProxyConntrackConfiguration struct {
|
||||
@ -195,6 +217,8 @@ type KubeProxyConfiguration struct {
|
||||
IPVS KubeProxyIPVSConfiguration
|
||||
// winkernel contains winkernel-related configuration options.
|
||||
Winkernel KubeProxyWinkernelConfiguration
|
||||
// nftables contains nftables-related configuration options.
|
||||
NFTables KubeProxyNFTablesConfiguration
|
||||
|
||||
// detectLocalMode determines mode to use for detecting local traffic, defaults to LocalModeClusterCIDR
|
||||
DetectLocalMode LocalMode
|
||||
@ -228,8 +252,8 @@ type KubeProxyConfiguration struct {
|
||||
|
||||
// ProxyMode represents modes used by the Kubernetes proxy server.
|
||||
//
|
||||
// Currently, two modes of proxy are available on Linux platforms: 'iptables' and 'ipvs'.
|
||||
// One mode of proxy is available on Windows platforms: 'kernelspace'.
|
||||
// Currently, three modes of proxy are available on Linux platforms: 'iptables', 'ipvs',
|
||||
// and 'nftables'. One mode of proxy is available on Windows platforms: 'kernelspace'.
|
||||
//
|
||||
// If the proxy mode is unspecified, the best-available proxy mode will be used (currently this
|
||||
// is `iptables` on Linux and `kernelspace` on Windows). If the selected proxy mode cannot be
|
||||
@ -240,6 +264,7 @@ type ProxyMode string
|
||||
const (
|
||||
ProxyModeIPTables ProxyMode = "iptables"
|
||||
ProxyModeIPVS ProxyMode = "ipvs"
|
||||
ProxyModeNFTables ProxyMode = "nftables"
|
||||
ProxyModeKernelspace ProxyMode = "kernelspace"
|
||||
)
|
||||
|
||||
|
@ -71,6 +71,15 @@ func SetDefaults_KubeProxyConfiguration(obj *kubeproxyconfigv1alpha1.KubeProxyCo
|
||||
if obj.IPVS.SyncPeriod.Duration == 0 {
|
||||
obj.IPVS.SyncPeriod = metav1.Duration{Duration: 30 * time.Second}
|
||||
}
|
||||
if obj.NFTables.SyncPeriod.Duration == 0 {
|
||||
obj.NFTables.SyncPeriod = metav1.Duration{Duration: 30 * time.Second}
|
||||
}
|
||||
if obj.NFTables.MinSyncPeriod.Duration == 0 {
|
||||
obj.NFTables.MinSyncPeriod = metav1.Duration{Duration: 1 * time.Second}
|
||||
}
|
||||
if obj.NFTables.LocalhostNodePorts == nil {
|
||||
obj.NFTables.LocalhostNodePorts = ptr.To(true)
|
||||
}
|
||||
|
||||
if obj.Conntrack.MaxPerCore == nil {
|
||||
obj.Conntrack.MaxPerCore = ptr.To[int32](32 * 1024)
|
||||
@ -83,6 +92,10 @@ func SetDefaults_KubeProxyConfiguration(obj *kubeproxyconfigv1alpha1.KubeProxyCo
|
||||
temp := int32(14)
|
||||
obj.IPTables.MasqueradeBit = &temp
|
||||
}
|
||||
if obj.NFTables.MasqueradeBit == nil {
|
||||
temp := int32(14)
|
||||
obj.NFTables.MasqueradeBit = &temp
|
||||
}
|
||||
if obj.Conntrack.TCPEstablishedTimeout == nil {
|
||||
obj.Conntrack.TCPEstablishedTimeout = &metav1.Duration{Duration: 24 * time.Hour} // 1 day (1/5 default)
|
||||
}
|
||||
|
@ -62,6 +62,13 @@ func TestDefaultsKubeProxyConfiguration(t *testing.T) {
|
||||
IPVS: kubeproxyconfigv1alpha1.KubeProxyIPVSConfiguration{
|
||||
SyncPeriod: metav1.Duration{Duration: 30 * time.Second},
|
||||
},
|
||||
NFTables: kubeproxyconfigv1alpha1.KubeProxyNFTablesConfiguration{
|
||||
MasqueradeBit: ptr.To[int32](14),
|
||||
MasqueradeAll: false,
|
||||
LocalhostNodePorts: ptr.To(true),
|
||||
SyncPeriod: metav1.Duration{Duration: 30 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
},
|
||||
OOMScoreAdj: &oomScore,
|
||||
Conntrack: kubeproxyconfigv1alpha1.KubeProxyConntrackConfiguration{
|
||||
MaxPerCore: &ctMaxPerCore,
|
||||
@ -102,6 +109,13 @@ func TestDefaultsKubeProxyConfiguration(t *testing.T) {
|
||||
IPVS: kubeproxyconfigv1alpha1.KubeProxyIPVSConfiguration{
|
||||
SyncPeriod: metav1.Duration{Duration: 30 * time.Second},
|
||||
},
|
||||
NFTables: kubeproxyconfigv1alpha1.KubeProxyNFTablesConfiguration{
|
||||
MasqueradeBit: ptr.To[int32](14),
|
||||
MasqueradeAll: false,
|
||||
LocalhostNodePorts: ptr.To(true),
|
||||
SyncPeriod: metav1.Duration{Duration: 30 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
},
|
||||
OOMScoreAdj: &oomScore,
|
||||
Conntrack: kubeproxyconfigv1alpha1.KubeProxyConntrackConfiguration{
|
||||
MaxPerCore: &ctMaxPerCore,
|
||||
|
@ -89,6 +89,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1alpha1.KubeProxyNFTablesConfiguration)(nil), (*config.KubeProxyNFTablesConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_KubeProxyNFTablesConfiguration_To_config_KubeProxyNFTablesConfiguration(a.(*v1alpha1.KubeProxyNFTablesConfiguration), b.(*config.KubeProxyNFTablesConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.KubeProxyNFTablesConfiguration)(nil), (*v1alpha1.KubeProxyNFTablesConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_KubeProxyNFTablesConfiguration_To_v1alpha1_KubeProxyNFTablesConfiguration(a.(*config.KubeProxyNFTablesConfiguration), b.(*v1alpha1.KubeProxyNFTablesConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1alpha1.KubeProxyWinkernelConfiguration)(nil), (*config.KubeProxyWinkernelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_KubeProxyWinkernelConfiguration_To_config_KubeProxyWinkernelConfiguration(a.(*v1alpha1.KubeProxyWinkernelConfiguration), b.(*config.KubeProxyWinkernelConfiguration), scope)
|
||||
}); err != nil {
|
||||
@ -144,6 +154,9 @@ func autoConvert_v1alpha1_KubeProxyConfiguration_To_config_KubeProxyConfiguratio
|
||||
if err := Convert_v1alpha1_KubeProxyIPVSConfiguration_To_config_KubeProxyIPVSConfiguration(&in.IPVS, &out.IPVS, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1alpha1_KubeProxyNFTablesConfiguration_To_config_KubeProxyNFTablesConfiguration(&in.NFTables, &out.NFTables, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1alpha1_KubeProxyWinkernelConfiguration_To_config_KubeProxyWinkernelConfiguration(&in.Winkernel, &out.Winkernel, s); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -190,6 +203,9 @@ func autoConvert_config_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfiguratio
|
||||
if err := Convert_config_KubeProxyWinkernelConfiguration_To_v1alpha1_KubeProxyWinkernelConfiguration(&in.Winkernel, &out.Winkernel, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_config_KubeProxyNFTablesConfiguration_To_v1alpha1_KubeProxyNFTablesConfiguration(&in.NFTables, &out.NFTables, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.DetectLocalMode = v1alpha1.LocalMode(in.DetectLocalMode)
|
||||
if err := Convert_config_DetectLocalConfiguration_To_v1alpha1_DetectLocalConfiguration(&in.DetectLocal, &out.DetectLocal, s); err != nil {
|
||||
return err
|
||||
@ -304,6 +320,34 @@ func Convert_config_KubeProxyIPVSConfiguration_To_v1alpha1_KubeProxyIPVSConfigur
|
||||
return autoConvert_config_KubeProxyIPVSConfiguration_To_v1alpha1_KubeProxyIPVSConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_KubeProxyNFTablesConfiguration_To_config_KubeProxyNFTablesConfiguration(in *v1alpha1.KubeProxyNFTablesConfiguration, out *config.KubeProxyNFTablesConfiguration, s conversion.Scope) error {
|
||||
out.MasqueradeBit = (*int32)(unsafe.Pointer(in.MasqueradeBit))
|
||||
out.MasqueradeAll = in.MasqueradeAll
|
||||
out.LocalhostNodePorts = (*bool)(unsafe.Pointer(in.LocalhostNodePorts))
|
||||
out.SyncPeriod = in.SyncPeriod
|
||||
out.MinSyncPeriod = in.MinSyncPeriod
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_KubeProxyNFTablesConfiguration_To_config_KubeProxyNFTablesConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_KubeProxyNFTablesConfiguration_To_config_KubeProxyNFTablesConfiguration(in *v1alpha1.KubeProxyNFTablesConfiguration, out *config.KubeProxyNFTablesConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_KubeProxyNFTablesConfiguration_To_config_KubeProxyNFTablesConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_KubeProxyNFTablesConfiguration_To_v1alpha1_KubeProxyNFTablesConfiguration(in *config.KubeProxyNFTablesConfiguration, out *v1alpha1.KubeProxyNFTablesConfiguration, s conversion.Scope) error {
|
||||
out.MasqueradeBit = (*int32)(unsafe.Pointer(in.MasqueradeBit))
|
||||
out.MasqueradeAll = in.MasqueradeAll
|
||||
out.LocalhostNodePorts = (*bool)(unsafe.Pointer(in.LocalhostNodePorts))
|
||||
out.SyncPeriod = in.SyncPeriod
|
||||
out.MinSyncPeriod = in.MinSyncPeriod
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_KubeProxyNFTablesConfiguration_To_v1alpha1_KubeProxyNFTablesConfiguration is an autogenerated conversion function.
|
||||
func Convert_config_KubeProxyNFTablesConfiguration_To_v1alpha1_KubeProxyNFTablesConfiguration(in *config.KubeProxyNFTablesConfiguration, out *v1alpha1.KubeProxyNFTablesConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_KubeProxyNFTablesConfiguration_To_v1alpha1_KubeProxyNFTablesConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_KubeProxyWinkernelConfiguration_To_config_KubeProxyWinkernelConfiguration(in *v1alpha1.KubeProxyWinkernelConfiguration, out *config.KubeProxyWinkernelConfiguration, s conversion.Scope) error {
|
||||
out.NetworkName = in.NetworkName
|
||||
out.SourceVip = in.SourceVip
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
logsapi "k8s.io/component-base/logs/api/v1"
|
||||
"k8s.io/component-base/metrics"
|
||||
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeproxyconfig "k8s.io/kubernetes/pkg/proxy/apis/config"
|
||||
netutils "k8s.io/utils/net"
|
||||
)
|
||||
@ -47,8 +48,11 @@ func Validate(config *kubeproxyconfig.KubeProxyConfiguration) field.ErrorList {
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, validateKubeProxyIPTablesConfiguration(config.IPTables, newPath.Child("KubeProxyIPTablesConfiguration"))...)
|
||||
if config.Mode == kubeproxyconfig.ProxyModeIPVS {
|
||||
switch config.Mode {
|
||||
case kubeproxyconfig.ProxyModeIPVS:
|
||||
allErrs = append(allErrs, validateKubeProxyIPVSConfiguration(config.IPVS, newPath.Child("KubeProxyIPVSConfiguration"))...)
|
||||
case kubeproxyconfig.ProxyModeNFTables:
|
||||
allErrs = append(allErrs, validateKubeProxyNFTablesConfiguration(config.NFTables, newPath.Child("KubeProxyNFTablesConfiguration"))...)
|
||||
}
|
||||
allErrs = append(allErrs, validateKubeProxyConntrackConfiguration(config.Conntrack, newPath.Child("KubeProxyConntrackConfiguration"))...)
|
||||
allErrs = append(allErrs, validateProxyMode(config.Mode, newPath.Child("Mode"))...)
|
||||
@ -152,6 +156,28 @@ func validateKubeProxyIPVSConfiguration(config kubeproxyconfig.KubeProxyIPVSConf
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKubeProxyNFTablesConfiguration(config kubeproxyconfig.KubeProxyNFTablesConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if config.MasqueradeBit != nil && (*config.MasqueradeBit < 0 || *config.MasqueradeBit > 31) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("MasqueradeBit"), config.MasqueradeBit, "must be within the range [0, 31]"))
|
||||
}
|
||||
|
||||
if config.SyncPeriod.Duration <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("SyncPeriod"), config.SyncPeriod, "must be greater than 0"))
|
||||
}
|
||||
|
||||
if config.MinSyncPeriod.Duration < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("MinSyncPeriod"), config.MinSyncPeriod, "must be greater than or equal to 0"))
|
||||
}
|
||||
|
||||
if config.MinSyncPeriod.Duration > config.SyncPeriod.Duration {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("SyncPeriod"), config.MinSyncPeriod, fmt.Sprintf("must be greater than or equal to %s", fldPath.Child("MinSyncPeriod").String())))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKubeProxyConntrackConfiguration(config kubeproxyconfig.KubeProxyConntrackConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
@ -198,6 +224,10 @@ func validateProxyModeLinux(mode kubeproxyconfig.ProxyMode, fldPath *field.Path)
|
||||
string(kubeproxyconfig.ProxyModeIPVS),
|
||||
)
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.NFTablesProxyMode) {
|
||||
validModes.Insert(string(kubeproxyconfig.ProxyModeNFTables))
|
||||
}
|
||||
|
||||
if mode == "" || validModes.Has(string(mode)) {
|
||||
return nil
|
||||
}
|
||||
|
29
pkg/proxy/apis/config/zz_generated.deepcopy.go
generated
29
pkg/proxy/apis/config/zz_generated.deepcopy.go
generated
@ -80,6 +80,7 @@ func (in *KubeProxyConfiguration) DeepCopyInto(out *KubeProxyConfiguration) {
|
||||
in.IPTables.DeepCopyInto(&out.IPTables)
|
||||
in.IPVS.DeepCopyInto(&out.IPVS)
|
||||
out.Winkernel = in.Winkernel
|
||||
in.NFTables.DeepCopyInto(&out.NFTables)
|
||||
out.DetectLocal = in.DetectLocal
|
||||
if in.NodePortAddresses != nil {
|
||||
in, out := &in.NodePortAddresses, &out.NodePortAddresses
|
||||
@ -206,6 +207,34 @@ func (in *KubeProxyIPVSConfiguration) DeepCopy() *KubeProxyIPVSConfiguration {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubeProxyNFTablesConfiguration) DeepCopyInto(out *KubeProxyNFTablesConfiguration) {
|
||||
*out = *in
|
||||
if in.MasqueradeBit != nil {
|
||||
in, out := &in.MasqueradeBit, &out.MasqueradeBit
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.LocalhostNodePorts != nil {
|
||||
in, out := &in.LocalhostNodePorts, &out.LocalhostNodePorts
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
out.SyncPeriod = in.SyncPeriod
|
||||
out.MinSyncPeriod = in.MinSyncPeriod
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeProxyNFTablesConfiguration.
|
||||
func (in *KubeProxyNFTablesConfiguration) DeepCopy() *KubeProxyNFTablesConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubeProxyNFTablesConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubeProxyWinkernelConfiguration) DeepCopyInto(out *KubeProxyWinkernelConfiguration) {
|
||||
*out = *in
|
||||
|
1613
pkg/proxy/nftables/proxier.go
Normal file
1613
pkg/proxy/nftables/proxier.go
Normal file
File diff suppressed because it is too large
Load Diff
7065
pkg/proxy/nftables/proxier_test.go
Normal file
7065
pkg/proxy/nftables/proxier_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -77,6 +77,28 @@ type KubeProxyIPVSConfiguration struct {
|
||||
UDPTimeout metav1.Duration `json:"udpTimeout"`
|
||||
}
|
||||
|
||||
// KubeProxyNFTablesConfiguration contains nftables-related configuration
|
||||
// details for the Kubernetes proxy server.
|
||||
type KubeProxyNFTablesConfiguration struct {
|
||||
// masqueradeBit is the bit of the iptables fwmark space to use for SNAT if using
|
||||
// the nftables proxy mode. Values must be within the range [0, 31].
|
||||
MasqueradeBit *int32 `json:"masqueradeBit"`
|
||||
// masqueradeAll tells kube-proxy to SNAT all traffic sent to Service cluster IPs,
|
||||
// when using the nftables mode. This may be required with some CNI plugins.
|
||||
MasqueradeAll bool `json:"masqueradeAll"`
|
||||
// localhostNodePorts, if false, tells kube-proxy to disable the legacy behavior
|
||||
// of allowing NodePort services to be accessed via localhost. FIXME: remove.
|
||||
LocalhostNodePorts *bool `json:"localhostNodePorts"`
|
||||
// syncPeriod is an interval (e.g. '5s', '1m', '2h22m') indicating how frequently
|
||||
// various re-synchronizing and cleanup operations are performed. Must be greater
|
||||
// than 0.
|
||||
SyncPeriod metav1.Duration `json:"syncPeriod"`
|
||||
// minSyncPeriod is the minimum period between iptables rule resyncs (e.g. '5s',
|
||||
// '1m', '2h22m'). A value of 0 means every Service or EndpointSlice change will
|
||||
// result in an immediate iptables resync.
|
||||
MinSyncPeriod metav1.Duration `json:"minSyncPeriod"`
|
||||
}
|
||||
|
||||
// KubeProxyConntrackConfiguration contains conntrack settings for
|
||||
// the Kubernetes proxy server.
|
||||
type KubeProxyConntrackConfiguration struct {
|
||||
@ -189,6 +211,8 @@ type KubeProxyConfiguration struct {
|
||||
IPTables KubeProxyIPTablesConfiguration `json:"iptables"`
|
||||
// ipvs contains ipvs-related configuration options.
|
||||
IPVS KubeProxyIPVSConfiguration `json:"ipvs"`
|
||||
// nftables contains nftables-related configuration options.
|
||||
NFTables KubeProxyNFTablesConfiguration `json:"nftables"`
|
||||
// winkernel contains winkernel-related configuration options.
|
||||
Winkernel KubeProxyWinkernelConfiguration `json:"winkernel"`
|
||||
|
||||
|
@ -57,6 +57,7 @@ func (in *KubeProxyConfiguration) DeepCopyInto(out *KubeProxyConfiguration) {
|
||||
in.Logging.DeepCopyInto(&out.Logging)
|
||||
in.IPTables.DeepCopyInto(&out.IPTables)
|
||||
in.IPVS.DeepCopyInto(&out.IPVS)
|
||||
in.NFTables.DeepCopyInto(&out.NFTables)
|
||||
out.Winkernel = in.Winkernel
|
||||
out.DetectLocal = in.DetectLocal
|
||||
if in.NodePortAddresses != nil {
|
||||
@ -184,6 +185,34 @@ func (in *KubeProxyIPVSConfiguration) DeepCopy() *KubeProxyIPVSConfiguration {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubeProxyNFTablesConfiguration) DeepCopyInto(out *KubeProxyNFTablesConfiguration) {
|
||||
*out = *in
|
||||
if in.MasqueradeBit != nil {
|
||||
in, out := &in.MasqueradeBit, &out.MasqueradeBit
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.LocalhostNodePorts != nil {
|
||||
in, out := &in.LocalhostNodePorts, &out.LocalhostNodePorts
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
out.SyncPeriod = in.SyncPeriod
|
||||
out.MinSyncPeriod = in.MinSyncPeriod
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeProxyNFTablesConfiguration.
|
||||
func (in *KubeProxyNFTablesConfiguration) DeepCopy() *KubeProxyNFTablesConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KubeProxyNFTablesConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubeProxyWinkernelConfiguration) DeepCopyInto(out *KubeProxyWinkernelConfiguration) {
|
||||
*out = *in
|
||||
|
Loading…
Reference in New Issue
Block a user