Code change:
"spec.hostPID", }, }, <del> { name: "reseting defaults for pre-v1.1 mirror pods", input: ` { "kind":"Pod", "apiVersion":"v1", "metadata":{ "name":"my-pod-name", "namespace":"my-pod-namespace", "annotations": { "kubernetes.io/config.mirror": "mirror" } }, "spec": { "containers":[{ "name":"a", "image":"my-container-image", "resources": { "limits": { "cpu": "100m" } } }] } } `, absentKeys: []string{ "spec.terminationGracePeriodSeconds", "spec.containers[0].resources.requests", }, }, { name: "preserving defaults for v1.1+ mirror pods", input: ` { "kind":"Pod", "apiVersion":"v1", "metadata":{ "name":"my-pod-name", "namespace":"my-pod-namespace", "annotations": { "kubernetes.io/config.mirror": "cbe924f710c7e26f7693d6a341bcfad0" } }, "spec": { "containers":[{ "name":"a", "image":"my-container-image", "resources": { "limits": { "cpu": "100m" } } }] } } `, expectedKeys: map[string]string{ "spec.terminationGracePeriodSeconds":    "30", "spec.containers[0].resources.requests": "map[cpu:100m]", }, }, </del> } validator := func(obj runtime.Object) field.ErrorList {

Related discussion:
text: Since the conversion stack does the defaulting at the end and runs in every component, and scheduler, node-controller, etc all consume api.Pod objects (instead of v1.Pod objects), they will have a view of the object with the fields defaulted. The conversion based fix essentially retains the defaulting in *api.Pod objects, but undoes it in any serialized representation of the object. Over the wire the defaulting will not be baked in to the object. Older clients that have not been recompiled (including these kubelets) would see a version of the object without the fields being defaulted.
Defaulting is run first:
Oh, you're right, I somehow had that backwards in my head. Sorry, everyone. I think that tilts me back in favor of . This means that defaulting is part of the versioned structs and therefore changing the defaulting is an API breaking change, which we claimed we wouldn't do. Can we change our minds about the defaulting? How about moving this particular defaulting into conversion functions, which is the intended way of doing something like this?
In , we only reset the defaults when converting api.Pod to v1.Pod. Shouldn't all components still see the defaulting values? Agreed that this is an API breaking change. Perhaps we should not change the defaults at all? mentioned in that scheduler already deals with empty requests. It's true in , but seems untrue in . Maybe this should be fixed. As for , we can also ask kubelet to apply a default value if we truly on to have the 30 second dfault.
resources.requests and terminationGracePeriodSeconds are effectively newly fields, so setting defaults is not a breaking change for most clients. If Kubelet were comparing the pre-decoded pods returned by apisever, it would barf on every new field we've . It's an accident of the implementation that it broke on exactly these fields.
Actually, neither priorities nor predicates takes values from limits any longer. That code is rely on the defaulting pass to copy limits to requests in the case that the requests field is absent. We would need to change that, yes, if we were to not set requests for the 1.0 mirror pods.
This Kubelet behavior was known to be broken back in May: What we're trying to do now is figure out a workaround for this broken behavior.