लोकल LLM इन्फरेंस सर्वर की हेल्थ मॉनिटरिंग को ऑटोमेट करने की कहानी

लोकल LLM इन्फरेंस सर्वर की हेल्थ मॉनिटरिंग को ऑटोमेट करने की कहानी

8 min read

2026.04 / Tech Blog / BASTION

लोकल LLM इन्फरेंस सर्वर की ऑटोमेटेड हेल्थ मॉनिटरिंग #

GPUStack की उस स्थिति का पता लगाना जहाँ वह “चलता हुआ दिखता है लेकिन इन्फरेंस नहीं कर पाता।” हमने 5-मिनट के अंतराल पर 2-स्टेज हेल्थ चेक + Slack नोटिफिकेशन + Zabbix इंटीग्रेशन चलाने वाला सिस्टम बनाया।

समस्या क्या थी? #

पिछले लेख (लोकल LLM से इन्फ्रास्ट्रक्चर लॉग का स्वचालित विश्लेषण करने वाला सिस्टम बनाना) में पेश किया गया BASTION एक ऐसा मैकेनिज़्म है जो लोकल LLM (Qwen2.5-14B) का उपयोग करके हर 15 मिनट में इन्फ्रास्ट्रक्चर लॉग का स्वचालित विश्लेषण करता है।

इस मैकेनिज़्म का सिंगल पॉइंट ऑफ़ फेल्योर है GPUStack (LLM इन्फरेंस सर्वर)। जब GPUStack डाउन हो जाता है, तो लॉग कलेक्शन जारी रहता है लेकिन विश्लेषण और नोटिफिकेशन सब रुक जाते हैं। इसके अलावा, यह नोटिस करने में समय लगता है कि वह रुक गया है। हर 15 मिनट में आने वाला Slack नोटिफिकेशन “नहीं आ रहा” — इंसान को यह नोटिस करने में कई घंटे लग सकते हैं।

GPUStack में खुद मॉडल ऑटो-रीस्टार्ट फीचर है। प्रोसेस क्रैश हो तो वह अपने आप रीस्टार्ट हो जाता है। हालाँकि, केवल इससे कुछ केस पकड़ में नहीं आते।

ऐसे केस जो GPUStack का ऑटो-रीस्टार्ट नहीं पकड़ पाता:
・API प्रोसेस ज़िंदा है लेकिन OOM के कारण मॉडल अनलोड हो गया है
・API 200 लौटाता है लेकिन मॉडल इन्फरेंस रिक्वेस्ट का जवाब नहीं देता
・नेटवर्क के नज़रिए से BASTION सर्वर GPUStack तक नहीं पहुँच पाता

दूसरे शब्दों में, “प्रोसेस का ज़िंदा होना” और “इन्फरेंस का वास्तव में काम करना” अलग-अलग मुद्दे हैं। बाहर से नियमित रूप से यह पुष्टि करने का मैकेनिज़्म चाहिए था कि “क्या हम वास्तव में इन्फरेंस कर सकते हैं”।

डिज़ाइन का तरीका #

काम सरल है: हर 5 मिनट में GPUStack API को कॉल करो, सामान्य हो तो कुछ मत करो, और असामान्य हो तो Slack पर नोटिफाई करो। हालाँकि, कई डिज़ाइन निर्णय लेने पड़ते हैं।

2-स्टेज चेक #

हमने हेल्थ चेक को 2 स्टेज में बाँटा।

स्टेजचेक की सामग्रीक्या पकड़ता हैफेल होने पर
CHECK1/v1/models API पर HTTP रिक्वेस्टGPUStack प्रोसेस का ज़िंदा होनाExit 1 (CRITICAL)
CHECK2chat/completions पर वास्तविक इन्फरेंस रिक्वेस्टमॉडल वास्तव में लोड है और जवाब दे पा रहा है या नहींExit 2 (WARNING)

वह केस महत्वपूर्ण है जहाँ CHECK1 पास होता है लेकिन CHECK2 फेल हो जाता है। यानी “API ज़िंदा है लेकिन मॉडल इन्फरेंस नहीं कर पाता” वाली स्थिति। केवल प्रोसेस मॉनिटरिंग से यह कभी पकड़ में नहीं आ सकती।

