mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-26 12:46:06 +00:00
dual stack services (#91824)
* api: structure change * api: defaulting, conversion, and validation * [FIX] validation: auto remove second ip/family when service changes to SingleStack * [FIX] api: defaulting, conversion, and validation * api-server: clusterIPs alloc, printers, storage and strategy * [FIX] clusterIPs default on read * alloc: auto remove second ip/family when service changes to SingleStack * api-server: repair loop handling for clusterIPs * api-server: force kubernetes default service into single stack * api-server: tie dualstack feature flag with endpoint feature flag * controller-manager: feature flag, endpoint, and endpointSlice controllers handling multi family service * [FIX] controller-manager: feature flag, endpoint, and endpointSlicecontrollers handling multi family service * kube-proxy: feature-flag, utils, proxier, and meta proxier * [FIX] kubeproxy: call both proxier at the same time * kubenet: remove forced pod IP sorting * kubectl: modify describe to include ClusterIPs, IPFamilies, and IPFamilyPolicy * e2e: fix tests that depends on IPFamily field AND add dual stack tests * e2e: fix expected error message for ClusterIP immutability * add integration tests for dualstack the third phase of dual stack is a very complex change in the API, basically it introduces Dual Stack services. Main changes are: - It pluralizes the Service IPFamily field to IPFamilies, and removes the singular field. - It introduces a new field IPFamilyPolicyType that can take 3 values to express the "dual-stack(mad)ness" of the cluster: SingleStack, PreferDualStack and RequireDualStack - It pluralizes ClusterIP to ClusterIPs. The goal is to add coverage to the services API operations, taking into account the 6 different modes a cluster can have: - single stack: IP4 or IPv6 (as of today) - dual stack: IPv4 only, IPv6 only, IPv4 - IPv6, IPv6 - IPv4 * [FIX] add integration tests for dualstack * generated data * generated files Co-authored-by: Antonio Ojea <aojea@redhat.com>
This commit is contained in:
committed by
GitHub
parent
d0e06cf3e0
commit
6675eba3ef
@@ -75,10 +75,18 @@ func Validate(config *kubeproxyconfig.KubeProxyConfiguration) field.ErrorList {
|
||||
}
|
||||
allErrs = append(allErrs, validateHostPort(config.MetricsBindAddress, newPath.Child("MetricsBindAddress"))...)
|
||||
|
||||
dualStackEnabled := effectiveFeatures.Enabled(kubefeatures.IPv6DualStack)
|
||||
endpointSliceEnabled := effectiveFeatures.Enabled(kubefeatures.EndpointSlice)
|
||||
|
||||
// dual stack has strong dependency on endpoint slice since
|
||||
// endpoint slice controller is the only capabable of producing
|
||||
// slices for *all* clusterIPs
|
||||
if dualStackEnabled && !endpointSliceEnabled {
|
||||
allErrs = append(allErrs, field.Invalid(newPath.Child("FeatureGates"), config.FeatureGates, "EndpointSlice feature flag must be turned on when turning on DualStack"))
|
||||
}
|
||||
|
||||
if config.ClusterCIDR != "" {
|
||||
cidrs := strings.Split(config.ClusterCIDR, ",")
|
||||
dualStackEnabled := effectiveFeatures.Enabled(kubefeatures.IPv6DualStack)
|
||||
|
||||
switch {
|
||||
// if DualStack only valid one cidr or two cidrs with one of each IP family
|
||||
case dualStackEnabled && len(cidrs) > 2:
|
||||
|
@@ -124,7 +124,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
|
||||
BindAddress: "10.10.12.11",
|
||||
HealthzBindAddress: "0.0.0.0:12345",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": true},
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": true, "EndpointSlice": true},
|
||||
ClusterCIDR: "192.168.59.0/24",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
@@ -290,7 +290,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
|
||||
HealthzBindAddress: "0.0.0.0:12345",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
// DualStack ClusterCIDR without feature flag enabled
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": false},
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": false, "EndpointSlice": false},
|
||||
ClusterCIDR: "192.168.59.0/24,fd00:192:168::/64",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
@@ -308,13 +308,38 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
|
||||
},
|
||||
msg: "only one CIDR allowed (e.g. 10.100.0.0/16 or fde4:8dba:82e1::/48)",
|
||||
},
|
||||
{
|
||||
config: kubeproxyconfig.KubeProxyConfiguration{
|
||||
BindAddress: "10.10.12.11",
|
||||
HealthzBindAddress: "0.0.0.0:12345",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
// DualStack ClusterCIDR with feature flag enabled but EndpointSlice is not enabled
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": true, "EndpointSlice": false},
|
||||
ClusterCIDR: "192.168.59.0/24,fd00:192:168::/64",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||
MasqueradeAll: true,
|
||||
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||
},
|
||||
Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{
|
||||
MaxPerCore: pointer.Int32Ptr(1),
|
||||
Min: pointer.Int32Ptr(1),
|
||||
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
},
|
||||
msg: "EndpointSlice feature flag must be turned on",
|
||||
},
|
||||
|
||||
{
|
||||
config: kubeproxyconfig.KubeProxyConfiguration{
|
||||
BindAddress: "10.10.12.11",
|
||||
HealthzBindAddress: "0.0.0.0:12345",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
// DualStack with multiple CIDRs but only one IP family
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": true},
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": true, "EndpointSlice": true},
|
||||
ClusterCIDR: "192.168.59.0/24,10.0.0.0/16",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
@@ -338,7 +363,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
|
||||
HealthzBindAddress: "0.0.0.0:12345",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
// DualStack with an invalid subnet
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": true},
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": true, "EndpointSlice": true},
|
||||
ClusterCIDR: "192.168.59.0/24,fd00:192:168::/64,a.b.c.d/f",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
@@ -361,7 +386,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
|
||||
BindAddress: "10.10.12.11",
|
||||
HealthzBindAddress: "0.0.0.0:12345",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": true},
|
||||
FeatureGates: map[string]bool{"IPv6DualStack": true, "EndpointSlice": true},
|
||||
ClusterCIDR: "192.168.59.0/24,fd00:192:168::/64,10.0.0.0/16",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
|
Reference in New Issue
Block a user