@@ -21,6 +21,7 @@ import (
2121 "crypto/tls"
2222 "flag"
2323 "os"
24+ "time"
2425
2526 // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
2627 // to ensure that exec-entrypoint and run can make use of them.
@@ -39,10 +40,13 @@ import (
3940 "sigs.k8s.io/controller-runtime/pkg/webhook"
4041
4142 monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
43+ gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
4244
4345 agentraxv1alpha1 "github.com/gitcommitankit/agentrax/api/v1alpha1"
4446 "github.com/gitcommitankit/agentrax/internal/controller"
47+ "github.com/gitcommitankit/agentrax/internal/metrics"
4548 "github.com/gitcommitankit/agentrax/internal/quota"
49+ "github.com/gitcommitankit/agentrax/internal/rollout"
4650 agentraxwebhook "github.com/gitcommitankit/agentrax/internal/webhook"
4751 // +kubebuilder:scaffold:imports
4852)
@@ -58,6 +62,7 @@ func init() {
5862 utilruntime .Must (autoscalingv2 .AddToScheme (scheme ))
5963 utilruntime .Must (apiextensionsv1 .AddToScheme (scheme ))
6064 utilruntime .Must (monitoringv1 .AddToScheme (scheme ))
65+ utilruntime .Must (gatewayv1 .Install (scheme ))
6166
6267 utilruntime .Must (agentraxv1alpha1 .AddToScheme (scheme ))
6368 // +kubebuilder:scaffold:scheme
@@ -71,6 +76,9 @@ func main() {
7176 var secureMetrics bool
7277 var enableHTTP2 bool
7378 var gpuResourceName string
79+ var prometheusURL string
80+ var gatewayName string
81+ var gatewayNamespace string
7482 var tlsOpts []func (* tls.Config )
7583 flag .StringVar (& metricsAddr , "metrics-bind-address" , "0" , "The address the metrics endpoint binds to. " +
7684 "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service." )
@@ -84,6 +92,13 @@ func main() {
8492 "If set, HTTP/2 will be enabled for the metrics and webhook servers" )
8593 flag .StringVar (& gpuResourceName , "gpu-resource-name" , quota .DefaultGPUResourceName ,
8694 "Kubernetes resource name used to count GPU units in AgentDeployment resource limits." )
95+ flag .StringVar (& prometheusURL , "prometheus-url" , "" ,
96+ "URL of the Prometheus HTTP API (e.g. http://prometheus-operated.monitoring.svc:9090). " +
97+ "Required for Canary rollout strategy; if empty, canary is unavailable." )
98+ flag .StringVar (& gatewayName , "gateway-name" , "agentrax-gateway" ,
99+ "Name of the Gateway API Gateway object used for canary traffic splitting." )
100+ flag .StringVar (& gatewayNamespace , "gateway-namespace" , "agentrax-system" ,
101+ "Namespace of the Gateway API Gateway object used for canary traffic splitting." )
87102 opts := zap.Options {
88103 Development : true ,
89104 }
@@ -171,10 +186,29 @@ func main() {
171186 // Shared quota enforcer used by both the webhook validator and TenantQuota reconciler.
172187 quotaEnforcer := quota .NewEnforcer (gpuResourceName )
173188
189+ // Build the CanaryController when --prometheus-url is provided.
190+ // When nil, AgentDeployments with strategy=Canary behave as Recreate.
191+ var canaryController * rollout.Controller
192+ if prometheusURL != "" {
193+ setupLog .Info ("canary rollout enabled" , "prometheusURL" , prometheusURL ,
194+ "gatewayName" , gatewayName , "gatewayNamespace" , gatewayNamespace )
195+ canaryController = & rollout.Controller {
196+ Client : mgr .GetClient (),
197+ Scheme : mgr .GetScheme (),
198+ PromClient : metrics .NewClient (prometheusURL ),
199+ GatewayName : gatewayName ,
200+ GatewayNamespace : gatewayNamespace ,
201+ FailSafeTimeout : 60 * time .Second ,
202+ }
203+ } else {
204+ setupLog .Info ("canary rollout disabled (no --prometheus-url)" )
205+ }
206+
174207 if err = (& controller.AgentDeploymentReconciler {
175- Client : mgr .GetClient (),
176- Scheme : mgr .GetScheme (),
177- GPUResourceName : gpuResourceName ,
208+ Client : mgr .GetClient (),
209+ Scheme : mgr .GetScheme (),
210+ GPUResourceName : gpuResourceName ,
211+ CanaryController : canaryController ,
178212 }).SetupWithManager (mgr ); err != nil {
179213 setupLog .Error (err , "unable to create controller" , "controller" , "AgentDeployment" )
180214 os .Exit (1 )
0 commit comments