<p dir="auto">Problem</p>
<p dir="auto">Some predicates may need precomputations or "preconditions" to be met before they can run.</p>
<ul dir="auto">
<li>As of now, those preconditions may or may not be gauranteed to exist in the <code class="notranslate">predicateMetadata</code> struct.</li>
<li>Some of those predicates may be able to bootstrap some of their own data (by redoing a query, if the predicate metadata  is incomplete).</li>
</ul>
<p dir="auto">Solution</p>
<p dir="auto">We should decide wether (1) predicates should try to create data which is precomputed and (2) if so, what the best way to do this is which is scalable and doesnt lead to duplication of error handling/querying.</p>
<p dir="auto">Two possible solutions:</p>
<ul dir="auto">
<li>make any predicate's precompute function (as of now, really we only have one - but there may be others) stand alone - so that it can be called outside of the standard precomputation  steps provided by the scheduler framework (this might help in corner cases - i.e. if a query fails randomly, the predicate has a retry built-in - but it will lead to duplication of logic).</li>
<li>Each predicates precompute function stays encapsulated, and predicates simply have preconditions of checking for missing data (this is simpler to maintain from the code perspective, but might be some corner cases where it hurts us).  Once we decide, we would update the predicates_test functions where necessary to include test cases for when precomputation is enabled.</li>
</ul>
<p dir="auto"><a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/wojtek-t/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/wojtek-t">@wojtek-t</a> Suggesting this as a follow on to <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="180094056" data-permission-text="Title is private" data-url="https://github.com/kubernetes/kubernetes/issues/33763" data-hovercard-type="pull_request" data-hovercard-url="/kubernetes/kubernetes/pull/33763/hovercard" href="https://github.com/kubernetes/kubernetes/pull/33763">#33763</a> .</p>
<p dir="auto">Currently in the existing implementation, how should a taint be unique (i.e. by <code class="notranslate">key</code> or <code class="notranslate">&lt;key, effect&gt;</code>) on a node is not clear,</p>
<ol dir="auto">
<li>server side validation don't actually check if there are duplicated taints any reject the request.</li>
<li>kubectl command has an implicit semantic that taint is unique by key.</li>
</ol>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoScheduleNoAdmitNoExecute'.
# If a taint with that key already exists, its value and effect are replaced as specified.
$ kubectl taint nodes foo dedicated=special-user:NoScheduleNoAdmitNoExecute

# Remove from node 'foo' the taint with key 'dedicated' if one exists.
$ kubectl taint nodes foo dedicated-"><pre class="notranslate"><span class="pl-c"><span class="pl-c">#</span> Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoScheduleNoAdmitNoExecute'.</span>
<span class="pl-c"><span class="pl-c">#</span> If a taint with that key already exists, its value and effect are replaced as specified.</span>
$ kubectl taint nodes foo dedicated=special-user:NoScheduleNoAdmitNoExecute

<span class="pl-c"><span class="pl-c">#</span> Remove from node 'foo' the taint with key 'dedicated' if one exists.</span>
$ kubectl taint nodes foo dedicated-</pre></div>
<p dir="auto">Discussed with <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/davidopp/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/davidopp">@davidopp</a> and <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/bgrant0607/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/bgrant0607">@bgrant0607</a> , David's idea is:</p>
<blockquote>
<p dir="auto">We cannot make taint <code class="notranslate">key</code> be unique on a node; we can only make <code class="notranslate">&lt;taint, effect&gt;</code> be unique. The reason is that we want to be able to express all of these (I am copying this from my <a href="https://github.com/kubernetes/kubernetes/issues/28082#issue-162318430" data-hovercard-type="issue" data-hovercard-url="/kubernetes/kubernetes/issues/28082/hovercard">comment</a> here):</p>
<ul dir="auto">
<li>don't schedule me there and evict me if I'm already running there</li>
<li>don't schedule me there but leave me bound if I'm already running there</li>
<li>schedule me there and leave me bound if I'm already running there</li>
</ul>
<p dir="auto">This means we need to decouple "no schedule" and "no execute" effects (let's ignore the NoAdmit part)<br>
I think there are only two ways to do it:</p>
<ol dir="auto">
<li>(original plan) we have NoSchedule effect and NoScheduleNoExecute effect</li>
<li>(suggested new plan) we have NoSchedule effect and NoExecute effect</li>
</ol>
<p dir="auto">In either approach, you need to put two separate taints, one with each of the effects, on a node if you want to allow some pods to request only "no schedule" (i.e. leave me bound if already running) and some pods to request "no schedule and no execute." (The only difference between the two approaches is which tolerations you need for the different use cases, but in both approaches you need two different taints with the same key and different effects if you want to allow the full flexibility.)</p>
</blockquote>
<p dir="auto">As discussed, we should make taints unique by <code class="notranslate">&lt;key, effect&gt;</code> on a node, basically, the following two steps are needed:</p>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> add some validation check that reject duplicated taints that have the same <code class="notranslate">&lt;key, effect&gt;</code></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> modify the existing semantic of <code class="notranslate">kubectl taint</code> command to:</li>
</ul>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoScheduleNoAdmit'.
# If a taint with that key and effect already exists, its value is replaced as specified.
$ kubectl taint nodes foo dedicated=special-user:NoScheduleNoAdmit

# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoScheduleNoAdmit' if one exists.
$ kubectl taint nodes foo dedicated:NoScheduleNoAdmit-"><pre class="notranslate"><span class="pl-c"><span class="pl-c">#</span> Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoScheduleNoAdmit'.</span>
<span class="pl-c"><span class="pl-c">#</span> If a taint with that key and effect already exists, its value is replaced as specified.</span>
$ kubectl taint nodes foo dedicated=special-user:NoScheduleNoAdmit

<span class="pl-c"><span class="pl-c">#</span> Remove from node 'foo' the taint with key 'dedicated' and effect 'NoScheduleNoAdmit' if one exists.</span>
$ kubectl taint nodes foo dedicated:NoScheduleNoAdmit-</pre></div>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox">  If the effect is omitted in the kubectlcommand line, treat that as a wildcard (all effects). That would be especially useful for removing taints.</li>
</ul>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# Remove from node 'foo' all the taints with key 'dedicated'
$ kubectl taint nodes foo dedicated-"><pre class="notranslate"><span class="pl-c"><span class="pl-c">#</span> Remove from node 'foo' all the taints with key 'dedicated'</span>
$ kubectl taint nodes foo dedicated-</pre></div>