Merge pull request #115314 from UiPath/fix-quota-monitoring

kubelet: Fix fs quota monitoring on volumes
This commit is contained in:
Kubernetes Prow Robot 2023-03-09 22:42:39 -08:00 committed by GitHub
commit ba7f4e2fee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 18 deletions

View File

@ -301,12 +301,6 @@ func (ed *emptyDir) assignQuota(dir string, mounterSize *resource.Quantity) erro
if err != nil { if err != nil {
klog.V(3).Infof("Unable to check for quota support on %s: %s", dir, err.Error()) klog.V(3).Infof("Unable to check for quota support on %s: %s", dir, err.Error())
} else if hasQuotas { } else if hasQuotas {
_, err := fsquota.GetQuotaOnDir(ed.mounter, dir)
if err != nil {
klog.V(4).Infof("Attempt to check quota on dir %s failed: %v", dir, err)
// this is not a fatal error so return nil
return nil
}
klog.V(4).Infof("emptydir trying to assign quota %v on %s", mounterSize, dir) klog.V(4).Infof("emptydir trying to assign quota %v on %s", mounterSize, dir)
if err := fsquota.AssignQuota(ed.mounter, dir, ed.pod.UID, mounterSize); err != nil { if err := fsquota.AssignQuota(ed.mounter, dir, ed.pod.UID, mounterSize); err != nil {
klog.V(3).Infof("Set quota on %s failed %s", dir, err.Error()) klog.V(3).Infof("Set quota on %s failed %s", dir, err.Error())

View File

@ -190,13 +190,13 @@ func addDirToProject(path string, id common.QuotaID, list *projectsList) (common
idMap := make(map[common.QuotaID]bool) idMap := make(map[common.QuotaID]bool)
for _, project := range list.projects { for _, project := range list.projects {
if project.data == path { if project.data == path {
if id != project.id { if id != common.BadQuotaID && id != project.id {
return common.BadQuotaID, false, fmt.Errorf("attempt to reassign project ID for %s", path) return common.BadQuotaID, false, fmt.Errorf("attempt to reassign project ID for %s", path)
} }
// Trying to reassign a directory to the project it's // Trying to reassign a directory to the project it's
// already in. Maybe this should be an error, but for // already in. Maybe this should be an error, but for
// now treat it as an idempotent operation // now treat it as an idempotent operation
return id, false, nil return project.id, false, nil
} }
idMap[project.id] = true idMap[project.id] = true
} }

View File

@ -35,6 +35,9 @@ import (
"k8s.io/kubernetes/pkg/volume/util/fsquota/common" "k8s.io/kubernetes/pkg/volume/util/fsquota/common"
) )
// Pod -> External Pod UID
var podUidMap = make(map[types.UID]types.UID)
// Pod -> ID // Pod -> ID
var podQuotaMap = make(map[types.UID]common.QuotaID) var podQuotaMap = make(map[types.UID]common.QuotaID)
@ -314,20 +317,32 @@ func AssignQuota(m mount.Interface, path string, poduid types.UID, bytes *resour
} }
quotaLock.Lock() quotaLock.Lock()
defer quotaLock.Unlock() defer quotaLock.Unlock()
// Current policy is to set individual quotas on each volumes. // Current policy is to set individual quotas on each volume,
// for each new volume we generate a random UUID and we use that as
// the internal pod uid.
// From fsquota point of view each volume is attached to a
// single unique pod.
// If we decide later that we want to assign one quota for all // If we decide later that we want to assign one quota for all
// volumes in a pod, we can simply remove this line of code. // volumes in a pod, we can simply use poduid parameter directly
// If and when we decide permanently that we're going to adopt // If and when we decide permanently that we're going to adopt
// one quota per volume, we can rip all of the pod code out. // one quota per volume, we can rip all of the pod code out.
volumeuid := types.UID(uuid.NewUUID()) externalPodUid := poduid
if pod, ok := dirPodMap[path]; ok && pod != volumeuid { internalPodUid, ok := dirPodMap[path]
return fmt.Errorf("requesting quota on existing directory %s but different pod %s %s", path, pod, volumeuid) if ok {
if podUidMap[internalPodUid] != externalPodUid {
return fmt.Errorf("requesting quota on existing directory %s but different pod %s %s", path, podUidMap[internalPodUid], externalPodUid)
} }
oid, ok := podQuotaMap[volumeuid] } else {
internalPodUid = types.UID(uuid.NewUUID())
}
oid, ok := podQuotaMap[internalPodUid]
if ok { if ok {
if quotaSizeMap[oid] != ibytes { if quotaSizeMap[oid] != ibytes {
return fmt.Errorf("requesting quota of different size: old %v new %v", quotaSizeMap[oid], bytes) return fmt.Errorf("requesting quota of different size: old %v new %v", quotaSizeMap[oid], bytes)
} }
if _, ok := dirPodMap[path]; ok {
return nil
}
} else { } else {
oid = common.BadQuotaID oid = common.BadQuotaID
} }
@ -342,12 +357,13 @@ func AssignQuota(m mount.Interface, path string, poduid types.UID, bytes *resour
ibytes = -1 ibytes = -1
} }
if err = setQuotaOnDir(path, id, ibytes); err == nil { if err = setQuotaOnDir(path, id, ibytes); err == nil {
quotaPodMap[id] = volumeuid quotaPodMap[id] = internalPodUid
quotaSizeMap[id] = ibytes quotaSizeMap[id] = ibytes
podQuotaMap[volumeuid] = id podQuotaMap[internalPodUid] = id
dirQuotaMap[path] = id dirQuotaMap[path] = id
dirPodMap[path] = volumeuid dirPodMap[path] = internalPodUid
podDirCountMap[volumeuid]++ podUidMap[internalPodUid] = externalPodUid
podDirCountMap[internalPodUid]++
klog.V(4).Infof("Assigning quota ID %d (%d) to %s", id, ibytes, path) klog.V(4).Infof("Assigning quota ID %d (%d) to %s", id, ibytes, path)
return nil return nil
} }
@ -436,6 +452,7 @@ func ClearQuota(m mount.Interface, path string) error {
delete(quotaPodMap, podQuotaMap[poduid]) delete(quotaPodMap, podQuotaMap[poduid])
delete(podDirCountMap, poduid) delete(podDirCountMap, poduid)
delete(podQuotaMap, poduid) delete(podQuotaMap, poduid)
delete(podUidMap, poduid)
} else { } else {
err = removeProjectID(path, projid) err = removeProjectID(path, projid)
podDirCountMap[poduid]-- podDirCountMap[poduid]--