apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: insert-podantiaffinity
spec:
  rules:
    - name: insert-podantiaffinity
      match:
        resources:
          kinds:
            - Deployment
      preconditions:
        # This precondition ensures that the label `app` is applied to Pods within the Deployment resource.
      - key: "{{request.object.metadata.labels.app}}"
        operator: NotEquals
        value: ""
      # Mutates the Deployment resource to add fields.
      mutate:
        patchStrategicMerge:
          spec:
            template:
              spec:
                # Add the `affinity` key and others if not already specified in the Deployment manifest.
                +(affinity):
                  +(podAntiAffinity):
                    +(preferredDuringSchedulingIgnoredDuringExecution):
                      - weight: 1
                        podAffinityTerm:
                          topologyKey: "kubernetes.io/hostname"
                          labelSelector:
                            matchExpressions:
                            - key: app
                              operator: In
                              values:
                              - "{{request.object.metadata.labels.app}}"