mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-05 15:37:24 +00:00
Promote sysctl annotations to API fields
This commit is contained in:
@@ -129,23 +129,6 @@ func ValidatePodSpecificAnnotations(annotations map[string]string, spec *core.Po
|
||||
allErrs = append(allErrs, ValidateSeccompPodAnnotations(annotations, fldPath)...)
|
||||
allErrs = append(allErrs, ValidateAppArmorPodAnnotations(annotations, spec, fldPath)...)
|
||||
|
||||
sysctls, err := helper.SysctlsFromPodAnnotation(annotations[core.SysctlsPodAnnotationKey])
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Key(core.SysctlsPodAnnotationKey), annotations[core.SysctlsPodAnnotationKey], err.Error()))
|
||||
} else {
|
||||
allErrs = append(allErrs, validateSysctls(sysctls, fldPath.Key(core.SysctlsPodAnnotationKey))...)
|
||||
}
|
||||
unsafeSysctls, err := helper.SysctlsFromPodAnnotation(annotations[core.UnsafeSysctlsPodAnnotationKey])
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Key(core.UnsafeSysctlsPodAnnotationKey), annotations[core.UnsafeSysctlsPodAnnotationKey], err.Error()))
|
||||
} else {
|
||||
allErrs = append(allErrs, validateSysctls(unsafeSysctls, fldPath.Key(core.UnsafeSysctlsPodAnnotationKey))...)
|
||||
}
|
||||
inBoth := sysctlIntersection(sysctls, unsafeSysctls)
|
||||
if len(inBoth) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Key(core.UnsafeSysctlsPodAnnotationKey), strings.Join(inBoth, ", "), "can not be safe and unsafe"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
@@ -3364,12 +3347,16 @@ func IsValidSysctlName(name string) bool {
|
||||
|
||||
func validateSysctls(sysctls []core.Sysctl, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
names := make(map[string]struct{})
|
||||
for i, s := range sysctls {
|
||||
if len(s.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("name"), ""))
|
||||
} else if !IsValidSysctlName(s.Name) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("name"), s.Name, fmt.Sprintf("must have at most %d characters and match regex %s", SysctlMaxLength, SysctlFmt)))
|
||||
} else if _, ok := names[s.Name]; ok {
|
||||
allErrs = append(allErrs, field.Duplicate(fldPath.Index(i).Child("name"), s.Name))
|
||||
}
|
||||
names[s.Name] = struct{}{}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
@@ -3408,6 +3395,10 @@ func ValidatePodSecurityContext(securityContext *core.PodSecurityContext, spec *
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("shareProcessNamespace"), *securityContext.ShareProcessNamespace, "ShareProcessNamespace and HostPID cannot both be enabled"))
|
||||
}
|
||||
}
|
||||
|
||||
if len(securityContext.Sysctls) != 0 {
|
||||
allErrs = append(allErrs, validateSysctls(securityContext.Sysctls, fldPath.Child("sysctls"))...)
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
@@ -5279,20 +5270,6 @@ func ValidateLoadBalancerStatus(status *core.LoadBalancerStatus, fldPath *field.
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func sysctlIntersection(a []core.Sysctl, b []core.Sysctl) []string {
|
||||
lookup := make(map[string]struct{}, len(a))
|
||||
result := []string{}
|
||||
for i := range a {
|
||||
lookup[a[i].Name] = struct{}{}
|
||||
}
|
||||
for i := range b {
|
||||
if _, found := lookup[b[i].Name]; found {
|
||||
result = append(result, b[i].Name)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// validateVolumeNodeAffinity tests that the PersistentVolume.NodeAffinity has valid data
|
||||
// returns:
|
||||
// - true if volumeNodeAffinity is set
|
||||
|
||||
@@ -6778,12 +6778,28 @@ func TestValidatePod(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "123",
|
||||
Namespace: "ns",
|
||||
Annotations: map[string]string{
|
||||
core.SysctlsPodAnnotationKey: "kernel.shmmni=32768,kernel.shmmax=1000000000",
|
||||
core.UnsafeSysctlsPodAnnotationKey: "knet.ipv4.route.min_pmtu=1000",
|
||||
},
|
||||
Spec: core.PodSpec{
|
||||
Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
||||
RestartPolicy: core.RestartPolicyAlways,
|
||||
DNSPolicy: core.DNSClusterFirst,
|
||||
SecurityContext: &core.PodSecurityContext{
|
||||
Sysctls: []core.Sysctl{
|
||||
{
|
||||
Name: "kernel.shmmni",
|
||||
Value: "32768",
|
||||
},
|
||||
{
|
||||
Name: "kernel.shmmax",
|
||||
Value: "1000000000",
|
||||
},
|
||||
{
|
||||
Name: "knet.ipv4.route.min_pmtu",
|
||||
Value: "1000",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Spec: validPodSpec(nil),
|
||||
},
|
||||
{ // valid extended resources for init container
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "valid-extended", Namespace: "ns"},
|
||||
@@ -7464,59 +7480,6 @@ func TestValidatePod(t *testing.T) {
|
||||
Spec: validPodSpec(nil),
|
||||
},
|
||||
},
|
||||
"invalid sysctl annotation": {
|
||||
expectedError: "metadata.annotations[security.alpha.kubernetes.io/sysctls]",
|
||||
spec: core.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "123",
|
||||
Namespace: "ns",
|
||||
Annotations: map[string]string{
|
||||
core.SysctlsPodAnnotationKey: "foo:",
|
||||
},
|
||||
},
|
||||
Spec: validPodSpec(nil),
|
||||
},
|
||||
},
|
||||
"invalid comma-separated sysctl annotation": {
|
||||
expectedError: "not of the format sysctl_name=value",
|
||||
spec: core.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "123",
|
||||
Namespace: "ns",
|
||||
Annotations: map[string]string{
|
||||
core.SysctlsPodAnnotationKey: "kernel.msgmax,",
|
||||
},
|
||||
},
|
||||
Spec: validPodSpec(nil),
|
||||
},
|
||||
},
|
||||
"invalid unsafe sysctl annotation": {
|
||||
expectedError: "metadata.annotations[security.alpha.kubernetes.io/sysctls]",
|
||||
spec: core.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "123",
|
||||
Namespace: "ns",
|
||||
Annotations: map[string]string{
|
||||
core.SysctlsPodAnnotationKey: "foo:",
|
||||
},
|
||||
},
|
||||
Spec: validPodSpec(nil),
|
||||
},
|
||||
},
|
||||
"intersecting safe sysctls and unsafe sysctls annotations": {
|
||||
expectedError: "can not be safe and unsafe",
|
||||
spec: core.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "123",
|
||||
Namespace: "ns",
|
||||
Annotations: map[string]string{
|
||||
core.SysctlsPodAnnotationKey: "kernel.shmmax=10000000",
|
||||
core.UnsafeSysctlsPodAnnotationKey: "kernel.shmmax=10000000",
|
||||
},
|
||||
},
|
||||
Spec: validPodSpec(nil),
|
||||
},
|
||||
},
|
||||
"invalid extended resource requirement: request must be == limit": {
|
||||
expectedError: "must be equal to example.com/a",
|
||||
spec: core.Pod{
|
||||
@@ -12805,6 +12768,11 @@ func TestValidateSysctls(t *testing.T) {
|
||||
"_invalid",
|
||||
}
|
||||
|
||||
duplicates := []string{
|
||||
"kernel.shmmax",
|
||||
"kernel.shmmax",
|
||||
}
|
||||
|
||||
sysctls := make([]core.Sysctl, len(valid))
|
||||
for i, sysctl := range valid {
|
||||
sysctls[i].Name = sysctl
|
||||
@@ -12829,6 +12797,17 @@ func TestValidateSysctls(t *testing.T) {
|
||||
t.Errorf("unexpected errors: expected=%q, got=%q", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
sysctls = make([]core.Sysctl, len(duplicates))
|
||||
for i, sysctl := range duplicates {
|
||||
sysctls[i].Name = sysctl
|
||||
}
|
||||
errs = validateSysctls(sysctls, field.NewPath("foo"))
|
||||
if len(errs) != 1 {
|
||||
t.Errorf("unexpected validation errors: %v", errs)
|
||||
} else if errs[0].Type != field.ErrorTypeDuplicate {
|
||||
t.Errorf("expected error type %v, got %v", field.ErrorTypeDuplicate, errs[0].Type)
|
||||
}
|
||||
}
|
||||
|
||||
func newNodeNameEndpoint(nodeName string) *core.Endpoints {
|
||||
|
||||
Reference in New Issue
Block a user