发生了什么?
我创建了两个具有不同范围的配额,一个是终止范围,另一个是非终止范围。我创建了一个属于非终止范围的pod,然后更新了pod的spec.activeDeadlineSeconds为5,pod应该属于终止范围。但是配额没有更新。
你期望会发生什么?
配额范围可以处理目标对象更新时的从一个范围到另一个范围的过渡情况。
我们如何尽可能精确地重现它?
- 创建2个配额。
apiVersion: v1
kind: ResourceQuota
metadata:
name: terminating
spec:
hard:
count/pods: "1"
scopes:
- Terminating
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: not-terminating
spec:
hard:
count/pods: "1"
scopes:
- NotTerminating
- 创建一个属于非终止范围的pod。
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test
image: ubuntu
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
- 更新pod的spec.activeDeadlineSeconds为5。pod应该属于终止范围。
kubectl patch pod test-pod -p '{"spec":{"activeDeadlineSeconds":5}}'
- 获取所有配额,你会看到终止配额没有更新。
kubectl get quota -A
我们需要知道其他任何事情吗?
根本原因是,当pod被更新时,计算delta基于旧对象和新对象,它不考虑更新对象所属的范围变化,因此最终的delta不正确。在这种情况下,最终的delta为零,因此终止配额没有更新。
相关k/k代码:
kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/resourcequota/controller.go
第495行到第558行 5a31a46
| | deltaUsage, err:=evaluator.Usage(inputObject) |
| | iferr!=nil { |
| | returnquotas, err |
| | } |
| | |
| | // ensure that usage for input object is never negative (this would mean a resource made a negative resource requirement) |
| | ifnegativeUsage:=quota.IsNegative(deltaUsage); len(negativeUsage) >0 { |
| | returnnil, admission.NewForbidden(a, fmt.Errorf("quota usage is negative for resource(s): %s", prettyPrintResourceNames(negativeUsage))) |
| | } |
| | |
| | ifadmission.Update==a.GetOperation() { |
| | prevItem:=a.GetOldObject() |
| | ifprevItem==nil { |
| | returnnil, admission.NewForbidden(a, fmt.Errorf("unable to get previous usage since prior version of object was not found")) |
| | } |
| | |
| | // if we can definitively determine that this is not a case of "create on update", |
| | // then charge based on the delta. Otherwise, bill the maximum |
| | metadata, err:=meta.Accessor(prevItem) |
| | iferr==nil&&len(metadata.GetResourceVersion()) >0 { |
| | prevUsage, innerErr:=evaluator.Usage(prevItem) |
| | ifinnerErr!=nil { |
| | returnquotas, innerErr |
| | } |
| | deltaUsage=quota.SubtractWithNonNegativeResult(deltaUsage, prevUsage) |
| | } |
| | } |
| | |
| | // ignore items in deltaUsage with zero usage |
| | deltaUsage=quota.RemoveZeros(deltaUsage) |
| | // if there is no remaining non-zero usage, short-circuit and return |
| | iflen(deltaUsage) ==0 { |
| | returnquotas, nil |
| | } |
| | |
| | // verify that for every resource that had limited by default consumption // enabled that there was a corresponding quota that covered its use. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the request. // if not, we reject the请求。 // if not, we reject the request。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the请求。 // if not, we reject the request。 // if not, we reject the request。 // ifnotexists := quotav1beta1helpers.IsQuotaNotFoundError(err) || apierrors.IsNotFound(err) || apierrors.IsInvalid(err) || apierrors.IsAlreadyExists(err) || apierrors.IsForbidden(err) || apierrors.IsMethodNotAllowed(err) || apierrors.IsInvalid(err) || apierrors.IsTooManyRequests(err) || apierrors.IsInternalError(err) || apierrors.IsUnavailable(err) || apierrors.IsServerTimeout(err) || apierrors.IsClientTimeout(err) || apierrors.IsTooManyHeaders(err) || apierrors.IsGone(err) || apierrors.IsConflict(err) || apierrors.IsPreconditionFailed(err) || apierrors.IsTooManyRequestBodyBytes(err) || apierrors.IsServiceUnavailable(err) || apierrors.IsInternalServerError(err) || apierrors.IsNotImplemented(err) || apierrors.IsBadGateway(err) || apierrors.IsDomainLimitExceeded(err) || apierrors.IsTooManyCookies(err) || apierrors.IsTooManyFiles(err) || apierrors.IsTooManyPostRequestsInBatch(err) || apierrors.IsTooManyUserAgentsInBatch(err) || apierrors.IsInvalidContentTypeOptions(err) || apierrors
2条答案
按热度按时间mfuanj7w1#
/sig api-machinery
/assign @liggitt@deads2k@derekwaynecarr
zwghvu4y2#
/triage accepted