kubernetes 在对CRD的Scale子资源进行打补丁时出现错误(合并打补丁时为静默错误)

92vpleto  于 9个月前  发布在  Kubernetes
关注(0)|答案(5)|浏览(229)

发生了什么?
创建了一个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:

  1. apiVersion: apiextensions.k8s.io/v1
  2. kind: CustomResourceDefinition
  3. metadata:
  4. name: noxus.mygroup.example.com
  5. spec:
  6. group: mygroup.example.com
  7. names:
  8. plural: noxus
  9. singular: nonenglishnoxu
  10. shortNames:
  11. - foo
  12. - bar
  13. - abc
  14. - def
  15. kind: WishIHadChosenNoxu
  16. listKind: NoxuItemList
  17. scope: Namespaced
  18. versions:
  19. - name: v1
  20. served: true
  21. storage: true
  22. schema:
  23. openAPIV3Schema:
  24. type: object
  25. x-kubernetes-preserve-unknown-fields: true
  26. subresources:
  27. status: {}
  28. scale:
  29. specReplicasPath: .spec.replicas
  30. statusReplicasPath: .status.replicas
  31. labelSelectorPath: .status.anotherLabelSelector
  32. conversion:
  33. strategy: None

使用kubectl apply --server-side应用示例:

  1. apiVersion: mygroup.example.com/v1
  2. kind: WishIHadChosenNoxu
  3. metadata:
  4. name: foo
  5. namespace: not-the-default
  6. spec:
  7. num: 10
  8. replicas: 3

使用merge patch更改Scale子资源spec.replicas:

  1. kubectl patch foo foo --subresource='scale' --type='merge' -p '{"spec":{"replicas":3}}' --namespace="not-the-default" --field-manager="scaler"
  2. scale.autoscaling/foo patched

查看服务器记录的错误:

  1. 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的托管字段条目已被删除:

  1. kubectl get foo foo --namespace=not-the-default -o yaml --show-managed-fields
  2. apiVersion: mygroup.example.com/v1
  3. kind: WishIHadChosenNoxu
  4. metadata:
  5. creationTimestamp: "2023-03-06T20:51:08Z"
  6. generation: 2
  7. managedFields:
  8. - apiVersion: mygroup.example.com/v1
  9. fieldsType: FieldsV1
  10. fieldsV1:
  11. f:spec:
  12. .: {}
  13. f:num: {}
  14. manager: kubectl
  15. operation: Apply
  16. time: "2023-03-06T20:51:08Z"
  17. name: foo
  18. namespace: not-the-default
  19. resourceVersion: "420"
  20. uid: 59014404-4fcb-4b12-a7f1-513c875de7f2
  21. spec:
  22. num: 10
  23. replicas: 5

如果我不通过子资源更改副本,我的托管字段将按预期更新:

  1. kubectl patch foo foo --type='merge' -p '{"spec":{"replicas":6}}' --namespace="not-the-default" --field-manager="scaler"
  2. wishihadchosennoxu.mygroup.example.com/foo patched
  3. ~/Desktop [⌛ 178ms]
  4. kubectl get foo foo --namespace=not-the-default -o yaml --show-managed-fields
  5. apiVersion: mygroup.example.com/v1
  6. kind: WishIHadChosenNoxu
  7. metadata:
  8. creationTimestamp: "2023-03-06T20:51:08Z"
  9. generation: 3
  10. managedFields:
  11. - apiVersion: mygroup.example.com/v1
  12. fieldsType: FieldsV1
  13. fieldsV1:
  14. f:spec:
  15. .: {}
  16. f:num: {}
  17. manager: kubectl
  18. operation: Apply
  19. time: "2023-03-06T20:51:08Z"
  20. - apiVersion: mygroup.example.com/v1
  21. fieldsType: FieldsV1
  22. fieldsV1:
  23. f:spec:
  24. f:replicas: {}
  25. manager: scaler
  26. operation: Update
  27. time: "2023-03-06T20:56:21Z"
  28. name: foo
  29. namespace: not-the-default
  30. resourceVersion: "483"
  31. uid: 59014404-4fcb-4b12-a7f1-513c875de7f2
  32. spec:
  33. num: 10
  34. 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()) |

dy1byipe

dy1byipe1#

我不确定我完全理解这个。如果我使用一个普通的apiserver,它会无法应用缩放对象吗?测试过去通过是因为它没有OpenAPI?但是现在既然OpenAPI无处不在,它开始失败了吗?是这样的吗?

7bsow1i6

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服务器

3pvhb19x

3pvhb19x3#

/triage accepted

v8wbuo2f

v8wbuo2f4#

这个问题已经超过一年没有更新了,应该重新进行优先级评估。
你可以:

  • 确认这个问题仍然与 /triage accepted (仅组织成员)相关
  • /close 关闭这个问题

有关优先级评估过程的更多详细信息,请参见 https://www.kubernetes.dev/docs/guide/issue-triage/
已接受移除优先级评估

v6ylcynt

v6ylcynt5#

/triage accepted

相关问题