From 3dd9aa6ec356cf03390dcd41b1a02d34b5ba934a Mon Sep 17 00:00:00 2001 From: Anudeep Nalla <121174814+anuddeeph1@users.noreply.github.com> Date: Tue, 6 Aug 2024 16:57:25 +0530 Subject: [PATCH] Add policy Ensure HPA for Deployments (#1080) * added policy to check HPA Signed-off-by: anuddeeph1 * deleted .chainsaw.yaml Signed-off-by: anuddeeph1 * modified changes in policies Signed-off-by: anuddeeph1 * modified subject in check-hpa-exists.yaml Signed-off-by: anuddeeph1 * modified subject in artifacthub-pkg.yml Signed-off-by: anuddeeph1 --------- Signed-off-by: anuddeeph1 Co-authored-by: Chip Zoller --- .../chainsaw-step-01-assert-1.yaml | 6 +++ .../.chainsaw-test/chainsaw-test.yaml | 32 ++++++++++++++ .../deployment-with-hpa-good.yaml | 29 ++++++++++++ .../deployment-without-hpa-bad.yaml | 28 ++++++++++++ .../check-hpa-exists/.chainsaw-test/hpa.yaml | 11 +++++ other/check-hpa-exists/artifacthub-pkg.yml | 21 +++++++++ other/check-hpa-exists/check-hpa-exists.yaml | 44 +++++++++++++++++++ 7 files changed, 171 insertions(+) create mode 100755 other/check-hpa-exists/.chainsaw-test/chainsaw-step-01-assert-1.yaml create mode 100755 other/check-hpa-exists/.chainsaw-test/chainsaw-test.yaml create mode 100644 other/check-hpa-exists/.chainsaw-test/deployment-with-hpa-good.yaml create mode 100644 other/check-hpa-exists/.chainsaw-test/deployment-without-hpa-bad.yaml create mode 100644 other/check-hpa-exists/.chainsaw-test/hpa.yaml create mode 100644 other/check-hpa-exists/artifacthub-pkg.yml create mode 100644 other/check-hpa-exists/check-hpa-exists.yaml diff --git a/other/check-hpa-exists/.chainsaw-test/chainsaw-step-01-assert-1.yaml b/other/check-hpa-exists/.chainsaw-test/chainsaw-step-01-assert-1.yaml new file mode 100755 index 000000000..c7e2ac55c --- /dev/null +++ b/other/check-hpa-exists/.chainsaw-test/chainsaw-step-01-assert-1.yaml @@ -0,0 +1,6 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: check-hpa-exists +status: + ready: true diff --git a/other/check-hpa-exists/.chainsaw-test/chainsaw-test.yaml b/other/check-hpa-exists/.chainsaw-test/chainsaw-test.yaml new file mode 100755 index 000000000..598d6c7a8 --- /dev/null +++ b/other/check-hpa-exists/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,32 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: check-hpa-exists +spec: + steps: + - name: step-01 + try: + - apply: + file: ../check-hpa-exists.yaml + - patch: + resource: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: check-hpa-exists + spec: + validationFailureAction: Enforce + - assert: + file: chainsaw-step-01-assert-1.yaml + - name: step-02 + try: + - apply: + file: hpa.yaml + - apply: + file: deployment-with-hpa-good.yaml + - apply: + expect: + - check: + ($error != null): true + file: deployment-without-hpa-bad.yaml diff --git a/other/check-hpa-exists/.chainsaw-test/deployment-with-hpa-good.yaml b/other/check-hpa-exists/.chainsaw-test/deployment-with-hpa-good.yaml new file mode 100644 index 000000000..aba909034 --- /dev/null +++ b/other/check-hpa-exists/.chainsaw-test/deployment-with-hpa-good.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment-uses-hpa + labels: + app: httpd-app +spec: + replicas: 1 + selector: + matchLabels: + app: httpd-app + template: + metadata: + labels: + app: httpd-app + spec: + containers: + - name: httpd-container + image: httpd:latest + ports: + - containerPort: 80 + resources: + requests: + cpu: "10m" + memory: "12Mi" + limits: + cpu: "25m" + memory: "25Mi" diff --git a/other/check-hpa-exists/.chainsaw-test/deployment-without-hpa-bad.yaml b/other/check-hpa-exists/.chainsaw-test/deployment-without-hpa-bad.yaml new file mode 100644 index 000000000..a9ef9299d --- /dev/null +++ b/other/check-hpa-exists/.chainsaw-test/deployment-without-hpa-bad.yaml @@ -0,0 +1,28 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment-without-hpa + labels: + app: app-without-hpa +spec: + replicas: 1 + selector: + matchLabels: + app: app-without-hpa + template: + metadata: + labels: + app: app-without-hpa + spec: + containers: + - name: nginx-container + image: nginx:latest + ports: + - containerPort: 80 + resources: + requests: + cpu: "10m" + memory: "12Mi" + limits: + cpu: "25m" + memory: "25Mi" diff --git a/other/check-hpa-exists/.chainsaw-test/hpa.yaml b/other/check-hpa-exists/.chainsaw-test/hpa.yaml new file mode 100644 index 000000000..29cfff2b5 --- /dev/null +++ b/other/check-hpa-exists/.chainsaw-test/hpa.yaml @@ -0,0 +1,11 @@ +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: httpd-deployment +spec: + maxReplicas: 3 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: deployment-uses-hpa diff --git a/other/check-hpa-exists/artifacthub-pkg.yml b/other/check-hpa-exists/artifacthub-pkg.yml new file mode 100644 index 000000000..e097f6f1c --- /dev/null +++ b/other/check-hpa-exists/artifacthub-pkg.yml @@ -0,0 +1,21 @@ +name: check-hpa-exists +version: 1.0.0 +displayName: Ensure HPA for Deployments +createdAt: "2024-07-19T13:02:58Z" +description: >- + This policy ensures that Deployments, ReplicaSets, StatefulSets, and DaemonSets are only allowed if they have a corresponding Horizontal Pod Autoscaler (HPA) configured in the same namespace. The policy checks for the presence of an HPA that targets the resource and denies the creation or update of the resource if no such HPA exists. This policy helps enforce scaling practices and ensures that resources are managed efficiently. +install: |- + ```shell + kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/other/check-hpa-exists/check-hpa-exists.yaml + ``` +keywords: + - kyverno + - Other +readme: | + This policy ensures that Deployments, ReplicaSets, StatefulSets, and DaemonSets are only allowed if they have a corresponding Horizontal Pod Autoscaler (HPA) configured in the same namespace. The policy checks for the presence of an HPA that targets the resource and denies the creation or update of the resource if no such HPA exists. This policy helps enforce scaling practices and ensures that resources are managed efficiently. + Refer to the documentation for more details on Kyverno annotations: https://artifacthub.io/docs/topics/annotations/kyverno/ +annotations: + kyverno/category: "Other" + kyverno/kubernetesVersion: "1.28" + kyverno/subject: "Deployment,ReplicaSet,StatefulSet,DaemonSet" +digest: 4b4c29dcaa05ad8967b2d1707c882aca05e622be135dff2e5c0c2decce3047c8 diff --git a/other/check-hpa-exists/check-hpa-exists.yaml b/other/check-hpa-exists/check-hpa-exists.yaml new file mode 100644 index 000000000..58d8eb274 --- /dev/null +++ b/other/check-hpa-exists/check-hpa-exists.yaml @@ -0,0 +1,44 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: check-hpa-exists + annotations: + policies.kyverno.io/title: Ensure HPA for Deployments + policies.kyverno.io/category: Other + policies.kyverno.io/severity: medium + kyverno.io/kyverno-version: 1.11.0 + policies.kyverno.io/minversion: 1.9.0 + kyverno.io/kubernetes-version: "1.28" + policies.kyverno.io/subject: Deployment,ReplicaSet,StatefulSet,DaemonSet + policies.kyverno.io/description: >- + This policy ensures that Deployments, ReplicaSets, StatefulSets, and DaemonSets are only allowed + if they have a corresponding Horizontal Pod Autoscaler (HPA) configured in the same namespace. + The policy checks for the presence of an HPA that targets the resource and denies the creation or update + of the resource if no such HPA exists. This policy helps enforce scaling practices + and ensures that resources are managed efficiently. +spec: + validationFailureAction: Audit + background: true + rules: + - name: validate-hpa + match: + any: + - resources: + kinds: + - Deployment + - ReplicaSet + - StatefulSet + - DaemonSet + context: + - name: hpas + apiCall: + urlPath: "/apis/autoscaling/v1/namespaces/{{ request.namespace }}/horizontalpodautoscalers" + jmesPath: "items[].spec.scaleTargetRef.name" + validate: + message: "Deployment is not allowed without a corresponding HPA." + deny: + conditions: + all: + - key: "{{ request.object.metadata.name }}" + operator: AnyNotIn + value: "{{ hpas }}"