CHECK2 में हम एक अकेला शब्द "healthcheck" भेजते हैं और max_tokens: 5 के साथ जवाब लेते हैं। चूँकि हमें बस यह पुष्टि करनी है कि इन्फरेंस काम करता है या नहीं, हम न्यूनतम टोकन का उपयोग करते हैं।

Exit कोड का डिज़ाइन #

हमने स्क्रिप्ट के exit कोड को 3-मान वाला डिज़ाइन किया।

Exit कोडअर्थSlack नोटिफिकेशनZabbix ट्रिगर
0सामान्यकेवल रिकवरी पर
1API डाउनCRITICAL (लाल)गंभीर विफलता
2मॉडल डाउनWARNING (नारंगी)चेतावनी

हमने 1 और 2 को इसलिए अलग किया क्योंकि रिस्पॉन्स अलग होता है। Exit 1 के लिए आपको खुद GPUStack प्रोसेस को जाँचना होता है। Exit 2 के लिए बस मॉडल स्टेटस के लिए GPUStack डैशबोर्ड देखना काफी है। नोटिफिकेशन पाने वाला व्यक्ति सिर्फ exit कोड से समझ सकता है कि उसे आगे क्या करना चाहिए।

लगातार अलर्ट का दमन #

5-मिनट के अंतराल पर चलाने का मतलब है कि अगर GPUStack 30 मिनट के लिए डाउन रहा, तो वही CRITICAL नोटिफिकेशन 6 बार भेजा जाएगा। तीसरी बार तक कोई Slack देखता ही नहीं।

इसे रोकने के लिए, हम पिछली स्थिति को एक फ़ाइल में सेव करते हैं और केवल स्थिति बदलने पर ही नोटिफिकेशन भेजते हैं

स्थिति परिवर्तननोटिफिकेशन
ok → api_downCRITICAL नोटिफिकेशन भेजें
ok → model_downWARNING नोटिफिकेशन भेजें
api_down → okRECOVERED नोटिफिकेशन भेजें
api_down → api_downकोई नोटिफिकेशन नहीं
model_down → model_downकोई नोटिफिकेशन नहीं

रिकवरी पर RECOVERED नोटिफिकेशन भेजना भी महत्वपूर्ण है। जिस व्यक्ति को CRITICAL नोटिफिकेशन मिला, उसे “क्या यह अभी भी डाउन है या ठीक हो चुका है” जाँचने के लिए डैशबोर्ड नहीं खोलना पड़ता।

इम्प्लीमेंटेशन #

सब कुछ एक ही शेल स्क्रिप्ट से हो जाता है। इसे बाकी BASTION स्क्रिप्ट्स (summarize.sh, analyze.sh आदि) के साथ उसी डायरेक्टरी में रखा गया है और cron द्वारा हर 5 मिनट में चलाया जाता है।

CHECK1: API रिस्पॉन्स की पुष्टि #

MODELS_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \
    --max-time 15 \
    -H "Authorization: Bearer ${API_KEY}" \
    "${GPUSTACK_HOST}/v1/models")

चूँकि GPUStack एक OpenAI-कम्पैटिबल API देता है, हम बस /v1/models एंडपॉइंट पर एक GET रिक्वेस्ट भेजते हैं। अगर HTTP 200 लौटता है, तो API ज़िंदा है। टाइमआउट 15 सेकंड है।

CHECK2: वास्तविक इन्फरेंस टेस्ट #

INFERENCE_RESPONSE=$(curl -s --max-time 15 \
    -H "Authorization: Bearer ${API_KEY}" \
    -H "Content-Type: application/json" \
    "${GPUSTACK_HOST}/v1/chat/completions" \
    -d '{"model":"qwen2.5-14b-instruct",
         "messages":[{"role":"user","content":"healthcheck"}],
         "max_tokens":5,"temperature":0}')

अगर रिस्पॉन्स JSON में "choices" मौजूद है, तो इन्फरेंस सफल है। नहीं है तो इसे मॉडल डाउन के रूप में प्रोसेस किया जाता है।

स्थिति की परसिस्टेंस #

# Read previous state
STATUS_FILE="/tmp/gpustack-health-status"
PREV_STATUS="ok"
[ -f "$STATUS_FILE" ] && PREV_STATUS=$(cat "$STATUS_FILE")

