mirror of https://github.com/k3s-io/k3s
moving image gc to images
parent
5841f6e164
commit
0c76d85cc8
|
@ -59,6 +59,7 @@ import (
|
|||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
"k8s.io/kubernetes/pkg/kubelet/dockertools"
|
||||
"k8s.io/kubernetes/pkg/kubelet/eviction"
|
||||
"k8s.io/kubernetes/pkg/kubelet/images"
|
||||
"k8s.io/kubernetes/pkg/kubelet/network"
|
||||
"k8s.io/kubernetes/pkg/kubelet/server"
|
||||
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
||||
|
@ -162,7 +163,7 @@ func UnsecuredKubeletConfig(s *options.KubeletServer) (*KubeletConfig, error) {
|
|||
dockerExecHandler = &dockertools.NativeExecHandler{}
|
||||
}
|
||||
|
||||
imageGCPolicy := kubelet.ImageGCPolicy{
|
||||
imageGCPolicy := images.ImageGCPolicy{
|
||||
MinAge: s.ImageMinimumGCAge.Duration,
|
||||
HighThresholdPercent: int(s.ImageGCHighThresholdPercent),
|
||||
LowThresholdPercent: int(s.ImageGCLowThresholdPercent),
|
||||
|
@ -549,7 +550,7 @@ func SimpleKubelet(client *clientset.Clientset,
|
|||
fileCheckFrequency, httpCheckFrequency, minimumGCAge, nodeStatusUpdateFrequency, syncFrequency, outOfDiskTransitionFrequency, evictionPressureTransitionPeriod time.Duration,
|
||||
maxPods int, podsPerCore int,
|
||||
containerManager cm.ContainerManager, clusterDNS net.IP) *KubeletConfig {
|
||||
imageGCPolicy := kubelet.ImageGCPolicy{
|
||||
imageGCPolicy := images.ImageGCPolicy{
|
||||
HighThresholdPercent: 90,
|
||||
LowThresholdPercent: 80,
|
||||
}
|
||||
|
@ -817,7 +818,7 @@ type KubeletConfig struct {
|
|||
HostPIDSources []string
|
||||
HostIPCSources []string
|
||||
HTTPCheckFrequency time.Duration
|
||||
ImageGCPolicy kubelet.ImageGCPolicy
|
||||
ImageGCPolicy images.ImageGCPolicy
|
||||
KubeClient *clientset.Clientset
|
||||
ManifestURL string
|
||||
ManifestURLHeader http.Header
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kubelet
|
||||
package images
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -38,7 +38,7 @@ import (
|
|||
// Manages lifecycle of all images.
|
||||
//
|
||||
// Implementation is thread-safe.
|
||||
type imageManager interface {
|
||||
type ImageGCManager interface {
|
||||
// Applies the garbage collection policy. Errors include being unable to free
|
||||
// enough space as per the garbage collection policy.
|
||||
GarbageCollect() error
|
||||
|
@ -50,8 +50,6 @@ type imageManager interface {
|
|||
|
||||
// Delete all unused images and returns the number of bytes freed. The number of bytes freed is always returned.
|
||||
DeleteUnusedImages() (int64, error)
|
||||
|
||||
// TODO(vmarmol): Have this subsume pulls as well.
|
||||
}
|
||||
|
||||
// A policy for garbage collecting images. Policy defines an allowed band in
|
||||
|
@ -69,7 +67,7 @@ type ImageGCPolicy struct {
|
|||
MinAge time.Duration
|
||||
}
|
||||
|
||||
type realImageManager struct {
|
||||
type realImageGCManager struct {
|
||||
// Container runtime
|
||||
runtime container.Runtime
|
||||
|
||||
|
@ -105,7 +103,7 @@ type imageRecord struct {
|
|||
size int64
|
||||
}
|
||||
|
||||
func newImageManager(runtime container.Runtime, cadvisorInterface cadvisor.Interface, recorder record.EventRecorder, nodeRef *api.ObjectReference, policy ImageGCPolicy) (imageManager, error) {
|
||||
func NewImageGCManager(runtime container.Runtime, cadvisorInterface cadvisor.Interface, recorder record.EventRecorder, nodeRef *api.ObjectReference, policy ImageGCPolicy) (ImageGCManager, error) {
|
||||
// Validate policy.
|
||||
if policy.HighThresholdPercent < 0 || policy.HighThresholdPercent > 100 {
|
||||
return nil, fmt.Errorf("invalid HighThresholdPercent %d, must be in range [0-100]", policy.HighThresholdPercent)
|
||||
|
@ -116,7 +114,7 @@ func newImageManager(runtime container.Runtime, cadvisorInterface cadvisor.Inter
|
|||
if policy.LowThresholdPercent > policy.HighThresholdPercent {
|
||||
return nil, fmt.Errorf("LowThresholdPercent %d can not be higher than HighThresholdPercent %d", policy.LowThresholdPercent, policy.HighThresholdPercent)
|
||||
}
|
||||
im := &realImageManager{
|
||||
im := &realImageGCManager{
|
||||
runtime: runtime,
|
||||
policy: policy,
|
||||
imageRecords: make(map[string]*imageRecord),
|
||||
|
@ -129,7 +127,7 @@ func newImageManager(runtime container.Runtime, cadvisorInterface cadvisor.Inter
|
|||
return im, nil
|
||||
}
|
||||
|
||||
func (im *realImageManager) Start() error {
|
||||
func (im *realImageGCManager) Start() error {
|
||||
go wait.Until(func() {
|
||||
// Initial detection make detected time "unknown" in the past.
|
||||
var ts time.Time
|
||||
|
@ -138,7 +136,7 @@ func (im *realImageManager) Start() error {
|
|||
}
|
||||
err := im.detectImages(ts)
|
||||
if err != nil {
|
||||
glog.Warningf("[ImageManager] Failed to monitor images: %v", err)
|
||||
glog.Warningf("[imageGCManager] Failed to monitor images: %v", err)
|
||||
} else {
|
||||
im.initialized = true
|
||||
}
|
||||
|
@ -148,7 +146,7 @@ func (im *realImageManager) Start() error {
|
|||
}
|
||||
|
||||
// Get a list of images on this node
|
||||
func (im *realImageManager) GetImageList() ([]kubecontainer.Image, error) {
|
||||
func (im *realImageGCManager) GetImageList() ([]kubecontainer.Image, error) {
|
||||
images, err := im.runtime.ListImages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -156,7 +154,7 @@ func (im *realImageManager) GetImageList() ([]kubecontainer.Image, error) {
|
|||
return images, nil
|
||||
}
|
||||
|
||||
func (im *realImageManager) detectImages(detectTime time.Time) error {
|
||||
func (im *realImageGCManager) detectImages(detectTime time.Time) error {
|
||||
images, err := im.runtime.ListImages()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -213,7 +211,7 @@ func (im *realImageManager) detectImages(detectTime time.Time) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (im *realImageManager) GarbageCollect() error {
|
||||
func (im *realImageGCManager) GarbageCollect() error {
|
||||
// Get disk usage on disk holding images.
|
||||
fsInfo, err := im.cadvisor.ImagesFsInfo()
|
||||
if err != nil {
|
||||
|
@ -237,7 +235,7 @@ func (im *realImageManager) GarbageCollect() error {
|
|||
usagePercent := 100 - int(available*100/capacity)
|
||||
if usagePercent >= im.policy.HighThresholdPercent {
|
||||
amountToFree := capacity*int64(100-im.policy.LowThresholdPercent)/100 - available
|
||||
glog.Infof("[ImageManager]: Disk usage on %q (%s) is at %d%% which is over the high threshold (%d%%). Trying to free %d bytes", fsInfo.Device, fsInfo.Mountpoint, usagePercent, im.policy.HighThresholdPercent, amountToFree)
|
||||
glog.Infof("[imageGCManager]: Disk usage on %q (%s) is at %d%% which is over the high threshold (%d%%). Trying to free %d bytes", fsInfo.Device, fsInfo.Mountpoint, usagePercent, im.policy.HighThresholdPercent, amountToFree)
|
||||
freed, err := im.freeSpace(amountToFree, time.Now())
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -253,7 +251,7 @@ func (im *realImageManager) GarbageCollect() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (im *realImageManager) DeleteUnusedImages() (int64, error) {
|
||||
func (im *realImageGCManager) DeleteUnusedImages() (int64, error) {
|
||||
return im.freeSpace(math.MaxInt64, time.Now())
|
||||
}
|
||||
|
||||
|
@ -263,7 +261,7 @@ func (im *realImageManager) DeleteUnusedImages() (int64, error) {
|
|||
// bytes freed is always returned.
|
||||
// Note that error may be nil and the number of bytes free may be less
|
||||
// than bytesToFree.
|
||||
func (im *realImageManager) freeSpace(bytesToFree int64, freeTime time.Time) (int64, error) {
|
||||
func (im *realImageGCManager) freeSpace(bytesToFree int64, freeTime time.Time) (int64, error) {
|
||||
err := im.detectImages(freeTime)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -302,7 +300,7 @@ func (im *realImageManager) freeSpace(bytesToFree int64, freeTime time.Time) (in
|
|||
}
|
||||
|
||||
// Remove image. Continue despite errors.
|
||||
glog.Infof("[ImageManager]: Removing image %q to free %d bytes", image.id, image.size)
|
||||
glog.Infof("[imageGCManager]: Removing image %q to free %d bytes", image.id, image.size)
|
||||
err := im.runtime.RemoveImage(container.ImageSpec{Image: image.id})
|
||||
if err != nil {
|
||||
deletionErrors = append(deletionErrors, err)
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kubelet
|
||||
package images
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -33,10 +33,10 @@ import (
|
|||
|
||||
var zero time.Time
|
||||
|
||||
func newRealImageManager(policy ImageGCPolicy) (*realImageManager, *containertest.FakeRuntime, *cadvisortest.Mock) {
|
||||
func newRealImageGCManager(policy ImageGCPolicy) (*realImageGCManager, *containertest.FakeRuntime, *cadvisortest.Mock) {
|
||||
fakeRuntime := &containertest.FakeRuntime{}
|
||||
mockCadvisor := new(cadvisortest.Mock)
|
||||
return &realImageManager{
|
||||
return &realImageGCManager{
|
||||
runtime: fakeRuntime,
|
||||
policy: policy,
|
||||
imageRecords: make(map[string]*imageRecord),
|
||||
|
@ -46,12 +46,12 @@ func newRealImageManager(policy ImageGCPolicy) (*realImageManager, *containertes
|
|||
}
|
||||
|
||||
// Accessors used for thread-safe testing.
|
||||
func (im *realImageManager) imageRecordsLen() int {
|
||||
func (im *realImageGCManager) imageRecordsLen() int {
|
||||
im.imageRecordsLock.Lock()
|
||||
defer im.imageRecordsLock.Unlock()
|
||||
return len(im.imageRecords)
|
||||
}
|
||||
func (im *realImageManager) getImageRecord(name string) (*imageRecord, bool) {
|
||||
func (im *realImageGCManager) getImageRecord(name string) (*imageRecord, bool) {
|
||||
im.imageRecordsLock.Lock()
|
||||
defer im.imageRecordsLock.Unlock()
|
||||
v, ok := im.imageRecords[name]
|
||||
|
@ -87,7 +87,7 @@ func makeContainer(id int) *container.Container {
|
|||
}
|
||||
|
||||
func TestDetectImagesInitialDetect(t *testing.T) {
|
||||
manager, fakeRuntime, _ := newRealImageManager(ImageGCPolicy{})
|
||||
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
|
||||
fakeRuntime.ImageList = []container.Image{
|
||||
makeImage(0, 1024),
|
||||
makeImage(1, 2048),
|
||||
|
@ -131,7 +131,7 @@ func TestDetectImagesInitialDetect(t *testing.T) {
|
|||
|
||||
func TestDetectImagesWithNewImage(t *testing.T) {
|
||||
// Just one image initially.
|
||||
manager, fakeRuntime, _ := newRealImageManager(ImageGCPolicy{})
|
||||
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
|
||||
fakeRuntime.ImageList = []container.Image{
|
||||
makeImage(0, 1024),
|
||||
makeImage(1, 2048),
|
||||
|
@ -176,7 +176,7 @@ func TestDetectImagesWithNewImage(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDetectImagesContainerStopped(t *testing.T) {
|
||||
manager, fakeRuntime, _ := newRealImageManager(ImageGCPolicy{})
|
||||
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
|
||||
fakeRuntime.ImageList = []container.Image{
|
||||
makeImage(0, 1024),
|
||||
makeImage(1, 2048),
|
||||
|
@ -212,7 +212,7 @@ func TestDetectImagesContainerStopped(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDetectImagesWithRemovedImages(t *testing.T) {
|
||||
manager, fakeRuntime, _ := newRealImageManager(ImageGCPolicy{})
|
||||
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
|
||||
fakeRuntime.ImageList = []container.Image{
|
||||
makeImage(0, 1024),
|
||||
makeImage(1, 2048),
|
||||
|
@ -238,7 +238,7 @@ func TestDetectImagesWithRemovedImages(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFreeSpaceImagesInUseContainersAreIgnored(t *testing.T) {
|
||||
manager, fakeRuntime, _ := newRealImageManager(ImageGCPolicy{})
|
||||
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
|
||||
fakeRuntime.ImageList = []container.Image{
|
||||
makeImage(0, 1024),
|
||||
makeImage(1, 2048),
|
||||
|
@ -259,7 +259,7 @@ func TestFreeSpaceImagesInUseContainersAreIgnored(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDeleteUnusedImagesRemoveAllUnusedImages(t *testing.T) {
|
||||
manager, fakeRuntime, _ := newRealImageManager(ImageGCPolicy{})
|
||||
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
|
||||
fakeRuntime.ImageList = []container.Image{
|
||||
makeImage(0, 1024),
|
||||
makeImage(1, 2048),
|
||||
|
@ -281,7 +281,7 @@ func TestDeleteUnusedImagesRemoveAllUnusedImages(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFreeSpaceRemoveByLeastRecentlyUsed(t *testing.T) {
|
||||
manager, fakeRuntime, _ := newRealImageManager(ImageGCPolicy{})
|
||||
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
|
||||
fakeRuntime.ImageList = []container.Image{
|
||||
makeImage(0, 1024),
|
||||
makeImage(1, 2048),
|
||||
|
@ -321,7 +321,7 @@ func TestFreeSpaceRemoveByLeastRecentlyUsed(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFreeSpaceTiesBrokenByDetectedTime(t *testing.T) {
|
||||
manager, fakeRuntime, _ := newRealImageManager(ImageGCPolicy{})
|
||||
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
|
||||
fakeRuntime.ImageList = []container.Image{
|
||||
makeImage(0, 1024),
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ func TestGarbageCollectBelowLowThreshold(t *testing.T) {
|
|||
HighThresholdPercent: 90,
|
||||
LowThresholdPercent: 80,
|
||||
}
|
||||
manager, _, mockCadvisor := newRealImageManager(policy)
|
||||
manager, _, mockCadvisor := newRealImageGCManager(policy)
|
||||
|
||||
// Expect 40% usage.
|
||||
mockCadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{
|
||||
|
@ -372,7 +372,7 @@ func TestGarbageCollectCadvisorFailure(t *testing.T) {
|
|||
HighThresholdPercent: 90,
|
||||
LowThresholdPercent: 80,
|
||||
}
|
||||
manager, _, mockCadvisor := newRealImageManager(policy)
|
||||
manager, _, mockCadvisor := newRealImageGCManager(policy)
|
||||
|
||||
mockCadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{}, fmt.Errorf("error"))
|
||||
assert.NotNil(t, manager.GarbageCollect())
|
||||
|
@ -383,7 +383,7 @@ func TestGarbageCollectBelowSuccess(t *testing.T) {
|
|||
HighThresholdPercent: 90,
|
||||
LowThresholdPercent: 80,
|
||||
}
|
||||
manager, fakeRuntime, mockCadvisor := newRealImageManager(policy)
|
||||
manager, fakeRuntime, mockCadvisor := newRealImageGCManager(policy)
|
||||
|
||||
// Expect 95% usage and most of it gets freed.
|
||||
mockCadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{
|
||||
|
@ -402,7 +402,7 @@ func TestGarbageCollectNotEnoughFreed(t *testing.T) {
|
|||
HighThresholdPercent: 90,
|
||||
LowThresholdPercent: 80,
|
||||
}
|
||||
manager, fakeRuntime, mockCadvisor := newRealImageManager(policy)
|
||||
manager, fakeRuntime, mockCadvisor := newRealImageGCManager(policy)
|
||||
|
||||
// Expect 95% usage and little of it gets freed.
|
||||
mockCadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{
|
||||
|
@ -424,7 +424,7 @@ func TestGarbageCollectImageNotOldEnough(t *testing.T) {
|
|||
}
|
||||
fakeRuntime := &containertest.FakeRuntime{}
|
||||
mockCadvisor := new(cadvisortest.Mock)
|
||||
manager := &realImageManager{
|
||||
manager := &realImageGCManager{
|
||||
runtime: fakeRuntime,
|
||||
policy: policy,
|
||||
imageRecords: make(map[string]*imageRecord),
|
|
@ -201,7 +201,7 @@ func NewMainKubelet(
|
|||
streamingConnectionIdleTimeout time.Duration,
|
||||
recorder record.EventRecorder,
|
||||
cadvisorInterface cadvisor.Interface,
|
||||
imageGCPolicy ImageGCPolicy,
|
||||
imageGCPolicy images.ImageGCPolicy,
|
||||
diskSpacePolicy DiskSpacePolicy,
|
||||
cloud cloudprovider.Interface,
|
||||
autoDetectCloudProvider bool,
|
||||
|
@ -492,7 +492,7 @@ func NewMainKubelet(
|
|||
klet.containerDeletor = newPodContainerDeletor(klet.containerRuntime, integer.IntMax(containerGCPolicy.MaxPerPodContainer, minDeadContainerInPod))
|
||||
|
||||
// setup imageManager
|
||||
imageManager, err := newImageManager(klet.containerRuntime, cadvisorInterface, recorder, nodeRef, imageGCPolicy)
|
||||
imageManager, err := images.NewImageGCManager(klet.containerRuntime, cadvisorInterface, recorder, nodeRef, imageGCPolicy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize image manager: %v", err)
|
||||
}
|
||||
|
@ -661,8 +661,8 @@ type Kubelet struct {
|
|||
// Policy for handling garbage collection of dead containers.
|
||||
containerGC kubecontainer.ContainerGC
|
||||
|
||||
// Manager for images.
|
||||
imageManager imageManager
|
||||
// Manager for image garbage collection.
|
||||
imageManager images.ImageGCManager
|
||||
|
||||
// Diskspace manager.
|
||||
diskSpaceManager diskSpaceManager
|
||||
|
|
|
@ -46,6 +46,7 @@ import (
|
|||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||
"k8s.io/kubernetes/pkg/kubelet/eviction"
|
||||
"k8s.io/kubernetes/pkg/kubelet/images"
|
||||
"k8s.io/kubernetes/pkg/kubelet/lifecycle"
|
||||
"k8s.io/kubernetes/pkg/kubelet/network"
|
||||
nettest "k8s.io/kubernetes/pkg/kubelet/network/testing"
|
||||
|
@ -193,11 +194,11 @@ func newTestKubeletWithImageList(
|
|||
UID: types.UID(testKubeletHostname),
|
||||
Namespace: "",
|
||||
}
|
||||
fakeImageGCPolicy := ImageGCPolicy{
|
||||
fakeImageGCPolicy := images.ImageGCPolicy{
|
||||
HighThresholdPercent: 90,
|
||||
LowThresholdPercent: 80,
|
||||
}
|
||||
kubelet.imageManager, err = newImageManager(fakeRuntime, mockCadvisor, fakeRecorder, fakeNodeRef, fakeImageGCPolicy)
|
||||
kubelet.imageManager, err = images.NewImageGCManager(fakeRuntime, mockCadvisor, fakeRecorder, fakeNodeRef, fakeImageGCPolicy)
|
||||
fakeClock := clock.NewFakeClock(time.Now())
|
||||
kubelet.backOff = flowcontrol.NewBackOff(time.Second, time.Minute)
|
||||
kubelet.backOff.Clock = fakeClock
|
||||
|
|
Loading…
Reference in New Issue