Skip to content

Commit d976b94

Browse files
committed
fix(istio): deploy vLLM backend for common E2E tests
Add Demo LLM (vLLM backend) deployment to Istio profile to fix common E2E test failures. Root cause: Istio profile was missing the vLLM backend that serves LLM requests. This caused 404 errors on /v1/chat/completions and 0% accuracy on all common tests (domain-classify, pii-detection, jailbreak-detection, etc.). Changes: - Add Step 4/6: Deploy Demo LLM backend (base-model.yaml) - Add deployDemoLLM() function to deploy vLLM backend - Add kubectl helper functions (kubectlApply, kubectlDelete, runKubectl) - Update cleanup functions to remove Demo LLM on teardown - Add timeoutDemoLLMDeploy constant for deployment timeout This fix brings the Istio profile in line with AIBrix and AI-Gateway profiles, which both deploy the vLLM backend for common tests. Expected result: All 17 tests (4 Istio-specific + 13 common) should now pass in CI. Signed-off-by: Asaad Balum <[email protected]>
1 parent 9b280a7 commit d976b94

File tree

1 file changed

+71
-13
lines changed

1 file changed

+71
-13
lines changed

e2e/profiles/istio/profile.go

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@ const (
2626
semanticRouterDeployment = "semantic-router"
2727
semanticRouterService = "semantic-router"
2828

29+
// Demo LLM Configuration
30+
demoLLMDeployment = "vllm-llama3-8b-instruct" // Demo LLM deployment name
31+
2932
// Timeouts
3033
timeoutIstioInstall = 5 * time.Minute
3134
timeoutSemanticRouterDeploy = 10 * time.Minute
35+
timeoutDemoLLMDeploy = 10 * time.Minute
3236
timeoutSidecarInjection = 2 * time.Minute
3337
timeoutGatewayReady = 5 * time.Minute
3438
timeoutStabilization = 60 * time.Second
@@ -74,14 +78,15 @@ func (p *Profile) Setup(ctx context.Context, opts *framework.SetupOptions) error
7478
istioInstalled bool
7579
namespaceConfigured bool
7680
semanticRouterDeployed bool
81+
demoLLMDeployed bool
7782
istioResourcesCreated bool
7883
)
7984

8085
// Ensure cleanup on error
8186
defer func() {
8287
if r := recover(); r != nil {
8388
p.log("Panic during setup, cleaning up...")
84-
p.cleanupPartialDeployment(ctx, opts, istioInstalled, namespaceConfigured, semanticRouterDeployed, istioResourcesCreated)
89+
p.cleanupPartialDeployment(ctx, opts, istioInstalled, namespaceConfigured, semanticRouterDeployed, demoLLMDeployed, istioResourcesCreated)
8590
panic(r) // Re-panic after cleanup
8691
}
8792
}()
@@ -93,41 +98,49 @@ func (p *Profile) Setup(ctx context.Context, opts *framework.SetupOptions) error
9398
}
9499

95100
// Step 1: Install Istio control plane
96-
p.log("Step 1/5: Installing Istio control plane (version: %s)", istioVersion)
101+
p.log("Step 1/6: Installing Istio control plane (version: %s)", istioVersion)
97102
if err := p.installIstio(ctx, opts); err != nil {
98103
return fmt.Errorf("failed to install Istio: %w", err)
99104
}
100105
istioInstalled = true
101106

102107
// Step 2: Configure namespace with sidecar injection
103-
p.log("Step 2/5: Configuring namespace for sidecar injection")
108+
p.log("Step 2/6: Configuring namespace for sidecar injection")
104109
if err := p.configureNamespace(ctx, opts); err != nil {
105-
p.cleanupPartialDeployment(ctx, opts, istioInstalled, false, false, false)
110+
p.cleanupPartialDeployment(ctx, opts, istioInstalled, false, false, false, false)
106111
return fmt.Errorf("failed to configure namespace: %w", err)
107112
}
108113
namespaceConfigured = true
109114

110115
// Step 3: Deploy Semantic Router with Istio sidecar
111-
p.log("Step 3/5: Deploying Semantic Router")
116+
p.log("Step 3/6: Deploying Semantic Router")
112117
if err := p.deploySemanticRouter(ctx, deployer, opts); err != nil {
113-
p.cleanupPartialDeployment(ctx, opts, istioInstalled, namespaceConfigured, false, false)
118+
p.cleanupPartialDeployment(ctx, opts, istioInstalled, namespaceConfigured, false, false, false)
114119
return fmt.Errorf("failed to deploy semantic router: %w", err)
115120
}
116121
semanticRouterDeployed = true
117122

118-
// Step 4: Create Istio Gateway and VirtualService
119-
p.log("Step 4/5: Creating Istio Gateway and VirtualService")
123+
// Step 4: Deploy Demo LLM (vLLM backend)
124+
p.log("Step 4/6: Deploying Demo LLM backend")
125+
if err := p.deployDemoLLM(ctx, opts); err != nil {
126+
p.cleanupPartialDeployment(ctx, opts, istioInstalled, namespaceConfigured, semanticRouterDeployed, false, false)
127+
return fmt.Errorf("failed to deploy demo LLM: %w", err)
128+
}
129+
demoLLMDeployed = true
130+
131+
// Step 5: Create Istio Gateway and VirtualService
132+
p.log("Step 5/6: Creating Istio Gateway and VirtualService")
120133
if err := p.createIstioResources(ctx, opts); err != nil {
121-
p.cleanupPartialDeployment(ctx, opts, istioInstalled, namespaceConfigured, semanticRouterDeployed, false)
134+
p.cleanupPartialDeployment(ctx, opts, istioInstalled, namespaceConfigured, semanticRouterDeployed, demoLLMDeployed, false)
122135
return fmt.Errorf("failed to create Istio resources: %w", err)
123136
}
124137
istioResourcesCreated = true
125138

