Include pod /etc/hosts in ephemeral storage calculation for eviction

This commit is contained in:
Joel Smith 2020-05-14 20:09:58 -06:00
parent bc60bdaded
commit f34b586d01
7 changed files with 27 additions and 6 deletions

View File

@ -65,6 +65,7 @@ go_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",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/clock: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/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library",

View File

@ -26,6 +26,7 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/clock" "k8s.io/apimachinery/pkg/util/clock"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
@ -98,6 +99,8 @@ type managerImpl struct {
thresholdNotifiers []ThresholdNotifier thresholdNotifiers []ThresholdNotifier
// thresholdsLastUpdated is the last time the thresholdNotifiers were updated. // thresholdsLastUpdated is the last time the thresholdNotifiers were updated.
thresholdsLastUpdated time.Time thresholdsLastUpdated time.Time
// etcHostsPath is a function that will get the etc-hosts file's path for a pod given its UID
etcHostsPath func(podUID types.UID) string
} }
// ensure it implements the required interface // ensure it implements the required interface
@ -114,6 +117,7 @@ func NewManager(
recorder record.EventRecorder, recorder record.EventRecorder,
nodeRef *v1.ObjectReference, nodeRef *v1.ObjectReference,
clock clock.Clock, clock clock.Clock,
etcHostsPath func(types.UID) string,
) (Manager, lifecycle.PodAdmitHandler) { ) (Manager, lifecycle.PodAdmitHandler) {
manager := &managerImpl{ manager := &managerImpl{
clock: clock, clock: clock,
@ -129,6 +133,7 @@ func NewManager(
thresholdsFirstObservedAt: thresholdsObservedAt{}, thresholdsFirstObservedAt: thresholdsObservedAt{},
dedicatedImageFs: nil, dedicatedImageFs: nil,
thresholdNotifiers: []ThresholdNotifier{}, thresholdNotifiers: []ThresholdNotifier{},
etcHostsPath: etcHostsPath,
} }
return manager, manager return manager, manager
} }
@ -514,7 +519,7 @@ func (m *managerImpl) podEphemeralStorageLimitEviction(podStats statsapi.PodStat
} else { } else {
fsStatsSet = []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource} fsStatsSet = []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}
} }
podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet) podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet, m.etcHostsPath(pod.UID))
if err != nil { if err != nil {
klog.Errorf("eviction manager: error getting pod disk usage %v", err) klog.Errorf("eviction manager: error getting pod disk usage %v", err)
return false return false

View File

@ -18,6 +18,7 @@ package eviction
import ( import (
"fmt" "fmt"
"os"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -424,7 +425,7 @@ func localEphemeralVolumeNames(pod *v1.Pod) []string {
} }
// podLocalEphemeralStorageUsage aggregates pod local ephemeral storage usage and inode consumption for the specified stats to measure. // podLocalEphemeralStorageUsage aggregates pod local ephemeral storage usage and inode consumption for the specified stats to measure.
func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType) (v1.ResourceList, error) { func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType, etcHostsPath string) (v1.ResourceList, error) {
disk := resource.Quantity{Format: resource.BinarySI} disk := resource.Quantity{Format: resource.BinarySI}
inodes := resource.Quantity{Format: resource.DecimalSI} inodes := resource.Quantity{Format: resource.DecimalSI}
@ -438,6 +439,12 @@ func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, stat
disk.Add(podLocalVolumeUsageList[v1.ResourceEphemeralStorage]) disk.Add(podLocalVolumeUsageList[v1.ResourceEphemeralStorage])
inodes.Add(podLocalVolumeUsageList[resourceInodes]) inodes.Add(podLocalVolumeUsageList[resourceInodes])
} }
if len(etcHostsPath) > 0 {
if stat, err := os.Stat(etcHostsPath); err == nil {
disk.Add(*resource.NewQuantity(int64(stat.Size()), resource.BinarySI))
inodes.Add(*resource.NewQuantity(int64(1), resource.DecimalSI))
}
}
return v1.ResourceList{ return v1.ResourceList{
v1.ResourceEphemeralStorage: disk, v1.ResourceEphemeralStorage: disk,
resourceInodes: inodes, resourceInodes: inodes,

View File

@ -772,8 +772,9 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
klet.backOff = flowcontrol.NewBackOff(backOffPeriod, MaxContainerBackOff) klet.backOff = flowcontrol.NewBackOff(backOffPeriod, MaxContainerBackOff)
klet.podKillingCh = make(chan *kubecontainer.PodPair, podKillingChannelCapacity) klet.podKillingCh = make(chan *kubecontainer.PodPair, podKillingChannelCapacity)
etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(klet.getPodDir(podUID)) }
// setup eviction manager // setup eviction manager
evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock) evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock, etcHostsPathFunc)
klet.evictionManager = evictionManager klet.evictionManager = evictionManager
klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler) klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)

View File

@ -288,11 +288,16 @@ func translateMountPropagation(mountMode *v1.MountPropagationMode) (runtimeapi.M
} }
} }
// getEtcHostsPath returns the full host-side path to a pod's generated /etc/hosts file
func getEtcHostsPath(podDir string) string {
return path.Join(podDir, "etc-hosts")
}
// makeHostsMount makes the mountpoint for the hosts file that the containers // makeHostsMount makes the mountpoint for the hosts file that the containers
// in a pod are injected with. podIPs is provided instead of podIP as podIPs // in a pod are injected with. podIPs is provided instead of podIP as podIPs
// are present even if dual-stack feature flag is not enabled. // are present even if dual-stack feature flag is not enabled.
func makeHostsMount(podDir string, podIPs []string, hostName, hostDomainName string, hostAliases []v1.HostAlias, useHostNetwork bool) (*kubecontainer.Mount, error) { func makeHostsMount(podDir string, podIPs []string, hostName, hostDomainName string, hostAliases []v1.HostAlias, useHostNetwork bool) (*kubecontainer.Mount, error) {
hostsFilePath := path.Join(podDir, "etc-hosts") hostsFilePath := getEtcHostsPath(podDir)
if err := ensureHostsFile(hostsFilePath, podIPs, hostName, hostDomainName, hostAliases, useHostNetwork); err != nil { if err := ensureHostsFile(hostsFilePath, podIPs, hostName, hostDomainName, hostAliases, useHostNetwork); err != nil {
return nil, err return nil, err
} }

View File

@ -292,8 +292,9 @@ func newTestKubeletWithImageList(
UID: types.UID(kubelet.nodeName), UID: types.UID(kubelet.nodeName),
Namespace: "", Namespace: "",
} }
etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kubelet.getPodDir(podUID)) }
// setup eviction manager // setup eviction manager
evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock) evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock, etcHostsPathFunc)
kubelet.evictionManager = evictionManager kubelet.evictionManager = evictionManager
kubelet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler) kubelet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)

View File

@ -126,7 +126,8 @@ func TestRunOnce(t *testing.T) {
return nil return nil
} }
fakeMirrodPodFunc := func(*v1.Pod) (*v1.Pod, bool) { return nil, false } fakeMirrodPodFunc := func(*v1.Pod) (*v1.Pod, bool) { return nil, false }
evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock) etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kb.getPodDir(podUID)) }
evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock, etcHostsPathFunc)
kb.evictionManager = evictionManager kb.evictionManager = evictionManager
kb.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler) kb.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)