Merge pull request #78593 from RobertKrawitz/ephemeral-storage-quota-cleanup

Ephemeral storage quota cleanup
This commit is contained in:
Kubernetes Prow Robot 2019-06-14 05:33:18 -07:00 committed by GitHub
commit 518f16636f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 44 additions and 40 deletions

View File

@ -20,7 +20,7 @@ go_library(
"//pkg/util/mount:go_default_library", "//pkg/util/mount:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//pkg/volume/util/quota:go_default_library", "//pkg/volume/util/fsquota:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

View File

@ -30,7 +30,7 @@ import (
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
volumeutil "k8s.io/kubernetes/pkg/volume/util" volumeutil "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/quota" "k8s.io/kubernetes/pkg/volume/util/fsquota"
utilstrings "k8s.io/utils/strings" utilstrings "k8s.io/utils/strings"
) )
@ -241,12 +241,12 @@ func (ed *emptyDir) SetUpAt(dir string, mounterArgs volume.MounterArgs) error {
if mounterArgs.DesiredSize != nil { if mounterArgs.DesiredSize != nil {
// Deliberately shadow the outer use of err as noted // Deliberately shadow the outer use of err as noted
// above. // above.
hasQuotas, err := quota.SupportsQuotas(ed.mounter, dir) hasQuotas, err := fsquota.SupportsQuotas(ed.mounter, dir)
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 {
klog.V(4).Infof("emptydir trying to assign quota %v on %s", mounterArgs.DesiredSize, dir) klog.V(4).Infof("emptydir trying to assign quota %v on %s", mounterArgs.DesiredSize, dir)
err := quota.AssignQuota(ed.mounter, dir, mounterArgs.PodUID, mounterArgs.DesiredSize) err := fsquota.AssignQuota(ed.mounter, dir, ed.pod.UID, mounterArgs.DesiredSize)
if err != nil { if 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())
} }
@ -416,7 +416,7 @@ func (ed *emptyDir) TearDownAt(dir string) error {
func (ed *emptyDir) teardownDefault(dir string) error { func (ed *emptyDir) teardownDefault(dir string) error {
// Remove any quota // Remove any quota
err := quota.ClearQuota(ed.mounter, dir) err := fsquota.ClearQuota(ed.mounter, dir)
if err != nil { if err != nil {
klog.Warningf("Warning: Failed to clear quota on %s: %v", dir, err) klog.Warningf("Warning: Failed to clear quota on %s: %v", dir, err)
} }

View File

@ -88,10 +88,10 @@ filegroup(
":package-srcs", ":package-srcs",
"//pkg/volume/util/exec:all-srcs", "//pkg/volume/util/exec:all-srcs",
"//pkg/volume/util/fs:all-srcs", "//pkg/volume/util/fs:all-srcs",
"//pkg/volume/util/fsquota:all-srcs",
"//pkg/volume/util/nestedpendingoperations:all-srcs", "//pkg/volume/util/nestedpendingoperations:all-srcs",
"//pkg/volume/util/nsenter:all-srcs", "//pkg/volume/util/nsenter:all-srcs",
"//pkg/volume/util/operationexecutor:all-srcs", "//pkg/volume/util/operationexecutor:all-srcs",
"//pkg/volume/util/quota:all-srcs",
"//pkg/volume/util/recyclerclient:all-srcs", "//pkg/volume/util/recyclerclient:all-srcs",
"//pkg/volume/util/subpath:all-srcs", "//pkg/volume/util/subpath:all-srcs",
"//pkg/volume/util/types:all-srcs", "//pkg/volume/util/types:all-srcs",

View File

@ -14,7 +14,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:darwin": [ "@io_bazel_rules_go//go/platform:darwin": [
"//pkg/volume/util/quota:go_default_library", "//pkg/volume/util/fsquota:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library",
], ],
@ -25,7 +25,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:linux": [ "@io_bazel_rules_go//go/platform:linux": [
"//pkg/volume/util/quota:go_default_library", "//pkg/volume/util/fsquota:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library",
], ],

View File

@ -27,7 +27,7 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/kubernetes/pkg/volume/util/quota" "k8s.io/kubernetes/pkg/volume/util/fsquota"
) )
// FSInfo linux returns (available bytes, byte capacity, byte usage, total inodes, inodes free, inode usage, error) // FSInfo linux returns (available bytes, byte capacity, byte usage, total inodes, inodes free, inode usage, error)
@ -60,7 +60,7 @@ func DiskUsage(path string) (*resource.Quantity, error) {
// First check whether the quota system knows about this directory // First check whether the quota system knows about this directory
// A nil quantity with no error means that the path does not support quotas // A nil quantity with no error means that the path does not support quotas
// and we should use other mechanisms. // and we should use other mechanisms.
data, err := quota.GetConsumption(path) data, err := fsquota.GetConsumption(path)
if data != nil { if data != nil {
return data, nil return data, nil
} else if err != nil { } else if err != nil {
@ -89,7 +89,7 @@ func Find(path string) (int64, error) {
// First check whether the quota system knows about this directory // First check whether the quota system knows about this directory
// A nil quantity with no error means that the path does not support quotas // A nil quantity with no error means that the path does not support quotas
// and we should use other mechanisms. // and we should use other mechanisms.
inodes, err := quota.GetInodes(path) inodes, err := fsquota.GetInodes(path)
if inodes != nil { if inodes != nil {
return inodes.Value(), nil return inodes.Value(), nil
} else if err != nil { } else if err != nil {

View File

@ -8,16 +8,17 @@ go_library(
"quota_linux.go", "quota_linux.go",
"quota_unsupported.go", "quota_unsupported.go",
], ],
importpath = "k8s.io/kubernetes/pkg/volume/util/quota", importpath = "k8s.io/kubernetes/pkg/volume/util/fsquota",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/util/mount:go_default_library", "//pkg/util/mount:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
] + select({ ] + select({
"@io_bazel_rules_go//go/platform:linux": [ "@io_bazel_rules_go//go/platform:linux": [
"//pkg/volume/util/quota/common:go_default_library", "//pkg/volume/util/fsquota/common:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
@ -34,8 +35,9 @@ go_test(
"@io_bazel_rules_go//go/platform:linux": [ "@io_bazel_rules_go//go/platform:linux": [
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/util/mount:go_default_library", "//pkg/util/mount:go_default_library",
"//pkg/volume/util/quota/common:go_default_library", "//pkg/volume/util/fsquota/common:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
], ],
@ -54,7 +56,7 @@ filegroup(
name = "all-srcs", name = "all-srcs",
srcs = [ srcs = [
":package-srcs", ":package-srcs",
"//pkg/volume/util/quota/common:all-srcs", "//pkg/volume/util/fsquota/common:all-srcs",
], ],
tags = ["automanaged"], tags = ["automanaged"],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],

View File

@ -6,7 +6,7 @@ go_library(
"quota_linux_common.go", "quota_linux_common.go",
"quota_linux_common_impl.go", "quota_linux_common_impl.go",
], ],
importpath = "k8s.io/kubernetes/pkg/volume/util/quota/common", importpath = "k8s.io/kubernetes/pkg/volume/util/fsquota/common",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = select({ deps = select({
"@io_bazel_rules_go//go/platform:linux": [ "@io_bazel_rules_go//go/platform:linux": [

View File

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package quota package fsquota
import ( import (
"bufio" "bufio"
@ -29,7 +29,7 @@ import (
"sync" "sync"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"k8s.io/kubernetes/pkg/volume/util/quota/common" "k8s.io/kubernetes/pkg/volume/util/fsquota/common"
) )
var projectsFile = "/etc/projects" var projectsFile = "/etc/projects"

View File

@ -14,10 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package quota package fsquota
import ( import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
@ -29,7 +30,7 @@ type Interface interface {
SupportsQuotas(m mount.Interface, path string) (bool, error) SupportsQuotas(m mount.Interface, path string) (bool, error)
// Assign a quota (picked by the quota mechanism) to a path, // Assign a quota (picked by the quota mechanism) to a path,
// and return it. // and return it.
AssignQuota(m mount.Interface, path string, poduid string, bytes *resource.Quantity) error AssignQuota(m mount.Interface, path string, poduid types.UID, bytes *resource.Quantity) error
// Get the quota-based storage consumption for the path // Get the quota-based storage consumption for the path
GetConsumption(path string) (*resource.Quantity, error) GetConsumption(path string) (*resource.Quantity, error)
@ -40,7 +41,7 @@ type Interface interface {
// Remove the quota from a path // Remove the quota from a path
// Implementations may assume that any data covered by the // Implementations may assume that any data covered by the
// quota has already been removed. // quota has already been removed.
ClearQuota(m mount.Interface, path string, poduid string) error ClearQuota(m mount.Interface, path string) error
} }
func enabledQuotasForMonitoring() bool { func enabledQuotasForMonitoring() bool {

View File

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package quota package fsquota
import ( import (
"bufio" "bufio"
@ -26,23 +26,24 @@ import (
"sync" "sync"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume/util/quota/common" "k8s.io/kubernetes/pkg/volume/util/fsquota/common"
) )
// Pod -> ID // Pod -> ID
var podQuotaMap = make(map[string]common.QuotaID) var podQuotaMap = make(map[types.UID]common.QuotaID)
// Dir -> ID (for convenience) // Dir -> ID (for convenience)
var dirQuotaMap = make(map[string]common.QuotaID) var dirQuotaMap = make(map[string]common.QuotaID)
// ID -> pod // ID -> pod
var quotaPodMap = make(map[common.QuotaID]string) var quotaPodMap = make(map[common.QuotaID]types.UID)
// Directory -> pod // Directory -> pod
var dirPodMap = make(map[string]string) var dirPodMap = make(map[string]types.UID)
// Backing device -> applier // Backing device -> applier
// This is *not* cleaned up; its size will be bounded. // This is *not* cleaned up; its size will be bounded.
@ -53,7 +54,7 @@ var dirApplierMap = make(map[string]common.LinuxVolumeQuotaApplier)
var dirApplierLock sync.RWMutex var dirApplierLock sync.RWMutex
// Pod -> refcount // Pod -> refcount
var podDirCountMap = make(map[string]int) var podDirCountMap = make(map[types.UID]int)
// ID -> size // ID -> size
var quotaSizeMap = make(map[common.QuotaID]int64) var quotaSizeMap = make(map[common.QuotaID]int64)
@ -296,7 +297,7 @@ func SupportsQuotas(m mount.Interface, path string) (bool, error) {
// AssignQuota chooses the quota ID based on the pod UID and path. // AssignQuota chooses the quota ID based on the pod UID and path.
// If the pod UID is identical to another one known, it may (but presently // If the pod UID is identical to another one known, it may (but presently
// doesn't) choose the same quota ID as other volumes in the pod. // doesn't) choose the same quota ID as other volumes in the pod.
func AssignQuota(m mount.Interface, path string, poduid string, bytes *resource.Quantity) error { func AssignQuota(m mount.Interface, path string, poduid types.UID, bytes *resource.Quantity) error {
if bytes == nil { if bytes == nil {
return fmt.Errorf("Attempting to assign null quota to %s", path) return fmt.Errorf("Attempting to assign null quota to %s", path)
} }
@ -311,7 +312,7 @@ func AssignQuota(m mount.Interface, path string, poduid string, bytes *resource.
// volumes in a pod, we can simply remove this line of code. // volumes in a pod, we can simply remove this line of code.
// If and when we decide permanently that we're going to adop // If and when we decide permanently that we're going to adop
// 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.
poduid = string(uuid.NewUUID()) poduid = types.UID(uuid.NewUUID())
if pod, ok := dirPodMap[path]; ok && pod != poduid { if pod, ok := dirPodMap[path]; ok && pod != poduid {
return fmt.Errorf("Requesting quota on existing directory %s but different pod %s %s", path, pod, poduid) return fmt.Errorf("Requesting quota on existing directory %s but different pod %s %s", path, pod, poduid)
} }

View File

@ -16,17 +16,18 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package quota package fsquota
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing" featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume/util/quota/common" "k8s.io/kubernetes/pkg/volume/util/fsquota/common"
"os" "os"
"strings" "strings"
"testing" "testing"
@ -389,7 +390,7 @@ func fakeSupportsQuotas(path string) (bool, error) {
return SupportsQuotas(dummyQuotaTest(), path) return SupportsQuotas(dummyQuotaTest(), path)
} }
func fakeAssignQuota(path string, poduid string, bytes int64) error { func fakeAssignQuota(path string, poduid types.UID, bytes int64) error {
dummySetFSInfo(path) dummySetFSInfo(path)
return AssignQuota(dummyQuotaTest(), path, poduid, resource.NewQuantity(bytes, resource.DecimalSI)) return AssignQuota(dummyQuotaTest(), path, poduid, resource.NewQuantity(bytes, resource.DecimalSI))
} }
@ -401,7 +402,7 @@ func fakeClearQuota(path string) error {
type quotaTestCase struct { type quotaTestCase struct {
path string path string
poduid string poduid types.UID
bytes int64 bytes int64
op string op string
expectedProjects string expectedProjects string

View File

@ -16,11 +16,12 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package quota package fsquota
import ( import (
"errors" "errors"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
) )
@ -35,7 +36,7 @@ func SupportsQuotas(_ mount.Interface, _ string) (bool, error) {
} }
// AssignQuota -- dummy implementation // AssignQuota -- dummy implementation
func AssignQuota(_ mount.Interface, _ string, _ string, _ *resource.Quantity) error { func AssignQuota(_ mount.Interface, _ string, _ types.UID, _ *resource.Quantity) error {
return errNotImplemented return errNotImplemented
} }

View File

@ -698,7 +698,6 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
mountErr := volumeMounter.SetUp(volume.MounterArgs{ mountErr := volumeMounter.SetUp(volume.MounterArgs{
FsGroup: fsGroup, FsGroup: fsGroup,
DesiredSize: volumeToMount.DesiredSizeLimit, DesiredSize: volumeToMount.DesiredSizeLimit,
PodUID: string(volumeToMount.Pod.UID),
}) })
if mountErr != nil { if mountErr != nil {
// On failure, return error. Caller will log and retry. // On failure, return error. Caller will log and retry.

View File

@ -105,7 +105,6 @@ type Attributes struct {
type MounterArgs struct { type MounterArgs struct {
FsGroup *int64 FsGroup *int64
DesiredSize *resource.Quantity DesiredSize *resource.Quantity
PodUID string
} }
// Mounter interface provides methods to set up/mount the volume. // Mounter interface provides methods to set up/mount the volume.

View File

@ -146,7 +146,7 @@ go_test(
"//pkg/kubelet/types:go_default_library", "//pkg/kubelet/types:go_default_library",
"//pkg/security/apparmor:go_default_library", "//pkg/security/apparmor:go_default_library",
"//pkg/util/mount:go_default_library", "//pkg/util/mount:go_default_library",
"//pkg/volume/util/quota:go_default_library", "//pkg/volume/util/fsquota:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/scheduling/v1:go_default_library", "//staging/src/k8s.io/api/scheduling/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",

View File

@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume/util/quota" "k8s.io/kubernetes/pkg/volume/util/fsquota"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
imageutils "k8s.io/kubernetes/test/utils/image" imageutils "k8s.io/kubernetes/test/utils/image"
@ -142,6 +142,6 @@ func diskConcealingPod(name string, diskConsumedMB int, volumeSource *v1.VolumeS
// Don't bother returning an error; if something goes wrong, // Don't bother returning an error; if something goes wrong,
// simply treat it as "no". // simply treat it as "no".
func supportsQuotas(dir string) bool { func supportsQuotas(dir string) bool {
supportsQuota, err := quota.SupportsQuotas(mount.New(""), dir) supportsQuota, err := fsquota.SupportsQuotas(mount.New(""), dir)
return supportsQuota && err == nil return supportsQuota && err == nil
} }