126-
// Step 5: Verify environment is ready
127-
p.log("Step 5/5: Verifying environment")
139+
// Step 6: Verify environment is ready
140+
p.log("Step 6/6: Verifying environment")
128141
if err := p.verifyEnvironment(ctx, opts); err != nil {
129142
p.log("ERROR: Environment verification failed: %v", err)
130-
p.cleanupPartialDeployment(ctx, opts, istioInstalled, namespaceConfigured, semanticRouterDeployed, istioResourcesCreated)
143+
p.cleanupPartialDeployment(ctx, opts, istioInstalled, namespaceConfigured, semanticRouterDeployed, demoLLMDeployed, istioResourcesCreated)
131144
return fmt.Errorf("failed to verify environment: %w", err)
132145
}
133146

@@ -146,6 +159,9 @@ func (p *Profile) Teardown(ctx context.Context, opts *framework.TeardownOptions)
146159
p.log("Cleaning up Istio resources")
147160
p.cleanupIstioResources(ctx, opts)
148161

162+
p.log("Cleaning up Demo LLM")
163+
p.kubectlDelete(ctx, opts.KubeConfig, "deploy/kubernetes/aibrix/aigw-resources/base-model.yaml")
164+
149165
p.log("Uninstalling Semantic Router")
150166
deployer.Uninstall(ctx, semanticRouterDeployment, semanticRouterNamespace)
151167

@@ -529,7 +545,7 @@ func (p *Profile) verifyDeployment(ctx context.Context, opts *framework.SetupOpt
529545
return nil
530546
}
531547

532-
func (p *Profile) cleanupPartialDeployment(ctx context.Context, opts *framework.SetupOptions, istioInstalled, namespaceConfigured, semanticRouterDeployed, istioResourcesCreated bool) {
548+
func (p *Profile) cleanupPartialDeployment(ctx context.Context, opts *framework.SetupOptions, istioInstalled, namespaceConfigured, semanticRouterDeployed, demoLLMDeployed, istioResourcesCreated bool) {
533549
p.log("Cleaning up partial deployment...")
534550

535551
teardownOpts := &framework.TeardownOptions{
@@ -543,6 +559,11 @@ func (p *Profile) cleanupPartialDeployment(ctx context.Context, opts *framework.
543559
p.cleanupIstioResources(ctx, teardownOpts)
544560
}
545561

562+
if demoLLMDeployed {
563+
p.log("Cleaning up Demo LLM")
564+
p.kubectlDelete(ctx, opts.KubeConfig, "deploy/kubernetes/aibrix/aigw-resources/base-model.yaml")
565+
}
566+
546567
if semanticRouterDeployed {
547568
deployer := helm.NewDeployer(opts.KubeConfig, opts.Verbose)
548569
deployer.Uninstall(ctx, semanticRouterDeployment, semanticRouterNamespace)
@@ -631,3 +652,40 @@ func containsMiddle(s, substr string) bool {
631652
}
632653
return false
633654
}
655+
656+
// deployDemoLLM deploys the demo LLM (vLLM backend) for testing
657+
func (p *Profile) deployDemoLLM(ctx context.Context, opts *framework.SetupOptions) error {
658+
// Apply base model (Demo LLM)
659+
if err := p.kubectlApply(ctx, opts.KubeConfig, "deploy/kubernetes/aibrix/aigw-resources/base-model.yaml"); err != nil {
660+
return fmt.Errorf("failed to apply base model: %w", err)
661+
}
662+
663+
// Wait for Demo LLM deployment
664+
p.log("Waiting for Demo LLM deployment to be ready...")
665+
if err := p.waitForDeployment(ctx, opts, semanticRouterNamespace, demoLLMDeployment, timeoutDemoLLMDeploy); err != nil {
666+
return fmt.Errorf("demo LLM deployment not ready: %w", err)
667+
}
668+
669+
return nil
670+
}
671+
672+
// kubectlApply applies a Kubernetes manifest
673+
func (p *Profile) kubectlApply(ctx context.Context, kubeConfig, manifest string) error {
674+
return p.runKubectl(ctx, kubeConfig, "apply", "--server-side", "-f", manifest)
675+
}
676+
677+
// kubectlDelete deletes a Kubernetes manifest
678+
func (p *Profile) kubectlDelete(ctx context.Context, kubeConfig, manifest string) error {
679+
return p.runKubectl(ctx, kubeConfig, "delete", "-f", manifest)
680+
}
681+
682+
// runKubectl runs a kubectl command
683+
func (p *Profile) runKubectl(ctx context.Context, kubeConfig string, args ...string) error {
684+
args = append([]string{"--kubeconfig", kubeConfig}, args...)
685+
cmd := exec.CommandContext(ctx, "kubectl", args...)
686+
if p.verbose {
687+
cmd.Stdout = os.Stdout
688+
cmd.Stderr = os.Stderr
689+
}
690+
return cmd.Run()
691+
}

0 commit comments

Comments
 (0)