@@ -80,10 +80,10 @@ func createCRDs() {
8080 _ = testutils .CreateObjsFromYaml (testConfig , gieCRDs , "" )
8181}
8282
83- // createEndPointPicker creates the scheduling ConfigMap and EPP Deployment (plus
84- // its ServiceAccount, RoleBinding, and Service) for the given phase from the
85- // supplied EPP config and waits for the EPP Deployment to become ready. Returns
86- // the created object ids for cleanup.
83+ // createEndPointPicker creates the scheduling ConfigMap and EPP Deployment for
84+ // the given phase from the supplied EPP config and waits for the EPP Deployment
85+ // to become ready. Its ServiceAccount, RoleBinding, and Service are created once
86+ // by createStableInfra. Returns the created object ids for cleanup.
8787func createEndPointPicker (phase , config string ) []string {
8888 manifest := map [string ]string {
8989 "encode" : encodeEPPManifest ,
@@ -96,7 +96,9 @@ func createEndPointPicker(phase, config string) []string {
9696
9797 objects := make ([]string , 1 , 8 )
9898 objects [0 ] = "ConfigMap/" + cmName
99- objects = append (objects , applyManifest (manifest , eppSubstitutions ())... )
99+ // The Service, ServiceAccount, and RoleBinding are created once by
100+ // createStableInfra; recreate only the Deployment per spec.
101+ objects = append (objects , applyManifest (manifest , eppSubstitutions (), "Service" , "ServiceAccount" , "RoleBinding" )... )
100102 podsInDeploymentsReady (objects )
101103 return objects
102104}
@@ -154,8 +156,8 @@ func createModelServers(encodeReplicas, prefillReplicas, decodeReplicas int) []s
154156}
155157
156158// createCoordinator builds the coordinator ConfigMap from the given pipeline
157- // config, deploys the coordinator component ( Deployment + Service + SA), and
158- // waits for readiness .
159+ // config, deploys the coordinator Deployment, and waits for readiness. Its
160+ // Service and ServiceAccount are created once by createStableInfra .
159161func createCoordinator (config string ) []string {
160162 nsName := getNamespace ()
161163 coordinatorYAML := e2eutil .SubstituteMany ([]string {config }, map [string ]string {
@@ -177,7 +179,9 @@ func createCoordinator(config string) []string {
177179 objects [0 ] = "ConfigMap/llm-d-coordinator-config"
178180
179181 docs := e2eutil .RunKustomize (coordinatorComponentDir )
180- docs = e2eutil .FilterKinds (docs , "ConfigMap" )
182+ // Service and ServiceAccount are created once by createStableInfra; recreate
183+ // only the Deployment per spec.
184+ docs = e2eutil .FilterKinds (docs , "ConfigMap" , "Service" , "ServiceAccount" )
181185 docs = e2eutil .SubstituteMany (docs , coordinatorSubstitutions ())
182186 docs = e2eutil .RemoveEmptyArgs (docs )
183187 objects = append (objects , testutils .CreateObjsFromYaml (testConfig , docs , nsName )... )
@@ -188,8 +192,11 @@ func createCoordinator(config string) []string {
188192}
189193
190194// waitForCoordinatorReady polls /readyz through Envoy until it returns 200,
191- // catching Envoy's STRICT_DNS resolution lagging behind the per-test Service
192- // (podsInDeploymentsReady already confirms the coordinator pod itself is ready).
195+ // confirming the freshly recreated coordinator pod is reachable through the
196+ // gateway before the test sends its request. The gateway Service is stable
197+ // across specs (see createStableInfra), so this waits only for the new pod to
198+ // appear behind it. (podsInDeploymentsReady already confirms the coordinator
199+ // pod itself is ready.)
193200func waitForCoordinatorReady () {
194201 ginkgo .By ("Waiting for coordinator to be reachable via gateway" )
195202 gomega .Eventually (func () bool {
@@ -222,13 +229,35 @@ func createEPPConfigMap(name, content string) {
222229 }
223230}
224231
225- func applyManifest (path string , subs map [string ]string ) []string {
232+ func applyManifest (path string , subs map [string ]string , excludeKinds ... string ) []string {
226233 docs := testutils .ReadYaml (path )
227234 docs = e2eutil .SubstituteMany (docs , subs )
228235 docs = e2eutil .RemoveEmptyArgs (docs )
236+ docs = e2eutil .FilterKinds (docs , excludeKinds ... )
229237 return testutils .CreateObjsFromYaml (testConfig , docs , getNamespace ())
230238}
231239
240+ // createStableInfra creates the coordinator and per-phase EPP Services,
241+ // ServiceAccounts, and RoleBindings once, up front. It appends each created id to
242+ // stableInfraObjects as it goes rather than returning them at the end, so a
243+ // partial failure still leaves the already-created objects tracked for suite
244+ // teardown. Envoy fronts the Services via STRICT_DNS clusters and outlives the
245+ // per-spec workload; recreating a Service each spec would rotate its ClusterIP and
246+ // force Envoy to re-resolve, so only the Deployments behind them churn per spec.
247+ // Mirrors the non-coordinator e2e, which creates the EPP Services and RBAC once in
248+ // its setup and recreates only the Deployment per test.
249+ func createStableInfra () {
250+ docs := e2eutil .RunKustomize (coordinatorComponentDir )
251+ docs = e2eutil .FilterKinds (docs , "ConfigMap" , "Deployment" )
252+ docs = e2eutil .SubstituteMany (docs , coordinatorSubstitutions ())
253+ docs = e2eutil .RemoveEmptyArgs (docs )
254+ stableInfraObjects = append (stableInfraObjects , testutils .CreateObjsFromYaml (testConfig , docs , getNamespace ())... )
255+
256+ for _ , manifest := range []string {encodeEPPManifest , prefillEPPManifest , decodeEPPManifest } {
257+ stableInfraObjects = append (stableInfraObjects , applyManifest (manifest , eppSubstitutions (), "Deployment" )... )
258+ }
259+ }
260+
232261func eppSubstitutions () map [string ]string {
233262 return map [string ]string {
234263 "${EPP_NAME}" : eppName ,
0 commit comments