> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Preconditions

> Demonstrates using Kyverno preconditions to validate NodePort Services and enforce externalTrafficPolicy set to Local.

In this lesson we use Kyverno preconditions to make a ClusterPolicy that only runs against Services of type `NodePort`. When the precondition is met, the policy validates that `spec.externalTrafficPolicy` is set to `Local`.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/rzUP76niRaOmk997/images/Prep-Course-Kyverno-Certified-Associate-KCA-Certification/Resource-Filters/Demo-Preconditions/preconditions-demo-kodekloud-background.jpg?fit=max&auto=format&n=rzUP76niRaOmk997&q=85&s=cef5f4f8af74f9775a048606a060fd66" alt="The image features the words &#x22;Preconditions&#x22; and &#x22;Demo&#x22; on a white and blue-green background, with a copyright notice for KodeKloud." width="1920" height="1080" data-path="images/Prep-Course-Kyverno-Certified-Associate-KCA-Certification/Resource-Filters/Demo-Preconditions/preconditions-demo-kodekloud-background.jpg" />
</Frame>

Goal

* Validate Services only when `spec.type` is `NodePort`.
* Enforce `spec.externalTrafficPolicy: Local` for those NodePort Services.

<Callout icon="lightbulb" color="#1CB2FE">
  Preconditions are evaluated against the incoming admission request. If preconditions pass, the rule's `validate`/`mutate`/`generate` actions run; otherwise the rule is skipped. Use preconditions to make policies highly selective and avoid unnecessary validation on unrelated resources.
</Callout>

Policy manifest (ClusterPolicy)

```yaml theme={null}
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: validate-nodeport-trafficpolicy
spec:
  rules:
    - name: validate-nodeport-trafficpolicy
      match:
        any:
          - resources:
              kinds:
                - Service
      preconditions:
        all:
          - key: "{{ request.object.spec.type }}"
            operator: Equals
            value: NodePort
      validationFailureAction: enforce
      validate:
        message: "All NodePort Services must use an externalTrafficPolicy of Local."
        pattern:
          spec:
            externalTrafficPolicy: Local
```

What this policy does

* `match` narrows targets to Kubernetes `Service` resources.
* `preconditions` further limit execution to Services whose `spec.type` equals `NodePort`.
* When the precondition passes, the `validate` block enforces that `spec.externalTrafficPolicy` is `Local`.
* If the precondition does not pass (for example, a `ClusterIP` Service), the rule is skipped.

Apply the policy

```bash theme={null}
kubectl apply -f validate-nodeport-trafficpolicy.yaml
```

Verify the ClusterPolicy is ready

```bash theme={null}
kubectl get cpol validate-nodeport-trafficpolicy
```

Example output:

```plaintext theme={null}
NAME                             ADMISSION   BACKGROUND   READY   AGE
validate-nodeport-trafficpolicy  true        true         Ready   10s
```

Test cases
We create three Service examples to demonstrate the policy behavior:

| Test case     | Service type | externalTrafficPolicy | Expected outcome                                               |
| ------------- | ------------ | --------------------- | -------------------------------------------------------------- |
| Bad NodePort  | `NodePort`   | `Cluster`             | Blocked by Kyverno; validation fails                           |
| Good NodePort | `NodePort`   | `Local`               | Created successfully                                           |
| ClusterIP     | `ClusterIP`  | n/a                   | Policy precondition fails → Rule skipped; created successfully |

1. Bad NodePort Service (should be rejected)

```bash theme={null}
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: bad-nodeport-service
spec:
  type: NodePort
  selector:
    app: bad-app
  ports:
    - port: 80
      targetPort: 8080
  externalTrafficPolicy: Cluster
EOF
```

Expected admission webhook error:

```plaintext theme={null}
Error from server: error when creating "STDIN": admission webhook "validate.kyverno.svc-fail" denied the request:
resource Service/default/bad-nodeport-service was blocked due to the following policies

validate-nodeport-trafficpolicy:
  validate-nodeport-trafficpolicy: 'validation error: All NodePort Services must use
    an externalTrafficPolicy of Local. rule validate-nodeport-trafficpolicy failed
    at path /spec/externalTrafficPolicy/'
```

<Callout icon="warning" color="#FF6B6B">
  The admission webhook will block creation when the policy's `validationFailureAction` is `enforce`. Inspect Kyverno logs and events if an expected create is denied.
</Callout>

2. Good NodePort Service (should be accepted)

```bash theme={null}
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: good-nodeport-service
spec:
  type: NodePort
  selector:
    app: good-app
  ports:
    - port: 80
      targetPort: 8080
  externalTrafficPolicy: Local
EOF
```

Expected response:

```plaintext theme={null}
service/good-nodeport-service created
```

3. ClusterIP Service (precondition not met; policy skipped — should be accepted)

```bash theme={null}
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: clusterip-service
spec:
  type: ClusterIP
  selector:
    app: clusterip-app
  ports:
    - port: 80
      targetPort: 8080
EOF
```

Expected response:

```plaintext theme={null}
service/clusterip-service created
```

Summary and references

* Use `match` to restrict resources to specific kinds (here: `Service`).
* Use `preconditions` to further filter requests before running policy logic.
* The `validate` block runs only when preconditions succeed; otherwise the rule is skipped.
* For more details, see the Kyverno documentation:
  * Kyverno documentation: [https://kyverno.io/docs/](https://kyverno.io/docs/)
  * Kubernetes Services: [https://kubernetes.io/docs/concepts/services-networking/service/](https://kubernetes.io/docs/concepts/services-networking/service/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/kyverno-certified-associate/module/65cbd27d-801d-4468-b4c5-47391c833127/lesson/3fd51029-2735-4b64-81c3-a5d8b16584cb" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/kyverno-certified-associate/module/65cbd27d-801d-4468-b4c5-47391c833127/lesson/64e85186-86bd-4f80-b9ad-a07807440c96" />
</CardGroup>