# Save current state
echo "ok" > "$STATUS_FILE"      # or "api_down" or "model_down"

बस स्थिति को एक फ़ाइल में लिखना है। किसी जटिल डेटाबेस की ज़रूरत नहीं। रीस्टार्ट के बाद भी, पहली रन पर फ़ाइल नहीं होती इसलिए ok डिफ़ॉल्ट रहता है, और अगर कोई असामान्यता हो तो पहली ही रन पर नोटिफिकेशन भेज दिया जाता है।

cron रजिस्ट्रेशन #

*/5 * * * * bash /opt/oc-seclogs/gpustack-healthcheck.sh >> /var/log/gpustack-healthcheck.log 2>&1

हमने इसे BASTION के पीरियोडिक विश्लेषण (15-मिनट अंतराल) से छोटे, 5-मिनट के अंतराल पर सेट किया। अगर LLM डाउन रहते हुए पीरियोडिक विश्लेषण चला, तो वह फेल हो जाएगा — इसलिए हम उससे पहले ही समस्या पकड़ना चाहते हैं।

जो चीज़ें हमें वास्तव में झेलनी पड़ीं #

API key ऑथेंटिकेशन नज़रअंदाज़ हो गया #

जब मैंने इसे पहली बार चलाया, CHECK1 ने तुरंत HTTP 401 लौटाया। GPUStack में API key ऑथेंटिकेशन सक्षम था, लेकिन मैंने curl में Authorization हेडर शामिल नहीं किया था। यह एक साफ़-साफ़ गलती है, लेकिन मुझे लगता है कि टेस्ट एनवायरनमेंट (बिना ऑथेंटिकेशन) में हेल्थ चेक स्क्रिप्ट लिखकर उसे ज्यों का त्यों प्रोडक्शन में ले जाना आम बात है। हमने इसे API key को एक .env फ़ाइल से पढ़ने के लिए बदलकर हल किया।

CHECK1 पास लेकिन CHECK2 फेल वाला केस वास्तव में होता है #

GPUStack API प्रोसेस चल रहा है, लेकिन मॉडल लोडिंग फेल हो गई है। /v1/models 200 लौटाता है लेकिन chat/completions 500 लौटाता है। केवल प्रोसेस मॉनिटरिंग इसे “सामान्य” ठहरा देती। 2-स्टेज चेक का निर्णय ऑपरेशन में सही साबित हुआ।

Slack नोटिफिकेशन फ़ॉर्मैट में “आगे क्या करना है” शामिल करना चाहिए #

