1"use strict";(self.webpackChunksemantic_router_docs=self.webpackChunksemantic_router_docs||[]).push([[17861],{58039(e,t,n){n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>d,default:()=>h,frontMatter:()=>i,metadata:()=>s,toc:()=>o});const s=JSON.parse('{"id":"installation/k8s/gateway-testing","title":"Test a Kubernetes Gateway Deployment","description":"Verify gateway reachability, direct model requests, semantic routing, headers, and backend selection.","source":"@site/docs/installation/k8s/gateway-testing.md","sourceDirName":"installation/k8s","slug":"/installation/k8s/gateway-testing","permalink":"/docs/installation/k8s/gateway-testing","draft":false,"unlisted":false,"editUrl":"https://github.com/vllm-project/semantic-router/edit/main/website/docs/installation/k8s/gateway-testing.md","tags":[],"version":"current","frontMatter":{"title":"Test a Kubernetes Gateway Deployment","sidebar_label":"Test a Gateway Deployment","description":"Verify gateway reachability, direct model requests, semantic routing, headers, and backend selection."},"sidebar":"tutorialSidebar","previous":{"title":"Gateway API Inference Extension","permalink":"/docs/installation/k8s/gateway-api-inference-extension"},"next":{"title":"Inference Platforms","permalink":"/docs/installation/k8s/inference-platforms"}}');var a=n(74848),r=n(28453);const i={title:"Test a Kubernetes Gateway Deployment",sidebar_label:"Test a Gateway Deployment",description:"Verify gateway reachability, direct model requests, semantic routing, headers, and backend selection."},d="Test a Kubernetes Gateway Deployment",l={},o=[{value:"1. Resolve the real gateway address",id:"1-resolve-the-real-gateway-address",level:2},{value:"2. Check Gateway API status",id:"2-check-gateway-api-status",level:2},{value:"3. List exposed models",id:"3-list-exposed-models",level:2},{value:"4. Send a direct-model request",id:"4-send-a-direct-model-request",level:2},{value:"5. Send a routed request",id:"5-send-a-routed-request",level:2},{value:"6. Verify the backend path",id:"6-verify-the-backend-path",level:2},{value:"Failure guide",id:"failure-guide",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"test-a-kubernetes-gateway-deployment",children:"Test a Kubernetes Gateway Deployment"})}),"\n",(0,a.jsx)(t.p,{children:"Use this checklist after installing Semantic Router behind Istio, Envoy\nGateway, Gateway API Inference Extension, or another supported gateway."}),"\n",(0,a.jsx)(t.h2,{id:"1-resolve-the-real-gateway-address",children:"1. Resolve the real gateway address"}),"\n",(0,a.jsx)(t.p,{children:"Do not copy an IP or NodePort from another cluster. Inspect the Service created\nfor your Gateway:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"kubectl get gateway -A\nkubectl get service -A | grep -i gateway\n"})}),"\n",(0,a.jsx)(t.p,{children:"For Minikube, the helper can print a reachable URL:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:'export GATEWAY_URL="$(minikube service inference-gateway-istio --url | head -n 1)"\n'})}),"\n",(0,a.jsxs)(t.p,{children:["For a LoadBalancer Service, use its assigned hostname or IP. For a local-only\ncluster, port-forward the Gateway Service and set ",(0,a.jsx)(t.code,{children:"GATEWAY_URL"})," to the forwarded\naddress."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:'test -n "$GATEWAY_URL" && printf \'Gateway: %s\\n\' "$GATEWAY_URL"\n'})}),"\n",(0,a.jsx)(t.h2,{id:"2-check-gateway-api-status",children:"2. Check Gateway API status"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"kubectl get gateway,httproute -A\nkubectl describe httproute <route-name> -n <namespace>\n"})}),"\n",(0,a.jsxs)(t.p,{children:["The route should be accepted and its backend references resolved. If the route\ntargets an ",(0,a.jsx)(t.code,{children:"InferencePool"}),", as in an llm-d deployment, also inspect the pool and\nthe endpoint picker (EPP) that schedules its replicas."]}),"\n",(0,a.jsx)(t.h2,{id:"3-list-exposed-models",children:"3. List exposed models"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:'curl -fsS "$GATEWAY_URL/v1/models"\n'})}),"\n",(0,a.jsx)(t.p,{children:"Confirm that the response contains the physical or virtual model names expected\nby the active Router configuration."}),"\n",(0,a.jsx)(t.h2,{id:"4-send-a-direct-model-request",children:"4. Send a direct-model request"}),"\n",(0,a.jsxs)(t.p,{children:["Replace ",(0,a.jsx)(t.code,{children:"physical-model"})," with a provider model exposed by the config:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:'curl -fsS -D /tmp/direct-headers.txt \\\n "$GATEWAY_URL/v1/chat/completions" \\\n -H \'Content-Type: application/json\' \\\n -d \'{\n "model": "physical-model",\n "messages": [{"role": "user", "content": "Reply with one short sentence."}],\n "max_tokens": 64,\n "temperature": 0\n }\'\n'})}),"\n",(0,a.jsx)(t.p,{children:"A direct provider name should reach that provider without running recipe\nsignals, decisions, route plugins, cache, learning, or session rout
1ing."}),"\n",(0,a.jsx)(t.h2,{id:"5-send-a-routed-request",children:"5. Send a routed request"}),"\n",(0,a.jsxs)(t.p,{children:["Replace ",(0,a.jsx)(t.code,{children:"virtual-model"})," with an entrypoint or automatic alias configured for the\ndeployment:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:'curl -fsS -D /tmp/routed-headers.txt \\\n "$GATEWAY_URL/v1/chat/completions" \\\n -H \'Content-Type: application/json\' \\\n -d \'{\n "model": "virtual-model",\n "messages": [{"role": "user", "content": "Explain why 2 + 2 equals 4."}],\n "max_tokens": 128,\n "temperature": 0\n }\'\n'})}),"\n",(0,a.jsx)(t.p,{children:"Inspect the response and routing headers supported by your deployment. Confirm\nthat the selected provider is valid for the matched decision; do not assume a\nparticular category or backend solely from the prompt wording."}),"\n",(0,a.jsx)(t.h2,{id:"6-verify-the-backend-path",children:"6. Verify the backend path"}),"\n",(0,a.jsx)(t.p,{children:"Correlate the request with Gateway, Router, and provider logs. A successful HTTP\nresponse alone does not prove that the intended route or scheduler handled it.\nWhen an Inference Router such as llm-d, vLLM Router, or the AIBrix gateway picks\nthe replica, include its logs as well."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"kubectl logs -n <router-namespace> deployment/<router-deployment> --since=5m\nkubectl logs -n <gateway-namespace> deployment/<gateway-deployment> --since=5m\n"})}),"\n",(0,a.jsx)(t.p,{children:"Keep request and response bodies out of shared logs when they may contain\nsensitive data."}),"\n",(0,a.jsx)(t.h2,{id:"failure-guide",children:"Failure guide"}),"\n",(0,a.jsxs)(t.table,{children:[(0,a.jsx)(t.thead,{children:(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.th,{children:"Symptom"}),(0,a.jsx)(t.th,{children:"Check first"})]})}),(0,a.jsxs)(t.tbody,{children:[(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"No external connection"}),(0,a.jsx)(t.td,{children:"Gateway Service address, LoadBalancer/NodePort, firewall"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"HTTPRoute not accepted"}),(0,a.jsx)(t.td,{children:"Parent reference, listener hostname, allowed routes"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"Backend reference unresolved"}),(0,a.jsx)(t.td,{children:"Service/InferencePool name, namespace, port"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsxs)(t.td,{children:[(0,a.jsx)(t.code,{children:"/v1/models"})," works but completions fail"]}),(0,a.jsx)(t.td,{children:"provider readiness, served model name, credentials"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"Direct request works but virtual model fails"}),(0,a.jsx)(t.td,{children:"entrypoint, recipe, signals/decisions, default model"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"Response succeeds through wrong pool"}),(0,a.jsx)(t.td,{children:"route match, selected-model headers, EPP/Gateway logs"})]})]})]}),"\n",(0,a.jsx)(t.p,{children:"Delete temporary header files after inspection if they may contain sensitive\nmetadata."})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},28453(e,t,n){n.d(t,{R:()=>i,x:()=>d});var s=n(96540);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.