
آموزش رفع مشکل "Host not found" در OpenResty/NGINX در محیط کوبرنیتز
مشکل: خطای "Host not found" در اتصال به سرویسها در NGINX
وقتی از OpenResty یا NGINX در یک محیط کوبرنیتز استفاده میکنید و سعی دارید به یک سرویس داخلی (مثل Redis یا دیتابیس) متصل شوید، ممکن است با خطای زیر مواجه شوید:
Failed to connect to Redis: <service-name> could not be resolved (3: Host not found)
این خطا به این معنی است که NGINX نمیتواند نام دامنه سرویس کوبرنیتز (مثل service-name.namespace.svc.cluster.local) را به آدرس IP تبدیل کند. دلیل اصلی این مشکل، عدم تنظیم رزالور DNS در تنظیمات NGINX است. در کوبرنیتز، نامهای سرویس توسط سرویس DNS داخلی (معمولاً kube-dns یا coredns) به IP تبدیل میشوند، اما NGINX بهطور پیشفرض از این تنظیمات استفاده نمیکند و نیاز به پیکربندی دستی دارد.
این مشکل بهخصوص در اسکریپتهای Lua رایج است. بدون تنظیم رزالور DNS، NGINX نمیتواند نام سرویس را resolve کند و اتصال با شکست مواجه میشود.
چرا این مشکل پیش میآید؟
در کوبرنیتز، سرویسها از طریق نامهای DNS (مثل service-name.namespace.svc.cluster.local) قابل دسترسی هستند. این نامها توسط سرویس DNS داخلی کوبرنیتز به IP پودها یا ClusterIP سرویسها ترجمه میشوند. اما NGINX/OpenResty بهطور پیشفرض از تنظیمات DNS سیستم عامل (مثل /etc/resolv.conf) استفاده نمیکند و باید رزالور DNS را در تنظیمات خود مشخص کنید. بدون این تنظیم، تلاش برای اتصال به سرویسهای کوبرنیتز با خطای "Host not found" مواجه میشود.
این مشکل ممکن است حتی زمانی رخ دهد که ابزارهایی مثل ping یا nslookup از داخل پود بهدرستی کار میکنند، چون این ابزارها از تنظیمات DNS سیستم استفاده میکنند، اما NGINX خیر.
راهحل: تنظیم رزالور DNS در NGINX
برای رفع این مشکل، باید آدرس رزالور DNS کوبرنیتز را پیدا کرده و آن را در تنظیمات NGINX اضافه کنید. مراحل زیر را دنبال کنید:
آدرس رزالور DNS در کوبرنیتز معمولاً ClusterIP سرویس kube-dns در namespace kube-system است. برای پیدا کردن این آدرس، دستور زیر را اجرا کنید:
kubectl get svc -n kube-system kube-dns
خروجی نمونه:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 30d
در این مثال، 10.96.0.10 آدرس رزالور DNS است. این آدرس را یادداشت کنید.
نکته: اگر سرویس kube-dns در cluster شما نام دیگری دارد (مثل coredns)، از همان نام استفاده کنید.
/etc/resolv.conf (اختیاری)برای اطمینان از اینکه پود شما به رزالور DNS درست دسترسی دارد، فایل /etc/resolv.conf را بررسی کنید:
kubectl exec -it <your-pod-name> -n <your-namespace> -- cat /etc/resolv.conf
خروجی نمونه:
nameserver 10.96.0.10 search <namespace>.svc.cluster.local svc.cluster.local cluster.local options ndots:5
خط nameserver نشاندهنده آدرس رزالور DNS است که باید با ClusterIP سرویس kube-dns مطابقت داشته باشد.
فایل تنظیمات NGINX (مثل /etc/nginx/nginx.conf یا فایل مربوط به ConfigMap) را ویرایش کنید و رزالور را در بلوک http یا بلوک مرتبط اضافه کنید:
http { resolver 10.96.0.10 valid=30s; resolver_timeout 5s; server { listen 80; location /api/ { lua_code_cache on; content_by_lua_file /path/to/your-script.lua; } } }
resolver 10.96.0.10: آدرس IP سرویس kube-dns که در مرحله اول پیدا کردید.
valid=30s: نتایج DNS برای ۳۰ ثانیه کش میشوند تا تعداد درخواستهای DNS کاهش یابد.
resolver_timeout 5s: حداکثر زمان انتظار برای پاسخ DNS را به ۵ ثانیه تنظیم میکند.
بعد از ویرایش فایل تنظیمات، NGINX را ریلود کنید:
kubectl exec -it <your-pod-name> -n <your-namespace> -- nginx -s reload
اگر تنظیمات NGINX از طریق ConfigMap مدیریت میشود، ConfigMap را ویرایش کنید:
kubectl edit configmap <nginx-configmap-name> -n <your-namespace>
سپس پود را ریاستارت کنید تا تغییرات اعمال شود:
kubectl delete pod <your-pod-name> -n <your-namespace>
بعد از اعمال تغییرات، درخواست خود را دوباره تست کنید (مثلاً با curl یا ارسال درخواست به API). لاگهای NGINX را بررسی کنید تا مطمئن شوید خطای "Host not found" برطرف شده است:
kubectl logs <your-pod-name> -n <your-namespace>
اگر اسکریپت Lua شما پیامهایی مثل "service connected successfully" را لاگ میکند، یعنی اتصال برقرار شده است.
راهحل موقت: استفاده از آدرس IP بهجای نام سرویس
اگر به هر دلیلی نمیتوانید تنظیمات NGINX را تغییر دهید، میتوانید بهطور موقت آدرس IP سرویس را مستقیماً در اسکریپت Lua یا متغیرهای محیطی استفاده کنید.
هشدار: هاردکد کردن IP راهحل دائمی نیست، چون IP سرویسها در کوبرنیتز ممکن است تغییر کند. بهتر است از رزالور DNS استفاده کنید.
نکات تکمیلی
بررسی NetworkPolicy: اگر مشکل همچنان پابرجاست، بررسی کنید که آیا NetworkPolicy در namespace شما ترافیک به سرویس مقصد را محدود کرده است:
kubectl get networkpolicy -n <your-namespace>
دیباگ DNS در Lua: اگر نیاز به دیباگ بیشتر دارید، از ماژول resty.dns.resolver در اسکریپت Lua استفاده کنید تا مطمئن شوید نام سرویس به IP درست resolve میشود:
local resolver = require "resty.dns.resolver" local r, err = resolver:new{ nameservers = {{"10.96.0.10", 53}}, -- آدرس kube-dns retrans = 5, timeout = 2000, } local answers, err = r:query("<service-name>") if not answers then ngx.log(ngx.ERR, "DNS resolution failed: ", err) else for _, ans in ipairs(answers) do ngx.log(ngx.DEBUG, "Resolved IP: ", ans.address) end end
نتیجهگیری
با اضافه کردن رزالور DNS (مثل 10.96.0.10) به تنظیمات NGINX، میتوانید مشکل "Host not found" را در OpenResty/NGINX برطرف کنید. این روش به NGINX اجازه میدهد تا نامهای سرویس کوبرنیتز را به آدرسهای IP درست ترجمه کند و اتصال به سرویسها برقرار شود. همیشه از رزولوشن DNS بهجای هاردکد کردن IP استفاده کنید تا سیستم شما در برابر تغییرات کوبرنیتز مقاوم باشد.