Skip to content

Commit 0c66ef4

Browse files
authored
Add rules for node and pod affinity (#65)
* Add rules for node and pod affinity Signed-off-by: wwwil <[email protected]> * Remove Pod affinity rule Signed-off-by: wwwil <[email protected]> * Add Rego rules and test for node affinity rule Signed-off-by: wwwil <[email protected]>
1 parent 4553b39 commit 0c66ef4

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

preflight-packages/jetstack.io/pods/pods.rego

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,12 @@ deployments_across_multiple_namespaces[message] {
186186
pod.metadata.namespace == "default"
187187
message := sprintf("pod '%s' is running in default namespace", [pod.metadata.name])
188188
}
189+
190+
# Affinity
191+
192+
# Node affinity used
193+
node_affinity_used[message] {
194+
pod := pods.items[_]
195+
pod.spec.nodeSelector
196+
message := sprintf("pod '%s' is using node selector", [pod.metadata.name])
197+
}

preflight-packages/jetstack.io/pods/pods_test.rego

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,3 +1826,64 @@ test_deployments_across_multiple_namespaces_multiple_default {
18261826
}
18271827
)
18281828
}
1829+
1830+
# Affinity
1831+
1832+
# Node affinity used
1833+
test_node_affinity_used_used {
1834+
output := node_affinity_used with input as pods(
1835+
[
1836+
{
1837+
"metadata": {
1838+
"name": "foo",
1839+
"namespace": "default"
1840+
},
1841+
"spec": {
1842+
"affinity": {
1843+
"nodeAffinity": {
1844+
"requiredDuringSchedulingIgnoredDuringExecution": {
1845+
"nodeSelectorTerms": [
1846+
{
1847+
"matchExpressions": [
1848+
{
1849+
"key": "kubernetes.io/e2e-az-name",
1850+
"operator": "In",
1851+
"values": [
1852+
"e2e-az1",
1853+
"e2e-az2"
1854+
]
1855+
}
1856+
]
1857+
}
1858+
]
1859+
}
1860+
}
1861+
}
1862+
}
1863+
}
1864+
]
1865+
)
1866+
assert_allowed(output)
1867+
}
1868+
test_node_affinity_used_node_selector {
1869+
output := node_affinity_used with input as pods(
1870+
[
1871+
{
1872+
"metadata": {
1873+
"name": "foo",
1874+
"namespace": "default"
1875+
},
1876+
"spec": {
1877+
"nodeSelector": {
1878+
"disktype": "ssd"
1879+
}
1880+
}
1881+
}
1882+
]
1883+
)
1884+
assert_violates(output,
1885+
{
1886+
"pod 'foo' is using node selector"
1887+
}
1888+
)
1889+
}

preflight-packages/jetstack.io/pods/policy-manifest.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,3 +277,24 @@ sections:
277277
section to include a `namespace`.
278278
links:
279279
- "https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/"
280+
- id: affinity
281+
name: Affinity
282+
rules:
283+
- id: node_affinity_used
284+
name: Node affinity used
285+
description: >
286+
In some cases it may be preferable or required for a Pod to run on a
287+
particular Node. This is usually when some Nodes have different resources,
288+
such as additional memory or SSD storage, that is beneficial or required
289+
for certain workloads.
290+
remediation: >
291+
Pods can be assigned to nodes using `nodeSelector`, however this is a very
292+
limited constraint. Instead it's recommended that `nodeAffinity` is used
293+
as it greatly expands the types of constraints you can express. There are
294+
two types of node affinity;
295+
`requiredDuringSchedulingIgnoredDuringExecution` which specifies a hard
296+
requirement, and `preferredDuringSchedulingIgnoredDuringExecution` which
297+
specifies a preference. Full details of the constraints can be found in
298+
the linked documentation.
299+
links:
300+
- "https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity"

0 commit comments

Comments
 (0)