[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fHR_eEOz2h3klxe6smqwI3jAHCecrowdBmA2oQ806UE4":3},{"data":4,"related":85},{"id":5,"title":6,"slug":7,"excerpt":8,"cover":9,"category":11,"author":14,"track":20,"level":23,"reading_minutes":26,"is_featured":27,"published_at":28,"updated_at":28,"body":29,"toc":30,"tags":56,"faqs":70,"related_services":80,"comments_enabled":83,"meta_title":19,"meta_description":84,"canonical_url":19,"noindex":27,"is_live":83},11,"تأخیر ۵ ثانیه‌ای DNS در Kubernetes؛ پای ndots:5 در میان است","kubernetes-dns-ndots5-latency","هرچند وقت یک‌بار یک درخواست خروجی دقیقاً ۵ ثانیه طول می‌کشد و بعد موفق می‌شود؟ ریشه معمولاً گزینه ndots:5 در resolv.conf پادها و لیست search است. این مقاله علت، تشخیص و راه‌حل کامل را بررسی می‌کند.",{"url":10,"alt":6},"https:\u002F\u002Fapi.cloudicap.com\u002Fmedia\u002Fposts\u002F79a6c679-300c-4c45-b692-9edb968f1d49.webp",{"name":12,"slug":13},"Kubernetes و کانتینر","kubernetes",{"name":15,"slug":16,"role":17,"bio":18,"linkedin_url":19,"avatar_url":19},"تحریریه کلودیکپ","cloudicap-editorial","تیم محتوای کلودیکپ","تیم فنی و محتوای کلودیکپ؛ مهندسانی که هر روز با DevOps، Kubernetes و زیرساخت ابری کار می‌کنند و تجربه‌هایشان را اینجا می‌نویسند.",null,{"value":21,"label":22},"engineers","مهندسان",{"value":24,"label":25},"intermediate","متوسط",7,false,"2026-10-12T09:53:03+00:00","\u003Cp>اگر مدتی با \u003Ca href=\"\u002Fservices\u002Fkubernetes\">Kubernetes\u003C\u002Fa> کار کرده باشید، حتماً این صحنه را دیده‌اید: سرویسی که بیشتر اوقات سالم است، اما هر چند وقت یک‌بار یک درخواست خروجی \u003Cstrong>دقیقاً\u003C\u002Fstrong> حدود ۵ ثانیه طول می‌کشد و بعد موفق می‌شود. نه CPU اشباع است، نه شبکه، و نه سرویس مقصد مشکل دارد. ردپای این الگوی ۵ ثانیه‌ای تقریباً همیشه به DNS و گزینه \u003Ccode>ndots:5\u003C\u002Fcode> در \u003Ccode>\u002Fetc\u002Fresolv.conf\u003C\u002Fcode> پادها می‌رسد.\u003C\u002Fp>\n\n\u003Ch2 id=\"شرح-مسئله-تأخیری-که-پترن-مشخصی-دارد\">شرح مسئله: تأخیری که پترن مشخصی دارد\u003C\u002Fh2>\n\u003Cp>نشانه‌های کلاسیک این مشکل را می‌توان در چند جا دید:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>در لاگ اپلیکیشن، خطاهایی مثل \u003Ccode>context deadline exceeded\u003C\u002Fcode>، \u003Ccode>dial tcp: i\u002Fo timeout\u003C\u002Fcode> یا \u003Ccode>lookup api.example.com: i\u002Fo timeout\u003C\u002Fcode> که بعد از ۵ ثانیه با یک retry موفق می‌شوند.\u003C\u002Fli>\n\u003Cli>تأخیر فقط برای نام‌های \u003Cstrong>خارج از کلاستر\u003C\u002Fstrong> دیده می‌شود؛ سرویس‌های داخلی سریع پاسخ می‌دهند.\u003C\u002Fli>\n\u003Cli>افزایش ناگهانی نرخ کوئری CoreDNS و بالا رفتن شمارنده پاسخ‌های \u003Ccode>NXDOMAIN\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>مصرف CPU کور‌دی‌ان‌اس به‌ازای هر Request Per Second بیشتر از حد انتظار.\u003C\u002Fli>\n\u003Cli>گاهی تأخیر فقط روی اولین درخواست یا بعد از یک دوره بی‌کاری دیده می‌شود.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>همین «۵ ثانیه ثابت» مهم‌ترین سرنخ است؛ چون یک عدد تصادفی نیست و به تایمر پیش‌فرض resolver برمی‌گردد.\u003C\u002Fp>\n\n\u003Ch2 id=\"علت-ریشه‌ای-ndots-5-و-لیست-search\">علت ریشه‌ای: ndots:5 و لیست search\u003C\u002Fh2>\n\u003Cp>وقتی پادی با \u003Ccode>dnsPolicy: ClusterFirst\u003C\u002Fcode> اجرا می‌شود، kubelet یک \u003Ccode>\u002Fetc\u002Fresolv.conf\u003C\u002Fcode> با این شکل می‌سازد:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">nameserver 10.96.0.10\nsearch default.svc.cluster.local svc.cluster.local cluster.local\noptions ndots:5\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>معنای \u003Ccode>ndots\u003C\u002Fcode> این است: اگر تعداد نقطه‌های یک نام \u003Cstrong>کمتر\u003C\u002Fstrong> از این مقدار باشد، resolver ابتدا نام را با هر یک از دامنه‌های \u003Ccode>search\u003C\u002Fcode> می‌آزماید و تنها در انتها نسخه مطلق (absolute) را می‌پرسد. چون \u003Ccode>ndots\u003C\u002Fcode> روی ۵ تنظیم شده و تقریباً هیچ نامی ۵ نقطه ندارد، عملاً \u003Cstrong>همه\u003C\u002Fstrong> نام‌ها از مسیر search رد می‌شوند.\u003C\u002Fp>\n\u003Cp>نتیجه برای \u003Ccode>api.stripe.com\u003C\u002Fcode> این ترتیب می‌شود:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Ccode>api.stripe.com.default.svc.cluster.local\u003C\u002Fcode> ← NXDOMAIN\u003C\u002Fli>\n\u003Cli>\u003Ccode>api.stripe.com.svc.cluster.local\u003C\u002Fcode> ← NXDOMAIN\u003C\u002Fli>\n\u003Cli>\u003Ccode>api.stripe.com.cluster.local\u003C\u002Fcode> ← NXDOMAIN\u003C\u002Fli>\n\u003Cli>\u003Ccode>api.stripe.com\u003C\u002Fcode> ← پاسخ درست\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>و چون برای هر نام هم رکورد \u003Ccode>A\u003C\u002Fcode> و هم \u003Ccode>AAAA\u003C\u002Fcode> پرسیده می‌شود، یک lookup ساده به ۸ کوئری تبدیل می‌شود. این هم glibc (سیستمی) و هم resolver خالص Go مصداق دارد.\u003C\u002Fp>\n\u003Cp>حالا نکته کلیدی: فایل \u003Ccode>resolv.conf\u003C\u002Fcode> مقدار \u003Ccode>timeout\u003C\u002Fcode> را تنظیم نمی‌کند، پس پیش‌فرض یعنی \u003Ccode>timeout:5\u003C\u002Fcode> اعمال می‌شود. هر بسته UDP که گم شود یا دیر برسد — به‌خاطر race کانترک UDP در kube-proxy، اشباع CoreDNS، یا NetworkPolicy — باعث می‌شود resolver پنج ثانیه منتظر بماند و بعد retry کند. با ۸ کوئری به‌جای ۲ کوئری، احتمال برخورد با این شرط عملاً چهار برابر می‌شود. اینجاست که «معماری ndots:5» و «۵ ثانیه» به هم می‌رسند.\u003C\u002Fp>\n\n\u003Ch2 id=\"گام-۱-بازتولید-و-تشخیص\">گام ۱: بازتولید و تشخیص\u003C\u002Fh2>\n\u003Cp>یک پاد موقت با ابزارهای شبکه بالا بیاورید:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">kubectl run tmp-dns --image=nicolaka\u002Fnetshoot --restart=Never --command -- sleep 3600\nkubectl exec -it tmp-dns -- cat \u002Fetc\u002Fresolv.conf\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>باید خط \u003Ccode>options ndots:5\u003C\u002Fcode> را ببینید. حالا کوئری‌ها را با \u003Ccode>tcpdump\u003C\u002Fcode> بشمارید تا ترتیب واقعی را ببینید:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">kubectl exec -it tmp-dns -- tcpdump -i any -n port 53\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>در یک ترمینال دیگر یک lookup خارجی انجام دهید:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">kubectl exec -it tmp-dns -- dig +search +stats api.stripe.com\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>خروجی \u003Ccode>tcpdump\u003C\u002Fcode> چیزی شبیه این است:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">10.244.1.7.52341 &gt; 10.96.0.10.53: A? api.stripe.com.default.svc.cluster.local. (58)\n10.96.0.10.53 &gt; 10.244.1.7.52341: NXDomain 0\u002F1\u002F0 (137)\n10.244.1.7.52341 &gt; 10.96.0.10.53: AAAA? api.stripe.com.default.svc.cluster.local. (58)\n10.96.0.10.53 &gt; 10.244.1.7.52341: NXDomain 0\u002F1\u002F0 (137)\n...\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>اگر ترافیک کلاستر شما بزرگ است، بهترین معیار، متریک خود CoreDNS است:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">kubectl -n kube-system logs -l k8s-app=kube-dns --tail=50\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>و در Prometheus نرخ پاسخ‌های منفی را ببینید:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">sum(rate(coredns_dns_responses_total{rcode=\"NXDOMAIN\"}[5m]))\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2 id=\"گام-۲-تنظیم-ndots-با-dnsconfig\">گام ۲: تنظیم ndots با dnsConfig\u003C\u002Fh2>\n\u003Cp>ساده‌ترین و مؤثرترین راه، تغییر ndots در سطح پاد است. بدون نیاز به دست زدن به CoreDNS:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-yaml\">apiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: api\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: api\n  template:\n    metadata:\n      labels:\n        app: api\n    spec:\n      dnsPolicy: ClusterFirst\n      dnsConfig:\n        options:\n          - name: ndots\n            value: \"2\"\n          - name: timeout\n            value: \"1\"\n          - name: attempts\n            value: \"3\"\n      containers:\n        - name: api\n          image: example\u002Fapi:1.0\n          ports:\n            - containerPort: 8080\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>انتخاب عدد ndots یکtrade-off است:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>ndots: 2\u003C\u002Fstrong> گزینه متعادل و پیشنهادی است. نام‌هایی مثل \u003Ccode>api.stripe.com\u003C\u002Fcode> (دو نقطه) مستقیم مطلق پرسیده می‌شوند و نام‌های داخلی کوتاه مثل \u003Ccode>redis\u003C\u002Fcode> یا \u003Ccode>my-svc.my-ns\u003C\u002Fcode> همچنان از search استفاده می‌کنند.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>ndots: 1\u003C\u002Fstrong> برای workloadهایی که تقریباً همیشه با دامنه‌های خارجی حرف می‌زنند مناسب است و کمترین تعداد کوئری را تولید می‌کند.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>ndots: 5\u003C\u002Fstrong> پیش‌فرض را فقط برای اپلیکیشن‌هایی نگه دارید که عمدتاً نام‌های کوتاه تک‌برچسبی داخل کلاستر را resolve می‌کنند.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>کاهش \u003Ccode>timeout\u003C\u002Fcode> به ۱ ثانیه هم مهم است: در صورت گم شدن بسته، به‌جای ۵ ثانیه انتظار، سریع‌تر retry می‌شود. مقدار \u003Ccode>attempts\u003C\u002Fcode> بالاتر، پوشش خطا را حفظ می‌کند.\u003C\u002Fp>\n\u003Cp>راه مکمل: در کد یا کانفیگ اپلیکیشن، برای مسیرهای داغ از \u003Cstrong>FQDN با نقطه پایانی\u003C\u002Fstrong> استفاده کنید (\u003Ccode>api.stripe.com.\u003C\u002Fcode>). نقطه انتهایی به resolver می‌گوید این نام مطلق است و لیست search کاملاً دور زده می‌شود.\u003C\u002Fp>\n\n\u003Ch2 id=\"گام-۳-nodelocal-dnscache-برای-کلاسترهای-بزرگ\">گام ۳: NodeLocal DNSCache برای کلاسترهای بزرگ\u003C\u002Fh2>\n\u003Cp>تنظیم ndots تعداد کوئری‌ها را کم می‌کند، اما race کانترک UDP را حل نمی‌کند. اگر تعداد پادها بالاست یا از kube-proxy با iptables استفاده می‌کنید، NodeLocal DNSCache را در نظر بگیرید: یک listener محلی روی هر نود که کوئری‌ها را قبل از عبور از iptables می‌گیرد و کَش می‌کند.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\"># ClusterIP سرویس DNS کلاستر\nkubectl -n kube-system get svc kube-dns -o jsonpath='{.spec.clusterIP}'\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>مانیفست رسمی \u003Ccode>nodelocaldns.yaml\u003C\u002Fcode> را دریافت کنید، مقدار \u003Ccode>__POD_IP__\u003C\u002Fcode> را با IP محلی (معمولاً \u003Ccode>169.254.25.10\u003C\u002Fcode>) جایگزین کنید و مطمئن شوید هدف \u003Ccode>forward\u003C\u002Fcode> در Corefile همان ClusterIP سرویس kube-dns است. سپس پکیج لازم را روی نودها نصب و اپلای کنید:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">sed -i 's\u002F__POD_IP__\u002F169.254.25.10\u002Fg' nodelocaldns.yaml\nkubectl apply -f nodelocaldns.yaml\nkubectl -n kube-system get pods -l k8s-app=node-local-dns -o wide\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>در نهایت مقدار \u003Ccode>--cluster-dns\u003C\u002Fcode> را در kubelet روی هر نود به \u003Ccode>169.254.25.10\u003C\u002Fcode> تغییر دهید و kubelet را ری‌استارت کنید تا پادهای جدید به listener محلی اشاره کنند. بعد از این تغییر، پاسخ‌های گم‌شده UDP تقریباً به صفر می‌رسد.\u003C\u002Fp>\n\n\u003Ch2 id=\"گام-۴-بهینه‌سازی-coredns\">گام ۴: بهینه‌سازی CoreDNS\u003C\u002Fh2>\n\u003Cp>حتی بعد از تنظیم ndots، CoreDNS باید بار را راحت تحمل کند. ConfigMap را ویرایش کنید:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-nginx\">.:53 {\n    errors\n    health {\n       lameduck 5s\n    }\n    ready\n    kubernetes cluster.local in-addr.arpa ip6.arpa {\n       pods insecure\n       fallthrough in-addr.arpa ip6.arpa\n       ttl 30\n    }\n    prometheus :9153\n    forward . \u002Fetc\u002Fresolv.conf {\n       max_concurrent 1000\n    }\n    cache 30 {\n       success 65536 30\n       denial 65536 5\n    }\n    loop\n    reload\n    loadbalance\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>دو نکته مهم: بخش \u003Ccode>denial\u003C\u002Fcode> در پلاگین \u003Ccode>cache\u003C\u002Fcode> پاسخ‌های NXDOMAIN پرتکرار را ۵ ثانیه کَش می‌کند و بار روی upstream را به‌شدت کم می‌کند؛ و \u003Ccode>max_concurrent\u003C\u002Fcode> جلوی صف‌شدن بی‌پایان کوئری‌ها را می‌گیرد. اگر پلاگین \u003Ccode>reload\u003C\u002Fcode> فعال باشد، تغییر ConfigMap خودکار اعمال می‌شود؛ در غیر این صورت:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">kubectl -n kube-system rollout restart deployment coredns\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>برای کلاسترهای بزرگ، تعداد replica را بالا ببرید و منابع بدهید:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">kubectl -n kube-system scale deployment coredns --replicas=4\nkubectl -n kube-system autoscale deployment coredns --min=2 --max=10 --cpu-percent=60\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2 id=\"چطور-بفهمیم-مشکل-واقعا-حل-شده-است\">چطور بفهمیم مشکل واقعاً حل شده است\u003C\u002Fh2>\n\u003Col>\n\u003Cli>روی یک پاد جدید چک کنید که \u003Ccode>resolv.conf\u003C\u002Fcode> درست نوشته شده باشد:\u003Cbr>\u003Ccode>kubectl exec -it deploy\u002Fapi -- cat \u002Fetc\u002Fresolv.conf\u003C\u002Fcode> و باید \u003Ccode>options ndots:2 timeout:1\u003C\u002Fcode> را ببینید.\u003C\u002Fli>\n\u003Cli>در پاد تست، تعداد کوئری‌ها را دوباره با \u003Ccode>tcpdump\u003C\u002Fcode> بشمارید. برای \u003Ccode>api.stripe.com\u003C\u002Fcode> باید فقط یک یا دو کوئری (A و AAAA) ببینید، نه هشت کوئری.\u003C\u002Fli>\n\u003Cli>زمان lookup را اندازه بگیرید:\u003Cbr>\u003Ccode>kubectl exec -it tmp-dns -- dig +stats api.stripe.com\u003C\u002Fcode> و مقدار \u003Ccode>Query time\u003C\u002Fcode> باید تک‌رقمی میلی‌ثانیه باشد.\u003C\u002Fli>\n\u003Cli>متریک CoreDNS را زیر بار واقعی رصد کنید. نرخ \u003Ccode>coredns_dns_responses_total{rcode=\"NXDOMAIN\"}\u003C\u002Fcode> باید به‌طور محسوسی افت کند (معمولاً بیش از ۵۰٪).\u003C\u002Fli>\n\u003Cli>نمودار تأخیر p99 اپلیکیشن را بعد از دیپلوی مقایسه کنید؛ حذف پیک‌های ۵ ثانیه‌ای بهترین تأیید است.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Ch2 id=\"پیشگیری-و-بهترین-روش‌ها\">پیشگیری و بهترین روش‌ها\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>ndots را با workload هماهنگ کنید.\u003C\u002Fstrong> مقدار ۲ انتخاب امن پیش‌فرض برای اکثر تیم‌هاست؛ آن را در قالب (template) دیپلوی‌منت‌ها بگذارید تا برای همه سرویس‌ها اعمال شود.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>در مسیرهای داغ از FQDN با نقطه پایانی استفاده کنید.\u003C\u002Fstrong> یک کاراکتر، هفت کوئری اضافه را حذف می‌کند.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>CoreDNS را مانیتور کنید، نه فقط اپلیکیشن.\u003C\u002Fstrong> داشبورد روی \u003Ccode>coredns_dns_requests_total\u003C\u002Fcode> و \u003Ccode>coredns_dns_responses_total\u003C\u002Fcode> بسازید و برای نرخ NXDOMAIN هشدار بگذارید.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>برای CoreDNS حتماً requests\u002Flimits تعیین کنید.\u003C\u002Fstrong> بدون آن، HPA بی‌اثر است و CoreDNS زیر بار throttled می‌شود.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>در کلاسترهای پرترافیک NodeLocal DNSCache را استاندارد کنید.\u003C\u002Fstrong> این تنها راه حل قطعی race کانترک UDP در kube-proxy است.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>NetworkPolicy روی پورت ۵۳ UDP\u002FTCP را فراموش نکنید.\u003C\u002Fstrong> اگر CoreDNS از برخی نودها قابل دسترس نباشد، همان الگوی ۵ ثانیه‌ای برمی‌گردد.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>بعد از هر تغییر DNS، تست بار بگیرید.\u003C\u002Fstrong> ابزارهایی مثل \u003Ccode>dnsperf\u003C\u002Fcode> یا یک اسکریپت ساده حلقه‌ای، رگرسیون را قبل از کاربر پیدا می‌کنند.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cblockquote>درس عملی: هر بار که در Kubernetes یک تأخیر «گرد و ثابت» می‌بینید، اول DNS و مقدار ndots را چک کنید. این مشکل انقدر رایج است که می‌ارزد برایش یک مرحله ثابت در runbook تیم داشته باشید.\u003C\u002Fblockquote>",[31,35,38,41,44,47,50,53],{"id":32,"text":33,"level":34},"شرح-مسئله-تأخیری-که-پترن-مشخصی-دارد","شرح مسئله: تأخیری که پترن مشخصی دارد",2,{"id":36,"text":37,"level":34},"علت-ریشه‌ای-ndots-5-و-لیست-search","علت ریشه‌ای: ndots:5 و لیست search",{"id":39,"text":40,"level":34},"گام-۱-بازتولید-و-تشخیص","گام ۱: بازتولید و تشخیص",{"id":42,"text":43,"level":34},"گام-۲-تنظیم-ndots-با-dnsconfig","گام ۲: تنظیم ndots با dnsConfig",{"id":45,"text":46,"level":34},"گام-۳-nodelocal-dnscache-برای-کلاسترهای-بزرگ","گام ۳: NodeLocal DNSCache برای کلاسترهای بزرگ",{"id":48,"text":49,"level":34},"گام-۴-بهینه‌سازی-coredns","گام ۴: بهینه‌سازی CoreDNS",{"id":51,"text":52,"level":34},"چطور-بفهمیم-مشکل-واقعا-حل-شده-است","چطور بفهمیم مشکل واقعاً حل شده است",{"id":54,"text":55,"level":34},"پیشگیری-و-بهترین-روش‌ها","پیشگیری و بهترین روش‌ها",[57,58,61,64,67],{"name":13,"slug":13},{"name":59,"slug":60},"Performance","performance",{"name":62,"slug":63},"DNS","dns",{"name":65,"slug":66},"CoreDNS","coredns",{"name":68,"slug":69},"NodeLocal DNSCache","nodelocal-dnscache",[71,74,77],{"question":72,"answer":73},"آیا تغییر ndots:5 به ۲ روی همه اپلیکیشن‌ها بی‌خطر است؟","بله، ترتیب جست‌وجو عوض می‌شود اما مجموعه نام‌هایی که resolve می‌شود یکسان است. با ndots:2 نام‌های کوتاه تک‌برچسبی مثل redis همچنان از لیست search استفاده می‌کنند و نام‌های دامنه‌دار خارجی مستقیم مطلق پرسیده می‌شوند. تنها اثر جانبی، یکی‌دو درخواست اضافه برای نام‌های دوسطحی داخلی مثل my-svc.my-ns است.",{"question":75,"answer":76},"بعد از ویرایش ConfigMap کور‌دی‌ان‌اس باید آن را ری‌استارت کنم؟","اگر پلاگین reload در Corefile فعال باشد (در Corefile پیش‌فرض kubeadm فعال است) تغییر خودکار حداکثر طی یک دقیقه اعمال می‌شود. اگر مطمئن نیستید یا تغییرات را نمی‌بینید، با kubectl -n kube-system rollout restart deployment coredns ری‌استارت کنید.",{"question":78,"answer":79},"NodeLocal DNSCache چه تفاوتی با کاهش ndots دارد و آیا به هر دو نیاز دارم؟","کاهش ndots تعداد کوئری‌ها را کم می‌کند، اما مسیر بسته‌های UDP همچنان از iptables و conntrack رد می‌شود و احتمال گم شدن بسته باقی می‌ماند. NodeLocal DNSCache با یک listener محلی روی هر نود، هم latency را کاهش می‌دهد و هم race کانترک را حذف می‌کند. برای کلاسترهای کوچک، تنطیم ndots و dnsConfig کافی است؛ برای کلاسترهای بزرگ هر دو را انجام دهید.",[81,13,82],"cloud-infrastructure","cloud-migration",true,"چرا DNS در Kubernetes گاهی ۵ ثانیه معطل می‌ماند؟ بررسی ریشه‌ای ndots:5 و search domains، تنظیم dnsConfig، NodeLocal DNSCache و بهینه‌سازی CoreDNS.",[86,99,113],{"id":87,"title":88,"slug":89,"excerpt":90,"cover":91,"category":93,"author":94,"track":95,"level":96,"reading_minutes":97,"is_featured":27,"published_at":98,"updated_at":98},9,"پاد Kubernetes در وضعیت Terminating گیر کرده؛ آزادسازی امن","kubernetes-pod-stuck-terminating-finalizer","پاد در حالت Terminating گیر کرده و با kubectl delete پاک نمی‌شود؟ این مقاله علت واقعی (finalizer باقی‌مانده، نود NotReady، ولوم گیرکرده) و راه‌حل گام‌به‌گام امن را نشان می‌دهد.",{"url":92,"alt":88},"https:\u002F\u002Fapi.cloudicap.com\u002Fmedia\u002Fposts\u002F8e6369a3-ad85-4e7e-8588-183bbd5a31f9.webp",{"name":12,"slug":13},{"name":15,"slug":16,"role":17,"avatar_url":19},{"value":21,"label":22},{"value":24,"label":25},6,"2026-10-10T09:34:08+00:00",{"id":100,"title":101,"slug":102,"excerpt":103,"cover":104,"category":106,"author":109,"track":110,"level":111,"reading_minutes":97,"is_featured":27,"published_at":112,"updated_at":112},8,"رفع dkim=none در Postfix با راه‌اندازی OpenDKIM","postfix-opendkim-dkim-signing-fix","اگر ایمیل‌های سرور Postfix شما در Gmail به اسپم می‌روند و هدر پیام dkim=none نشان می‌دهد، یعنی هیچ امضای DKIM روی پیام‌ها درج نمی‌شود. در این مقاله OpenDKIM را نصب، پیکربندی و به Postfix وصل می‌کنیم و رکورد DNS را منتشر می‌کنیم.",{"url":105,"alt":101},"https:\u002F\u002Fapi.cloudicap.com\u002Fmedia\u002Fposts\u002F1b1288db-c0ed-41f3-8ee5-01f7b997c11d.webp",{"name":107,"slug":108},"ابزارهای Self-Hosted","self-hosted",{"name":15,"slug":16,"role":17,"avatar_url":19},{"value":21,"label":22},{"value":24,"label":25},"2026-10-09T13:30:31+00:00",{"id":114,"title":115,"slug":116,"excerpt":117,"cover":118,"category":120,"author":123,"track":124,"level":125,"reading_minutes":100,"is_featured":27,"published_at":126,"updated_at":126},1,"«idle in transaction» در PostgreSQL: قاتل خاموش autovacuum","postgres-idle-in-transaction-autovacuum-bloat","نشست‌های idle in transaction تراکنش را باز نگه می‌دارند، جلوی autovacuum را می‌گیرند و جدول‌ها را باد می‌کنند تا جایی که دیسک پر و اتصال‌ها تمام می‌شود. این مقاله تشخیص و درمان کامل آن است.",{"url":119,"alt":115},"https:\u002F\u002Fapi.cloudicap.com\u002Fmedia\u002Fposts\u002F40aa29f7-e1d0-4c30-94f6-631ea9a173a0.webp",{"name":121,"slug":122},"مانیتورینگ و پایداری","monitoring",{"name":15,"slug":16,"role":17,"avatar_url":19},{"value":21,"label":22},{"value":24,"label":25},"2026-10-06T17:33:36+00:00"]