发生了什么?
创建了一个CRD,并尝试通过patch子资源而不是通过顶层资源来更改其/scale
子资源。
当合并应用/scale时,apiserver后端会有一个可怕的日志记录错误,但对象的托管字段已更新为不正确的值。
当应用/scale patch时,会向客户端返回一个错误:failed to create typed patch object (/; autoscaling/v1, Kind=Scale): no corresponding type for autoscaling/v1, Kind=Scale
预期会发生什么?
成功地应用补丁,并为拥有replicas字段的"scaler"字段管理器添加新的托管字段条目。
我们如何尽可能精确地重现它?
使用kubectl apply --server-side
应用CRD:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: noxus.mygroup.example.com
spec:
group: mygroup.example.com
names:
plural: noxus
singular: nonenglishnoxu
shortNames:
- foo
- bar
- abc
- def
kind: WishIHadChosenNoxu
listKind: NoxuItemList
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
x-kubernetes-preserve-unknown-fields: true
subresources:
status: {}
scale:
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
labelSelectorPath: .status.anotherLabelSelector
conversion:
strategy: None
使用kubectl apply --server-side
应用示例:
apiVersion: mygroup.example.com/v1
kind: WishIHadChosenNoxu
metadata:
name: foo
namespace: not-the-default
spec:
num: 10
replicas: 3
使用merge patch更改Scale子资源spec.replicas:
❯ kubectl patch foo foo --subresource='scale' --type='merge' -p '{"spec":{"replicas":3}}' --namespace="not-the-default" --field-manager="scaler"
scale.autoscaling/foo patched
查看服务器记录的错误:
E0306 12:51:16.136193 31856 fieldmanager.go:152] "[SHOULD NOT HAPPEN] failed to update managedFields" err="failed to convert new object (not-the-default/foo; autoscaling/v1, Kind=Scale) to smd typed: no corresponding type for autoscaling/v1, Kind=Scale" versionKind="autoscaling/v1, Kind=Scale" namespace="not-the-default" name="foo"
同时观察到,尽管字段已更新,但replicas的托管字段条目已被删除:
❯ kubectl get foo foo --namespace=not-the-default -o yaml --show-managed-fields
apiVersion: mygroup.example.com/v1
kind: WishIHadChosenNoxu
metadata:
creationTimestamp: "2023-03-06T20:51:08Z"
generation: 2
managedFields:
- apiVersion: mygroup.example.com/v1
fieldsType: FieldsV1
fieldsV1:
f:spec:
.: {}
f:num: {}
manager: kubectl
operation: Apply
time: "2023-03-06T20:51:08Z"
name: foo
namespace: not-the-default
resourceVersion: "420"
uid: 59014404-4fcb-4b12-a7f1-513c875de7f2
spec:
num: 10
replicas: 5
如果我不通过子资源更改副本,我的托管字段将按预期更新:
❯ kubectl patch foo foo --type='merge' -p '{"spec":{"replicas":6}}' --namespace="not-the-default" --field-manager="scaler"
wishihadchosennoxu.mygroup.example.com/foo patched
~/Desktop [⌛ 178ms]
❯ kubectl get foo foo --namespace=not-the-default -o yaml --show-managed-fields
apiVersion: mygroup.example.com/v1
kind: WishIHadChosenNoxu
metadata:
creationTimestamp: "2023-03-06T20:51:08Z"
generation: 3
managedFields:
- apiVersion: mygroup.example.com/v1
fieldsType: FieldsV1
fieldsV1:
f:spec:
.: {}
f:num: {}
manager: kubectl
operation: Apply
time: "2023-03-06T20:51:08Z"
- apiVersion: mygroup.example.com/v1
fieldsType: FieldsV1
fieldsV1:
f:spec:
f:replicas: {}
manager: scaler
operation: Update
time: "2023-03-06T20:56:21Z"
name: foo
namespace: not-the-default
resourceVersion: "483"
uid: 59014404-4fcb-4b12-a7f1-513c875de7f2
spec:
num: 10
replicas: 6
使用ApplyPatchType
控制器通过更新状态也会产生相同的行为,只是与MergePatchType
不同,它不会像它那样静默失败,而是向客户端返回错误:failed to create typed patch object (/; autoscaling/v1, Kind=Scale): no corresponding type for autoscaling/v1, Kind=Scale
我们需要了解其他信息吗?
对于这种情况有一个集成测试,但由于它不提供任何openapi定义,因此在导致SSA对所有类型使用推断类型转换器的配置下运行测试apiserver。在测试中,Scale
模型从未被查找。由于kube-apiserver提供了open api定义,因此强制执行查找并失败。
kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go
第386行 964529b | funcTestApplyScaleSubresource(t*testing.T) { |
我认为查找失败是因为Scale
类型是由构建器注入到CRD openapi规范中的,而没有它们的GVK。它们没有GVK,因为用于注入CRD类型的定义名称器在初始化为空方案时使用空方案初始化。该方案用于将具有GVK的扩展添加到定义中:
kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/openapi/builder/builder.go
第471行 68eea24 | namer=openapi.NewDefinitionNamer(runtime.NewScheme()) |
5条答案
按热度按时间dy1byipe1#
我不确定我完全理解这个。如果我使用一个普通的apiserver,它会无法应用缩放对象吗?测试过去通过是因为它没有OpenAPI?但是现在既然OpenAPI无处不在,它开始失败了吗?是这样的吗?
7bsow1i62#
这个测试曾经通过,因为它没有OpenAPI?但现在既然到处都有openapi,它就开始失败了?
不,测试仍然通过。我相信这是一个长期存在的bug,不是由最近的任何更改引起的。测试通过了,但它本不应该通过。它之所以通过,是因为测试环境根本不提供openapi模型,所以使用了SSA推断类型转换器:
kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go
77fad93中的第683行到第689行
| vartypeConverter fieldmanager.TypeConverter=fieldmanager.NewDeducedTypeConverter() |
| iflen(openAPIModels) >0 { |
| typeConverter, err=fieldmanager.NewTypeConverter(openAPIModels, crd.Spec.PreserveUnknownFields) |
| iferr!=nil { |
| returnnil, err |
| } |
| } |
对于kube-apiserver,提供了openAPIModels,因此构造了类型转换器。但是类型转换器无法正确索引autoscaling/v1.Scale的定义。如果我使用一个普通的apiserver,它会在应用scale对象时失败吗?
是的,这会影响通过
/scale
子资源修补CRD示例的普通API服务器3pvhb19x3#
/triage accepted
v8wbuo2f4#
这个问题已经超过一年没有更新了,应该重新进行优先级评估。
你可以:
/triage accepted
(仅组织成员)相关/close
关闭这个问题有关优先级评估过程的更多详细信息,请参见 https://www.kubernetes.dev/docs/guide/issue-triage/
已接受移除优先级评估
v6ylcynt5#
/triage accepted