Add policy demo to handle topology spread
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: enforce-topology-spread
|
||||
namespace: rossum
|
||||
annotations:
|
||||
policies.kyverno.io/title: Spread pods based on zone topology
|
||||
policies.kyverno.io/subject: Pod
|
||||
spec:
|
||||
# Depending on the desired outcome for the applications, there could be multiple solutions
|
||||
# to the problem, naturally, the most complex and difficult was chosen in order to:
|
||||
# 1. Preserve existing topology spread if defined
|
||||
# 2. Inject topology spread if not defined
|
||||
# 3. Override any settings of topology spread based on zones
|
||||
#
|
||||
# see https://github.com/kyverno/kyverno/issues/10655 for details why it cannot
|
||||
# be achieved using the merge patch
|
||||
rules:
|
||||
# Check if existing zone topology spread is defined and overwrite it
|
||||
- name: enforce-zone-topology-spread-configuration
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Deployment
|
||||
- StatefulSet
|
||||
selector:
|
||||
matchLabels:
|
||||
# Additional validation policies would be needed to ensure the label is present on every resource
|
||||
app.kubernetes.io/name: "*"
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
mutate:
|
||||
foreach:
|
||||
- list: "request.object.spec.template.spec.topologySpreadConstraints || []"
|
||||
# Use precondition to mutate
|
||||
preconditions:
|
||||
any:
|
||||
- key: "{{ element.topologyKey }}"
|
||||
operator: Equals
|
||||
value: topology.kubernetes.io/zone
|
||||
patchesJson6902: |-
|
||||
- path: /spec/template/spec/topologySpreadConstraints/{{elementIndex}}
|
||||
op: replace
|
||||
value:
|
||||
maxSkew: 1
|
||||
topologyKey: topology.kubernetes.io/zone
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: '{{request.object.spec.selector.matchLabels."app.kubernetes.io/name"}}'
|
||||
# Check if the zone topology spread is not defined and inject it
|
||||
- name: inject-zone-topology-spread
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Deployment
|
||||
- StatefulSet
|
||||
selector:
|
||||
matchLabels:
|
||||
# Additional validation policies would be needed to ensure the label is present on every resource
|
||||
app.kubernetes.io/name: "*"
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
mutate:
|
||||
foreach:
|
||||
- list: "request.object.spec.template.spec.topologySpreadConstraints || []"
|
||||
# Use precondition to mutate
|
||||
preconditions:
|
||||
any:
|
||||
- key: "{{ request.object.spec.template.spec.topologySpreadConstraints[].topologyKey }}"
|
||||
operator: AllNotIn
|
||||
value:
|
||||
- topology.kubernetes.io/zone
|
||||
patchesJson6902: |-
|
||||
- path: /spec/template/spec/topologySpreadConstraints/0
|
||||
op: add
|
||||
value:
|
||||
maxSkew: 1
|
||||
topologyKey: topology.kubernetes.io/zone
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: '{{request.object.spec.selector.matchLabels."app.kubernetes.io/name"}}'
|
||||
# Create topology spread if it does not exist
|
||||
- name: create-topology-spread
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Deployment
|
||||
- StatefulSet
|
||||
selector:
|
||||
matchLabels:
|
||||
# Additional validation policies would be needed to ensure the label is present on every resource
|
||||
app.kubernetes.io/name: "*"
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
mutate:
|
||||
patchStrategicMerge:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
# Ensure the zone topology spread is present if undefined
|
||||
+(topologySpreadConstraints):
|
||||
- maxSkew: 1
|
||||
topologyKey: topology.kubernetes.io/zone
|
||||
# Depending on the workload and requirements, ScheduleAnyway or DoNotSchedule might be chosen
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: '{{request.object.spec.selector.matchLabels."app.kubernetes.io/name"}}'
|
||||
Reference in New Issue
Block a user