Padmanav commited on
Commit
3614ecc
·
1 Parent(s): 912c51b

infra(k8s): add HorizontalPodAutoscaler for api (CPU-based) and worker (queue-depth-based)

Browse files
Files changed (1) hide show
  1. kubernetes/hpa.yaml +145 -0
kubernetes/hpa.yaml ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # HorizontalPodAutoscaler for the AI Code Review Agent
2
+ #
3
+ # Two HPAs:
4
+ #
5
+ # api-hpa — scales the FastAPI pod on CPU utilisation.
6
+ # Rationale: API pods are stateless and CPU-bound during
7
+ # request parsing and response serialisation. CPU at 60%
8
+ # is a reliable proxy for saturation without over-provisioning.
9
+ #
10
+ # worker-hpa — scales the Celery worker pod on a custom metric:
11
+ # the depth of the Celery task queue exposed via Prometheus.
12
+ # Rationale: CPU is a lagging indicator for queue workers —
13
+ # a worker sitting idle waiting on an LLM response shows low
14
+ # CPU but the queue may be backing up. Queue depth is a
15
+ # leading indicator that triggers scale-out before jobs pile up.
16
+ #
17
+ # Prerequisites:
18
+ # - metrics-server installed in the cluster (for CPU-based HPA)
19
+ # - Prometheus Adapter installed and configured to expose
20
+ # celery_queue_length as a custom metric (for worker HPA)
21
+ # - kubectl apply -f kubernetes/hpa.yaml
22
+
23
+ apiVersion: autoscaling/v2
24
+ kind: HorizontalPodAutoscaler
25
+ metadata:
26
+ name: api-hpa
27
+ namespace: default
28
+ labels:
29
+ app: ai-code-review-agent
30
+ component: api
31
+ spec:
32
+ scaleTargetRef:
33
+ apiVersion: apps/v1
34
+ kind: Deployment
35
+ name: api # must match metadata.name in deployment.yaml
36
+
37
+ minReplicas: 2 # always run at least 2 for availability
38
+ maxReplicas: 10 # cap prevents runaway LLM cost under attack
39
+
40
+ metrics:
41
+ - type: Resource
42
+ resource:
43
+ name: cpu
44
+ target:
45
+ type: Utilization
46
+ averageUtilization: 60 # scale out when avg CPU across pods exceeds 60%
47
+
48
+ - type: Resource
49
+ resource:
50
+ name: memory
51
+ target:
52
+ type: Utilization
53
+ averageUtilization: 75 # secondary guard — large repos spike memory
54
+
55
+ behavior:
56
+ scaleUp:
57
+ stabilizationWindowSeconds: 30 # react quickly to traffic spikes
58
+ policies:
59
+ - type: Pods
60
+ value: 2 # add at most 2 pods per scale event
61
+ periodSeconds: 30
62
+ scaleDown:
63
+ stabilizationWindowSeconds: 300 # wait 5 min before scaling down
64
+ policies: # prevents flapping after burst traffic
65
+ - type: Pods
66
+ value: 1 # remove at most 1 pod per scale event
67
+ periodSeconds: 60
68
+
69
+ ---
70
+
71
+ apiVersion: autoscaling/v2
72
+ kind: HorizontalPodAutoscaler
73
+ metadata:
74
+ name: worker-hpa
75
+ namespace: default
76
+ labels:
77
+ app: ai-code-review-agent
78
+ component: worker
79
+ spec:
80
+ scaleTargetRef:
81
+ apiVersion: apps/v1
82
+ kind: Deployment
83
+ name: worker # must match metadata.name in deployment.yaml
84
+
85
+ minReplicas: 1 # one worker is enough at idle
86
+ maxReplicas: 8 # each worker holds 2 Celery slots (--concurrency=2)
87
+ # so 8 pods = 16 concurrent analysis tasks max
88
+
89
+ metrics:
90
+ - type: Pods
91
+ pods:
92
+ metric:
93
+ name: celery_queue_length # exposed by Prometheus Adapter
94
+ # configure in prometheus-adapter ConfigMap:
95
+ # - seriesQuery: 'celery_queue_length{queue=~"high|low"}'
96
+ # name: { as: "celery_queue_length" }
97
+ # metricsQuery: 'sum(celery_queue_length{<<.LabelMatchers>>})'
98
+ target:
99
+ type: AverageValue
100
+ averageValue: "5" # scale out when avg queue depth per pod exceeds 5 jobs
101
+
102
+ - type: Resource
103
+ resource:
104
+ name: cpu
105
+ target:
106
+ type: Utilization
107
+ averageUtilization: 70 # fallback CPU metric if Prometheus Adapter unavailable
108
+
109
+ behavior:
110
+ scaleUp:
111
+ stabilizationWindowSeconds: 15 # workers need to react faster than API pods
112
+ policies:
113
+ - type: Pods
114
+ value: 2
115
+ periodSeconds: 15 # burst: add 2 workers every 15s if queue keeps growing
116
+ scaleDown:
117
+ stabilizationWindowSeconds: 600 # wait 10 min — draining a long analysis task
118
+ policies: # takes time; premature scale-down kills in-flight jobs
119
+ - type: Pods
120
+ value: 1
121
+ periodSeconds: 120
122
+
123
+ ---
124
+
125
+ # Prometheus Adapter ConfigMap reference (apply separately if not already present)
126
+ # This tells the adapter how to translate the Prometheus metric into a
127
+ # Kubernetes custom metric that the worker HPA can consume.
128
+ #
129
+ # apiVersion: v1
130
+ # kind: ConfigMap
131
+ # metadata:
132
+ # name: prometheus-adapter-config
133
+ # namespace: monitoring
134
+ # data:
135
+ # config.yaml: |
136
+ # rules:
137
+ # - seriesQuery: 'celery_queue_length{queue=~"high|low"}'
138
+ # resources:
139
+ # overrides:
140
+ # namespace: { resource: namespace }
141
+ # pod: { resource: pod }
142
+ # name:
143
+ # matches: "celery_queue_length"
144
+ # as: "celery_queue_length"
145
+ # metricsQuery: 'sum(celery_queue_length{<<.LabelMatchers>>})'