mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 07:20:13 +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
|
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
|
// ValidatePodSubnetNodeMask validates that the relation between podSubnet and node-masks is correct
|
||||||
func ValidatePodSubnetNodeMask(subnetStr string, c *kubeadm.ClusterConfiguration, fldPath *field.Path) field.ErrorList {
|
func ValidatePodSubnetNodeMask(subnetStr string, c *kubeadm.ClusterConfiguration, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
@ -468,6 +487,8 @@ func ValidateNetworking(c *kubeadm.ClusterConfiguration, fldPath *field.Path) fi
|
|||||||
|
|
||||||
if len(c.Networking.ServiceSubnet) != 0 {
|
if len(c.Networking.ServiceSubnet) != 0 {
|
||||||
allErrs = append(allErrs, ValidateIPNetFromString(c.Networking.ServiceSubnet, constants.MinimumAddressesInServiceSubnet, isDualStack, field.NewPath("serviceSubnet"))...)
|
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 {
|
if len(c.Networking.PodSubnet) != 0 {
|
||||||
allErrs = append(allErrs, ValidateIPNetFromString(c.Networking.PodSubnet, constants.MinimumAddressesInPodSubnet, isDualStack, field.NewPath("podSubnet"))...)
|
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) {
|
func TestValidateHostPort(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
name string
|
name string
|
||||||
@ -521,7 +552,7 @@ func TestValidateInitConfiguration(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Networking: kubeadm.Networking{
|
Networking: kubeadm.Networking{
|
||||||
ServiceSubnet: "2001:db8::1/98",
|
ServiceSubnet: "2001:db8::1/112",
|
||||||
DNSDomain: "cluster.local",
|
DNSDomain: "cluster.local",
|
||||||
},
|
},
|
||||||
CertificatesDir: "/some/other/cert/dir",
|
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
|
// We need at least ten, because the DNS service is always at the tenth cluster clusterIP
|
||||||
MinimumAddressesInServiceSubnet = 10
|
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.
|
// 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
|
// We need at least more than services, an IPv4 /28 or IPv6 /128 subnet means 14 util addresses
|
||||||
MinimumAddressesInPodSubnet = 14
|
MinimumAddressesInPodSubnet = 14
|
||||||
|
Loading…
Reference in New Issue
Block a user