[ci skip] kyverno: scale to 2 replicas, eliminate API calls from policies
- Scale admission controller to 2 replicas with topology spread across nodes - Rewrite inject-priority-class-from-tier: use namespaceSelector instead of API call per pod admission (eliminates Kyverno→API server round-trip) - Rewrite sync-tier-label-from-namespace: same namespaceSelector approach - Extract governance_tiers local to DRY up tier definitions
This commit is contained in:
parent
900f72d60d
commit
ef158ed431
2 changed files with 100 additions and 93 deletions
|
|
@ -28,6 +28,8 @@ resource "helm_release" "kyverno" {
|
||||||
}
|
}
|
||||||
|
|
||||||
admissionController = {
|
admissionController = {
|
||||||
|
replicas = 2
|
||||||
|
|
||||||
container = {
|
container = {
|
||||||
resources = {
|
resources = {
|
||||||
limits = {
|
limits = {
|
||||||
|
|
@ -53,12 +55,30 @@ resource "helm_release" "kyverno" {
|
||||||
failureThreshold = 4
|
failureThreshold = 4
|
||||||
successThreshold = 1
|
successThreshold = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Spread replicas across nodes for HA
|
||||||
|
topologySpreadConstraints = [
|
||||||
|
{
|
||||||
|
maxSkew = 1
|
||||||
|
topologyKey = "kubernetes.io/hostname"
|
||||||
|
whenUnsatisfiable = "DoNotSchedule"
|
||||||
|
labelSelector = {
|
||||||
|
matchLabels = {
|
||||||
|
"app.kubernetes.io/component" = "admission-controller"
|
||||||
|
"app.kubernetes.io/instance" = "kyverno"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
})]
|
})]
|
||||||
}
|
}
|
||||||
|
|
||||||
# To unlabel all:
|
# To unlabel all:
|
||||||
# kubectl label deployment,statefulset,daemonset --all-namespaces -l tier tier-
|
# kubectl label deployment,statefulset,daemonset --all-namespaces -l tier tier-
|
||||||
|
#
|
||||||
|
# Uses namespaceSelector to match tiers — no API call needed.
|
||||||
|
# One rule per tier so Kyverno resolves the tier value from its informer cache.
|
||||||
resource "kubernetes_manifest" "mutate_tier_from_namespace" {
|
resource "kubernetes_manifest" "mutate_tier_from_namespace" {
|
||||||
manifest = {
|
manifest = {
|
||||||
apiVersion = "kyverno.io/v1"
|
apiVersion = "kyverno.io/v1"
|
||||||
|
|
@ -67,49 +87,41 @@ resource "kubernetes_manifest" "mutate_tier_from_namespace" {
|
||||||
name = "sync-tier-label-from-namespace"
|
name = "sync-tier-label-from-namespace"
|
||||||
}
|
}
|
||||||
spec = {
|
spec = {
|
||||||
rules = [
|
rules = [for tier in local.governance_tiers : {
|
||||||
{
|
name = "sync-tier-${tier}"
|
||||||
name = "lookup-and-add-tier"
|
match = {
|
||||||
match = {
|
any = [
|
||||||
any = [
|
|
||||||
{
|
|
||||||
resources = {
|
|
||||||
kinds = ["Deployment", "StatefulSet", "DaemonSet"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
exclude = {
|
|
||||||
any = [
|
|
||||||
{
|
|
||||||
resources = {
|
|
||||||
namespaces = ["kube-system", "metallb-system", "n8n"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
# Context allows us to perform an API call to get Namespace metadata
|
|
||||||
context = [
|
|
||||||
{
|
{
|
||||||
name = "namespaceLabel"
|
resources = {
|
||||||
apiCall = {
|
kinds = ["Deployment", "StatefulSet", "DaemonSet"]
|
||||||
urlPath = "/api/v1/namespaces/{{request.namespace}}"
|
namespaceSelector = {
|
||||||
jmesPath = "metadata.labels.tier || 'default'"
|
matchLabels = {
|
||||||
|
tier = tier
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
mutate = {
|
}
|
||||||
patchStrategicMerge = {
|
exclude = {
|
||||||
metadata = {
|
any = [
|
||||||
labels = {
|
{
|
||||||
# Injects the variable discovered in the context above
|
resources = {
|
||||||
"+(tier)" = "{{namespaceLabel}}"
|
namespaces = ["kube-system", "metallb-system", "n8n"]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
mutate = {
|
||||||
|
patchStrategicMerge = {
|
||||||
|
metadata = {
|
||||||
|
labels = {
|
||||||
|
"+(tier)" = tier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@
|
||||||
# 3. ResourceQuotas (Kyverno generate) - hard ceiling on namespace resource consumption
|
# 3. ResourceQuotas (Kyverno generate) - hard ceiling on namespace resource consumption
|
||||||
# 4. Priority injection (Kyverno mutate) - set priorityClassName based on namespace tier label
|
# 4. Priority injection (Kyverno mutate) - set priorityClassName based on namespace tier label
|
||||||
|
|
||||||
|
locals {
|
||||||
|
governance_tiers = ["0-core", "1-cluster", "2-gpu", "3-edge", "4-aux"]
|
||||||
|
excluded_namespaces = ["kube-system", "metallb-system", "kyverno", "calico-system", "calico-apiserver"]
|
||||||
|
}
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Layer 1: PriorityClasses
|
# Layer 1: PriorityClasses
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
@ -661,6 +666,7 @@ resource "kubernetes_manifest" "generate_resourcequota_by_tier" {
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Automatically sets priorityClassName on Pods based on their namespace's tier label.
|
# Automatically sets priorityClassName on Pods based on their namespace's tier label.
|
||||||
# Skips pods that already have a priorityClassName set.
|
# Skips pods that already have a priorityClassName set.
|
||||||
|
# Uses namespaceSelector instead of API calls — no round-trip to the API server.
|
||||||
|
|
||||||
resource "kubernetes_manifest" "mutate_priority_from_tier" {
|
resource "kubernetes_manifest" "mutate_priority_from_tier" {
|
||||||
manifest = {
|
manifest = {
|
||||||
|
|
@ -674,69 +680,58 @@ resource "kubernetes_manifest" "mutate_priority_from_tier" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spec = {
|
spec = {
|
||||||
rules = [
|
rules = [for tier in local.governance_tiers : {
|
||||||
{
|
name = "inject-priority-${tier}"
|
||||||
name = "inject-priority-class"
|
match = {
|
||||||
match = {
|
any = [
|
||||||
any = [
|
|
||||||
{
|
|
||||||
resources = {
|
|
||||||
kinds = ["Pod"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
exclude = {
|
|
||||||
any = [
|
|
||||||
{
|
|
||||||
resources = {
|
|
||||||
namespaces = ["kube-system", "metallb-system", "kyverno", "calico-system", "calico-apiserver"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
context = [
|
|
||||||
{
|
{
|
||||||
name = "tierLabel"
|
resources = {
|
||||||
apiCall = {
|
kinds = ["Pod"]
|
||||||
urlPath = "/api/v1/namespaces/{{request.namespace}}"
|
namespaceSelector = {
|
||||||
jmesPath = "metadata.labels.tier || ''"
|
matchLabels = {
|
||||||
|
tier = tier
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
preconditions = {
|
|
||||||
all = [
|
|
||||||
{
|
|
||||||
key = "{{request.object.spec.priorityClassName || ''}}"
|
|
||||||
operator = "Equals"
|
|
||||||
value = ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key = "{{tierLabel}}"
|
|
||||||
operator = "NotEquals"
|
|
||||||
value = ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
mutate = {
|
|
||||||
patchesJson6902 = yamlencode([
|
|
||||||
{
|
|
||||||
op = "remove"
|
|
||||||
path = "/spec/priority"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
op = "remove"
|
|
||||||
path = "/spec/preemptionPolicy"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
op = "add"
|
|
||||||
path = "/spec/priorityClassName"
|
|
||||||
value = "tier-{{tierLabel}}"
|
|
||||||
}
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
exclude = {
|
||||||
|
any = [
|
||||||
|
{
|
||||||
|
resources = {
|
||||||
|
namespaces = local.excluded_namespaces
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
preconditions = {
|
||||||
|
all = [
|
||||||
|
{
|
||||||
|
key = "{{request.object.spec.priorityClassName || ''}}"
|
||||||
|
operator = "Equals"
|
||||||
|
value = ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
mutate = {
|
||||||
|
patchesJson6902 = yamlencode([
|
||||||
|
{
|
||||||
|
op = "remove"
|
||||||
|
path = "/spec/priority"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op = "remove"
|
||||||
|
path = "/spec/preemptionPolicy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op = "add"
|
||||||
|
path = "/spec/priorityClassName"
|
||||||
|
value = "tier-${tier}"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue