-
Notifications
You must be signed in to change notification settings - Fork 39.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add EmptyDir volume and container overlay capacity isolation #45686
Conversation
if used != nil && size.Cmp(*zero) > 0 && used.Cmp(size) > 0 { | ||
// the emptyDir usage exceeds the size limit, evict the pod | ||
gracePeriod := int64(0) | ||
m.evictPod(pod, v1.ResourceName("EmptyDir"), gracePeriod, fmt.Sprintf("emptyDir usage exceeds the limit %q", size.String())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err = m.evictPod(...) ?
@@ -0,0 +1,213 @@ | |||
/* | |||
Copyright 2016 The Kubernetes Authors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/2016/2017
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Files should not have capital letters in their names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not review all the eviction logic, just the API
pkg/api/v1/types.go
Outdated
@@ -668,6 +668,11 @@ type EmptyDirVolumeSource struct { | |||
// More info: http://kubernetes.io/docs/user-guide/volumes#emptydir | |||
// +optional | |||
Medium StorageMedium `json:"medium,omitempty" protobuf:"bytes,1,opt,name=medium,casttype=StorageMedium"` | |||
// Total amount of local storage required for this directory. | |||
// The default is nil which means that the directory can use all available local storage on the node. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't document the default as "nil" (that's a go-ism). Instead document as "If not specified, the default is to not enforce a limit". Though we might want to loosen this and say "If not specified, the default limit is implementation defined". Default tmpfs is (I think) 1/2 physical mem. Default disk is all storage, etc. I don't think we need to define that here, though.
pkg/api/validation/validation.go
Outdated
if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { | ||
unsetSizeLimit := resource.Quantity{} | ||
if unsetSizeLimit.Cmp(source.EmptyDir.SizeLimit) != 0 { | ||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("emptyDir").Child("sizeLimit"), "LocalStorageCapacityIsolation are disabled by feature-gate")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"is disabled"
@@ -0,0 +1,213 @@ | |||
/* | |||
Copyright 2016 The Kubernetes Authors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Files should not have capital letters in their names
@@ -32,6 +32,7 @@ import ( | |||
"k8s.io/client-go/util/clock" | |||
"k8s.io/kubernetes/pkg/api/v1" | |||
"k8s.io/kubernetes/pkg/features" | |||
statsapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/stats" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching it. fix it. strange it was working in this way too...
glog.Errorf("eviction manager: pod %s exceeds emptyDir sizeLimit but failed to evict %v", format.Pod(pod), err) | ||
} else { | ||
glog.Infof("eviction manager: pod %s exceeds emptyDir sizeLimit and is evicted successfully", format.Pod(pod)) | ||
evict = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we return early since the pod is already evicted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic here is to evict all pods that violate the size limit for emptyDir volume. So we have to continue with the loop even after some pods are evicted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, you are right, return early is fine.
adb9650
to
431baee
Compare
|
||
// evict pods if there is a resource uage violation from local volume temporary storage | ||
// If eviction happenes in localVolumeEviction function, skip the rest of eviction action | ||
if m.localVolumeEviction(activePods) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vishh @derekwaynecarr, any preference as to whether doing local volume evictions is part of the same control loop as the rest of evictions? The main advantage of having them together is to not perform other evictions when pods are already being evicted for exceeding their local volume storage space
return evict | ||
} | ||
|
||
func (m *managerImpl) evictPod(pod *v1.Pod, resourceName v1.ResourceName, gracePeriod int64, evictMsg string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gracePeriod is always passed as 0, so you dont need it as an argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will this change in the future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could, but adding a parameter to a function is easy enough. Better to leave it out for now.
Changes to the eviction manager need unit testing as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a couple small things
size := source.EmptyDir.SizeLimit | ||
used := podVolumeUsed[pod.Spec.Volumes[i].Name] | ||
zero := resource.NewQuantity(int64(0), resource.BinarySI) | ||
glog.Infof("Jing pod %s limit %v, used %v", format.Pod(pod), size, used) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably left over from testing. Remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
used := podVolumeUsed[pod.Spec.Volumes[i].Name] | ||
zero := resource.NewQuantity(int64(0), resource.BinarySI) | ||
glog.Infof("Jing pod %s limit %v, used %v", format.Pod(pod), size, used) | ||
if used != nil && size.Cmp(*zero) > 0 && used.Cmp(size) > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of Cmp(*zero)
, I think you can use Sign
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
if overlayThreshold, ok := thresholdsMap[containerStat.Name]; ok { | ||
if overlayThreshold.Cmp(*rootfs) < 0 { | ||
gracePeriod := int64(0) | ||
err := m.evictPod(pod, v1.ResourceName("containerOverlay"), gracePeriod, fmt.Sprintf("container's overlay usage exceeds the limit %q", overlayThreshold.String())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are passing in a relevant message to evictPod, why not do the logging inside of evictPod using that message. evictPod doesnt need to return an error in this case, and we can avoid having essentially the same log messages duplicated in 3 places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, put logging inside of evictPod, and return bool to indicate whether pod is evicted or not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it matter whether the pod is evicted or not? I believe we set the pod's status to failed, so kubelet housekeeping will terminate it even if the eviction manager failed.
Essentially, we should treat any pod that we attempt to evict as evicted.
addressed the comments. @dashpole PTAL |
This message was created automatically by mail delivery software.
A message that you sent could not be delivered to one or more of its
recipients. This is a temporary error. The following address(es) deferred:
[email protected]
Domain imwiz.com has exceeded the max emails per hour (173/150 (115%)) allowed. Message will be reattempted later
…------- This is a copy of the message, including all the headers. ------
Received: from github-smtp2-ext2.iad.github.net ([192.30.252.193]:45681 helo=github-smtp2b-ext-cp1-prd.iad.github.net)
by box969.bluehost.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256)
(Exim 4.87)
(envelope-from <[email protected]>)
id 1dGU8E-000QTR-8a
for [email protected]; Thu, 01 Jun 2017 11:43:34 -0600
Date: Thu, 01 Jun 2017 10:43:23 -0700
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=github.com;
s=pf2014; t=1496339003;
bh=B+ObljmZ5DCGW8z6BDSL8CP5MjEMQL1mHGl1TzAqIgs=;
h=From:Reply-To:To:Cc:In-Reply-To:References:Subject:List-ID:
List-Archive:List-Post:List-Unsubscribe:From;
b=x1esfSNpWD2lAcEg08vJBK9OwfCGtIktXyti8PHS2KLK+16Uss1Cicap6D3ifx3vw
8hKw6JYQv06ZfW5qKB7R5hLJSYZOgVcsrtCD0LV6QKCo6JaQZVEBv+zNvqyjqgWHug
z8+ij/hSpEeClA7TUWS1kEojUf5+HjqiZFUiJGbE=
From: Kubernetes Submit Queue <[email protected]>
Reply-To: kubernetes/kubernetes <[email protected]>
To: kubernetes/kubernetes <[email protected]>
Cc: Subscribed <[email protected]>
Message-ID: <kubernetes/kubernetes/pull/45686/[email protected]>
In-Reply-To: <kubernetes/kubernetes/pull/[email protected]>
References: <kubernetes/kubernetes/pull/[email protected]>
Subject: Re: [kubernetes/kubernetes] Add EmptyDir volume capacity isolation
(#45686)
Mime-Version: 1.0
Content-Type: multipart/alternative;
boundary="--==_mimepart_5930523b6b593_633a3f90a0a15c3c3415";
charset=UTF-8
Content-Transfer-Encoding: 7bit
Precedence: list
X-GitHub-Sender: k8s-merge-robot
X-GitHub-Recipient: falenn
X-GitHub-Reason: subscribed
List-ID: kubernetes/kubernetes <kubernetes.kubernetes.github.com>
List-Archive: https://github.com/kubernetes/kubernetes
List-Post: <mailto:[email protected]>
List-Unsubscribe: <mailto:unsub+000ab60a4fc71667972ec148ee09c82ad73e7bf321f496c892cf000000011548143b92a169ce0d98d100@reply.github.com>,
<https://github.com/notifications/unsubscribe/AAq2CvmN_qeNvOh8dgRVdyPYzVjFBsU5ks5r_vg7gaJpZM4NYi21>
X-Auto-Response-Suppress: All
X-GitHub-Recipient-Address: [email protected]
X-Spam-Status: No, score=-5.0
X-Spam-Score: -49
X-Spam-Bar: -----
X-Ham-Report: Spam detection software, running on the system "box969.bluehost.com",
has NOT identified this incoming email as spam. The original
message has been attached to this so you can view it or label
similar future email. If you have any questions, see
root\@localhost for details.
Content preview: /lgtm cancel //PR changed after LGTM, removing LGTM. @dashpole
@jingxu97 @smarterclayton @thockin @vishh -- You are receiving this because
you are subscribed to this thread. Reply to this email directly or view it
on GitHub: #45686 (comment)
[...]
Content analysis details: (-5.0 points, 4.0 required)
pts rule name description
---- ---------------------- --------------------------------------------------
-5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high
trust
[192.30.252.193 listed in list.dnswl.org]
-2.8 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2)
[192.30.252.193 listed in wl.mailspike.net]
-0.0 SPF_PASS SPF: sender matches SPF record
1.3 HTML_IMAGE_ONLY_24 BODY: HTML: images with 2000-2400 bytes of words
0.0 HTML_MESSAGE BODY: HTML included in message
-0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's
domain
-0.1 DKIM_VALID Message has at least one valid DKIM or DK signature
0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid
1.7 AWL AWL: Adjusted score from AWL reputation of From: address
X-Spam-Flag: NO
----==_mimepart_5930523b6b593_633a3f90a0a15c3c3415
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bit
/lgtm cancel //PR changed after LGTM, removing LGTM. @dashpole @jingxu97 @smarterclayton @thockin @vishh
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
#45686 (comment)
----==_mimepart_5930523b6b593_633a3f90a0a15c3c3415
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit
<p>/lgtm cancel //PR changed after LGTM, removing LGTM. <a href="https://github.com/dashpole" class="user-mention">@dashpole</a> <a href="https://github.com/jingxu97" class="user-mention">@jingxu97</a> <a href="https://github.com/smarterclayton" class="user-mention">@smarterclayton</a> <a href="https://github.com/thockin" class="user-mention">@thockin</a> <a href="https://github.com/vishh" class="user-mention">@vishh</a></p>
<p style="font-size:small;-webkit-text-size-adjust:none;color:#666;">—<br />You are receiving this because you are subscribed to this thread.<br />Reply to this email directly, <a href="#45686 (comment)">view it on GitHub</a>, or <a href="https://github.com/notifications/unsubscribe-auth/AAq2Cpu3p24GLtJqTDUpNwFiScXHWZibks5r_vg7gaJpZM4NYi21">mute the thread</a>.<img alt="" height="1" src="https://github.com/notifications/beacon/AAq2CqQ3xploWN3q-yY6cQY_hlRtkUWzks5r_vg7gaJpZM4NYi21.gif" width="1" /></p>
<div itemscope itemtype="http://schema.org/EmailMessage">
<div itemprop="action" itemscope itemtype="http://schema.org/ViewAction">
<link itemprop="url" href="#45686 (comment)"></link>
<meta itemprop="name" content="View Pull Request"></meta>
</div>
<meta itemprop="description" content="View this Pull Request on GitHub"></meta>
</div>
<script type="application/json" data-scope="inboxmarkup">{"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/kubernetes/kubernetes","title":"kubernetes/kubernetes","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/kubernetes/kubernetes"}},"updates":{"snippets":[{"icon":"PERSON","message":"@k8s-merge-robot in #45686: /lgtm cancel //PR changed after LGTM, removing LGTM. @dashpole @jingxu97 @smarterclayton @thockin @vishh"}],"action":{"name":"View Pull Request","url":"#45686 (comment)"}}}</script>
----==_mimepart_5930523b6b593_633a3f90a0a15c3c3415--
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: falenn, jingxu97, thockin, vishh The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
@k8s-bot unit test this |
@k8s-bot pull-kubernetes-e2e-kops-aws test this |
This PR adds two features: 1. add support for isolating the emptyDir volume use. If user sets a size limit for emptyDir volume, kubelet's eviction manager monitors its usage and evict the pod if the usage exceeds the limit. 2. add support for isolating the local storage for container overlay. If the container's overly usage exceeds the limit defined in container spec, eviction manager will evict the pod.
@k8s-bot gce etcd3 e2e test this |
@k8s-bot pull-kubernetes-verify test this |
@k8s-bot kops aws e2e test this |
@jingxu97: The following tests failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
@k8s-bot kops aws e2e test this |
rebased, add /lgtm back |
Automatic merge from submit-queue |
|
This PR adds the support for isolating the emptyDir volume use. If user
sets a size limit for emptyDir volume, kubelet's eviction manager monitors its usage
and evict the pod if the usage exceeds the limit.
This feature is part of local storage capacity isolation and described in the proposal kubernetes/community#306
Release note: