|
| 1 | +# SGLang on Intel Enterprise Inference - Single Node Deployment Guide |
| 2 | + |
| 3 | +This guide provides step-by-step instructions for deploying LLM models using the SGLang server on an existing Intel® AI for Enterprise Inference single-node cluster. |
| 4 | + |
| 5 | +> **IMPORTANT:** Unlike other inference engines in this repository, **SGLang natively supports ONLY Intel® Xeon® Processors (CPU)** in this helm chart implementation. Gaudi (HPU) accelerator support is NOT available for SGLang within this enterprise inference stack. Therefore, SGLang must be deployed using the explicit CPU paths and overrides as shown below. |
| 6 | +
|
| 7 | +## Prerequisites |
| 8 | +Before running the deployment, ensure you have completed all general [prerequisites](./prerequisites.md), and standard cluster deployments. SGLang deployment is performed via Helm directly and is not yet mapped into the main Ansible playbooks like vLLM. |
| 9 | + |
| 10 | +## Setup Steps |
| 11 | + |
| 12 | +### Step 1: Modify the hosts file |
| 13 | +Since we are testing locally, we need to map a testing domain (`api.example.com`) to `localhost` in the `/etc/hosts` file. |
| 14 | + |
| 15 | +Run the following command to edit the hosts file: |
| 16 | +```bash |
| 17 | +sudo nano /etc/hosts |
| 18 | +``` |
| 19 | +Add this line at the end: |
| 20 | +```text |
| 21 | +127.0.0.1 api.example.com |
| 22 | +``` |
| 23 | +Save and exit (`CTRL+X`, then `Y` and `Enter`). |
| 24 | + |
| 25 | +### Step 2: Generate a self-signed SSL certificate |
| 26 | +Run the following command to create a self-signed SSL certificate that covers api.example.com and trace-api.example.com (used if deploying ingress routes): |
| 27 | +```bash |
| 28 | +mkdir -p ~/certs && cd ~/certs && \ |
| 29 | +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes \ |
| 30 | + -subj "/CN=api.example.com" \ |
| 31 | + -addext "subjectAltName = DNS:api.example.com, DNS:trace-api.example.com" |
| 32 | +``` |
| 33 | +Note: the -addext option requires OpenSSL >= 1.1.1. |
| 34 | + |
| 35 | +### Step 3: Configure the Automation config file |
| 36 | +Move the single node preset inference config file to the working directory: |
| 37 | + |
| 38 | +```bash |
| 39 | +cd ~/Enterprise-Inference |
| 40 | +cp -f docs/examples/single-node/inference-config.cfg core/inventory/inference-config.cfg |
| 41 | +``` |
| 42 | + |
| 43 | +### Step 4: Modify `inference-config.cfg` and set deploy_llm_models to off |
| 44 | + |
| 45 | +Since automatic LLM deployment via the playbook is supported natively for vLLM but not SGLang, turn off automatic model deployment: |
| 46 | + |
| 47 | +```bash |
| 48 | +nano ~/Enterprise-Inference/core/inventory/inference-config.cfg |
| 49 | +``` |
| 50 | +Change `" deploy_llm_models=on "` -> `" deploy_llm_models=off "` |
| 51 | + |
| 52 | +Ensure the `cluster_url` field is set to the DNS used, and the paths to the certificate and key files are valid. The deployment options can be left unchanged. |
| 53 | + |
| 54 | +### Step 5: Update `hosts.yaml` File and run the Setup |
| 55 | +Copy the single node preset hosts config file to the working directory: |
| 56 | + |
| 57 | +```bash |
| 58 | +cp -f docs/examples/single-node/hosts.yaml core/inventory/hosts.yaml |
| 59 | +``` |
| 60 | + |
| 61 | +> **Note** The `ansible_user` field is set to *ubuntu* by default. Change it to the actual username. |
| 62 | +
|
| 63 | +Export your Hugging Face API token and run the automation deployer: |
| 64 | + |
| 65 | +```bash |
| 66 | +export HUGGINGFACE_TOKEN="Your_Hugging_Face_Token_ID" |
| 67 | + |
| 68 | +cd ~/Enterprise-Inference/core |
| 69 | +chmod +x inference-stack-deploy.sh |
| 70 | + |
| 71 | +./inference-stack-deploy.sh --cpu-or-gpu "cpu" --hugging-face-token $HUGGINGFACE_TOKEN |
| 72 | +``` |
| 73 | + |
| 74 | +**Select Option 1 and confirm the Yes/No prompt.** |
| 75 | + |
| 76 | +This will deploy the setup automatically. Once the cluster setup is complete, you can configure your SGLang endpoints. |
| 77 | + |
| 78 | +### Step 6: Configure Authentication (OIDC) via Keycloak |
| 79 | + |
| 80 | +If your cluster has Keycloak deployed for API security, you need to grab the auto-generated Client ID and Secret and configure them in the SGLang chart. |
| 81 | + |
| 82 | +```bash |
| 83 | +cd ~/Enterprise-Inference/core/scripts |
| 84 | +source generate-token.sh |
| 85 | + |
| 86 | +cd ~/Enterprise-Inference/core/helm-charts/sglang/ |
| 87 | + |
| 88 | +echo $KEYCLOAK_CLIENT_ID # Prints your keycloak client ID |
| 89 | +echo $KEYCLOAK_CLIENT_SECRET # Prints your keycloak client secret |
| 90 | +``` |
| 91 | + |
| 92 | +Open the `values.yaml` file to configure OIDC: |
| 93 | +```bash |
| 94 | +nano ~/Enterprise-Inference/core/helm-charts/sglang/values.yaml |
| 95 | +``` |
| 96 | + |
| 97 | +Update the OIDC block: |
| 98 | +```yaml |
| 99 | +oidc: |
| 100 | + realm: master |
| 101 | + client_id: "<<replace with your KEYCLOAK_CLIENT_ID>>" |
| 102 | + client_secret: "<<replace with your KEYCLOAK_CLIENT_SECRET>>" |
| 103 | + discovery: "http://keycloak.default.svc.cluster.local/realms/master/.well-known/openid-configuration" |
| 104 | + introspection_endpoint: "http://keycloak.default.svc.cluster.local/realms/master/protocol/openid-connect/token/introspect" |
| 105 | + use_jwks: true |
| 106 | +``` |
| 107 | +
|
| 108 | +#### Host Configuration |
| 109 | +If you depend on APISIX for routing, assure you update the host parameter under `apisixRoute`: |
| 110 | +```yaml |
| 111 | +apisixRoute: |
| 112 | + enabled: true |
| 113 | + namespace: default |
| 114 | + name: "" |
| 115 | + host: "api.example.com" # Update this to your configured DNS |
| 116 | +``` |
| 117 | + |
| 118 | +## Optimized Model List |
| 119 | +A list of popular LLMs are optimized and run efficiently on CPU, including the most notable open-source models like Llama series, Qwen series, and DeepSeek series like DeepSeek-R1 and DeepSeek-V3.1-Terminus. |
| 120 | + |
| 121 | +| Model Name | BF16 | W8A8_INT8 | FP8 | |
| 122 | +| --- | --- | --- | --- | |
| 123 | +| DeepSeek-R1 | | meituan/DeepSeek-R1-Channel-INT8 | deepseek-ai/DeepSeek-R1 | |
| 124 | +| DeepSeek-V3.1-Terminus | | IntervitensInc/DeepSeek-V3.1-Terminus-Channel-int8 | deepseek-ai/DeepSeek-V3.1-Terminus | |
| 125 | +| Llama-3.2-3B | meta-llama/Llama-3.2-3B-Instruct | RedHatAI/Llama-3.2-3B-quantized.w8a8 | | |
| 126 | +| Llama-3.1-8B | meta-llama/Llama-3.1-8B-Instruct | RedHatAI/Meta-Llama-3.1-8B-quantized.w8a8 | | |
| 127 | +| QwQ-32B | | RedHatAI/QwQ-32B-quantized.w8a8 | | |
| 128 | +| DeepSeek-Distilled-Llama | | RedHatAI/DeepSeek-R1-Distill-Llama-70B-quantized.w8a8 | | |
| 129 | +| Qwen3-235B | | | Qwen/Qwen3-235B-A22B-FP8 | |
| 130 | + |
| 131 | +> **Note:** The model identifiers listed in the table above have been verified on 6th Gen Intel® Xeon® P-core platforms. |
| 132 | + |
| 133 | +## Deploying LLMs with SGLang (Xeon Only) |
| 134 | + |
| 135 | +To deploy SGLang, you must pass the `xeon-values.yaml` file so it adopts the CPU-specific resource scaling and parameter logic. |
| 136 | + |
| 137 | +### Example: Deploying Meta Llama-3.2-3B-Instruct |
| 138 | +Deploying Llama-3 leveraging CPU execution: |
| 139 | +```bash |
| 140 | +cd ~/Enterprise-Inference/core/helm-charts/sglang/ |
| 141 | +
|
| 142 | +helm install sglang-llama3 . \ |
| 143 | + -f xeon-values.yaml \ |
| 144 | + --set LLM_MODEL_ID="meta-llama/Llama-3.2-3B-Instruct" \ |
| 145 | + --set global.HUGGINGFACEHUB_API_TOKEN=$HUGGINGFACE_TOKEN |
| 146 | +``` |
| 147 | + |
| 148 | +### Example: Deploying Neural-Chat |
| 149 | +Deploying Intel's Neural Chat: |
| 150 | +```bash |
| 151 | +helm install sglang-neural-chat . \ |
| 152 | + -f xeon-values.yaml \ |
| 153 | + --set LLM_MODEL_ID="Intel/neural-chat-7b-v3-3" \ |
| 154 | + --set global.HUGGINGFACEHUB_API_TOKEN=$HUGGINGFACE_TOKEN |
| 155 | +``` |
| 156 | + |
| 157 | +**Note:** Since models are pulled remotely (unless attached to a host path / PVC), the deployment may take several minutes to download depending on the model's weight topology. |
| 158 | + |
| 159 | +Verify the deployment pods are running: |
| 160 | +```bash |
| 161 | +kubectl get pods -l app.kubernetes.io/instance=sglang-llama3 |
| 162 | +``` |
| 163 | + |
| 164 | +## Accessing the Deployed Models |
| 165 | + |
| 166 | +First, obtain a Bearer token: |
| 167 | +```bash |
| 168 | +cd ~/Enterprise-Inference/core/scripts |
| 169 | +source generate-token.sh |
| 170 | +cd - |
| 171 | +
|
| 172 | +export CLIENTID=$KEYCLOAK_CLIENT_ID |
| 173 | +export CLIENT_SECRET=$KEYCLOAK_CLIENT_SECRET |
| 174 | +export BASE_URL=https://api.example.com |
| 175 | +export TOKEN_URL=${BASE_URL}/token |
| 176 | +export TOKEN=$(curl -k -X POST ${TOKEN_URL} -H 'Content-Type: application/x-www-form-urlencoded' -d "grant_type=client_credentials&client_id=${CLIENTID}&client_secret=${CLIENT_SECRET}" | jq -r .access_token) |
| 177 | +
|
| 178 | +echo "Access Token: $TOKEN" |
| 179 | +``` |
| 180 | + |
| 181 | +### Test via External URL (Chat Completions) |
| 182 | + |
| 183 | +SGLang provides an OpenAI-compatible API Server endpoint layout. You can interact with it precisely the same as standard APIs. |
| 184 | + |
| 185 | +```bash |
| 186 | +# Inferencing with Llama-3.2-3B |
| 187 | +curl -k ${BASE_URL}/llama-3/v1/chat/completions \ |
| 188 | + -X POST \ |
| 189 | + -d '{"messages": [{"role": "system","content": "You are a helpful AI assistant."},{"role": "user","content": "What is AI inference?"}],"model": "llama-3","max_tokens": 64,"temperature": 0.5}' \ |
| 190 | + -H 'Content-Type: application/json' \ |
| 191 | + -H "Authorization: Bearer $TOKEN" \ |
| 192 | + -sS |
| 193 | +``` |
| 194 | + |
| 195 | +## Undeployment |
| 196 | + |
| 197 | +To completely extract the deployment, run Helm uninstall: |
| 198 | + |
| 199 | +```bash |
| 200 | +# Uninstall the Helm release |
| 201 | +helm uninstall sglang-llama3 |
| 202 | +helm uninstall sglang-neural-chat |
| 203 | +
|
| 204 | +# Verify removal |
| 205 | +helm list | grep sglang |
| 206 | +kubectl get pods | grep sglang |
| 207 | +``` |
0 commit comments