|
| 1 | += LMEvalJob with TLS Certificates from OAuth-Protected Models |
| 2 | +:sectnums: |
| 3 | +:icons: font |
| 4 | + |
| 5 | +== Overview |
| 6 | + |
| 7 | +This guide explains how to configure LMEvalJob Custom Resources to use TLS certificates from OAuth-protected KServe InferenceServices for proper SSL verification. Instead of disabling SSL verification (`verify_certificate: "False"`), this approach mounts the actual TLS certificates and CA bundle for secure communication. |
| 8 | + |
| 9 | +== TLS Certificate Architecture |
| 10 | + |
| 11 | +When using TLS certificates with OAuth-protected InferenceServices: |
| 12 | + |
| 13 | +1. **TLS Secret**: Contains the InferenceService's TLS certificate and private key |
| 14 | +2. **CA Bundle ConfigMap**: Contains the Certificate Authority bundle for trust chain |
| 15 | +3. **Volume Mounts**: Mount certificates into the evaluation pod |
| 16 | +4. **SSL Verification**: Configure evaluation client to use mounted certificates |
| 17 | + |
| 18 | +== Step-by-Step Setup |
| 19 | + |
| 20 | +=== Step 1: Identify TLS Resources |
| 21 | + |
| 22 | +First, identify the TLS secret and CA bundle for your InferenceService. |
| 23 | + |
| 24 | +==== Find the TLS Secret |
| 25 | + |
| 26 | +[source,bash] |
| 27 | +---- |
| 28 | +kubectl get secret -n $NAMESPACE | grep serving-cert |
| 29 | +---- |
| 30 | + |
| 31 | +Expected output shows secrets like `$MODEL-predictor-serving-cert`. |
| 32 | + |
| 33 | +==== Examine the TLS Secret Structure |
| 34 | + |
| 35 | +[source,bash] |
| 36 | +---- |
| 37 | +kubectl get secret $MODEL-predictor-serving-cert -n $NAMESPACE -o yaml |
| 38 | +---- |
| 39 | + |
| 40 | +The secret contains: |
| 41 | + |
| 42 | +- `tls.crt`: The TLS certificate |
| 43 | +- `tls.key`: The private key |
| 44 | + |
| 45 | +==== Verify CA Bundle ConfigMap |
| 46 | + |
| 47 | +[source,bash] |
| 48 | +---- |
| 49 | +kubectl get configmap openshift-service-ca.crt -n openshift-config-managed -o yaml |
| 50 | +---- |
| 51 | + |
| 52 | +This contains the `service-ca.crt` key with the Certificate Authority bundle. |
| 53 | + |
| 54 | +IMPORTANT: The `openshift-service-ca.crt` ConfigMap exists in the `openshift-config-managed` namespace, but Kubernetes cannot mount ConfigMaps across namespaces. To use this CA bundle in your LMEvalJob, you have two options: |
| 55 | + |
| 56 | +1. **Copy the ConfigMap** to your target namespace: |
| 57 | ++ |
| 58 | +[source,bash] |
| 59 | +---- |
| 60 | +kubectl get configmap openshift-service-ca.crt -n openshift-config-managed -o yaml | \ |
| 61 | + sed 's/namespace: openshift-config-managed/namespace: $NAMESPACE/' | \ |
| 62 | + kubectl apply -f - |
| 63 | +---- |
| 64 | + |
| 65 | +2. **Use OpenShift's service CA injection** (recommended): |
| 66 | ++ |
| 67 | +Create a ConfigMap with the injection annotation: |
| 68 | ++ |
| 69 | +[source,yaml] |
| 70 | +---- |
| 71 | +apiVersion: v1 |
| 72 | +kind: ConfigMap |
| 73 | +metadata: |
| 74 | + name: service-ca-bundle |
| 75 | + namespace: $NAMESPACE |
| 76 | + annotations: |
| 77 | + service.beta.openshift.io/inject-cabundle: "true" |
| 78 | +data: {} # left empty; the operator will add service-ca.crt |
| 79 | +---- |
| 80 | ++ |
| 81 | +Then reference this ConfigMap in your volume configuration. |
| 82 | + |
| 83 | +=== Step 2: Create LMEvalJob with TLS Configuration |
| 84 | + |
| 85 | +Before creating the LMEvalJob, make sure you have created the service CA bundle ConfigMap in your namespace using one of the methods described above. |
| 86 | + |
| 87 | +Create an LMEvalJob that mounts TLS certificates and configures SSL verification. |
| 88 | + |
| 89 | +Create `tls-lmeval-job.yaml`: |
| 90 | + |
| 91 | +[source,yaml] |
| 92 | +---- |
| 93 | +apiVersion: trustyai.opendatahub.io/v1alpha1 |
| 94 | +kind: LMEvalJob |
| 95 | +metadata: |
| 96 | + name: tls-eval-job |
| 97 | + namespace: $NAMESPACE # <1> |
| 98 | +spec: |
| 99 | + model: local-completions # <2> |
| 100 | + taskList: |
| 101 | + taskNames: ["mmlu"] |
| 102 | + logSamples: true |
| 103 | + batchSize: "1" |
| 104 | + allowOnline: true |
| 105 | + allowCodeExecution: true |
| 106 | + modelArgs: # <3> |
| 107 | + - name: model |
| 108 | + value: granite |
| 109 | + - name: base_url |
| 110 | + value: https://$MODEL-predictor.$NAMESPACE.svc.cluster.local:8443/v1/completions # <4> |
| 111 | + - name: num_concurrent |
| 112 | + value: "1" |
| 113 | + - name: max_retries |
| 114 | + value: "3" |
| 115 | + - name: tokenized_requests |
| 116 | + value: "false" |
| 117 | + - name: tokenizer |
| 118 | + value: ibm-granite/granite-7b-instruct |
| 119 | + - name: verify_certificate |
| 120 | + value: "/etc/ssl/certs/ca-bundle.crt" # <5> |
| 121 | + pod: |
| 122 | + container: |
| 123 | + env: |
| 124 | + - name: OPENAI_API_KEY # <6> |
| 125 | + valueFrom: |
| 126 | + secretKeyRef: |
| 127 | + name: lmeval-sa-token |
| 128 | + key: token |
| 129 | + volumeMounts: # <7> |
| 130 | + - name: tls-certs |
| 131 | + mountPath: /etc/ssl/certs/tls.crt |
| 132 | + subPath: tls.crt |
| 133 | + readOnly: true |
| 134 | + - name: ca-bundle |
| 135 | + mountPath: /etc/ssl/certs/ca-bundle.crt |
| 136 | + subPath: service-ca.crt |
| 137 | + readOnly: true |
| 138 | + volumes: # <8> |
| 139 | + - name: tls-certs |
| 140 | + secret: |
| 141 | + secretName: $MODEL-predictor-serving-cert |
| 142 | + - name: ca-bundle |
| 143 | + configMap: |
| 144 | + name: service-ca-bundle |
| 145 | +---- |
| 146 | +<1> Replace `$NAMESPACE` with your target namespace |
| 147 | +<2> Use `local-completions` for OpenAI-compatible API endpoints |
| 148 | +<3> Model arguments configure the evaluation client |
| 149 | +<4> HTTPS endpoint of the OAuth-protected InferenceService |
| 150 | +<5> Path to mounted CA bundle for SSL verification |
| 151 | +<6> Service account token for OAuth authentication (see xref:lmeval-oauth-authentication.adoc#_step_2_create_service_account_token_secret[Create Service Account Token Secret]) |
| 152 | +<7> Mount TLS certificate and CA bundle into container |
| 153 | +<8> Define volumes for TLS secret and CA bundle ConfigMap |
| 154 | + |
| 155 | +Apply the LMEvalJob: |
| 156 | + |
| 157 | +[source,bash] |
| 158 | +---- |
| 159 | +kubectl apply -f tls-lmeval-job.yaml -n $NAMESPACE |
| 160 | +---- |
| 161 | + |
| 162 | +== Configuration Reference |
| 163 | + |
| 164 | +=== TLS Certificate Paths |
| 165 | + |
| 166 | +[cols="1,2,1"] |
| 167 | +|=== |
| 168 | +|Mount Path |Description |Source |
| 169 | + |
| 170 | +|`/etc/ssl/certs/tls.crt` |
| 171 | +|InferenceService TLS certificate |
| 172 | +|Secret `tls.crt` key |
| 173 | + |
| 174 | +|`/etc/ssl/certs/ca-bundle.crt` |
| 175 | +|Certificate Authority bundle |
| 176 | +|ConfigMap `service-ca.crt` key |
| 177 | + |
| 178 | +|`/etc/ssl/certs/tls.key` |
| 179 | +|Private key (if needed) |
| 180 | +|Secret `tls.key` key |
| 181 | +|=== |
| 182 | + |
| 183 | +=== SSL Verification Options |
| 184 | + |
| 185 | +[cols="1,2,1"] |
| 186 | +|=== |
| 187 | +|Value |Description |Use Case |
| 188 | + |
| 189 | +|`"False"` |
| 190 | +|Disable SSL verification (insecure) |
| 191 | +|Development only |
| 192 | + |
| 193 | +|`"/etc/ssl/certs/ca-bundle.crt"` |
| 194 | +|Use mounted CA bundle |
| 195 | +|Production with proper certificates |
| 196 | + |
| 197 | +|`"True"` |
| 198 | +|Use system default CA bundle |
| 199 | +|Standard SSL verification |
| 200 | +|=== |
| 201 | + |
| 202 | +=== Volume Configuration Patterns |
| 203 | + |
| 204 | +==== TLS Secret Volume |
| 205 | +[source,yaml] |
| 206 | +---- |
| 207 | +volumes: |
| 208 | + - name: tls-certs |
| 209 | + secret: |
| 210 | + secretName: $MODEL-predictor-serving-cert |
| 211 | + items: # Optional: specify specific keys |
| 212 | + - key: tls.crt |
| 213 | + path: tls.crt |
| 214 | + - key: tls.key |
| 215 | + path: tls.key |
| 216 | +---- |
| 217 | + |
| 218 | +==== CA Bundle ConfigMap Volume |
| 219 | + |
| 220 | +**Option 1: Using Service CA Injection (Recommended)** |
| 221 | +[source,yaml] |
| 222 | +---- |
| 223 | +volumes: |
| 224 | + - name: ca-bundle |
| 225 | + configMap: |
| 226 | + name: service-ca-bundle # <1> |
| 227 | + items: # Optional: specify specific keys |
| 228 | + - key: service-ca.crt |
| 229 | + path: service-ca.crt |
| 230 | +---- |
| 231 | +<1> ConfigMap created with `service.beta.openshift.io/inject-cabundle: "true"` annotation |
| 232 | + |
| 233 | +**Option 2: Using Copied ConfigMap** |
| 234 | +[source,yaml] |
| 235 | +---- |
| 236 | +volumes: |
| 237 | + - name: ca-bundle |
| 238 | + configMap: |
| 239 | + name: openshift-service-ca.crt # <1> |
| 240 | + items: # Optional: specify specific keys |
| 241 | + - key: service-ca.crt |
| 242 | + path: service-ca.crt |
| 243 | +---- |
| 244 | +<1> ConfigMap manually copied from `openshift-config-managed` namespace |
| 245 | + |
| 246 | +==== Volume Mount Options |
| 247 | +[source,yaml] |
| 248 | +---- |
| 249 | +volumeMounts: |
| 250 | + - name: tls-certs |
| 251 | + mountPath: /etc/ssl/certs/tls.crt |
| 252 | + subPath: tls.crt # Mount specific file, not entire volume |
| 253 | + readOnly: true |
| 254 | + - name: ca-bundle |
| 255 | + mountPath: /etc/ssl/certs/ca-bundle.crt |
| 256 | + subPath: service-ca.crt |
| 257 | + readOnly: true |
| 258 | +---- |
| 259 | + |
| 260 | +== Verification and Troubleshooting |
| 261 | + |
| 262 | +=== Verify TLS Configuration |
| 263 | + |
| 264 | +Check that the LMEvalJob has proper TLS configuration: |
| 265 | + |
| 266 | +[source,bash] |
| 267 | +---- |
| 268 | +kubectl get lmevaljob tls-eval-job -n $NAMESPACE -o yaml |
| 269 | +---- |
| 270 | + |
| 271 | +Look for: |
| 272 | + |
| 273 | +- `verify_certificate: "/etc/ssl/certs/ca-bundle.crt"` in modelArgs |
| 274 | +- `volumeMounts` section in pod.container |
| 275 | +- `volumes` section in pod |
| 276 | + |
| 277 | +=== Check Pod Volume Mounts |
| 278 | + |
| 279 | +[source,bash] |
| 280 | +---- |
| 281 | +kubectl describe pod tls-eval-job -n $NAMESPACE |
| 282 | +---- |
| 283 | + |
| 284 | +Verify: |
| 285 | + |
| 286 | +- Volumes are listed in the pod spec |
| 287 | +- Volume mounts are correctly configured |
| 288 | +- No mount conflicts or permission issues |
| 289 | + |
| 290 | +=== Verify Certificate Access |
| 291 | + |
| 292 | +Check that certificates are accessible inside the pod: |
| 293 | + |
| 294 | +[source,bash] |
| 295 | +---- |
| 296 | +kubectl exec tls-eval-job -n $NAMESPACE -- ls -la /etc/ssl/certs/ |
| 297 | +kubectl exec tls-eval-job -n $NAMESPACE -- cat /etc/ssl/certs/ca-bundle.crt | head -5 |
| 298 | +---- |
| 299 | + |
| 300 | +=== Check SSL Warnings |
| 301 | + |
| 302 | +Monitor job logs for SSL-related messages: |
| 303 | + |
| 304 | +[source,bash] |
| 305 | +---- |
| 306 | +kubectl logs tls-eval-job -n $NAMESPACE | grep -i ssl |
| 307 | +kubectl logs tls-eval-job -n $NAMESPACE | grep -i certificate |
| 308 | +kubectl logs tls-eval-job -n $NAMESPACE | grep -i verify |
| 309 | +---- |
| 310 | + |
| 311 | +== Troubleshooting |
| 312 | + |
| 313 | +[cols="1,2,2"] |
| 314 | +|=== |
| 315 | +|Problem |Causes |Solution |
| 316 | + |
| 317 | +|Certificate Not Found + |
| 318 | +*(File not found errors for certificate paths)* |
| 319 | +a|* Secret or configmap missing |
| 320 | +* Incorrect volume mount paths |
| 321 | +* Wrong secret/configmap names |
| 322 | +* ConfigMap in wrong namespace |
| 323 | +a|* Verify secret and configmap exist in the same namespace as LMEvalJob |
| 324 | +* Check volume mount paths and subPath values |
| 325 | +* Ensure correct secret/configmap names |
| 326 | +* Use service CA injection or copy ConfigMap to target namespace |
| 327 | + |
| 328 | +|SSL Verification Still Disabled + |
| 329 | +*(`InsecureRequestWarning` in logs, `verify_certificate: False` in modelArgs)* |
| 330 | +a|* Incorrect `verify_certificate` value in modelArgs |
| 331 | +* Certificate path not accessible |
| 332 | +* Wrong CA bundle content |
| 333 | +a|* Set `verify_certificate: "/etc/ssl/certs/ca-bundle.crt"` |
| 334 | +* Verify certificate files are mounted correctly |
| 335 | +* Check CA bundle contains valid certificates |
| 336 | + |
| 337 | +|Permission Denied + |
| 338 | +*(Permission errors accessing mounted certificates)* |
| 339 | +a|* Volume mount permissions |
| 340 | +* Secret and configmap access issues |
| 341 | +* Pod security context restrictions |
| 342 | +a|* Ensure volumes are mounted as `readOnly: true` |
| 343 | +* Check secret and configmap permissions |
| 344 | +* Verify pod security context if applicable |
| 345 | + |
| 346 | +|Certificate Trust Issues + |
| 347 | +*(SSL verification fails even with certificates mounted)* |
| 348 | +a|* Wrong CA bundle for the certificate chain |
| 349 | +* Certificate expired or invalid |
| 350 | +* Trust chain incomplete |
| 351 | +a|* Verify certificate validity: `openssl x509 -in /etc/ssl/certs/tls.crt -text -noout` |
| 352 | +* Check certificate chain matches CA bundle |
| 353 | +* Use correct ConfigMap for your cluster's CA |
| 354 | + |
| 355 | +|Cross-Namespace ConfigMap Error + |
| 356 | +*(ConfigMap `openshift-service-ca.crt` not found in target namespace)* |
| 357 | +a|* Trying to mount ConfigMap from `openshift-config-managed` namespace |
| 358 | +* Kubernetes cannot mount ConfigMaps across namespaces |
| 359 | +* Missing service CA injection setup |
| 360 | +a|* Create ConfigMap with `service.beta.openshift.io/inject-cabundle: "true"` annotation |
| 361 | +* Or copy ConfigMap: `kubectl get configmap openshift-service-ca.crt -n openshift-config-managed -o yaml \| sed 's/namespace: openshift-config-managed/namespace: $NAMESPACE/' \| kubectl apply -f -` |
| 362 | +* Update volume to reference the namespaced ConfigMap |
| 363 | +|=== |
0 commit comments