# Docker Swarm یا Kubernetes؟ تفاوت‌ها، معماری و انتخاب مناسب برای زیرساخت سازمانی

مقایسه معماری، امنیت، شبکه، Storage و هزینه نگهداری Docker Swarm و Kubernetes با شش سناریوی سازمانی، دو آزمایشگاه سه‌نودی و راهنمای تصمیم‌گیری.

## ۱. ERP کانتینری شده؛ ساعت دو بامداد چه کسی آن را برمی‌گرداند؟

Frontend سامانه ERP روی یک VM لینوکسی اجرا می‌شود، API جاوا روی VM دیگر است و Redis کنار سرویس گزارش‌گیری داخلی قرار دارد. Jenkins ایمیج می‌سازد و بعد از انتشار، یکی از همکاران Compose را اجرا می‌کند. حالا وسط پردازش حقوق، یک میزبان خاموش می‌شود. ایمیج هنوز در Registry هست، اما معلوم نیست API کجا بالا بیاید، فایل‌های بارگذاری‌شده چطور همراهش منتقل شوند و Nginx مقصد جدید را از کجا بفهمد. Pipeline کارش را انجام داده؛ معماری زمان اجرا یک سؤال بی‌پاسخ دارد.

انتخاب Orchestrator از همین نقطه معنی پیدا می‌کند. ابتدا مدت قطعی قابل قبول، تحمل از دست رفتن داده، الگوی ترافیک، دفعات انتشار و مسئول On-call را بنویسید. Swarm مدل کلاستر یکپارچه با اجزای کمتر می‌دهد؛ Kubernetes API و اکوسیستم گسترده‌تری برای ساخت پلتفرم در اختیار تیم‌ها می‌گذارد. هیچ‌کدام خرابی Storage مشترک را تعمیر نمی‌کنند یا ERP ناسازگار با اجرای هم‌زمان را با سه Replica ایمن نمی‌سازند. مثال‌های این مقاله سناریوی مهندسی هستند و ادعای تجربه شخصی نویسنده نیستند.

## ۲. Engine، Compose، Swarm و Kubernetes در لایه‌های متفاوت کار می‌کنند

| ابزار | مسئولیت | مثال ERP |
| --- | --- | --- |
| Docker Engine | ساخت و اجرای کانتینر روی میزبان با Daemon و API | اجرای کانتینر API جاوا |
| Docker Compose | تعریف برنامه چندکانتینری؛ compose up معمولی یک Engine را هدف می‌گیرد و Scheduler چندنودی نیست | اجرای API، Redis و Frontend روی یک VM |
| Docker Swarm mode | Orchestration مبتنی بر وضعیت مطلوب، داخل Engine و بین میزبان‌ها | نگهداری سه Task از API روی نودهای واجد شرایط |
| Kubernetes | Orchestration مبتنی بر API با Runtime سازگار با CRI | Deployment پادهای API را مدیریت و Runtime کانتینرها را اجرا می‌کند |

Image الگوی نسخه‌دار فایل‌سیستم و تنظیمات است. Container نمونه اجرایی ایزوله با لایه نوشتنی موقت است؛ برخلاف VM سیستم‌عامل مهمان کامل ندارد و کرنل میزبان را به اشتراک می‌گذارد. Volume داده را بیرون آن لایه نگه می‌دارد و Network مرز ارتباط و نام‌گذاری را می‌سازد. با جایگزینی کانتینر، لایه نوشتنی آن از دست می‌رود؛ ذخیره فایل مشتری در آن طراحی اشتباه است. ماندگار شدن داده هم بکاپ ایجاد نمی‌کند.

YAML در Compose و Swarm ممکن است شبیه باشد، اما docker stack deploy قالب قدیمی مبتنی بر Compose v3 را می‌خواند و همه قابلیت‌های Compose جدید را پیاده نمی‌کند. ایمیج را پیش از Deploy بسازید؛ انتشار Stack مرحله Build نیست. Kubernetes روی نود به Docker Engine نیاز ندارد؛ kubelet از CRI با Runtimeهایی مثل containerd یا CRI-O صحبت می‌کند. ایمیج OCI ساخته‌شده با Docker قابل اجراست و حذف dockershim آن را غیرقابل استفاده نکرده است.

