All Policies
Kubecost Proactive Cost Control
Kubecost Enterprise allows users to define budgets for Namespaces and clusters as well as predict the cost of new Deployments based on historical cost data. By combining these abilities, users can achieve proactive cost controls for clusters with Kubecost installed by denying Deployments which would exceed the remaining configured monthly budget, if applicable. This policy checks for the creation of Deployments and compares the predicted cost of the Deployment to the remaining amount in the monthly budget, if one is found. If the predicted cost is greater than the remaining budget, the Deployment is denied. This policy requires Kubecost Enterprise at a version of 1.108 or greater.
Policy Definition
/kubecost/kubecost-proactive-cost-control/kubecost-proactive-cost-control.yaml
1apiVersion: kyverno.io/v1
2kind: ClusterPolicy
3metadata:
4 name: kubecost-proactive-cost-control
5 annotations:
6 policies.kyverno.io/title: Kubecost Proactive Cost Control
7 policies.kyverno.io/category: Kubecost
8 policies.kyverno.io/severity: medium
9 policies.kyverno.io/subject: Deployment
10 policies.kyverno.io/minversion: 1.11.0
11 kyverno.io/kyverno-version: 1.11.4
12 kyverno.io/kubernetes-version: "1.26"
13 policies.kyverno.io/description: >-
14 Kubecost Enterprise allows users to define budgets for Namespaces and clusters
15 as well as predict the cost of new Deployments based on historical cost data.
16 By combining these abilities, users can achieve proactive cost controls for
17 clusters with Kubecost installed by denying Deployments which would exceed the
18 remaining configured monthly budget, if applicable. This policy checks for the creation of
19 Deployments and compares the predicted cost of the Deployment to the remaining amount
20 in the monthly budget, if one is found. If the predicted cost is greater than the remaining
21 budget, the Deployment is denied. This policy requires Kubecost Enterprise
22 at a version of 1.108 or greater.
23spec:
24 validationFailureAction: Audit
25 rules:
26 - name: enforce-monthly-namespace-budget
27 match:
28 any:
29 - resources:
30 kinds:
31 - Deployment
32 operations:
33 - CREATE
34 # First, check if this Namespace is subject to a budget.
35 # If it is not, always allow the Deployment.
36 preconditions:
37 all:
38 - key: "{{ budget }}"
39 operator: NotEquals
40 value: nobudget
41 context:
42 # Get the budget of the destination Namespace. Select the first budget returned which matches the Namespace.
43 # If no budget is found, set budget to "nobudget".
44 - name: budget
45 apiCall:
46 method: GET
47 service:
48 url: http://kubecost-cost-analyzer.kubecost:9090/model/budgets
49 jmesPath: "data[?values.namespace[?contains(@,'{{ request.namespace }}')]] | [0] || 'nobudget'"
50 # Call the prediction API and pass it the Deployment from the admission request. Extract the totalMonthlyRate.
51 - name: predictedMonthlyCost
52 apiCall:
53 method: POST
54 data:
55 - key: apiVersion
56 value: "{{ request.object.apiVersion }}"
57 - key: kind
58 value: "{{ request.object.kind }}"
59 - key: spec
60 value: "{{ request.object.spec }}"
61 service:
62 url: http://kubecost-cost-analyzer.kubecost:9090/model/prediction/speccost?clusterID=cluster-one&defaultNamespace=default
63 jmesPath: "[0].costChange.totalMonthlyRate"
64 # Calculate the budget that remains from the window by subtracting the currentSpend from the spendLimit.
65 - name: remainingBudget
66 variable:
67 jmesPath: subtract(budget.spendLimit,budget.currentSpend)
68 validate:
69 message: >-
70 This Deployment, which costs ${{ round(predictedMonthlyCost, `2`) }} to run for a month,
71 will overrun the remaining budget of ${{ round(remainingBudget,`2`) }}. Please seek approval or request
72 a Policy Exception.
73 # Deny the request if the predictedMonthlyCost is greater than the remainingBudget.
74 deny:
75 conditions:
76 all:
77 - key: "{{ predictedMonthlyCost }}"
78 operator: GreaterThan
79 value: "{{ remainingBudget }}"