|
| 1 | +--- |
| 2 | +title: FinOps Agent |
| 3 | +description: Configure the FinOps Agent in OpenChoreo for AI-powered cloud cost analysis and optimization. |
| 4 | +--- |
| 5 | + |
| 6 | +import CodeBlock from "@theme/CodeBlock"; |
| 7 | +import { versions } from "../_constants.mdx"; |
| 8 | + |
| 9 | +# FinOps Agent |
| 10 | + |
| 11 | +The FinOps Agent is an AI-powered component that analyzes Kubernetes resource usage and cloud cost data from your OpenChoreo components to generate reports with cost optimization recommendations. It integrates with Large Language Models (LLMs) to provide cost attribution, rightsizing suggestions, and actionable insights to help teams reduce cloud spend. |
| 12 | + |
| 13 | +## Prerequisites |
| 14 | + |
| 15 | +Before enabling the FinOps Agent, ensure the following: |
| 16 | + |
| 17 | +- OpenChoreo Observability Plane installed with at least a metrics module. |
| 18 | +- An LLM API key from [OpenAI](https://platform.openai.com/) (support for other providers coming soon) |
| 19 | +- [Metrics collection configured](../platform-engineer-guide/observability-alerting.mdx) for your components. |
| 20 | + |
| 21 | +## Enabling the FinOps Agent |
| 22 | + |
| 23 | +### Step 1: Create the FinOps Agent Secret |
| 24 | + |
| 25 | +The FinOps Agent requires a Kubernetes Secret named `finops-agent` in the `openchoreo-observability-plane` namespace with the following keys: |
| 26 | + |
| 27 | +| Key | Description | |
| 28 | +| --------------------- | -------------------------------------------------- | |
| 29 | +| `LLM_API_KEY` | Your LLM provider API key | |
| 30 | +| `OAUTH_CLIENT_SECRET` | OAuth client secret (only needed for external IdP) | |
| 31 | + |
| 32 | +You can create this secret using any method you prefer. If you followed the [Try It Out on k3d locally](../getting-started/try-it-out/on-k3d-locally.mdx) guide, you can follow along: |
| 33 | + |
| 34 | +```bash |
| 35 | +kubectl exec -n openbao openbao-0 -- \ |
| 36 | + env BAO_ADDR=http://127.0.0.1:8200 BAO_TOKEN=root \ |
| 37 | + bao kv put secret/finops-llm-api-key value="<YOUR_LLM_API_KEY>" |
| 38 | +``` |
| 39 | + |
| 40 | +```bash |
| 41 | +kubectl apply -f - <<EOF |
| 42 | +apiVersion: external-secrets.io/v1 |
| 43 | +kind: ExternalSecret |
| 44 | +metadata: |
| 45 | + name: finops-agent |
| 46 | + namespace: openchoreo-observability-plane |
| 47 | +spec: |
| 48 | + refreshInterval: 1h |
| 49 | + secretStoreRef: |
| 50 | + kind: ClusterSecretStore |
| 51 | + name: default |
| 52 | + target: |
| 53 | + name: finops-agent |
| 54 | + data: |
| 55 | + - secretKey: LLM_API_KEY |
| 56 | + remoteRef: |
| 57 | + key: finops-llm-api-key |
| 58 | + property: value |
| 59 | + - secretKey: OAUTH_CLIENT_SECRET |
| 60 | + remoteRef: |
| 61 | + key: finops-agent-oauth-client-secret |
| 62 | + property: value |
| 63 | +EOF |
| 64 | +``` |
| 65 | + |
| 66 | +### Step 2: Upgrade the Observability Plane |
| 67 | + |
| 68 | +Enable the FinOps Agent and configure the LLM model. The `--reuse-values` flag preserves your existing configuration. |
| 69 | + |
| 70 | +<CodeBlock language="bash"> |
| 71 | + {`helm upgrade --install openchoreo-observability-plane ${versions.helmSource}/openchoreo-observability-plane \\ |
| 72 | + --version ${versions.helmChart} \\ |
| 73 | + --namespace openchoreo-observability-plane \\ |
| 74 | + --reuse-values \\ |
| 75 | + --set finOpsAgent.enabled="true" \\ |
| 76 | + --set finOpsAgent.llmName=<model-name>`} |
| 77 | +</CodeBlock> |
| 78 | + |
| 79 | +:::note Supported Models |
| 80 | +The FinOps Agent currently supports the [OpenAI](https://platform.openai.com/) GPT model series (e.g., `gpt-5.4`, `gpt-5.2-pro`, `gpt-5` etc.). Support for additional model providers is coming soon. |
| 81 | +::: |
| 82 | + |
| 83 | +If the observability plane and control plane are in separate clusters, also set `finOpsAgent.openchoreoApiUrl` to the control plane API URL (defaults to `http://api.openchoreo.localhost:8080`). |
| 84 | + |
| 85 | +### Step 3: Register with the control plane |
| 86 | + |
| 87 | +Configure `finOpsAgentURL` in the `ClusterObservabilityPlane` resource so the UI knows where to reach the FinOps Agent: |
| 88 | + |
| 89 | +<CodeBlock language="bash"> |
| 90 | + {`kubectl patch clusterobservabilityplane default --type=merge -p '{"spec":{"finOpsAgentURL":"http://finops-agent.openchoreo.localhost:11080"}}'`} |
| 91 | +</CodeBlock> |
| 92 | + |
| 93 | +### Step 4: Verify the installation |
| 94 | + |
| 95 | +Check that the FinOps Agent pod is running: |
| 96 | + |
| 97 | +```bash |
| 98 | +kubectl get pods -n openchoreo-observability-plane -l app.kubernetes.io/component=finops-agent |
| 99 | +``` |
| 100 | + |
| 101 | +If you are using the default identity provider (Thunder) and the default SQLite report storage, your setup is complete. |
| 102 | + |
| 103 | +<details id="authentication-and-authorization"> |
| 104 | +<summary><strong>Authentication and Authorization (External IdP)</strong></summary> |
| 105 | + |
| 106 | +By default, OpenChoreo configures Thunder as the identity provider for the FinOps Agent with a pre-configured OAuth client for testing purposes. If you are using an external identity provider, follow the steps below. |
| 107 | + |
| 108 | +#### Authentication |
| 109 | + |
| 110 | +Create an OAuth 2.0 client that supports the `client_credentials` grant type for service-to-service authentication. |
| 111 | + |
| 112 | +Store your OAuth client secret in OpenBao: |
| 113 | + |
| 114 | +```bash |
| 115 | +kubectl exec -n openbao openbao-0 -- \ |
| 116 | + env BAO_ADDR=http://127.0.0.1:8200 BAO_TOKEN=root \ |
| 117 | + bao kv put secret/finops-agent-oauth-client-secret value="<YOUR_OAUTH_CLIENT_SECRET>" |
| 118 | +``` |
| 119 | + |
| 120 | +Then configure the Observability Plane Helm values with your client credentials: |
| 121 | + |
| 122 | +```yaml |
| 123 | +security: |
| 124 | + oidc: |
| 125 | + tokenUrl: "<your-idp-token-url>" |
| 126 | + |
| 127 | +finOpsAgent: |
| 128 | + secretName: "finops-agent" |
| 129 | + oauth: |
| 130 | + clientId: "<your-client-id>" |
| 131 | +``` |
| 132 | +
|
| 133 | +See [Identity Provider Configuration](../platform-engineer-guide/identity-configuration.mdx) for detailed setup instructions. |
| 134 | +
|
| 135 | +#### Authorization |
| 136 | +
|
| 137 | +The FinOps Agent uses the `client_credentials` grant to authenticate with the OpenChoreo API as a service account. The API matches the `sub` claim in the issued JWT to identify the caller, so the new client must be granted the `finops-agent` role via a bootstrap authorization mapping. |
| 138 | + |
| 139 | +Add the following to your Control Plane values override, replacing `<your-client-id>` with the same client ID used above: |
| 140 | + |
| 141 | +```yaml |
| 142 | +openchoreoApi: |
| 143 | + config: |
| 144 | + security: |
| 145 | + authorization: |
| 146 | + bootstrap: |
| 147 | + mappings: |
| 148 | + - name: finops-agent-binding |
| 149 | + roleRef: |
| 150 | + name: finops-agent |
| 151 | + entitlement: |
| 152 | + claim: sub |
| 153 | + value: "<your-client-id>" |
| 154 | + effect: allow |
| 155 | +``` |
| 156 | + |
| 157 | +</details> |
| 158 | + |
| 159 | +<details> |
| 160 | +<summary><strong>Report Storage</strong></summary> |
| 161 | + |
| 162 | +By default, FinOps reports are stored in **SQLite** with a persistent volume — no external database required. |
| 163 | + |
| 164 | +For production deployments that need horizontal scaling or shared storage, you can use **PostgreSQL** instead. |
| 165 | + |
| 166 | +Store the PostgreSQL connection URI in OpenBao: |
| 167 | + |
| 168 | +```bash |
| 169 | +kubectl exec -n openbao openbao-0 -- \ |
| 170 | + env BAO_ADDR=http://127.0.0.1:8200 BAO_TOKEN=root \ |
| 171 | + bao kv put secret/finops-sql-backend-uri value="postgresql+asyncpg://<USER>:<PASSWORD>@<HOST>:<PORT>/<DBNAME>" |
| 172 | +``` |
| 173 | + |
| 174 | +Add the `SQL_BACKEND_URI` key to the ExternalSecret from [Step 1](#step-1-create-the-finops-agent-secret): |
| 175 | + |
| 176 | +```bash |
| 177 | +kubectl patch externalsecret finops-agent -n openchoreo-observability-plane --type=json \ |
| 178 | + -p '[{"op":"add","path":"/spec/data/-","value":{"secretKey":"SQL_BACKEND_URI","remoteRef":{"key":"finops-sql-backend-uri","property":"value"}}}]' |
| 179 | +``` |
| 180 | + |
| 181 | +Then set the report backend in your Helm values: |
| 182 | + |
| 183 | +```yaml |
| 184 | +finOpsAgent: |
| 185 | + reportBackend: postgresql |
| 186 | +``` |
| 187 | + |
| 188 | +</details> |
0 commit comments