[Docker: انتشار Stack و سازگاری Compose](https://docs.docker.com/engine/swarm/stack-deploy/)

[Kubernetes: رابط CRI و Runtime](https://kubernetes.io/docs/setup/production-environment/container-runtimes/)

## ۳. معماری Swarm: سرویس تعهد است و Task یک تلاش اجرایی

![Managerهای Swarm وضعیت را تکثیر و Workerها Task سرویس را روی Overlay اجرا می‌کنند](/assets/img/articles/content/docker-swarm-vs-kubernetes-enterprise-guide-swarm-architecture.svg)

| مفهوم | مسئله و مثال عملی |
| --- | --- |
| Manager Node | تغییر را می‌پذیرد، وضعیت کلاستر را نگه می‌دارد و زمان‌بندی می‌کند؛ manager-01 درخواست Scale API را می‌گیرد. Manager در صورت Drain نبودن می‌تواند Workload هم اجرا کند. |
| Worker Node | Task واگذارشده را اجرا می‌کند؛ worker-02 کانتینر API را بالا می‌آورد ولی در Raft رأی ندارد. |
| Raft / Cluster State | Managerها درباره مشخصات سرویس، اعضا و Secret توافق می‌کنند؛ تغییر Replica از دو به سه اکثریت می‌خواهد. رکوردهای دیتابیس برنامه جزو این وضعیت نیستند. |
| Service / Task / Replica | Service ایمیج و تعداد مطلوب API را تعریف می‌کند؛ هر Task یک تلاش اجرای کانتینر است. سه Replica یعنی سه Task مطلوب؛ Task خراب جایگزین می‌شود و حافظه آن جابه‌جا نمی‌شود. |
| Global Service | روی هر نود واجد شرایط یک Task مثل Log Collector اجرا می‌شود؛ Constraint می‌تواند Managerها را کنار بگذارد. |
| Overlay Network | API و Redis را با شبکه منطقی بین میزبان‌ها وصل می‌کند؛ MTU و فایروال زیرساخت همچنان مهم‌اند. |
| Routing Mesh | پورت منتشرشده روی نود قابل دسترس به Task سرویس هدایت می‌شود؛ LB خارجی باید نود مرده را از مسیر بردارد. |
| Service Discovery | DNS سرویس و VIP پیش‌فرض تغییر Task را پنهان می‌کنند؛ API به redis وصل می‌شود نه IP کانتینر. DNSRR حالت جایگزین است. |
| Docker Secrets / Configs | رمز دیتابیس به‌صورت Secret فقط به سرویس مجاز Mount می‌شود؛ nginx.conf یک Config است. Config محل اطلاعات محرمانه نیست. |
| Rolling Update / Rollback | Taskهای API را دسته‌ای جایگزین و مشخصات سرویس قبلی را بازیابی می‌کند؛ هیچ‌کدام Migration دیتابیس را برنمی‌گرداند. |
| Placement Constraints | قید node.labels.zone==a یا node.role==worker می‌گذارد؛ قید سخت ممکن است Task را Pending بگذارد. ترجیح Spread تضمین توزیع نیست. |
| Resource Limits / Reservations | برای زمان‌بندی ظرفیت رزرو و CPU/RAM API را محدود می‌کند؛ بعد از خرابی میزبان همچنان ظرفیت فیزیکی آزاد لازم است. |
| Node Drain | پیش از وصله worker-01، Taskهای سرویس Swarm را تخلیه می‌کند؛ کانتینر مستقل با این تنظیم تخلیه نمی‌شود. |

سه میزبان Ubuntu، یک Manager و دو Worker با سه Replica از API را در نظر بگیرید. با از دست رفتن Worker، اگر Manager فعال، Registry قابل دسترس و منابع رزروشده کافی باشند، Taskهای جایگزین روی نودهای مجاز ساخته می‌شوند. این تنظیم به‌خودی‌خود یک Replica در هر نود را تضمین نمی‌کند؛ Constraint و سقف Replica در هر نود نتیجه را تغییر می‌دهند. Volume محلی نود خراب همراه Task نمی‌رود. اگر Manager قطع باشد کانتینرهای موجود ممکن است ادامه دهند، اما کنترل و زمان‌بندی مجدد در دسترس نیست.

برای HA مدیریت، معمولاً سه یا پنج Manager رأی‌دهنده را در Failure Domain مستقل قرار دهید. Quorum برابر floor(N/2)+1 است: سه Manager خرابی یک عضو و پنج Manager خرابی دو عضو را تحمل می‌کند. دو Manager تحمل از دست رفتن Quorum ندارند. Worker بیشتر رأی اضافه نمی‌کند. نبود Quorum تغییر و زمان‌بندی بازیابی را متوقف می‌کند، حتی اگر Task قدیمی پاسخ بدهد. از وضعیت Manager طبق رویه رسمی Docker با توقف Manager بکاپ بگیرید؛ در Autolock کلید بازگشایی را هم نگه دارید و بازیابی جداگانه را تمرین کنید.

[Docker: Quorum، بکاپ و بازیابی](https://docs.docker.com/engine/swarm/admin_guide/)

## ۴. معماری Kubernetes: همگرا شدن وضعیت از مسیر API

![اجزای Control Plane در Kubernetes و مرز اجرای Worker](/assets/img/articles/content/docker-swarm-vs-kubernetes-enterprise-guide-kubernetes-architecture.svg)

API مرز هماهنگی است. kubectl یک Deployment ثبت می‌کند؛ Controller وضعیت مطلوب را می‌بیند و Object وابسته می‌سازد، Scheduler پاد بی‌نود را جانمایی می‌کند و kubelet از Runtime اجرای کانتینر را می‌خواهد. ترافیک معمول برنامه از API Server عبور نمی‌کند. اختلال API یا etcd می‌تواند Orchestration را متوقف کند، در حالی که پاد موجود با توجه به وابستگی‌هایش هنوز پاسخ می‌دهد.

| جزء | مسئولیت عملیاتی |
| --- | --- |
| kube-apiserver | تغییر API را احراز هویت، مجوزدهی و پذیرش می‌کند؛ هویت CI انتشار را اینجا ثبت می‌کند. |
| etcd | ذخیره وضعیت API با اجماع؛ به Quorum، دیسک پایدار کم‌تأخیر و Snapshot آزموده نیاز دارد و دیتابیس ERP نیست. |
| kube-scheduler | با Requests، Taint، Affinity و قیود نود انتخاب می‌کند؛ ظرفیت فیزیکی تازه ایجاد نمی‌کند. |
| kube-controller-manager | حلقه‌هایی مثل کنترل Deployment/ReplicaSet و نود را اجرا می‌کند؛ وضعیت Object را به‌مرور اصلاح می‌کند. |
| cloud-controller-manager | اتصال اختیاری Provider برای عملیات زیرساخت؛ روی Bare Metal وجود آن را فرض نکنید. |
| kubelet / Runtime | kubelet پاد واگذارشده و Probe را نظارت می‌کند؛ containerd یا CRI-O با CRI کانتینر را مدیریت می‌کند. |
| CNI / kube-proxy | پیاده‌سازی CNI شبکه پاد را می‌دهد؛ kube-proxy معمولاً Forwarding سرویس را پیاده می‌کند. پیاده‌سازی eBPF می‌تواند آن مسیر داده را جایگزین کند. |

| Object | مسئله‌ای که در سازمان حل می‌کند |
| --- | --- |
| Pod | کوچک‌ترین واحد زمان‌بندی؛ API و Helper وابسته را با شبکه و Volume مشترک کنار هم می‌گذارد. |
| Deployment / ReplicaSet | Deployment نسخه و انتشار API بدون State را مدیریت و ReplicaSet تعداد جاری را نگه می‌دارد؛ تغییر را از Deployment اعمال کنید. |
| DaemonSet | Agent نود، مثلاً جمع‌آوری Telemetry را روی نودهای واجد شرایط اجرا می‌کند. |
| StatefulSet | هویت ثابت، ترتیب و Claim ذخیره برای اعضای Stateful می‌دهد؛ Replication دیتابیس و بکاپ را پیاده نمی‌کند. |
| Job / CronJob | Import پایان‌پذیر یا گزارش شبانه زمان‌بندی می‌کند؛ Job باید Idempotent و سیاست هم‌زمانی روشن باشد. |
| Service | با جایگزینی پاد، دسترسی ثابت به Endpoint آماده می‌دهد؛ مصرف‌کننده Backend از DNS سرویس استفاده می‌کند. |
| ConfigMap / Secret | تنظیم غیرمحرمانه و مقدار حساس را از ایمیج جدا می‌کند؛ برنامه باید در زمان لازم Reload یا Restart شود. |
| Namespace | منابع تیم و محیط را سازمان می‌دهد؛ برای ایزوله‌سازی با RBAC، Quota و کنترل شبکه ترکیب کنید. |
| PV / PVC / StorageClass | PV ذخیره را معرفی، PVC آن را درخواست و StorageClass سیاست Provision را انتخاب می‌کند؛ CSI و سامانه ذخیره سازگار باید Volume بدهند. |
| Ingress / Gateway API | مسیریابی ورودی را تعریف می‌کنند. Ingress به Controller و Gateway API به CRD و پیاده‌سازی سازگار نیاز دارد؛ هیچ‌کدام به‌تنهایی تجهیز خارجی نمی‌سازند. |
| NetworkPolicy | ترافیک مجاز پاد را تعریف می‌کند؛ اعمال آن پیاده‌سازی شبکه پشتیبان می‌خواهد. از Default Deny و مجوز صریح DNS و وابستگی شروع کنید. |
| ServiceAccount / RBAC | هویت Workload و قواعد مجوز: Agent انتشار می‌تواند Deployment تیم خود را تغییر دهد بدون خواندن Secret همه Namespaceها. |

[Kubernetes: مسئولیت اجزا](https://kubernetes.io/docs/concepts/overview/components/)

[Kubernetes: کنترلرهای Workload](https://kubernetes.io/docs/concepts/workloads/)

## ۵. پلتفرمی را مقایسه کنید که واقعاً نگهداری خواهید کرد

Native یعنی بخشی از API پلتفرم یا Engine، نه الزاماً فعال یا کافی در تنظیم پیش‌فرض. Add-on پیاده‌سازی جداگانه نصب‌شده و External سرویس یا فرایند مستقلی است که تیم تأمین می‌کند. این تفاوت در برآورد ارتقا، مالکیت و پاسخ به رخداد مهم است. Swarm Mode همچنان در مستندات Docker Engine وجود دارد؛ در این راهنما منسوخ یا نامناسب برای Production فرض نشده است.

| معیار | Docker Swarm | Kubernetes |
| --- | --- | --- |
| Architecture | Manager و Worker یکپارچه با Engine | API، Controller، etcd و مسیر داده قابل تعویض |
| Installation | اجزای یکپارچه کمتر | Bootstrap همراه CNI؛ اتصال Storage و ورودی |
| Learning Curve | مدل Object کوچک‌تر | مدل Object و عملیات گسترده‌تر |
| Cluster Management | Docker CLI و مشخصات Service | API اعلانی، Controller و ابزارها |
| High Availability | Quorum مدیریت همراه طراحی برنامه و وابستگی | HA کنترل و etcd همراه طراحی برنامه و وابستگی |
| Scaling | تعداد Replica دستی Native | Replica و API مربوط به HPA به‌صورت Native |
| Auto Scaling | اتوماسیون خارجی؛ HPA بومی ندارد | کنترلر HPA؛ منبع Metrics افزونه و Scale نود جداست |
| Networking | Overlay و DNS سرویس یکپارچه | نیازمند پیاده‌سازی CNI |
| Load Balancing | Routing Mesh و VIP؛ LB ورودی خارجی | Forwarding سرویس؛ اتصال LB و Controller ورودی |
| Service Discovery | DNS داخلی سرویس با VIP یا DNSRR | Service؛ DNS کلاستر معمولاً افزونه CoreDNS |
| Storage | Volume و Bind محلی؛ Shared Storage و Plugin خارجی | API از نوع PV/PVC؛ پیاده‌سازی CSI و Provisioner |
| Security | mTLS نود، Secret و مرز مدیریتی نسبتاً درشت | RBAC، API پذیرش و هویت Workload؛ نیازمند تنظیم سیاست |
| Secrets Management | Secret رمز‌شده در Raft؛ Rotation دستی یا خارجی | API Secret؛ تنظیم رمزنگاری ذخیره یا KMS خارجی |
| Rolling Updates | سیاست Update بومی Service | Strategy بومی Deployment |
| Rollback | مشخصات قبلی Service | تاریخچه Deployment؛ نیازمند حفظ Revision |
| Scheduling | Constraint، Reservation و ترجیح Spread | Requests، Taint، Affinity و Topology Spread |
| Monitoring | آمار CLI؛ Prometheus/Grafana خارجی | API و Event؛ Metrics و داشبورد افزونه |
| Logging | Driverهای Engine و تجمیع خارجی | لاگ نود و کانتینر و تجمیع خارجی |
| CI/CD Integration | Pipeline دستور Service یا Stack می‌دهد | Pipeline مانیفست یا تغییر GitOps ثبت می‌کند |
| GitOps | با Reconciliation خارجی یا سفارشی ممکن | افزونه Argo CD یا Flux؛ جزو هسته نیست |
| Multi-Tenancy | در Engine Swarm معادل Native برای Namespace/RBAC ندارد | Namespace همراه RBAC، Quota و کنترل شبکه و پذیرش |
| Resource Management | Reservation و Limit | Requests/limits، LimitRange و ResourceQuota |
| Cloud Integration | Provision میزبان و LB و Storage جدا | Controller و CSI مخصوص Provider و خدمات Managed |
| On-Premises | قابل اجرا روی میزبان Linux؛ HA وابستگی جداست | روی VM و Bare Metal؛ نیازمند طراحی ورودی و Storage |
| Operational Complexity | اجزای کمتر؛ کار سفارشی بیشتر برای نیاز پیشرفته | اجزای بیشتر و هماهنگی سیاست و ارتقا |
| Maintenance Cost | معمولاً کمتر در دامنه محدود؛ ابزار سفارشی را هم بسنجید | نیروی پلتفرم، چرخه افزونه و پشتیبانی |
| Enterprise Ecosystem | اتصال‌های محدودتر | Controller، Operator و اتصال‌های فروشنده گسترده‌تر |

### تفاوت‌هایی که مدل عملیات را تغییر می‌دهند

در Kubernetes مرزبندی تیم و توسعه‌پذیری جزو طراحی API است. وقتی ده تیم مستقل Deploy می‌کنند این مزیت مهم است، اما هر Controller، قانون Admission و CRD مسئول نگهداری و سازگاری ارتقا می‌خواهد. Swarm عمداً مفهوم‌های کمتری دارد. اگر مدل داخلی آن انتشار شما را پوشش دهد، اجزای کمتر مسیر عیب‌یابی را ساده می‌کند. اگر دور آن Quota، مجوز ریزدانه و Autoscaling بازسازی می‌کنید، آن پلتفرم سفارشی را هم در مقایسه حساب کنید.

[Kubernetes: وابستگی Metrics و رفتار HPA](https://kubernetes.io/docs/concepts/workloads/autoscaling/horizontal-pod-autoscale/)

## ۶. شش سازمان و شش مجموعه محدودیت

![تیم عملیاتی کوچک و پلتفرم چندتیمی نیاز یکسانی از Orchestration ندارند](/assets/img/articles/content/docker-swarm-vs-kubernetes-enterprise-guide-enterprise-decision.svg)

### سناریو ۱ — دو سرور Linux و سه Application

اگر زمان بازیابی مستند قابل قبول است و سرور دوم مقصد بازیابی است، Compose روی یک میزبان همراه بکاپ آزموده و Monitoring می‌تواند کافی باشد؛ نام آن Failover چندنودی نیست. اگر جانمایی و جایگزینی خودکار سرویس لازم است، Swarm قدم معقولی است، اما دو Manager، HA مبتنی بر Quorum نمی‌دهند. میزبان رأی‌دهنده مستقل سوم اضافه کنید یا تک‌نقطه خرابی کنترل را بپذیرید و مستند کنید. Kubernetes باید نیاز اضافی مشخص و تیم نگهدار داشته باشد؛ صرف داشتن دو سرور دلیل انتخاب نیست.

### سناریو ۲ — پنج VM روی vSphere، ده برنامه، Nginx، GitLab و Jenkins

Swarm با سه VM دارای نقش Manager و ظرفیت Worker مناسب، همگرایی سرویس و انتشار تدریجی می‌دهد. Health Check ورودی، لاگ مرکزی، بکاپ وضعیت Manager و بازیابی SQL همچنان جدا لازم‌اند. Kubernetes در صورت نیاز سازمان، API سیاست و Storage قوی‌تری می‌دهد، با هزینه نگهداری CNI، CSI و Controller. پنج VM روی یک ESXi یا یک Datastore آسیب‌پذیر، پنج Failure Domain نیستند. Replica و رأی‌دهنده را بین میزبان‌ها پخش و ظرفیت خرابی مورد تعهد را رزرو کنید.

### سناریو ۳ — بیست Application و تیم‌های انتشار مستقل

Deployment برای هر Backend بدون State، قرارداد انتشار یکسانی در Dev، Test و Production می‌دهد. Requests جانمایی را هدایت و Limits مصرف را محدود می‌کند؛ CPU ممکن است Throttle و حافظه با OOM خاتمه یابد. HPA از تقاضای اندازه‌گیری‌شده Replica را عوض می‌کند، اما منبع Metrics فعال و برای درصد مصرف CPU، Requests معقول لازم دارد. HPA اشباع SQL را رفع و VM جدید ایجاد نمی‌کند. در Swarm دستور Service Scale تعداد را صریح عوض می‌کند؛ Controller خارجی می‌تواند آن را خودکار کند، اما رفتار خرابی، نوسان و امنیت آن مسئولیت تیم شما می‌شود.

Scaling دستی اقدام آگاهانه اپراتور یا Pipeline است. Autoscaling حلقه بازخورد است: حداقل و حداکثر، Stabilisation، Metrics و سقف ظرفیت تعریف کنید و بار و ایمنی Scale Down را بسنجید. Rolling Update در هر دو بومی است؛ تقسیم ترافیک Canary و Blue/Green طراحی مسیریابی و انتشار بیشتری می‌خواهد. محیط‌های مختلف Secret و مجوز مستقل می‌خواهند؛ Namespace سازمان‌دهی مفیدی است ولی برای Tenant نامطمئن ایزولاسیون کافی نیست.

### سناریو ۴ — پنجاه تا صد Microservice

با چند تیم، هویت سرویس دقیق، Policy، GitLab CI، Registry خصوصی، Prometheus/Grafana و لاگ مرکزی، Kubernetes اغلب با مرز پلتفرم سازگارتر است. Namespace، RBAC، Quota، Admission و NetworkPolicy کنترل ترکیب‌پذیر می‌دهند؛ Operator و CSI در صورت سازگاری ماتریس پشتیبانی، اتصال سفارشی را کم می‌کنند. Swarm می‌تواند سرویس‌های زیادی اجرا کند، اما تعداد سرویس معیار نهایی نیست؛ سؤال مهم، کفایت مدل دسترسی و اتوماسیون اطراف آن است. پیش از انتخاب Kubernetes مسئول پلتفرم، تمرین ارتقا، تمدید گواهی، بازیابی etcd و پوشش On-call را بودجه‌بندی کنید.

### سناریو ۵ — Java و React روی ESXi و vCenter

هر دو Orchestrator در VM لینوکسی اجرا می‌شوند. انتشار فایل ایستای React و API جاوا را مستقل و در صورت نیاز Session و Upload را خارج از کانتینر نگه دارید. Volume در Swarm به راهبرد صریح Shared Storage یا Plugin نیاز دارد. Kubernetes با vSphere CSI سازگار می‌تواند ذخیره ماندگار vSphere درخواست کند؛ Topology، Access Mode و StorageClass باید با Datastore هماهنگ باشند. ماتریس دقیق Kubernetes، Driver و vSphere را بررسی کنید؛ نصب kubeadm به‌تنهایی Driver نصب نمی‌کند.

vSphere HA بعد از خرابی میزبان، VM آسیب‌دیده را راه‌اندازی مجدد می‌کند. HA در Swarm/Kubernetes وضعیت کنترل را نگه می‌دارد و Task یا Pod برنامه را همگرا می‌کند. این حلقه‌های بازیابی مکمل‌اند و زمان تشخیص متفاوت دارند. Anti-affinity ماشین مجازی رأی‌دهنده‌ها را بین ESXi و Anti-affinity پاد Replica برنامه را بین نود Kubernetes پخش می‌کند. هیچ‌کدام خرابی SAN، Uplink، برق یا دیتاسنتر مشترک را پوشش نمی‌دهد. از Overcommit پردازنده و Ballooning حافظه بی‌ثبات‌کننده etcd دوری، ظرفیت بازیابی رزرو و تأخیر دیسک را اندازه‌گیری کنید.

### سناریو ۶ — SQL Server Always On از قبل برقرار است

کانتینری کردن برنامه الزام انتقال SQL Server نیست. نگه داشتن Always On Availability Group پشتیبانی‌شده بیرون کلاستر اغلب فرایند جاافتاده DBA برای بکاپ، وصله، لایسنس و بازیابی را حفظ می‌کند. از Listener گروه با TLS معتبر و Client و Connection Configuration پشتیبانی‌شده وصل شوید؛ اتصال مجدد، Timeout و Retry امن را هنگام Failover بسنجید. کش Redis و Connection Pool ممکن است وضعیت قدیمی نگه دارند. سلامت کلاستر اثبات سلامت دیتابیس نیست.

اجرای SQL در Kubernetes وقتی قابل بررسی است که نسخه و Edition دقیق SQL، پشتیبانی Linux و Container، رفتار Storage، معماری Availability و روش Operator و پشتیبانی تأیید شده باشند. اتصال Volume، Fencing، هویت، ترتیب بازیابی و تعامل ارتقا به مسئولیت‌ها اضافه می‌شود. StatefulSet به‌تنهایی Always On نیست. انتقال SQL بازیابی دیتابیس را به بازیابی کلاستر و Storage گره می‌زند. پیش از مهاجرت RPO/RTO و Restore را بسنجید؛ AG سالم را صرفاً برای قرار گرفتن همه کادرها داخل یک دیاگرام منتقل نکنید.

![Frontend، API و Redis در هر Orchestrator به Listener گروه SQL Server خارجی متصل می‌شوند](/assets/img/articles/content/docker-swarm-vs-kubernetes-enterprise-guide-erp-deployment.svg)

[Microsoft: ملاحظات SQL Server در Kubernetes](https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-kubernetes-best-practices?view=sql-server-ver17)

[Driver ذخیره vSphere CSI و مستندات سازگاری](https://github.com/kubernetes-sigs/vsphere-csi-driver)

## ۷. دسترس‌پذیری زنجیره‌ای از وابستگی‌هاست

![خرابی Worker فقط با کنترل، ظرفیت، ایمیج و Storage در دسترس به Task یا Pod جایگزین می‌رسد](/assets/img/articles/content/docker-swarm-vs-kubernetes-enterprise-guide-ha-failover.svg)

| خرابی | واکنش و محدودیت Swarm | واکنش و محدودیت Kubernetes |
| --- | --- | --- |
| Container یا Pod | Task سرویس طبق Restart Policy جایگزین؛ Healthcheck می‌تواند جایگزینی را تحریک کند | kubelet ممکن است کانتینر را Restart کند؛ Controller پاد مفقود را جایگزین می‌کند؛ Pod مستقل تضمین Deployment ندارد |
| نود Worker | بعد از تشخیص خرابی، با Quorum، ظرفیت و وابستگی سالم جایگزین می‌شود | وضعیت نود، Taint، Toleration تخلیه و Controller تعیین‌کننده‌اند؛ فوری نیست |
| Manager یا Control Plane | با Quorum انتخاب رهبر؛ بدون Quorum تغییر زمان‌بندی متوقف | Endpoint API دارای HA و Quorum در etcd لازم؛ مسیر داده موجود ممکن است ادامه یابد |
| جدایی شبکه | سمت دارای Quorum کنترل می‌کند؛ Task یا نویسنده Storage جداشده ممکن است زنده باشد | شبکه کنترل و پاد متفاوت خراب می‌شوند؛ Fencing برای جلوگیری از نویسنده Stateful تکراری لازم |
| خرابی Storage | جانمایی مجدد داده غیرقابل دسترس را بازیابی نمی‌کند | PVC وابسته به Driver و Backend است؛ Attach و Mount می‌تواند بازیابی را متوقف کند |
| از دست رفتن دیتاسنتر | نیازمند DR جدا، تکثیر داده و برنامه Restore و DNS آزموده | همان نیاز؛ کشیدن etcd بین سایت‌های پرتأخیر راه‌حل ساده HA نیست |

سه Replica روی یک نود خرابی مشترک دارند. سه نود روی یک Hypervisor هم همین‌طور. سه Replica با یک دیتابیس و یک NFS همچنان همان وابستگی‌ها را دارند. Failure Domain را دقیق بنویسید: نود، ESXi، رک، آرایه ذخیره یا سایت. اگر جدایی الزامی است قید سخت Topology بگذارید و بپذیرید که کمبود Domain می‌تواند Replica را بی‌نود بگذارد. ظرفیت آزاد روی کاغذ وقتی Registry، DNS یا مسیر Storage قطع است کافی نیست.

Readiness در Kubernetes ورود به ترافیک Service را کنترل می‌کند؛ Liveness می‌تواند کانتینر گیرکرده را Restart و Startup Probe آزمون‌های دیگر را تا پایان شروع کند به تأخیر بیندازد. قطع کوتاه SQL نباید لزوماً Liveness API را خراب کند؛ وگرنه هنگام رخداد دیتابیس همه Replicaها Restart می‌شوند. Swarm، Healthcheck کانتینر و سیاست Update و Restart دارد اما API همسان Readiness و Startup ندارد. پروکسی خارجی و Endpoint سلامت برنامه را متناسب طراحی کنید. پذیرش TCP به‌تنهایی پردازش تراکنش ERP را ثابت نمی‌کند.

PodDisruptionBudget با minAvailable یا maxUnavailable تخلیه اختیاری پشتیبانی‌شده مثل Drain را محدود می‌کند. در برابر خاموشی ناگهانی نود محافظ نیست و Strategy انتشار خود Deployment را کنترل نمی‌کند؛ آن را جدا تنظیم کنید. Graceful Shutdown یعنی برنامه کار جدید نگیرد، درخواست جاری را تمام یا Checkpoint کند و در مهلت خارج شود. stop-grace-period در Swarm و terminationGracePeriodSeconds در Kubernetes به همکاری برنامه و Drain در LB نیاز دارند. هنگام Rolling Release، تغییر دیتابیس باید با نسخه قدیم و جدید برنامه سازگار باشد.

[Kubernetes: بودجه اختلال و محدودیت آن](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/)

[Kubernetes: Probeهای Readiness، Liveness و Startup](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)

## ۸. مسیر یک درخواست از اینترنت تا برنامه

در Swarm داخلی، DNS عمومی به LB یا جفت Reverse Proxy دارای افزونگی اشاره می‌کند. TLS آنجا یا در Gateway امن مشخص خاتمه می‌یابد. LB به پورت منتشرشده نودهای قابل دسترس می‌فرستد؛ Routing Mesh از Overlay ورودی به Task می‌رساند. API از Overlay برنامه به Redis وصل می‌شود. Published Port مجوز برنامه نیست و API مدیریت نباید اینترنتی شود. در انتشار Host، فقط نود میزبان Task آن پورت را سرویس می‌دهد؛ Discovery در LB باید با جانمایی هماهنگ باشد.

در Kubernetes مسیر منطقی DNS عمومی ← LB ورودی افزونه ← Controller از نوع Gateway/Ingress ← Service ← Endpoint پاد آماده است. Controller یا CNI ممکن است مسیر واقعی را بهینه کند؛ Service قرارداد منطقی ثابت است. ClusterIP داخلی است، NodePort پورت نود می‌دهد و نوع LoadBalancer از یک پیاده‌سازی درخواست Endpoint می‌کند. روی Bare Metal یا vSphere این Endpoint خودکار نیست؛ اتصال LB پشتیبانی‌شده مثل MetalLB با طراحی دقیق یا تجهیز خارجی متصل به NodePort و Endpoint کنترلر لازم است. مالکیت IP، دسترسی BGP/L2 و Failover را طراحی کنید.

Ingress در دسترس است ولی API آن Frozen است؛ Gateway API مدل مسیریابی نقش‌محور غنی‌تری با پیاده‌سازی نصب‌شده جدا می‌دهد. NetworkPolicy سیاست L3/L4 است، نه WAF یا سیاست عمومی TLS. CNI پشتیبان باید آن را اعمال کند. در Default Deny خروجی DNS، مقصد Listener SQL و مسیر برگشت را بسنجید؛ قبول شدن YAML اثبات مسدود شدن بسته نیست. در هر دو پلتفرم MTU، ترافیک ورودی و خروجی و داخلی و مسیر نامتقارن را پیش از Production آزمایش کنید.

[Docker: Routing Mesh و انتشار Host](https://docs.docker.com/engine/swarm/ingress/)

[Kubernetes: سرویس و شبکه](https://kubernetes.io/docs/concepts/services-networking/)

[Kubernetes: وضعیت Ingress و نیاز به Controller](https://kubernetes.io/docs/concepts/services-networking/ingress/)

[Gateway API: پیاده‌سازی‌ها و مدل مسیریابی](https://gateway-api.sigs.k8s.io/)

## ۹. Replica جدید دیسک قدیمی را همراه نمی‌آورد

API بدون State وضعیت کاری را از درخواست و سرویس مرجع بیرونی بازسازی می‌کند. جزء Stateful رکورد پایدار یا هویت دارد. Frontend اغلب بدون State است؛ Upload کاربر آن را Stateful می‌کند مگر فایل در سرویس Object یا File خارجی باشد. Redis ممکن است کش قابل حذف یا مرجع Session و Queue باشد؛ پیش از قابل‌جایگزین نامیدن آن تصمیم بگیرید. Replica داشتن، Replication دیتابیس نیست. سه کانتینر SQL با دایرکتوری محلی مستقل سه دیتابیس مستقل هستند، نه Availability Group.

Volume محلی یا Bind Mount در Swarm به نود تعلق دارد. Task جایگزین روی نود دیگر ممکن است Volume خالی هم‌نام ببیند، به خطای مسیر Bind برسد یا دیتاست متفاوت داشته باشد. Shared Storage یا Volume Driver پشتیبانی‌شده را با کنترل دسترسی، Locking و رفتار خرابی انتخاب کنید. NFS دسترسی فایل مشترک می‌دهد ولی خودکار رفتار ایمن دیتابیس، کارایی یا HA سرور NFS نمی‌دهد. یک Data Directory دیتابیس را Read/Write به چند نمونه ناهماهنگ Mount نکنید.

PV/PVC درخواست ذخیره را از پیاده‌سازی جدا می‌کند. StorageClass و CSI دیسک را Provision و Attach می‌کنند، اما Access Mode، Topology، Reclaim Policy، تأخیر Attach/Detach و سلامت Backend همچنان مطرح‌اند. ReadWriteOnce قید دسترسی تک‌نودی است و تضمین تک‌نویسنده بودن Pod نیست؛ Access Mode مناسب و Fencing دیتابیس لازم است. Local PV وابسته به نود می‌ماند. Pod جابه‌جاشده ممکن است منتظر Detach/Attach ایمن بماند و Backend خراب همچنان خراب است.

داده برنامه را با سازگاری آگاه از دیتابیس، Transaction Log لازم، تنظیمات و کلید رمزنگاری بکاپ بگیرید. Snapshot از etcd وضعیت API را برمی‌گرداند نه محتوای همه PVCها. بکاپ Swarm متادیتای کلاستر را برمی‌گرداند نه Volume برنامه. RPO/RTO تعریف، نسخه خارج سایت محافظت و Restore جدا با Query واقعی برنامه آزمایش و زمان را ثبت کنید. Snapshot و Replication می‌توانند حذف یا خرابی منطقی را هم منتقل کنند؛ Retention و تمرین بازیابی لازم می‌ماند.

[Kubernetes: چرخه PV و Access Mode](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)

[Docker: ماندگاری و دامنه Volume](https://docs.docker.com/engine/storage/volumes/)

## ۱۰. امنیت به مسئول و مرز قابل اعمال نیاز دارد

Swarm برای هویت نود و ارتباط رمز‌شده مدیریت از mTLS استفاده می‌کند. Secret بومی در Raft رمز می‌شود و فقط به Task سرویس مجاز می‌رسد؛ در Linux به‌صورت حافظه‌ای Mount می‌شود. رمزنگاری Overlay برنامه گزینه جداست و TLS برنامه تا دیتابیس هم تنظیم مستقل دارد. Rotation معمولاً با Secret تغییرناپذیر جدید، Update سرویس و لغو Credential قدیمی در مبدأ انجام می‌شود. دسترسی Manager، Docker Socket، Join Token و Unlock Key را محافظت کنید؛ Engine Swarm معادل بومی RBAC محدود به Namespace در Kubernetes ندارد. ابزار تجاری یا خارجی کنترل دسترسی را جدا ارزیابی کنید.

RBAC در Kubernetes مجوز API می‌دهد نه ایزولاسیون شبکه. ServiceAccount هویت Workload است؛ در جای مناسب Token کوتاه‌عمر Projected و در موارد بدون نیاز، غیرفعال کردن Automount را انتخاب کنید. Secret دارای مقدار Base64 است؛ این Encoding رمزنگاری نیست. Encryption at Rest برای API را با نگهداری کلید یا KMS و Rotation مناسب تنظیم و خواندن Secret و ساخت Pod افشاکننده آن را محدود کنید. Audit Policy و نگهداری امن لاگ را آگاهانه فعال کنید. Namespace به‌تنهایی مرز سخت Tenant نیست؛ RBAC، Admission، Quota، NetworkPolicy پشتیبانی‌شده و برای جداسازی قوی‌تر کلاستر مستقل یا Sandbox لازم است.

هر دو پلتفرم کانتینر با حداقل مجوز، هویت Non-root در صورت پشتیبانی، حذف Capability اضافی، seccomp، محدودیت Host Mount، فایل‌سیستم Read-only در صورت امکان و Resource Limit می‌خواهند. Image و Dependency را Scan، ایمیج Production را با Digest ثابت، نوشتن Registry را محافظت و Provenance و Signature را با کنترل زنجیره تأمین منتخب بررسی و میزبان و Runtime را وصله کنید. Admission در Kubernetes با سازوکار داخلی تنظیم‌شده یا Policy Engine افزوده سیاست اعمال می‌کند؛ Scan ایمیج و Service Mesh قابلیت خودکار هسته نیستند. mTLS بین Workload به تنظیم برنامه یا Mesh نصب‌شده نیاز دارد. درخواست ردشده را پایش و Rotation را تمرین کنید؛ نتیجه سبز Scanner معادل امنیت نیست.

[Docker: ذخیره، دسترسی و Rotation اطلاعات محرمانه](https://docs.docker.com/engine/swarm/secrets/)

[Kubernetes: مدل امنیت و کنترل‌ها](https://kubernetes.io/docs/concepts/security/)

[Kubernetes: امنیت Secret و هشدار رمزنگاری](https://kubernetes.io/docs/concepts/configuration/secret/)

## ۱۱. Pipeline نسخه را تحویل می‌دهد؛ Orchestrator آن را اجرا نگه می‌دارد

![GitLab و Jenkins ایمیج ثابت می‌سازند و منتشر می‌کنند؛ Orchestrator اجرای Production را همگرا می‌کند](/assets/img/articles/content/docker-swarm-vs-kubernetes-enterprise-guide-cicd.svg)

توسعه‌دهنده به GitLab Push می‌کند. Jenkins یا GitLab CI کامیت بازبینی‌شده را دریافت، تست و Package در Maven برای Java و Build فرانت‌اند را اجرا، Dependency را Scan و Image را می‌سازد. Registry آن Artifact نسخه‌دار را نگه می‌دارد و زمان‌بندی نمی‌کند. CI کد را ادغام و اعتبارسنجی می‌کند. Continuous Delivery خروجی قابل انتشار و مسیر Promotion کنترل‌شده می‌دهد؛ Continuous Deployment تغییر موفق را طبق سیاست خودکار منتشر می‌کند. Jenkins و GitLab CI موتور Pipeline هستند. Swarm و Kubernetes بعد از پایان Pipeline وضعیت اجرا را حفظ می‌کنند.

```text
Developer -> GitLab -> Jenkins / GitLab CI -> Maven test/package
          -> Docker image build -> scan/sign -> Container registry
          -> immutable digest promotion
             +-> Swarm service/stack update -> Production tasks
             +-> Kubernetes manifests / GitOps -> Production Pods
```

هویت انتشار با مجوز محدود، Branch و Environment محافظت‌شده و Digest ثابت استفاده کنید. Credential مخزن را از سورس و لاگ دور نگه دارید. در Swarm، Parallelism، Delay، Monitor و Failure Action تنظیم کنید؛ Rollback مشخصات قبلی سرویس را برمی‌گرداند. در Kubernetes، maxSurge/maxUnavailable، Probe و progressDeadlineSeconds را تنظیم کنید؛ rollout status می‌تواند Pipeline را ناموفق کند، اما Deployment صرف پایان Progress Deadline خودکار Rollback نمی‌کند. Pipeline یا Release Controller باید تصمیم بگیرد. ایمیج قبلی را حفظ و Migration دیتابیس Expand/Contract طراحی کنید تا برگشت برنامه ممکن بماند.

Argo CD یک Reconciler افزوده GitOps برای Kubernetes است. تنظیم تأییدشده Git را با کلاستر مقایسه و Drift را اصلاح می‌کند؛ Maven یا جایگزین Scheduler اجرا نیست. وقتی چند تیم و محیط Promotion قابل ردیابی و وضعیت مطلوب یکسان می‌خواهند مفید می‌شود. مسئول Update ایمیج، تحویل Secret، تغییر اضطراری و توقف موقت Reconciliation هنگام رخداد را تعیین کنید. برای Swarm کوچک، Pipeline کنترل‌شده با تنظیم Stack نسخه‌دار می‌تواند بدون ساخت Controller سفارشی GitOps کافی باشد.

[Argo CD: مستندات کنترلر GitOps](https://argo-cd.readthedocs.io/en/stable/)

## ۱۲. آزمایشگاه A — Docker Swarm سه‌نودی

سه VM تازه Ubuntu Server 24.04 LTS بسازید: swarm-manager-01 با 10.20.0.11 و swarm-worker-01 با .12 و swarm-worker-02 با .13. پیشنهاد آموزشی برای هرکدام ۲ vCPU، چهار GiB RAM و دیسک ۲۵ GiB است؛ Benchmark ظرفیت Production نیست. Hostname یکتا، IP ثابت، DNS و زمان درست و ارتباط خصوصی فراهم کنید. TCP 2377 به Manager و TCP/UDP 7946 و UDP 4789 را فقط بین نودهای مورد اعتماد و TCP 8080 را فقط برای کلاینت آزمایش باز کنید. VXLAN را اینترنتی نکنید. پورت Docker با قواعد فایروال میزبان تعامل دارد؛ به UFW اکتفا نکنید و دسترسی واقعی را بسنجید. یک Manager تک‌نقطه خرابی کنترل است.

### نصب Engine روی هر سه میزبان تازه

دستورها از مخزن امضاشده رسمی Docker استفاده می‌کنند، نه اجرای مستقیم اسکریپت دانلودشده با root. روی میزبان موجود ابتدا طبق راهنمای رسمی بسته متعارض را شناسایی کنید؛ Runtime عملیاتی را کورکورانه حذف نکنید. روی همه نودها نسخه تأییدشده یکسان نصب و Candidate بسته را پیش از Promotion ثبت کنید.

```bash
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
. /etc/os-release
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $VERSION_CODENAME stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update
apt-cache policy docker-ce
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo docker version
sudo docker run --rm hello-world
```

### Init، عضویت، Deploy و Scale

```bash
# On swarm-manager-01
sudo docker swarm init --advertise-addr 10.20.0.11
sudo docker swarm join-token worker
# On EACH worker: run the join command printed above, with its real token.
# sudo docker swarm join --token <printed-worker-token> 10.20.0.11:2377
# Back on the manager
sudo docker node ls
sudo docker network create --driver overlay app-net
sudo docker service create --name web --network app-net --replicas 2   --constraint 'node.role==worker'   --reserve-cpu 0.10 --reserve-memory 64M --limit-cpu 0.50 --limit-memory 128M   --publish published=8080,target=80   --health-cmd 'curl -fsS http://localhost/ || exit 1'   --health-interval 10s --health-timeout 3s --health-retries 3   --update-parallelism 1 --update-delay 10s --update-monitor 30s   --update-failure-action rollback --stop-grace-period 30s nginx:1.28.0
sudo docker service scale web=3
sudo docker service ls
sudo docker service ps web --no-trunc
curl -I http://10.20.0.12:8080/
```

خروجی مورد انتظار: node ls سه نود Ready/Active و service ls پس از همگرایی 3/3 نشان می‌دهد و HTTP برابر 200 است. ایمیج رسمی Nginx مبتنی بر Debian این مثال curl دارد؛ با تغییر ایمیج، دستور سلامت را دوباره بررسی کنید. Tag نسخه برای خوانایی آزمایش Update است، نه Pin واقعی Production؛ ایمیج منتخب را تأیید و Scan و تست و Digest آن را ثابت کنید. سه Replica روی دو Worker عمداً هم‌مکانی را مجاز می‌گذارد تا در صورت ظرفیت، Worker باقی‌مانده هر سه را اجرا کند.

```bash
# Manager: update, observe, then deliberately restore the prior service spec.
sudo docker service update --image nginx:1.28.1 web
sudo docker service ps web
sudo docker service inspect --format '{{json .UpdateStatus}}' web
sudo docker service rollback web
sudo docker service ps web
# Planned maintenance: drain worker-01, check replacement tasks, then re-enable it.
sudo docker node update --availability drain swarm-worker-01
sudo docker service ps web
sudo docker node update --availability active swarm-worker-01
# Abrupt failure test: power off worker-02 from the lab hypervisor ONLY.
# Manager: observe detection and replacement; client: measure errors throughout.
sudo docker node ls
sudo docker service ps web --no-trunc
sudo docker service logs --tail 50 web
# After powering worker-02 back on:
sudo docker node ls
# Lab cleanup, on manager (removes this lab service/network):
sudo docker service rm web
sudo docker network rm app-net
```

هنگام خرابی HTTP را از نود سالم یا LB دارای Health Check پایش کنید؛ ارسال همه درخواست‌ها به نود خاموش آزمون Endpoint خراب است، نه بازیابی Routing Mesh. خطا و زمان جایگزینی را ثبت کنید و زمان ثابت وعده ندهید. Active کردن نود همه Taskهای موجود را خودکار بازتوزیع نمی‌کند. در Pending/Rejected، خطای کامل service ps را برای ظرفیت، Constraint، Pull و شبکه بخوانید. اگر تنها Manager خاموش باشد Worker ممکن است سرویس قبلی را بدهد ولی این Lab زمان‌بندی نمی‌کند؛ Manager را برگردانید یا Lab مصرفی را بازسازی کنید. عملیات مخرب Leave و Reset را بداهه وارد بازیابی Production نکنید.

[نصب رسمی Docker Engine روی Ubuntu](https://docs.docker.com/engine/install/ubuntu/)

## ۱۳. آزمایشگاه B — kubeadm، containerd و Calico

Lab جدا با سه VM تازه Ubuntu 24.04 بسازید: k8s-control-01 با 10.30.0.11، k8s-worker-01 با .12 و k8s-worker-02 با .13؛ برای این تمرین هرکدام ۲ vCPU، چهار GiB حافظه و دیسک ۲۵ GiB. یک Control Plane و دو Worker است و HA Production نیست. شاخه مرجع Kubernetes 1.36 و Calico 3.33.0 است؛ صفحه رسمی سازگاری 1.35 تا 1.37 را فهرست می‌کند. Patch جاری یکسان 1.36 را روی همه نودها انتخاب کنید. تاریخ بازبینی ۶ نوامبر ۲۰۲۶ است؛ موقع اجرا چرخه پشتیبانی و وصله امنیتی را دوباره ببینید. برای جلوگیری از تعارض Runtime و مخزن، این Lab از میزبان‌های Swarm جدا باشد.

Hostname، MAC و Product UUID یکتا، IP خصوصی ثابت، DNS و همگامی زمان لازم‌اند. پورت‌های مستند Kubernetes را باز کنید: TCP 6443 به Control Plane، پورت etcd یعنی TCP 2379–2380 فقط بین اعضای کنترل، TCP 10250 برای kubelet از مبدأ کنترل و مدیریت مجاز، پورت محلی Scheduler/Controller طبق مستند و NodePort منتخب TCP 30080 برای کلاینت Lab. VXLAN در Calico زیر UDP 4789 بین نودها می‌خواهد. Pod CIDR برابر 192.168.0.0/16 و Service CIDR برابر 10.96.0.0/12 نباید با شبکه میزبان، VPN یا سازمان هم‌پوشانی داشته باشند. فایروال را کلی خاموش نکنید.

### آماده‌سازی همه نودها و Runtime سازگار

مثال میزبان تازه از مخزن امضاشده Docker برای containerd.io نسخه 2.x استفاده می‌کند، نه Docker Engine. Candidate بسته و جدول پشتیبانی containerd را پیش از نصب ببینید. تنظیم زیر عمداً برای containerd 2.x است؛ کلیدهای CRI با 1.x فرق دارند. Swap را هم در اجرا و هم در fstab برای این Lab غیرفعال کنید. از fstab کپی نگه دارید و فقط ورودی واقعی Swap را حذف یا Comment کنید؛ Mountهای دیگر را بازنویسی نکنید.

```bash
# All nodes; fresh Ubuntu 24.04 only.
sudo swapoff -a
sudo cp /etc/fstab /etc/fstab.before-k8s
sudoedit /etc/fstab
# Comment the swap entry, save, then verify no active swap:
swapon --show
sudo modprobe overlay
sudo modprobe br_netfilter
printf 'overlay
br_netfilter
' | sudo tee /etc/modules-load.d/k8s.conf
cat <<'EOF' | sudo tee /etc/sysctl.d/99-kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
sudo apt-get update
sudo apt-get install -y ca-certificates curl gpg
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
. /etc/os-release
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $VERSION_CODENAME stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update
apt-cache policy containerd.io
sudo apt-get install -y containerd.io
containerd --version
# For Kubernetes 1.36, upstream recommends containerd 2.2.0+ or 2.3.0+.
# Select a maintained patch in one of those branches; stop for an incompatible candidate.
sudo mkdir -p /etc/containerd
cat <<'EOF' | sudo tee /etc/containerd/config.toml
version = 3
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc]
  runtime_type = 'io.containerd.runc.v2'
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
  SystemdCgroup = true
EOF
sudo systemctl enable --now containerd
sudo systemctl restart containerd
sudo ctr plugins ls | grep cri
```

### نصب Patch یکسان Kubernetes و Bootstrap

```bash
# All nodes
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
apt-cache madison kubeadm
# Choose ONE available, approved 1.36.x package version and use it on ALL nodes:
read -r -p 'Exact package version (for example from madison): ' K8S_PACKAGE_VERSION
sudo apt-get install -y kubelet="$K8S_PACKAGE_VERSION" kubeadm="$K8S_PACKAGE_VERSION" kubectl="$K8S_PACKAGE_VERSION"
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable kubelet
# On k8s-control-01 only:
K8S_VERSION=$(kubeadm version -o short)
sudo kubeadm init --kubernetes-version "$K8S_VERSION"   --apiserver-advertise-address 10.30.0.11   --pod-network-cidr 192.168.0.0/16   --cri-socket unix:///run/containerd/containerd.sock
mkdir -p "$HOME/.kube"
sudo cp /etc/kubernetes/admin.conf "$HOME/.kube/config"
sudo chown "$(id -u):$(id -g)" "$HOME/.kube/config"
chmod 600 "$HOME/.kube/config"
# Run the printed kubeadm join command with sudo on BOTH workers.
# Add --cri-socket unix:///run/containerd/containerd.sock if runtime selection is ambiguous.
# If the join token expires, on control plane:
sudo kubeadm token create --print-join-command
```

پیش از ساخت تنظیم توسط kubeadm ممکن است kubelet Restart شود. قبل از نصب CNI، نود NotReady و CoreDNS در Pending انتظار می‌رود؛ دلیل حذف Taint کنترل نیست. admin.conf و Join Token را محافظت کنید. Bootstrap Token موقت است و نباید در Issue عمومی قرار بگیرد. مانیفست بعدی مسیر نصب Legacy CRD در Calico را انتخاب می‌کند تا فرایند مهاجرت Native v3 و Webhook را با Lab پایه مخلوط نکند.

```bash
# Control plane, as the user holding the lab kubeconfig.
curl -fL https://raw.githubusercontent.com/projectcalico/calico/v3.33.0/manifests/calico-vxlan.yaml -o calico.yaml
# Review the downloaded manifest and record its hash before applying.
sha256sum calico.yaml
# This upstream VXLAN-only variant already disables BIRD and its health probes.
# Change IPv4 encapsulation from CrossSubnet to Always for this fresh lab:
sed -i '/name: CALICO_IPV4POOL_VXLAN/{n;s/value: "CrossSubnet"/value: "Always"/;}' calico.yaml
# Confirm the exact resulting environment settings before applying:
grep -A1 -E 'name: CALICO_IPV4POOL_(IPIP|VXLAN)' calico.yaml
grep 'calico_backend:' calico.yaml
if grep -E -- '--bird-(ready|live)' calico.yaml; then echo 'Unexpected BIRD probe; stop'; exit 1; fi
# Expected: IPIP Never; VXLAN Always; backend vxlan; no BIRD probe. Stop if different.
kubectl apply -f calico.yaml
kubectl -n kube-system rollout status daemonset/calico-node --timeout=300s
kubectl get nodes -o wide
kubectl -n kube-system get pods
# Expected: all three Ready; CoreDNS and Calico Running/Ready.
```

### انتشار Workload بدون State قابل مقایسه

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  revisionHistoryLimit: 5
  progressDeadlineSeconds: 180
  selector:
    matchLabels: {app: web}
  strategy:
    type: RollingUpdate
    rollingUpdate: {maxSurge: 1, maxUnavailable: 0}
  template:
    metadata:
      labels: {app: web}
    spec:
      terminationGracePeriodSeconds: 30
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels: {app: web}
      containers:
        - name: nginx
          image: nginx:1.28.0
          ports: [{containerPort: 80}]
          resources:
            requests: {cpu: 100m, memory: 64Mi}
            limits: {cpu: 500m, memory: 128Mi}
          startupProbe:
            httpGet: {path: /, port: 80}
            periodSeconds: 2
            failureThreshold: 30
          readinessProbe:
            httpGet: {path: /, port: 80}
            periodSeconds: 5
          livenessProbe:
            httpGet: {path: /, port: 80}
            periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: NodePort
  selector: {app: web}
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web
spec:
  minAvailable: 2
  selector:
    matchLabels: {app: web}
```

```bash
kubectl apply --dry-run=server -f kubernetes-web.yaml
kubectl apply -f kubernetes-web.yaml
kubectl rollout status deployment/web --timeout=180s
kubectl get pods -l app=web -o wide
kubectl get service web
curl -I http://10.30.0.12:30080/
kubectl scale deployment/web --replicas=4
kubectl rollout status deployment/web --timeout=180s
kubectl set image deployment/web nginx=nginx:1.28.1
kubectl rollout status deployment/web --timeout=180s
kubectl rollout history deployment/web
kubectl rollout undo deployment/web
kubectl rollout status deployment/web --timeout=180s
kubectl drain k8s-worker-01 --ignore-daemonsets
kubectl get pods -l app=web -o wide
kubectl uncordon k8s-worker-01
# Abrupt failure: power off worker-02 from the disposable lab hypervisor.
kubectl get nodes -w
# In another terminal, observe delayed replacement and client errors:
kubectl get pods -l app=web -o wide -w
# After restoring worker-02:
kubectl get nodes
kubectl get events --sort-by=.metadata.creationTimestamp
# Remove only this lab workload when done:
kubectl delete -f kubernetes-web.yaml
```

انتظار می‌رود Rollout پیام successfully rolled out بدهد، سه پاد اولیه Ready شوند، NodePort پاسخ 200 بدهد و بعد Scale چهار Replica مطلوب شود. ScheduleAnyway پخش ترجیحی می‌دهد بدون جلوگیری از بازیابی روی یک Worker. Toleration پیش‌فرض Node Unreachable/NotReady معمولاً تخلیه را حدود پنج دقیقه عقب می‌اندازد؛ زمان واقعی به تشخیص، Controller، Pull و Storage هم وابسته است. PDB برای Drain است نه خرابی ناگهانی. HTTP را طی آزمایش از نود سالم یا LB بسنجید. نود NotReady ممکن است کانتینر جداشده را هنوز اجرا کند؛ بازیابی Stateful به Fencing نیاز دارد، نه Force Delete کورکورانه.

در شکست Bootstrap، journalctl سرویس kubelet و containerd، CRI، Swap، cgroup، پورت و انتخاب Route را بررسی کنید. در NotReady پس از CNI، لاگ Calico، VXLAN و MTU و هم‌پوشانی CIDR را ببینید. در پایان مهلت Rollout، پیش از Undo پاد و Event را Describe کنید. برگشت برنامه rollout undo است؛ برگشت نسخه کلاستر همان عملیات نیست. اگر Bootstrap Lab مصرفی خراب شد از Snapshot سالم VM بازسازی کنید. kubeadm reset را Rollback امن Production معرفی نکنید. این‌ها Runbook مبتنی بر مستندات‌اند؛ هنگام نگارش مقاله زیرساخت سه‌VM و تزریق خرابی اجرا نشده است.

[kubeadm: پیش‌نیاز و مخزن نسخه‌دار](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)

[kubeadm: ساخت کلاستر و CNI](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/)

[Calico: روش‌های رسمی نصب داخلی](https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises)

[Calico: مانیفست VXLAN و Probe سلامت](https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/config-options)

[containerd: نسخه پشتیبانی‌شده و سازگاری Kubernetes](https://containerd.io/releases/)

[Kubernetes: شاخه‌های پشتیبانی‌شده](https://kubernetes.io/releases/)

## ۱۴. مهاجرت از مالکیت وابستگی شروع می‌شود

وقتی بازیابی چندنودی، انتشار کنترل‌شده چندمیزبانی یا وضعیت مطلوب متمرکز نیاز واقعی شد، عبور از Compose منطقی است. مهاجرت Swarm به Kubernetes وقتی ارزش دارد که مرزبندی تیم، Policy، اتصال Storage پشتیبانی‌شده، Autoscaling یا API پلتفرم مدل عملیات اضافه را توجیه کند. تعداد زیاد کانتینر به‌تنهایی محرک مهاجرت نیست. پیش از تعهد، یک برنامه نماینده را از انتشار، خرابی، بکاپ و ارتقا عبور دهید؛ SQL، احراز هویت، DNS و اتصال خارجی را هم دخیل کنید.

| مرحله | خروجی و آزمون پذیرش |
| --- | --- |
| 1. Inventory | فهرست Image، مسئول، پورت، Job، SLA و داده؛ شناسایی Image پشتیبانی‌نشده. |
| 2. Dependency Mapping | نقشه تماس همگام و غیرهمگام، DNS، Listener و فرض شروع؛ شبیه‌سازی قطع وابستگی. |
| 3. Image Registry | Mirror کردن Digest تأییدشده و Credential؛ اثبات Pull از همه نودها. |
| 4. Networking | ترجمه نام سرویس، ورودی و Policy؛ آزمون مسیر کاربر و ارتباط داخلی. |
| 5. Storage | انتخاب CSI یا Backend مشترک، Access Mode، کپی و Fencing؛ Restore و مقایسه رکورد. |
| 6. Secrets | تحویل امن هویت و Credential جدید؛ اثبات Rotation و حداقل مجوز. |
| 7. Deployment Configuration | تعریف Probe، Requests، Limits، Placement و Shutdown؛ آزمون انتشار خراب. |
| 8. CI/CD | Promotion همان Digest؛ محافظت هویت انتشار و تأیید محیط. |
| 9. Monitoring | انتقال هشدار، Probe مربوط به SLO، لاگ و داشبورد؛ اثبات رسیدن هشدار قابل اقدام به On-call. |
| 10. Rollback Strategy | تعریف برگشت ترافیک، مالک داده و سازگاری Schema؛ جلوگیری از دو نویسنده ناهماهنگ. |

مبدل YAML نمی‌فهمد Bind Mount باید PVC شود، Healthcheck معادل Readiness است یا Liveness، یا Secret باید به Vault خارجی برود. ابتدا سرویس بدون State را Canary، ترافیک نماینده را مشاهده و سپس State را با Cutover آگاه از برنامه و رویه روشن توقف نوشتن یا Replication منتقل کنید. بعد از نوشتن داده جدید، برگرداندن DNS می‌تواند داده را از دست بدهد یا دوپاره کند. نگهداری Deploy و Image قبلی فقط در چارچوب برنامه برگشت با سازگاری داده معنی دارد.

## ۱۵. پیش از تعویض همه‌چیز، علت را پیدا کنید

Event و آخرین تلاش ناموفق را بخوانید، نه فقط پردازش سبز فعلی. خروجی جدول الگوی تشخیصی مورد انتظار است، نه خروجی ضبط‌شده Production. نام Service، Pod، Namespace، Node و PVC واقعی را جایگزین کنید. Log و Describe ممکن است اطلاعات حساس داشته باشند؛ مدرک کامل را در محل محدود رخداد نگه دارید.

| نشانه | دستور تشخیص | الگوی خروجی و معنی | رفع مشکل |
| --- | --- | --- | --- |
| Container Restart Loop | docker service ps web --no-trunc; docker service logs --tail 100 web | Taskهای Failed/Rejected تکراری یا Exit غیرصفر | تنظیم خراب، وابستگی قطع یا Healthcheck؛ ورودی و Command را اصلاح، Image را تأیید و انتشار خراب را برگردانید |
| Pod CrashLoopBackOff | kubectl logs POD -c CONTAINER --previous; kubectl describe pod POD | Back-off restarting failed container | Exit قبلی و Probe را بررسی؛ برنامه و تنظیم را اصلاح کنید، نه حذف مکرر Pod |
| ImagePullBackOff | kubectl describe pod POD; docker service ps web --no-trunc | unauthorized، manifest unknown یا timeout | Digest، Credential، DNS، TLS رجیستری و دسترسی هر نود را بررسی کنید |
| Node NotReady | kubectl describe node NODE; sudo journalctl -u kubelet -n 100 | Ready=False/Unknown و خطای Runtime یا CNI | Heartbeat، Runtime، دیسک و CNI میزبان را ببینید؛ پیش از Eviction ناامن ارتباط را درست کنید |
| Resource Exhaustion | kubectl describe node NODE; kubectl top nodes; docker stats --no-stream | MemoryPressure/DiskPressure یا مصرف بالا | top به metrics-server نیاز دارد؛ علت واقعی فشار دیسک را رفع، Requests را تنظیم و ظرفیت اندازه‌گیری‌شده اضافه کنید |
| Memory OOM | kubectl describe pod POD; sudo journalctl -k -n 100 | OOMKilled، اغلب Exit 137؛ شاهد OOM در کرنل | 137 به‌تنهایی اثبات نیست؛ Limit را از OOM میزبان جدا، Leak را Profile و حافظه را آگاهانه تعیین کنید |
| Network Connectivity | kubectl get endpointslices -l kubernetes.io/service-name=web; docker network inspect app-net | Endpoint آماده خالی یا عضویت شبکه اشتباه | Selector و Readiness، پورت، MTU در CNI/Overlay، Policy و مسیر برگشت را بررسی کنید |
| DNS Failure | kubectl -n kube-system logs deployment/coredns --tail=100; docker service inspect web | SERVFAIL، timeout یا نام سرویس اشتباه | resolv.conf، Search Domain، سلامت CoreDNS، خروجی DNS در Policy و DNS بالادست را ببینید |
| Storage Mount Failure | kubectl describe pod POD; kubectl describe pvc PVC | FailedMount، Multi-Attach یا PVC Pending | لاگ CSI، Credential، Topology، Access Mode، اتصال قدیمی و Backend را ببینید؛ پیش از Detach، Fencing کنید |
| Failed Deployment | kubectl rollout status deployment/web --timeout=180s; docker service inspect web | ProgressDeadlineExceeded یا Update در حالت Paused/Rollback | Image، Probe، ظرفیت Surge و Event را ببینید؛ برنامه را اصلاح یا آگاهانه Rollback کنید، نه تاریخچه دیتابیس |
| Replica Scheduling Failure | kubectl describe pod POD; docker service ps web --no-trunc | FailedScheduling، insufficient cpu، Taint یا no suitable node | تعارض Placement و Storage یا ظرفیت را رفع؛ قید ایمنی را بدون فهم Failure Domain حذف نکنید |

Prometheus متریک جمع می‌کند و Grafana نمایش می‌دهد؛ هیچ‌کدام SLO شما را خودکار تعریف نمی‌کند. علاوه بر CPU، تأخیر و خطای کاربر، Replica غیرقابل دسترس، سن Queue، انقضای گواهی و سن بکاپ را هشدار دهید. Zabbix برای ESXi، VM، OS و شبکه مفید می‌ماند؛ Metrics و Event در Kubernetes زمینه Workload را اضافه می‌کند. Loki یا سامانه لاگ مرکزی به Collector، Label، Retention و دسترسی محافظت‌شده نیاز دارد. Revision انتشار، Digest و Request ID را مرتبط کنید تا رخداد به تغییر مشخص وصل شود.

## ۱۶. هزینه عملیات فراتر از ردیف لایسنس است

| سازمان | انتخاب محتمل | محرک هزینه قابل اندازه‌گیری |
| --- | --- | --- |
| کوچک: سه برنامه | Compose با پذیرش بازیابی تک‌میزبان؛ Swarm برای نیاز واقعی چندمیزبانی | زمان بکاپ و Restore، میزبان دوم، Monitoring، ظرفیت آزاد و دسترس‌پذیری تیم کوچک |
| متوسط: پانزده برنامه | Swarm با مالکیت انتشار توسط تیم عملیات مشترک؛ Kubernetes با نیاز موجه Policy و مرز تیم | VM رأی‌دهنده، CPU/RAM کارگر، Storage مشترک، ورودی افزونه، ارتقا و اتوماسیون سفارشی |
| Enterprise: Microservice متعدد | Kubernetes اغلب کنترل پلتفرم قابل استفاده مجدد می‌دهد؛ نیرو و پشتیبانی را بسنجید | مهندس پلتفرم، CNI/CSI، نگهداری Telemetry، DR، امنیت و Audit، تمرین ارتقا و رخداد |

صورت‌حساب عملیات بنویسید: تعداد VM کنترل و Worker، CPU/RAM رزروشده، رشد Image و Log، IOPS و تأخیر Storage، مسیر شبکه و پهنای باند بکاپ. زمان آموزش، وصله، Rotation گواهی و کلید، تمرین ارتقا، رسیدگی رخداد و قرارداد پشتیبانی را اضافه کنید. هزینه فرصت انتشار عقب‌افتاده و اسکریپت سفارشی برای نیاز پوشش‌داده‌نشده را حساب کنید. لایسنس موجود vSphere، VM و ظرفیت Datastore را رایگان نمی‌کند. عدد قیمت یا Benchmark ساختگی جای اندازه‌گیری Workload و هزینه نیروی محلی را نمی‌گیرد.

## ۱۷. اشتباهاتی که هنگام انتخاب Docker Swarm یا Kubernetes انجام می‌دهیم

نصب Kubernetes پیش از تعریف هدف بازیابی، کار بدون آزمون پذیرش روشن ایجاد می‌کند. انتخاب با محبوبیت، افرادی را که باید نگهداری کنند نادیده می‌گیرد. تصور کانتینر به‌عنوان VM کوچک، کرنل مشترک و فایل‌سیستم موقت را پنهان می‌کند. دیتابیس بدون طراحی Storage، Fencing، Backup و Restore، جانمایی مجدد را خطرناک می‌کند. سه Replica، سه VM و داشبورد سبز اثبات HA سرتاسری نیستند.

بدون Monitoring اولین گزارش خرابی از واحد حقوق می‌رسد. بدون بکاپ آزموده فقط فایل داریم و بازیابی نامعلوم است. نبود Resource Limit اجازه می‌دهد یک Leak به همسایه آسیب بزند؛ Limit کورکورانه کم هم قطعی می‌سازد. نبود سیاست امنیتی Workload دارای Privilege، API مدیریت عمومی و Credential بلندعمر Deploy را بی‌حاکمیت می‌گذارد. نبود Rollback یا DR، ارتقا یا قطع سایت را به جراحی بداهه داده تبدیل می‌کند. Mesh، Operator یا Orchestrator دوم را صرف حضور در دیاگرام مرجع اضافه نکنید. معماری ساده با رفتار خرابی شناخته‌شده و بازیابی تمرین‌شده می‌تواند از کلاستر پیچیده‌ای که مسئولش آن را توضیح نمی‌دهد قابل اعتمادتر باشد.

## ۱۸. جدول تصمیم نهایی

C یعنی Compose، S یعنی Swarm و K یعنی Kubernetes. گزینه‌ها مشروط‌اند، نه توصیه همگانی. ستون آخر مزیت و محدودیتی را می‌گوید که باید پذیرفته شود. تعداد برنامه زمینه است؛ کنترل عملیاتی مورد نیاز معماری را تعیین می‌کند.

| سناریو | گزینه و شرط | مزیت و محدودیت |
| --- | --- | --- |
| یک برنامه ساده | C؛ S/K در صورت نیاز موجه | چرخه ساده؛ C بازیابی چندمیزبانی ندارد |
| چند کانتینر روی یک سرور | C | Stack خوانا؛ میزبان Failure Domain باقی می‌ماند |
| سه سرور با چند برنامه | S؛ K برای Policy | کنترل یکپارچه S؛ سه Manager فقط خرابی یک رأی‌دهنده را تحمل می‌کند |
| پنج سرور Production | S یا K | انتخاب از مالکیت و Policy و Storage؛ رزرو ظرفیت بازیابی |
| چند تیم توسعه | اغلب K | RBAC و Quota و Self-service؛ نیازمند عملیات پلتفرم |
| Microservice متعدد | اغلب K؛ S ممکن | Controller و اکوسیستم؛ تعداد سرویس به‌تنهایی کافی نیست |
| نیاز به Autoscaling | K با Metrics؛ S با کنترل خارجی | حلقه HPA بومی K؛ Metrics و ظرفیت نود جدا |
| زیرساخت VMware | C/S/K مشروط | استفاده از مهارت VM؛ CSI و Storage و Failure Domain نیازمند طراحی |
| زیرساخت Bare Metal | C/S/K مشروط | منابع مستقیم؛ LB ورودی و Storage را خودتان تأمین کنید |
| Hybrid Cloud | اغلب K با کلاسترهای جدا | API مشترک؛ محل داده و IAM و شبکه همچنان خاص Provider |
| نیاز به Multi-Tenancy | K همراه کنترل | ایزولاسیون ترکیب‌پذیر؛ Tenant نامطمئن ممکن است کلاستر جدا بخواهد |
| نیاز به GitOps | K و Argo CD/Flux؛ S سفارشی | Reconciliation قابل Audit؛ مسئولیت و هزینه Controller |
| تیم IT کوچک | اغلب C/S | مفاهیم کمتر؛ Policy پیشرفته باید جدا تأمین شود |
| تیم DevOps تخصصی | K یا S طبق نیاز | توان نگهداری ابزار غنی‌تر؛ تخصص به‌تنهایی نیاز کسب‌وکار نیست |
| Enterprise با SLA سخت | اغلب K؛ S را با کنترل‌ها بسنجید | مدرک HA/DR سرتاسری لازم؛ هیچ Orchestrator تضمین SLA نیست |

### اگر مسئول زیرساخت این سازمان بودم، کدام را انتخاب می‌کردم؟

برای سه برنامه محدود با زمان Restore پذیرفته‌شده، از Compose، داده خارج از کانتینر، Monitoring و Restore اثبات‌شده شروع می‌کردم. برای تیم عملیات مشترک و Production چندمیزبانی محدود، ابتدا Swarm را می‌سنجیدم، به شرط کفایت مدل امنیت و انتشار برای نیاز مکتوب. تنظیم دو Manager را HA نمی‌نامیدم. برای تیم‌های مستقل متعدد با Policy، Quota، GitOps و اتصال پشتیبانی‌شده، Kubernetes را با مسئول پلتفرم دارای بودجه و برنامه آزموده ارتقا و بازیابی ترجیح می‌دادم.

برای سازمان VMware با SQL AG جاافتاده، طراحی اولیه معمولاً SQL را بیرون کلاستر برنامه نگه می‌داشت، رأی‌دهنده و Replica را بین میزبان ESXi پخش می‌کرد و مسیر کامل کاربر تا دیتابیس را هنگام خرابی می‌سنجید. کوچک‌ترین پلتفرم پاسخ‌گوی قرارداد بازیابی و حاکمیت را انتخاب و سپس اندازه‌گیری می‌کردم. تصمیم درباره مسئول هر وابستگی در ساعت دو بامداد و کارکرد بازیابی است، نه لوگوی روی اسلاید معماری.

## ۱۹. پرسش‌های رایج

### آیا Docker Swarm منسوخ است؟

Swarm Mode همچنان در مستندات Docker Engine است. قابلیت واقعی، روش پشتیبانی و نیاز اتصال را ارزیابی کنید و نامناسب بودن برای Production را فرض نکنید.

### آیا Compose یک Orchestrator چندنودی است؟

docker compose up معمولی برنامه را روی یک Docker Engine مدیریت می‌کند و زمان‌بندی و Failover بین میزبان نمی‌دهد.

### آیا سه Replica قطعی صفر را تضمین می‌کند؟

خیر؛ جانمایی، Readiness، ظرفیت، ورودی، Storage، دیتابیس و Shutdown کنترل‌شده بر نتیجه اثر دارند.

### آیا SQL Server باید به Kubernetes منتقل شود؟

خیر؛ SQL AG پشتیبانی‌شده می‌تواند پلتفرم دیتابیس بماند و برنامه کانتینری از Listener متصل شود.

### آیا HPA ماشین Worker جدید می‌سازد؟

خیر؛ HPA با Metrics تعداد Replica را عوض می‌کند. Provision و Autoscaling نود اتصال و مسئله ظرفیت جداست.

### آیا Labها کلاستر HA Production هستند؟

خیر؛ هر دو یک نود کنترل یا Manager دارند. انتشار و بازیابی Worker را توضیح می‌دهند و هنگام تهیه مقاله به‌صورت Lab سه‌VM اجرا نشده‌اند.

## ۲۰. منابع رسمی و مقاله‌های مرتبط Meet AJ

مستندات فنی در ۶ نوامبر ۲۰۲۶ بررسی شده‌اند. Lab عمداً شاخه تحت نگهداری 1.36 را انتخاب می‌کند، نه ادعای نصب آخرین انتشار. پیش از اجرا Candidate بسته، سازگاری Runtime و CNI و چرخه پشتیبانی را دوباره ببینید. API بومی، پیاده‌سازی نصب‌شده جدا و زیرساخت خارجی در متن تفکیک شده‌اند. دستورها Runbook مرجع هستند؛ بررسی Build و نمایش سایت، رفتار اجرای کلاستر را اثبات نمی‌کند.

[Swarm Mode رسمی Docker](https://docs.docker.com/engine/swarm/)

[مستندات Docker Compose](https://docs.docker.com/compose/)

[اجماع Raft در Swarm](https://docs.docker.com/engine/swarm/raft/)

[Service و سیاست Update در Swarm](https://docs.docker.com/engine/swarm/services/)

[معماری Kubernetes](https://kubernetes.io/docs/concepts/architecture/)

[Storage در Kubernetes](https://kubernetes.io/docs/concepts/storage/)

[نیازمندی NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)

[مدیریت کلاستر Kubernetes](https://kubernetes.io/docs/concepts/cluster-administration/)

[مستندات Availability در vSphere](https://techdocs.broadcom.com/us/en/vmware-cis/vsphere/vsphere/8-0/vsphere-availability-8-0.html)

[ماتریس سازگاری Calico](https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements)

[مرتبط: نصب و نگهداری GitLab](/articles/gitlab-installation-ubuntu-24)

[مرتبط: محیط Build در Maven](/articles/maven-installation-ubuntu-24)

[مرتبط: عملیات خط فرمان Linux](/articles/linux-cli-common-commands)

[مرتبط: مثال Docker Compose در Reverse Proxy](/articles/caddy-vs-nginx-web-server-reverse-proxy)

[مرتبط: Monitoring با Grafana و Zabbix](/articles/grafana-installation-zabbix-integration)

[مرتبط: بکاپ SQL Server](/articles/sql-server-automatic-backup-job)

[مرتبط: شبکه vSphere](/articles/vsphere-standard-switch-vs-distributed-switch)

[دانلود دستورهای انتشار Swarm؛ ابتدا بخوانید و مرحله‌ای اجرا کنید](/downloads/docker-swarm-vs-kubernetes-enterprise-guide/swarm-deploy.sh)

[دانلود Deployment، Service و PDB آزمایشگاه Kubernetes](/downloads/docker-swarm-vs-kubernetes-enterprise-guide/kubernetes-web.yaml)

[دانلود نسخه کامل فارسی Markdown](/downloads/docker-swarm-vs-kubernetes-enterprise-guide/article.fa.md)

[دانلود نسخه کامل انگلیسی Markdown](/downloads/docker-swarm-vs-kubernetes-enterprise-guide/article.en.md)
