- Removed trade-dashboard/ (moved to hermes-projects/trade-dashboard/) - Removed .github/workflows/trade-dashboard.yml (CI now handled by hermes-projects root workflow) - Deleted rays-new-deployment.yaml (orphan deployment YAML) K8s manifests remain in apps/base/customer1/trade-dashboard/. See hermes-projects PR #8 for the addition side.
345 lines
11 KiB
Markdown
345 lines
11 KiB
Markdown
# Telegram Webhook Failure Analysis - Hermes Agent on GKE
|
|
|
|
**Date:** 2026-05-10
|
|
**Repo:** https://github.com/sirius0xdev/gcloud-lab
|
|
**Cluster:** devops-lab (GKE)
|
|
**Namespace:** customer1
|
|
**Webhook URL:** https://ws.siriusdevops.com/telegram/webhook/default
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
The Telegram webhook is failing because **there is no valid TLS certificate for `ws.siriusdevops.com`** at the Gateway layer. Telegram strictly requires HTTPS with a publicly-trusted certificate for webhook delivery. The Gateway listener declares `protocol: HTTPS` but has no `tls.certificateRefs` and relies on a GKE `CertMap` annotation referencing `gateway-cert-map` — a resource that **does not exist** in the repository. Cert-manager is configured but disconnected from the GatewayAPI setup (HTTP-01 solver points to a non-existent Traefik ingress class).
|
|
|
|
**TL;DR:** Telegram tries to POST to `https://ws.siriusdevops.com/...`, but the Gateway has no certificate to present during the TLS handshake. Connection fails before it ever reaches the hermes-agent pod.
|
|
|
|
---
|
|
|
|
## Root Cause #1: Missing TLS Certificate (CRITICAL)
|
|
|
|
### What's happening
|
|
|
|
**File:** `infrastructure/gatewayapi/apigateway.yaml`
|
|
|
|
```yaml
|
|
listeners:
|
|
- name: https
|
|
protocol: HTTPS
|
|
port: 443
|
|
allowedRoutes:
|
|
namespaces:
|
|
from: All
|
|
```
|
|
|
|
The listener says HTTPS but has **no `tls:` block**. It relies entirely on this annotation:
|
|
|
|
```yaml
|
|
annotations:
|
|
networking.gke.io/certmap: gateway-cert-map
|
|
```
|
|
|
|
### The problem
|
|
|
|
- **No `CertMap` or `CertMapEntry` resource** exists anywhere in the repository for `gateway-cert-map`
|
|
- Without it, GKE has no managed certificate to attach to the Gateway
|
|
- Telegram's webhook delivery gets a TLS handshake failure or no certificate
|
|
|
|
### Cert-manager is also broken
|
|
|
|
**File:** `infrastructure/controllers/base/certmanager/clusterissuer.yaml`
|
|
|
|
```yaml
|
|
solvers:
|
|
- http01:
|
|
ingress:
|
|
class: traefik
|
|
```
|
|
|
|
- HTTP-01 solver references `class: traefik`, but **no Traefik ingress controller exists** in the cluster
|
|
- **No `Certificate` CRs** exist for `ws.siriusdevops.com` or any other domain
|
|
- Cert-manager is completely disconnected from the GatewayAPI setup
|
|
|
|
### How to fix (choose ONE approach)
|
|
|
|
**Option A: GKE Managed Certificates (recommended for GatewayAPI)**
|
|
|
|
Create a `ManagedCertificate` + `BackendConfig` or `CertMap`/`CertMapEntry`:
|
|
|
|
```yaml
|
|
apiVersion: networking.gke.io/v1
|
|
kind: ManagedCertificate
|
|
metadata:
|
|
name: hermes-webhook-cert
|
|
namespace: customer1
|
|
spec:
|
|
domains:
|
|
- ws.siriusdevops.com
|
|
- brain.siriusdevops.com
|
|
- paaas.siriusdevops.com
|
|
```
|
|
|
|
Then add `tls.certificateRefs` to the Gateway listener:
|
|
|
|
```yaml
|
|
listeners:
|
|
- name: https
|
|
protocol: HTTPS
|
|
port: 443
|
|
tls:
|
|
certificateRefs:
|
|
- name: hermes-webhook-cert
|
|
group: networking.gke.io
|
|
```
|
|
|
|
**Option B: Fix Cert-manager with DNS-01**
|
|
|
|
Switch ClusterIssuer from HTTP-01/Traefik to DNS-01 (e.g., Cloudflare, GCP DNS, or Route53), then create `Certificate` resources for each domain.
|
|
|
|
---
|
|
|
|
## Root Cause #2: No Readiness/Liveness Probes (HIGH)
|
|
|
|
**File:** `apps/base/customer1/hermes-agent/new-deployment.yaml`
|
|
|
|
No readiness or liveness probes are defined on any hermes-agent deployment.
|
|
|
|
### Impact
|
|
- Pods are marked "Ready" immediately after container start
|
|
- Gateway routes traffic to the webhook port (9118) before the process has bound to it
|
|
- During restarts, traffic hits pods that haven't initialized
|
|
|
|
### Fix
|
|
Add probes to the deployment:
|
|
|
|
```yaml
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 9118
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 9118
|
|
initialDelaySeconds: 15
|
|
periodSeconds: 30
|
|
```
|
|
|
|
---
|
|
|
|
## Root Cause #3: SOPS Encrypted Secrets (HIGH)
|
|
|
|
**Files:**
|
|
- `apps/base/customer1/hermes-agent/hermes-secret.yaml` (SOPS encrypted)
|
|
- `apps/base/customer1/hermes-agent/tele-webhook.yaml` (SOPS encrypted)
|
|
|
|
These contain `TELEGRAM_BOT_TOKEN` and `TELEGRAM_WEBHOOK_SECRET`.
|
|
|
|
### Risk
|
|
- If the deployment pipeline (Flux/Kustomize controller) is **not decrypting SOPS secrets**, pods receive literal `ENC[...]` strings
|
|
- The bot token would be invalid, so even if TLS worked, Telegram auth would fail
|
|
- The webhook secret would not match, causing Telegram to reject payloads
|
|
|
|
### Verify
|
|
Run `kubectl get secret hermes-secrets -n customer1 -o yaml` and check if values are base64-encoded real tokens or `ENC[...]` strings.
|
|
|
|
---
|
|
|
|
## Secondary Issues
|
|
|
|
### 3a. Service Name Mismatch (vLLM Integration)
|
|
|
|
**File:** `apps/base/customer1/hermes-agent/new-deployment.yaml`
|
|
|
|
```yaml
|
|
OPENAI_BASE_URL: "http://openclaw-brain-service.customer1.svc.cluster.local:8000/v1"
|
|
```
|
|
|
|
But the active vLLM deployment (`rtx6000-vllm.yaml`) creates a service named **`rtx6000-brain-service`**.
|
|
|
|
- `OPENAI_BASE_URL` points to `openclaw-brain-service` which may not exist
|
|
- If Hermes ever switches to the `openai` provider (instead of `xai`), local vLLM is unreachable
|
|
- The model provider defaults to `HERMES_MODEL_PROVIDER: xai` (Grok external API)
|
|
|
|
### 3b. Duplicate HTTPRoute Deployment
|
|
|
|
The webhook HTTPRoute (`hermes-webhook.yaml`) is included in **two** kustomization trees:
|
|
|
|
1. `infrastructure/gatewayapi/gateway-routes/kustomization.yaml` -> deployed via Flux
|
|
2. `apps/base/customer1/hermes-agent/kustomization.yaml` -> deployed via Flux
|
|
|
|
Same resource (`http-telegram-webhook` in `customer1`) from two sources. This may cause Flux reconciliation conflicts.
|
|
|
|
### 3c. Empty HF_TOKEN in vLLM Deployments
|
|
|
|
All vLLM deployments have:
|
|
|
|
```yaml
|
|
- name: HF_TOKEN
|
|
value: ""
|
|
```
|
|
|
|
If the model `edp1096/Huihui-Qwen3.6-27B-abliterated-FP8` is a gated model on HuggingFace, it will fail to download.
|
|
|
|
### 3d. KEDA Scale-to-Zero
|
|
|
|
**File:** `infrastructure/gpus/base/keda-gpu-scaling/keda-vllm.yaml`
|
|
|
|
```yaml
|
|
minReplicaCount: 0
|
|
maxReplicaCount: 1
|
|
```
|
|
|
|
- vLLM scales to **zero** when idle
|
|
- First request after cold start incurs full model load time (30-60 seconds)
|
|
- For real-time Telegram responses, this causes visible latency
|
|
|
|
### 3e. PVC Name Collision
|
|
|
|
Both `rtx6000-vllm.yaml` and `a100-vllm.yaml` define a PVC named `vllm-model-qwen3.6-27b-uncensored` in namespace `customer1`. If both are ever active simultaneously, they conflict.
|
|
|
|
---
|
|
|
|
## Architecture Overview
|
|
|
|
```
|
|
Internet
|
|
|
|
|
v
|
|
[GKE External LB]
|
|
|
|
|
Gateway: external-http-gateway
|
|
(port 443/HTTPS, NO TLS cert!)
|
|
|
|
|
+-----------+-----------+
|
|
| | |
|
|
ws.siriusdevops.com brain.siriusdevops.com paaas.siriusdevops.com
|
|
| | |
|
|
v v v
|
|
/telegram/webhook / /
|
|
| | |
|
|
v v v
|
|
http-tele-webhook rtx6000- paaas-landing
|
|
:9118 brain- :8080
|
|
service:8000
|
|
|
|
|
v
|
|
hermes-agent pod
|
|
(ports: 8642, 8644, 9118)
|
|
|
|
|
v
|
|
Model Provider: xai (Grok via external API)
|
|
Fallback: OPENAI_BASE_URL -> openclaw-brain-service (MISMATCHED)
|
|
```
|
|
|
|
---
|
|
|
|
## vLLM Server Status
|
|
|
|
| Server | GPU | Model | Quantization | Status |
|
|
|--------|-----|-------|-------------|--------|
|
|
| RTX 6000 | 1x Pro 6000 (96GB) | edp1096/Huihui-Qwen3.6-27B-abliterated-FP8 | FP8 | **ACTIVE** |
|
|
| A100 | 1x A100 (80GB) | Youssofal/Qwen3.6-27B-Abliterated-Heretic-Uncensored-BF16 | BF16 | Commented out |
|
|
| L4 | 1x L4 (24GB) | p-e-w/Qwen3-8B-heretic | auto | Commented out |
|
|
| Gemma | 1x A100 (80GB) | coder3101/Qwen3.5-27B-heretic | BF16 | Not in kustomization |
|
|
|
|
**Note:** The architecture plan (`plans/AI_ARCHITECTURE.md`) describes a dual-tier L4 dispatcher + A100 deep thinker setup, but the active deployment only has RTX 6000.
|
|
|
|
---
|
|
|
|
## Action Plan (Priority Order)
|
|
|
|
### P0 - Fix TLS (will unblock Telegram webhooks)
|
|
|
|
1. **Create a `CertMap`/`CertMapEntry`** or **`ManagedCertificate`** resource for `ws.siriusdevops.com`
|
|
2. **Add `tls.certificateRefs`** to the Gateway listener in `apigateway.yaml`
|
|
3. Verify with: `curl -vI https://ws.siriusdevops.com/telegram/webhook/default`
|
|
4. If cert is valid, Telegram should start delivering webhooks
|
|
|
|
### P1 - Verify Secrets
|
|
|
|
5. Check if SOPS secrets are actually decrypted in the cluster
|
|
6. Run: `kubectl get secret hermes-secrets -n customer1 -o jsonpath='{.data.TELEGRAM_BOT_TOKEN}' | base64 -d`
|
|
|
|
### P2 - Add Probes
|
|
|
|
7. Add readiness/liveness probes to hermes-agent deployment
|
|
8. Redeploy
|
|
|
|
### P3 - Clean Up GatewayAPI
|
|
|
|
9. Remove duplicate `hermes-webhook.yaml` reference from one kustomization
|
|
10. Fix or remove Traefik-referencing ClusterIssuers
|
|
|
|
### P4 - Fix vLLM Integration
|
|
|
|
11. Fix `OPENAI_BASE_URL` service name or update kustomization to create `openclaw-brain-service`
|
|
12. Set real `HF_TOKEN` in vLLM deployments
|
|
13. Consider setting `minReplicaCount: 1` in KEDA for consistent response times
|
|
|
|
---
|
|
|
|
## Files Referenced
|
|
|
|
### GatewayAPI & TLS
|
|
- `infrastructure/gatewayapi/apigateway.yaml` - Gateway definition (missing TLS)
|
|
- `infrastructure/gatewayapi/gateway-routes/hermes-webhook.yaml` - Webhook HTTPRoute
|
|
- `infrastructure/gatewayapi/gateway-routes/route.yaml` - General route
|
|
- `infrastructure/controllers/base/certmanager/clusterissuer.yaml` - Cert-manager (Traefik mismatch)
|
|
|
|
### Hermes Agent Deployment
|
|
- `apps/base/customer1/hermes-agent/new-deployment.yaml` - Active deployment + webhook service
|
|
- `apps/base/customer1/hermes-agent/deployment.yaml` - Old deployment (no webhook config)
|
|
- `apps/base/customer1/hermes-agent/configmap.yaml` - Hermes config
|
|
- `apps/base/customer1/hermes-agent/hermes-secret.yaml` - SOPS encrypted secrets
|
|
- `apps/base/customer1/hermes-agent/tele-webhook.yaml` - SOPS encrypted webhook secret
|
|
- `apps/base/customer1/hermes-agent/kustomization.yaml` - Kustomize composition
|
|
|
|
### vLLM Infrastructure
|
|
- `infrastructure/gpus/base/vllm-servers/rtx6000-vllm.yaml` - Active vLLM server
|
|
- `infrastructure/gpus/base/keda-gpu-scaling/keda-vllm.yaml` - KEDA scaling
|
|
- `infrastructure/gpus/base/keda-gpu-scaling/vllm-route.yaml` - vLLM external route
|
|
|
|
### Architecture Plans
|
|
- `plans/AI_ARCHITECTURE.md` - AI architecture plan
|
|
- `plans/models-to-try.md` - Models being considered
|
|
|
|
---
|
|
|
|
## Quick Diagnostic Commands
|
|
|
|
Run these on the cluster to confirm findings:
|
|
|
|
```bash
|
|
# 1. Check if TLS cert exists for the webhook domain
|
|
curl -vI https://ws.siriusdevops.com/telegram/webhook/default 2>&1 | grep -E 'SSL|certificate|subject|issuer'
|
|
|
|
# 2. Check Gateway status
|
|
kubectl get gateway external-http-gateway -n customer1 -o yaml
|
|
|
|
# 3. Check HTTPRoute status (attached/programmed)
|
|
kubectl get httproute http-telegram-webhook -n customer1 -o yaml
|
|
|
|
# 4. Verify secrets are decrypted
|
|
kubectl get secret hermes-secrets -n customer1 -o jsonpath='{.data.TELEGRAM_BOT_TOKEN}' | base64 -d && echo
|
|
|
|
# 5. Check if pods are actually ready
|
|
kubectl get pods -n customer1 -l app=hermes-agent -o wide
|
|
|
|
# 6. Check CertMap exists
|
|
kubectl get certmap gateway-cert-map -A 2>/dev/null || echo "CertMap NOT FOUND"
|
|
|
|
# 7. Check managed certificates
|
|
kubectl get managedcertificate -A 2>/dev/null || echo "No ManagedCertificates"
|
|
|
|
# 8. Check cert-manager certificates
|
|
kubectl get certificate -A 2>/dev/null || echo "No Certificates"
|
|
|
|
# 9. Check vLLM pod status
|
|
kubectl get pods -n customer1 -l app=rtx6000-brain-vllm -o wide
|
|
|
|
# 10. Test internal webhook endpoint
|
|
kubectl exec -n customer1 deploy/hermes-agent -- curl -s http://localhost:9118/health || echo "Health check failed"
|
|
```
|