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 }}"
yaml