mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 15:05:27 +00:00
kubeadm validate maximum service subnet size
Validate that the maximum service subnet size doesn't exceed the limits. Co-authored-by: Arvinderpal Wander <awander@gmail.com>
This commit is contained in:
parent
8b52995d32
commit
7fc6b4157b
@ -403,6 +403,25 @@ func ValidateIPNetFromString(subnetStr string, minAddrs int64, isDualStack bool,
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateServiceSubnetSize validates that the maximum subnet size is not exceeded
|
||||
// Should be a small cidr due to how it is stored in etcd.
|
||||
// bigger cidr (specially those offered by IPv6) will add no value
|
||||
// and significantly increase snapshotting time.
|
||||
// NOTE: This is identical to validation performed in the apiserver.
|
||||
func ValidateServiceSubnetSize(subnetStr string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
// subnets were already validated
|
||||
subnets, _ := utilnet.ParseCIDRs(strings.Split(subnetStr, ","))
|
||||
for _, serviceSubnet := range subnets {
|
||||
ones, bits := serviceSubnet.Mask.Size()
|
||||
if bits-ones > constants.MaximumBitsForServiceSubnet {
|
||||
errMsg := fmt.Sprintf("specified service subnet is too large; for %d-bit addresses, the mask must be >= %d", bits, bits-constants.MaximumBitsForServiceSubnet)
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, serviceSubnet.String(), errMsg))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidatePodSubnetNodeMask validates that the relation between podSubnet and node-masks is correct
|
||||
func ValidatePodSubnetNodeMask(subnetStr string, c *kubeadm.ClusterConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
@ -468,6 +487,8 @@ func ValidateNetworking(c *kubeadm.ClusterConfiguration, fldPath *field.Path) fi
|
||||
|
||||
if len(c.Networking.ServiceSubnet) != 0 {
|
||||
allErrs = append(allErrs, ValidateIPNetFromString(c.Networking.ServiceSubnet, constants.MinimumAddressesInServiceSubnet, isDualStack, field.NewPath("serviceSubnet"))...)
|
||||
// Service subnet was already validated, we need to validate now the subnet size
|
||||
allErrs = append(allErrs, ValidateServiceSubnetSize(c.Networking.ServiceSubnet, field.NewPath("serviceSubnet"))...)
|
||||
}
|
||||
if len(c.Networking.PodSubnet) != 0 {
|
||||
allErrs = append(allErrs, ValidateIPNetFromString(c.Networking.PodSubnet, constants.MinimumAddressesInPodSubnet, isDualStack, field.NewPath("podSubnet"))...)
|
||||
|
@ -287,6 +287,37 @@ func TestValidatePodSubnetNodeMask(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateServiceSubnetSize(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
subnet string
|
||||
expected bool
|
||||
}{
|
||||
{"single IPv4, but mask too large.", "10.0.0.16/2", false},
|
||||
{"single IPv6, but mask too large.", "2001:db8::1/64", false},
|
||||
{"single IPv4 CIDR", "10.0.0.16/12", true},
|
||||
{"single IPv6 CIDR", "2001:db8::/112", true},
|
||||
// dual-stack:
|
||||
{"dual, but IPv4 mask too large.", "2001:db8::1/112,10.0.0.16/6", false},
|
||||
{"dual, but IPv6 mask too large.", "2001:db8::1/12,10.0.0.16/16", false},
|
||||
{"dual IPv4 IPv6", "10.0.0.16/12,2001:db8::/112", true},
|
||||
{"dual IPv6 IPv4", "2001:db8::/112,10.0.0.16/12", true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
|
||||
actual := ValidateServiceSubnetSize(rt.subnet, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed :\n\texpected: %t\n\t actual: %t\n\t err(s): %v\n\t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateHostPort(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
@ -521,7 +552,7 @@ func TestValidateInitConfiguration(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "2001:db8::1/98",
|
||||
ServiceSubnet: "2001:db8::1/112",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
|
@ -199,6 +199,12 @@ const (
|
||||
// We need at least ten, because the DNS service is always at the tenth cluster clusterIP
|
||||
MinimumAddressesInServiceSubnet = 10
|
||||
|
||||
// MaximumBitsForServiceSubnet defines maximum possible size of the service subnet in terms of bits.
|
||||
// For example, if the value is 20, then the largest supported service subnet is /12 for IPv4 and /108 for IPv6.
|
||||
// Note however that anything in between /108 and /112 will be clamped to /112 due to the limitations of the underlying allocation logic.
|
||||
// TODO: https://github.com/kubernetes/enhancements/pull/1881
|
||||
MaximumBitsForServiceSubnet = 20
|
||||
|
||||
// MinimumAddressesInPodSubnet defines minimum amount of pods in the cluster.
|
||||
// We need at least more than services, an IPv4 /28 or IPv6 /128 subnet means 14 util addresses
|
||||
MinimumAddressesInPodSubnet = 14
|
||||
|
Loading…
Reference in New Issue
Block a user