Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Karpenter Optimizer helps you optimize your Karpenter NodePool configurations by

- 🎯 **Automatic Workload Discovery**: Automatically fetch workloads from your Kubernetes cluster
- 📊 **Real-time Node Usage**: Visualize actual CPU and memory usage per node with interactive charts
- 🗺️ **Topology View**: Bird’s-eye view of pods on nodes with segment sizes by CPU or memory requests (grouped by NodePool)
- 🏗️ **NodePool Analysis**: Analyze existing Karpenter NodePool configurations for accurate before/after comparisons
- 💡 **AI-Powered Recommendations**: Get intelligent NodePool recommendations optimized for cost and performance using Ollama/LiteLLM/VLLM
- 💰 **AWS Pricing Integration**: Real-time pricing from AWS Pricing API for accurate cost calculations
Expand Down Expand Up @@ -233,6 +234,7 @@ make swagger
- `GET /api/v1/nodepools/:name` - Get specific NodePool details
- `GET /api/v1/nodepools/recommendations` - Get NodePool recommendations
- `GET /api/v1/nodes` - Get nodes with usage data
- `GET /api/v1/topology` - Get nodes with scheduled pods and per-pod requests (topology view)
- `GET /api/v1/cluster/summary` - Get cluster-wide statistics
- `GET /api/v1/disruptions` - Get node disruption information
- `GET /api/v1/disruptions/recent` - Get recent node deletions
Expand Down Expand Up @@ -405,6 +407,7 @@ For detailed architecture documentation, see [docs/architecture.md](docs/archite
- `GET /api/v1/nodepools/recommendations` - Get NodePool recommendations
- `GET /api/v1/recommendations/cluster-summary` - Get cluster-wide recommendations with AI explanations
- `GET /api/v1/nodes` - List nodes with usage data
- `GET /api/v1/topology` - Nodes with pods and request sizes for topology visualization
- `GET /api/v1/disruptions` - Get node disruption information

See the [Swagger UI](http://localhost:8080/swagger/index.html) for complete interactive API documentation with request/response schemas, or generate the docs with `make swagger`.
Expand Down
44 changes: 44 additions & 0 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,50 @@ Get all nodes with usage data.
]
```

### Topology (pods on nodes)

```http
GET /api/v1/topology
```

Returns every node (same metadata as `/api/v1/nodes`) plus the pods scheduled on that node, with **CPU and memory requests** parsed to floats for visualization.

**Query parameters**:
- `maxPodsPerNode` (optional): Maximum pods returned per node after sorting by CPU request (default `200`, max `1000`). Use this to cap payload size on large nodes.

**Response**:
```json
{
"count": 2,
"nodes": [
{
"name": "ip-10-0-1-2.ec2.internal",
"nodePool": "general",
"instanceType": "m6i.large",
"capacityType": "on-demand",
"architecture": "amd64",
"zone": "us-east-1a",
"cpuUsage": { "used": 1.2, "allocatable": 1.93, "capacity": 2.0, "percent": 62.0 },
"memoryUsage": { "used": 4.1, "allocatable": 6.9, "capacity": 8.0, "percent": 59.0 },
"podCount": 12,
"pods": [
{
"name": "myapp-7d9f8c6b5-xk2j4",
"namespace": "prod",
"nodeName": "ip-10-0-1-2.ec2.internal",
"workloadName": "myapp",
"workloadType": "deployment",
"qosClass": "Burstable",
"requests": { "cpuCores": 0.25, "memoryGiB": 0.5 }
}
]
}
]
}
```

Pods in terminal phases (`Succeeded`, `Failed`) are omitted.

### Get Node Disruptions

```http
Expand Down
4 changes: 2 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import './App.css';
import NodePoolCard from './components/NodePoolCard';
import DisruptionTracker from './components/DisruptionTracker';
import NodeUsageView from './components/NodeUsageView';
import TopologyView from './components/TopologyView';
import WorkloadUsageView from './components/WorkloadUsageView';
import GlobalClusterSummary from './components/GlobalClusterSummary';
import AgentRecommendations from './components/AgentRecommendations';
Expand Down Expand Up @@ -115,6 +116,17 @@ function App() {
>
Nodes
</button>
<button
onClick={() => setActiveTab('topology')}
className={cn(
"px-4 py-2 text-sm font-medium border-b-2 transition-colors",
activeTab === 'topology'
? "border-blue-600 text-blue-600"
: "border-transparent text-muted-foreground hover:text-foreground hover:border-gray-300"
)}
>
Topology
</button>
<button
onClick={() => setActiveTab('workloads')}
className={cn(
Expand Down Expand Up @@ -397,6 +409,9 @@ function App() {
{/* Nodes Tab */}
{activeTab === 'nodes' && <NodeUsageView />}

{/* Topology Tab */}
{activeTab === 'topology' && <TopologyView />}

{/* Workloads Tab */}
{activeTab === 'workloads' && <WorkloadUsageView />}

Expand Down
Loading
Loading