शुरुआत में हम बस “GPUStack API जवाब नहीं दे रहा” कहते थे, लेकिन नोटिफिकेशन पाने वाला व्यक्ति (मैं खुद) आगे हमेशा वही काम करता है। इसलिए हमने पुष्टि करने वाला कमांड (curl -s http://<endpoint>/v1/models) नोटिफिकेशन टेक्स्ट में ही शामिल कर दिया। नोटिफिकेशन मिलते ही उसे टर्मिनल में कॉपी-पेस्ट करके तुरंत स्थिति जाँची जा सकती है।

Zabbix इंटीग्रेशन #

Cron-आधारित Slack नोटिफिकेशन की तात्कालिकता ऊँची है, लेकिन “पिछले महीने का अपटाइम क्या रहा” या “रिस्पॉन्स टाइम का ट्रेंड क्या है” जैसे दीर्घकालिक नज़रिए की कमी रहती है। यह Zabbix की खासियत है, इसलिए हम UserParameters भी रजिस्टर करते हैं ताकि Zabbix से मॉनिटरिंग हो सके।

UserParameter #

हमने Zabbix Agent की कॉन्फ़िगरेशन फ़ाइल में 3 UserParameters जोड़े।

Keyसामग्रीडेटा टाइप
gpustack.healthहेल्थ चेक स्क्रिप्ट का exit कोड (0/1/2)Integer
gpustack.response_timeAPI रिस्पॉन्स टाइम (मिलीसेकंड)Integer
gpustack.modelsमॉडल सूची का JSONText

gpustack.health खुद हेल्थ चेक स्क्रिप्ट को कॉल करता है और exit कोड लौटाता है। एक ही स्क्रिप्ट को cron और Zabbix दोनों में दोबारा इस्तेमाल करके, हम जजमेंट लॉजिक की डुप्लिकेशन से बचते हैं।

ट्रिगर #

हमने 3-स्तर के ट्रिगर सेट किए।

गंभीरताशर्तअर्थ
गंभीर विफलताgpustack.health = 1API डाउन। LLM इन्फरेंस पूरी तरह ठप।
चेतावनीgpustack.health = 2API ज़िंदा है लेकिन मॉडल इन्फरेंस नहीं कर पाता।
सूचनाgpustack.response_time > 5000API रिस्पॉन्स में 5+ सेकंड लगते हैं। GPU पर ऊँचे लोड का संकेत।

तीसरा “रिस्पॉन्स में देरी” वाला ट्रिगर CRITICAL बनने से पहले प्री-सिम्प्टम डिटेक्शन का काम करता है। अगर ग्राफ़ में रिस्पॉन्स टाइम धीरे-धीरे बढ़ता दिखे, तो OOM होने से पहले मॉडल का बैच साइज़ या कॉन्करेंट रिक्वेस्ट काउंट एडजस्ट किया जा सकता है।

cron और Zabbix के बीच भूमिकाओं का बँटवारा #

cron (5-मिनट अंतराल): असामान्यता पकड़ते ही तुरंत Slack पर नोटिफाई। सरल और भरोसेमंद।
Zabbix (5-मिनट अंतराल): हिस्ट्री स्टोरेज, रिस्पॉन्स टाइम ग्राफ़, एस्केलेशन, विफलता का इतिहास।

दोनों को चलाने से रिडंडेंसी सुनिश्चित होती है। cron रुक जाए तो Zabbix पकड़ लेता है; Zabbix डाउन हो जाए तो भी cron नोटिफाई करता रहता है।

ऑपरेशन के नतीजे #

ऑपरेशन शुरू करने के बाद से, हमने 2 केस पकड़े जहाँ GPUStack मॉडल ने जवाब देना बंद कर दिया था। दोनों में CHECK1 पास हुआ लेकिन CHECK2 ने पकड़ा (Exit 2)। GPUStack डैशबोर्ड जाँचने पर मॉडल “Error” स्थिति में दिखा। GPUStack के ऑटो-रीस्टार्ट फीचर ने मॉडल को दोबारा लोड किया और कुछ मिनट बाद RECOVERED नोटिफिकेशन आया, जिसने रिकवरी की पुष्टि की।

बिना हेल्थ चेक के, अगला पीरियोडिक विश्लेषण (15 मिनट बाद तक) फेल होता, और इंसान को यह नोटिस करने में और भी समय लगता कि Slack नोटिफिकेशन नहीं भेज रहा।

सारांश #

हमने शेल स्क्रिप्ट + cron + Zabbix से लोकल LLM इन्फरेंस सर्वर (GPUStack) की हेल्थ मॉनिटरिंग ऑटोमेट की।

तीन डिज़ाइन पॉइंट खास हैं। 2-स्टेज चेक (डिटेक्शन एक्युरेसी बढ़ाने के लिए API रिस्पॉन्स और वास्तविक इन्फरेंस को अलग करना), लगातार अलर्ट का दमन (केवल स्थिति बदलने पर नोटिफाई करके बर्नआउट रोकना), cron और Zabbix का संयुक्त उपयोग (तुरंत नोटिफिकेशन और दीर्घकालिक ट्रेंड दोनों हासिल करना)।

चूँकि सब कुछ एक ही शेल स्क्रिप्ट से हो जाता है, वही तरीका vLLM या Ollama जैसे OpenAI-कम्पैटिबल API देने वाले दूसरे LLM सर्वरों की मॉनिटरिंग में भी इस्तेमाल किया जा सकता है।

BASTION एक ऐसी सेवा है जो क्लोज़्ड एनवायरनमेंट में AI सिक्योरिटी मॉनिटरिंग साकार करती है।

BASTION सेवा पृष्ठ
संपर्क

Updated on 2026 वर्ष 6 माह 10 दिन

What are your feelings

  • Happy
  • Normal
  • Sad