لوگوی هاکان سرور
لوگوی هاکان سرور

کوبرنتیز چیست؟ معماری، تفاوت با داکر و آموزش نصب k3s روی سرور

سه نود کوبرنتیز، یک control-plane و دو worker، متصل به سرور؛ نمای ساده از کلاستر کوبرنتیز
فهرست مطالب
  1. کوبرنتیز چیست و چه مشکلی را حل می‌کند؟
  2. تفاوت داکر و کوبرنتیز
  3. معماری کوبرنتیز: لایهٔ کنترل و نودها
  4. مفاهیم اصلی کوبرنتیز
  5. انواع Service
  6. Ingress، Gateway API و پایان ingress-nginx
  7. Secret فقط base64 است
  8. آیا به کوبرنتیز نیاز دارید؟
  9. توزیع‌های کوبرنتیز: kubeadm، k3s، MicroK8s و k0s
  10. نصب k3s روی اوبونتو، گام‌به‌گام
  11. پیش‌نیازها و پورت‌ها
  12. گام ۱: تنظیمات و نصب k3s
  13. گام ۲: kubectl بدون sudo
  14. گام ۳: فایروال
  15. گام ۴: Deployment و Service
  16. گام ۵: انتشار با Ingress و Traefik
  17. گام ۶: مقیاس‌دهی، به‌روزرسانی و بازگشت
  18. گام ۷: افزودن نود کارگر
  19. حذف k3s
  20. دستورات پرکاربرد kubectl
  21. کوبرنتیز روی سرورهای داخل ایران
  22. میرور Docker Hub با registries.yaml
  23. نصب آفلاین k3s (Air-gap)
  24. رجیستری خصوصی یا نود خارج از ایران
  25. رفع خطاهای رایج کوبرنتیز
  26. امنیت و نگهداری کلاستر
  27. چرخهٔ پشتیبانی نسخه‌ها
  28. سرور مناسب برای کوبرنتیز
  29. پرسش‌های متداول
  30. کوبرنتیز به زبان ساده چیست؟
  31. تفاوت k3s و k8s چیست؟
  32. آیا کوبرنتیز رایگان است؟
  33. یادگیری کوبرنتیز را از کجا شروع کنم؟
  34. آیا کوبرنتیز جای داکر را می‌گیرد؟
  35. آیا کوبرنتیز روی سرور ایران نصب می‌شود؟
  36. جمع‌بندی

کوبرنتیز چیست؟ کوبرنتیز (Kubernetes یا K8s) نرم‌افزاری متن‌باز برای اجرا و مدیریت کانتینرها روی یک یا چند سرور است: شما می‌نویسید چه برنامه‌ای با چند نسخه اجرا شود و کوبرنتیز جای اجرا، ری‌استارت کانتینر خراب، توزیع بار و به‌روزرسانی بدون قطعی را خودکار انجام می‌دهد.

در این راهنما معماری کوبرنتیز و زمان نیاز به آن را می‌بینید و در بخش عملی، k3s را روی Ubuntu 24.04 نصب می‌کنید و یک برنامه را منتشر، به‌روز و بازگردانی می‌کنید. نکته‌های سرورهای داخل ایران بخش جداگانه‌ای دارد و دستورها در آبان ۱۴۰۵ با مستندات رسمی تطبیق داده شده‌اند.

به‌طور خلاصه: وضعیت مطلوب را (مثلاً «۳ نسخه از این ایمیج، پشت یک آدرس ثابت») در فایل YAML می‌نویسید و کوبرنتیز مدام وضعیت واقعی را به آن می‌رساند.

  • داکر ایمیج می‌سازد و کانتینر را روی یک سرور اجرا می‌کند؛ کوبرنتیز همان ایمیج‌ها را روی چند نود مدیریت می‌کند.
  • برای یک سایت یا اپ کوچک، Docker Compose روی یک سرور کافی است.
  • برای شروع روی سرور، k3s کم‌دردسر است؛ نود سرور آن طبق مستندات دست‌کم ۲ هستهٔ CPU و ۲ گیگابایت رم می‌خواهد.
  • روی سرور ایران حتی ایمیج‌های سیستمی k3s از Docker Hub می‌آیند؛ پیش از نصب، میرور یا نصب آفلاین را آماده کنید.

کوبرنتیز چیست و چه مشکلی را حل می‌کند؟

نام کوبرنتیز (که کوبرنتیس هم نوشته می‌شود) از واژه‌ای یونانی به معنای سکان‌دار است و K8s شکل کوتاه آن است: ۸ حرف بین K و s. گوگل آن را در ۲۰۱۴ متن‌باز کرد و امروز از پروژه‌های بالغ (Graduated) بنیاد CNCF است.

اجرای چند کانتینر روی یک سرور با داکر ساده است. مشکل از ده‌ها کانتینر روی چند سرور شروع می‌شود: هر کانتینر کجا اجرا شود، با خاموش شدن یک سرور چه شود، نسخهٔ جدید چطور بدون قطعی جایگزین شود و سرویس‌ها با IPهای متغیر چطور همدیگر را پیدا کنند. کوبرنتیز این کارها را خودکار می‌کند:

  • زمان‌بندی (Scheduling): هر کانتینر را بر اساس CPU و رمی که لازم دارد، روی سروری (نود) با ظرفیت کافی اجرا می‌کند.
  • خودترمیمی (Self-healing): کانتینر خراب را دوباره اجرا می‌کند و اگر نودی از دسترس خارج شود، به‌طور پیش‌فرض حدود ۵ دقیقه بعد کانتینرهایش را روی نودهای سالم می‌سازد.
  • مقیاس‌دهی (Scaling): تعداد نسخه‌ها را دستی یا خودکار بر اساس مصرف CPU تغییر می‌دهد.
  • به‌روزرسانی تدریجی و بازگشت (Rolling Update و Rollback): نسخهٔ جدید را کم‌کم جایگزین می‌کند و با یک دستور به نسخهٔ قبل برمی‌گردد.
  • کشف سرویس و توزیع بار: به هر گروه کانتینر نام DNS و IP ثابت می‌دهد و درخواست‌ها را بینشان پخش می‌کند.

کوبرنتیز پلتفرم کامل و آماده (PaaS) نیست: کد را build نمی‌کند (این کار CI/CD است)، دیتابیس آماده نمی‌دهد و ابزار لاگ و مانیتورینگ را خودتان انتخاب می‌کنید.

تفاوت داکر و کوبرنتیز

داکر (Docker) ایمیج می‌سازد و کانتینر را روی یک سرور اجرا می‌کند و Docker Compose چند کانتینر مرتبط را روی همان سرور بالا می‌آورد. کوبرنتیز همان ایمیج‌ها را روی یک کلاستر (Cluster)، یعنی گروهی از سرورها، اجرا و مدیریت می‌کند؛ پس رقیب نیستند و معمولاً ایمیج با داکر ساخته و با کوبرنتیز اجرا می‌شود. برای چند سرور، حالت Swarm خود Docker Engine هم هست که ساده‌تر است، اما امکانات کمتری دارد. نصب داکر و Compose در آموزش نصب داکر روی اوبونتو آمده است.

آموزش‌های قدیمی این نکته را ندارند: کوبرنتیز کانتینر را با یک محیط اجرای سازگار با رابط CRI (Container Runtime Interface)، معمولاً containerd یا CRI-O، اجرا می‌کند و اتصال مستقیمش به Docker Engine (به نام dockershim) از نسخهٔ 1.24 در سال ۲۰۲۲ حذف شده است. ایمیج‌های داکر استاندارد OCI هستند و بدون تغییر روی کوبرنتیز اجرا می‌شوند.

ویژگی Docker Compose کوبرنتیز
خرابی کانتینر ری‌استارت با restart policy ری‌استارت خودکار و جایگزینی پاد ازدست‌رفته
خرابی سرور همه‌چیز متوقف می‌شود پادها روی نودهای سالم دیگر ساخته می‌شوند
به‌روزرسانی معمولاً با قطعی کوتاه تدریجی، با بازگشت یک‌دستوری

معماری کوبرنتیز: لایهٔ کنترل و نودها

هر کلاستر یک لایهٔ کنترل (Control Plane) دارد که تصمیم می‌گیرد و نودهای کارگر (Worker Node) که کانتینرها را اجرا می‌کنند. در کلاستر کوچک هر دو روی یک سرورند و k3s روی نود سرور هم برنامه اجرا می‌کند.

جزء محل وظیفه
kube-apiserver لایهٔ کنترل درِ ورود کلاستر؛ همهٔ درخواست‌ها از API آن می‌گذرند
etcd لایهٔ کنترل پایگاه‌دادهٔ وضعیت کلاستر (در k3s تک‌سرور: SQLite)
kube-scheduler لایهٔ کنترل انتخاب نود برای پادهای تازه
kube-controller-manager لایهٔ کنترل کنترلرهایی که وضعیت را به حالت مطلوب می‌رسانند
kubelet هر نود اجرا و پایش پادهای نود
kube-proxy هر نود، اختیاری قانون‌های شبکه برای Service
Container Runtime هر نود اجرای کانتینر، مثلاً containerd

افزونهٔ شبکه (CNI) مثل Flannel به پادها IP می‌دهد و CoreDNS نام سرویس‌ها را ترجمه می‌کند. با kubectl apply، شیء در etcd ذخیره می‌شود، کنترلرها پادها را تعریف می‌کنند، scheduler نود را برمی‌گزیند و kubelet کانتینر را اجرا می‌کند.

مفاهیم اصلی کوبرنتیز

هر چیزی در کوبرنتیز یک شیء (Object) است که در YAML تعریف می‌شود:

شیء کاربرد مثال
Pod کوچک‌ترین واحد اجرا؛ یک یا چند کانتینر با IP مشترک یک کانتینر وب
Deployment و ReplicaSet تعداد ثابتی پاد یکسان، با به‌روزرسانی تدریجی و بازگشت اپ بدون حالت
StatefulSet پادهایی با نام و دیسک ثابت دیتابیس
DaemonSet یک پاد روی هر نود جمع‌آوری لاگ
Job و CronJob کار یک‌باره یا زمان‌بندی‌شده بکاپ شبانه
Service IP و نام DNS ثابت جلوی پادها web.default.svc.cluster.local
Ingress مسیریابی HTTP بر اساس دامنه و مسیر app.example.com
ConfigMap و Secret تنظیمات و اطلاعات حساس، بیرون از ایمیج رمز دیتابیس
Namespace جداسازی منطقی منابع dev و prod
PV و PVC فضای ذخیرهٔ ماندگار و درخواست آن ۱۰ گیگابایت دیسک

پادها موقتی‌اند و هر پاد تازه IP تازه می‌گیرد؛ برای همین پاد را با Deployment می‌سازید و با Service به آن وصل می‌شوید. Service پادها را با برچسب (Label) پیدا می‌کند: هر پادی که برچسب‌های انتخابگرش (Selector) را داشته باشد.

انواع Service

  • ClusterIP (پیش‌فرض): فقط از داخل کلاستر در دسترس است؛ مثلاً برای اتصال اپ به دیتابیس.
  • NodePort: پورتی ثابت روی همهٔ نودها، به‌طور پیش‌فرض از بازهٔ 30000 تا 32767.
  • LoadBalancer: انتشار با لود بالانسر بیرونی که خود کوبرنتیز ندارد؛ در ابرها لود بالانسر ارائه‌دهنده و در k3s، ServiceLB با پورت‌های خود نودها این کار را می‌کند.

Ingress، Gateway API و پایان ingress-nginx

Ingress درخواست‌های HTTP را بر اساس دامنه و مسیر به Serviceها می‌فرستد و بدون Ingress Controller کاری نمی‌کند؛ k3s کنترلر Traefik را خودش نصب می‌کند. در زمان نگارش این مطلب (آبان ۱۴۰۵) دو تغییر مهم است:

  • API مربوط به Ingress منجمد شده است: حذف نمی‌شود، اما امکان تازه‌ای هم نمی‌گیرد. جانشین پیشنهادی Gateway API است که از ۲۰۲۳ نسخهٔ پایدار v1 دارد و با منابعی مثل Gateway و HTTPRoute کار می‌کند. Gateway API افزونه‌ای جداست؛ Traefik همراه k3s از آن پشتیبانی می‌کند، اما به‌طور پیش‌فرض خاموش است.
  • ingress-nginx بازنشسته شد: طبق اعلام رسمی کوبرنتیز، این کنترلر محبوب از مارس ۲۰۲۶ نسخهٔ جدید، رفع باگ و وصلهٔ امنیتی نمی‌گیرد و مخزنش فقط‌خواندنی است. نصب‌های موجود کار می‌کنند، اما توصیهٔ رسمی مهاجرت به Gateway API یا کنترلری دیگر است. NGINX Ingress Controller شرکت F5 پروژهٔ جدایی است و همچنان به‌روز می‌شود. بررسی استفاده:
    kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx

Secret فقط base64 است

base64 رمزنگاری نیست و با base64 -d برمی‌گردد. طبق مستندات کوبرنتیز، Secretها به‌طور پیش‌فرض رمزنشده در etcd ذخیره می‌شوند و هر کس اجازهٔ ساخت پاد در یک Namespace را داشته باشد، عملاً Secretهای آن را هم می‌خواند. رمزنگاری در حالت ذخیره (Encryption at Rest) را روشن کنید (در k3s در گام ۱ بخش عملی)، دسترسی‌ها را با RBAC (کنترل دسترسی بر اساس نقش) محدود کنید و Secret را در گیت نگذارید.

آیا به کوبرنتیز نیاز دارید؟

منصفانه بگوییم: بیشتر سایت‌ها و اپ‌های کوچک و متوسط به آن نیاز ندارند. یک سایت وردپرسی، یک API با دیتابیسش یا یک ربات، با Docker Compose روی یک سرور مجازی ساده‌تر و کم‌هزینه‌تر اجرا می‌شود. کوبرنتیز سربار دارد: لایهٔ کنترل خودش منابع می‌خواهد، یادگیری‌اش زمان می‌برد و کلاستر دست‌کم سالی یک بار ارتقا می‌خواهد.

وضعیت شما پیشنهاد
یک سایت یا اپ با دیتابیس Docker Compose روی یک سرور
چند سرویس روی یک سرور Compose، یا k3s تک‌نود برای یادگیری
چند سرویس و چند توسعه‌دهنده با استقرار مکرر کوبرنتیز (k3s یا kubeadm)
تحمل خرابی یک سرور دست‌کم ۳ نود سرور
نمی‌خواهید کلاستر نگه دارید سرویس کانتینری مدیریت‌شده (PaaS)

کلاستر تک‌نود دسترس‌پذیری بالا (HA) نمی‌دهد و حالت HA در k3s با etcd داخلی، تعداد فردی نود سرور می‌خواهد. برای شروع، دیتابیس اصلی را بیرون از کلاستر نگه دارید. کوبرنتیز مدیریت‌شدهٔ ابرهای خارجی هم معمولاً به دلیل تحریم برای کاربران ایرانی در دسترس نیست.

توزیع‌های کوبرنتیز: kubeadm، k3s، MicroK8s و k0s

هر چهار توزیع زیر کوبرنتیز استاندارد اجرا می‌کنند و فرقشان در بسته‌بندی، پیش‌فرض‌ها و منابع است. حداقل منابع از مستندات رسمی هر پروژه است و مصرف برنامه‌ها جداست:

توزیع ویژگی حداقل منابع مناسب برای
kubeadm ابزار رسمی پروژه؛ runtime و شبکه جدا نصب می‌شوند ۲ گیگابایت رم هر نود؛ ۲ هسته برای لایهٔ کنترل کلاستر استاندارد
k3s یک فایل اجرایی زیر ۱۰۰ مگابایت با Traefik و ServiceLB سرور ۲ هسته و ۲ گیگابایت؛ کارگر ۱ هسته و ۵۱۲ مگابایت سرور مجازی و کلاستر کوچک
MicroK8s بستهٔ snap شرکت Canonical از ۵۴۰ مگابایت؛ پیشنهادی ۴ گیگابایت رم اوبونتو و محیط توسعه
k0s یک فایل اجرایی بدون وابستگی، از Mirantis کنترلر ۱ گیگابایت؛ کارگر ۰٫۵ گیگابایت کلاستر چندنودی با k0sctl

برای تمرین روی لپ‌تاپ kind و minikube کافی‌اند و برای سرور مجازی، k3s معمولاً کم‌دردسرتر است.

نصب k3s روی اوبونتو، گام‌به‌گام

در این بخش یک کلاستر تک‌نود k3s روی Ubuntu 24.04 می‌سازید، برنامه‌ای منتشر می‌کنید و در پایان یک نود کارگر اضافه می‌کنید. طبق جدول پشتیبانی k3s 1.36 در سایت SUSE، Ubuntu 22.04 و 26.04 هم آزموده شده‌اند.

پیش‌نیازها و پورت‌ها

  • سروری با Ubuntu 24.04 و مجازی‌سازی کامل مثل KVM؛ روی OpenVZ و LXC ممکن است اجرا نشود. نود سرور طبق مستندات دست‌کم ۲ هسته و ۲ گیگابایت رم و ترجیحاً دیسک SSD می‌خواهد؛ برای تمرین، یک سرور لینوکس با ۴ گیگابایت رم راحت‌تر است.
  • hostname یکتا برای هر نود و دسترسی SSH با کاربر دارای sudo (آموزش اتصال به سرور لینوکسی از طریق SSH).
  • اگر Nginx یا Apache خود سرور روی پورت‌های 80 و 443 کار می‌کند، Traefik همراه k3s این دو پورت را بی‌صدا از آن می‌گیرد (جدول رفع خطاها).
پورت جهت کاربرد
6443/tcp کارگرها و kubectl به سرور API کوبرنتیز
8472/udp بین نودها Flannel با VXLAN (پیش‌فرض)
51820/udp بین نودها Flannel با WireGuard
10250/tcp بین نودها kubelet
2379-2380/tcp بین سرورها etcd در حالت HA
80 و 443/tcp اینترنت به نودها Traefik

هشدار: طبق مستندات k3s، پورت 8472/udp نباید روی اینترنت باز باشد، چون شبکهٔ داخلی کلاستر را در دسترس همه می‌گذارد؛ 6443 را هم فقط برای IP نودها باز کنید. اگر سرور در ایران است، اول آزمون دسترسی بخش «کوبرنتیز روی سرورهای داخل ایران» را اجرا کنید.

گام ۱: تنظیمات و نصب k3s

k3s تنظیمات را از /etc/rancher/k3s/config.yaml می‌خواند و این فایل، برخلاف پارامترهای دستور نصب، در ارتقاها حفظ می‌شود. این تنظیم رمزنگاری Secretها را از اول روشن می‌کند:

sudo mkdir -p /etc/rancher/k3s
sudo tee /etc/rancher/k3s/config.yaml > /dev/null <<'EOF'
secrets-encryption: true
EOF

اگر نودهای بعدی از راه اینترنت عمومی وصل می‌شوند، خط flannel-backend: wireguard-native را هم اضافه کنید تا ترافیک بین نودها رمزنگاری شود. این گزینه فقط روی نود سرور تنظیم می‌شود، پس از اول تصمیم بگیرید؛ ماژول کرنل WireGuard هم باید روی همهٔ نودها باشد (آزمون: sudo modprobe wireguard بدون خطا). برای سرور ایران، فایل میرور Docker Hub را هم بسازید:

sudo mkdir -p /etc/rancher/k3s
sudo tee /etc/rancher/k3s/registries.yaml > /dev/null <<'EOF'
mirrors:
  docker.io:
    endpoint:
      - "https://docker.arvancloud.ir"
EOF

حالا اسکریپت رسمی را اجرا کنید؛ بدون تعیین نسخه، آخرین نسخهٔ کانال stable نصب می‌شود که در زمان نگارش این مطلب (آبان ۱۴۰۵) v1.36.5+k3s1، یعنی کوبرنتیز 1.36، است:

curl -sfL https://get.k3s.io | sh -

اسکریپت /usr/local/bin/k3s، سرویس k3s، ابزارهای kubectl، crictl و ctr (اگر از قبل نباشند) و اسکریپت حذف را نصب می‌کند. یکی دو دقیقه بعد:

sudo systemctl is-active k3s
sudo kubectl get nodes
sudo kubectl get pods -A
sudo k3s secrets-encrypt status

خروجی اول active است و دومی شبیه این نمونه:

NAME    STATUS   ROLES           AGE   VERSION
k3s-1   Ready    control-plane   90s   v1.36.5+k3s1

پادهای coredns، local-path-provisioner، metrics-server، traefik و svclb-traefik باید Running و پادهای helm-install در وضعیت Completed باشند و دستور آخر Encryption Status: Enabled نشان دهد. اگر kubectl دیگری از قبل دارید، بنویسید sudo k3s kubectl.

گام ۲: kubectl بدون sudo

فایل دسترسی کلاستر (kubeconfig) در /etc/rancher/k3s/k3s.yaml با مجوز 600 است و دسترسی کامل مدیر می‌دهد. برای کاربر عادی نسخهٔ شخصی بسازید و KUBECONFIG را تنظیم کنید، چون kubectl همراه k3s بدون آن سراغ فایل /etc می‌رود:

mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
chmod 600 ~/.kube/config
echo 'export KUBECONFIG=$HOME/.kube/config' >> ~/.bashrc
source ~/.bashrc
kubectl get nodes

سراغ chmod 644 روی k3s.yaml نروید؛ دسترسی مدیر را به همهٔ کاربران سرور می‌دهد. k3s گواهی‌های فایل اصلی را به‌روز می‌کند، اما نسخهٔ کپی به‌روز نمی‌شود؛ اگر بعدها خطای گواهی دیدید، کپی را تکرار کنید. با root این گام لازم نیست.

گام ۳: فایروال

مستندات k3s خاموش کردن UFW را پیشنهاد می‌کند و اگر روشن بماند، باز کردن 6443/tcp و مجاز کردن شبکهٔ پادها (10.42.0.0/16) و سرویس‌ها (10.43.0.0/16) را. روشن ماندن UFW امن‌تر است، چون پورت‌های خود سرور مثل 6443، 10250 و 8472 را از اینترنت می‌بندد. در این راهنما 6443 باز نمی‌شود و kubectl از بیرون با تونل SSH وصل می‌شود:

sudo ufw allow OpenSSH
sudo ufw allow from 10.42.0.0/16 to any
sudo ufw allow from 10.43.0.0/16 to any
sudo ufw enable
sudo ufw status

پورت‌های 80 و 443 قانون UFW لازم ندارند، چون ServiceLB ترافیک آن‌ها را پیش از قانون‌های ورودی UFW با NAT به Traefik می‌رساند (بخش امنیت). اگر پورت SSH را عوض کرده‌اید، پیش از enable آن را باز کنید. مبانی UFW در فعال‌سازی فایروال در لینوکس آمده است.

گام ۴: Deployment و Service

برنامهٔ نمونه traefik/whoami است که نام پاد پاسخ‌دهنده را برمی‌گرداند:

cat > app.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: whoami
          image: traefik/whoami:v1.11.0
          ports:
            - containerPort: 80
          readinessProbe:
            httpGet:
              path: /health
              port: 80
          resources:
            requests:
              cpu: 50m
              memory: 32Mi
            limits:
              memory: 64Mi
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80
EOF
kubectl apply -f app.yaml
kubectl get pods -o wide
kubectl get svc web
  • selector.matchLabels باید با labels قالب پاد یکی باشد و selector سرویس هم همین برچسب را پیدا می‌کند؛ ناهمخوانی‌شان خطای رایجی است.
  • readinessProbe پاد را تا پاسخ 200 از /health در توزیع بار نمی‌گذارد.
  • requests سهم رزروشده برای زمان‌بندی است و limits سقف مصرف؛ پادی که از سقف رم بگذرد OOMKilled می‌شود.
  • تگ نسخه را صریح بنویسید، نه latest.

دو پاد web باید 1/1 و Running باشند. Service از نوع ClusterIP فقط از داخل کلاستر و خود نودها در دسترس است؛ روی سرور امتحان کنید:

CIP=$(kubectl get svc web -o jsonpath='{.spec.clusterIP}')
for i in 1 2 3 4 5 6; do curl -s "http://$CIP/" | grep Hostname; done

معمولاً نام هر دو پاد را می‌بینید، چون Service هر درخواست را تصادفی به یکی از پادهای آماده می‌دهد.

گام ۵: انتشار با Ingress و Traefik

cat > ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  ingressClassName: traefik
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80
EOF
kubectl apply -f ingress.yaml
kubectl get ingress web

به‌جای app.example.com دامنهٔ خودتان را بنویسید؛ جلوی ADDRESS باید IP سرور بیاید. پیش از تنظیم DNS، از کامپیوتر خودتان امتحان کنید (در PowerShell بنویسید curl.exe):

curl -H "Host: app.example.com" http://SERVER_IP/

پاسخ باید Hostname یکی از پادها را نشان دهد. پاسخ 404 page not found از خود Traefik است و یعنی هیچ Ingressی با این Host جور نشد. بعد از تنظیم رکورد A، آدرس در مرورگر باز می‌شود. برای HTTPS معتبر معمولاً cert-manager با Let’s Encrypt نصب می‌شود (مثلاً با Helm، مدیر بستهٔ کوبرنتیز)؛ تا آن موقع Traefik روی 443 گواهی پیش‌فرضی را نشان می‌دهد که خودش ساخته و مرورگر به آن اعتماد نمی‌کند.

گام ۶: مقیاس‌دهی، به‌روزرسانی و بازگشت

kubectl scale deployment/web --replicas=4
kubectl set image deployment/web whoami=traefik/whoami:v1.12.0
kubectl rollout status deployment/web
kubectl get deployment web -o wide
kubectl rollout history deployment/web
kubectl rollout undo deployment/web

set image به‌روزرسانی تدریجی را شروع می‌کند. پیش‌فرض Deployment حداکثر ۲۵ درصد پاد اضافه و ۲۵ درصد پاد ناموجود است، پس با readinessProbe سرویس معمولاً قطع نمی‌شود. ستون IMAGES نسخهٔ فعلی را نشان می‌دهد و undo به v1.11.0 برمی‌گردد؛ کوبرنتیز به‌طور پیش‌فرض ۱۰ نسخهٔ قبلی را نگه می‌دارد.

نکته: scale و set image فقط کلاستر را عوض می‌کنند و kubectl apply -f app.yaml بعدی، تعداد و نسخه را به مقدار فایل برمی‌گرداند. در کار واقعی فایل را تغییر دهید، در گیت نگه دارید و apply کنید.

گام ۷: افزودن نود کارگر

سرور دوم را با hostname متفاوت در همان لوکیشن آماده کنید (sudo hostnamectl set-hostname k3s-2). روی سرور اول توکن را بخوانید و نود جدید را در فایروال مجاز کنید:

sudo cat /var/lib/rancher/k3s/server/node-token
sudo ufw allow from WORKER_IP

روی نود جدید (برای سرور ایران، اول registries.yaml گام ۱ را بسازید):

sudo ufw allow OpenSSH
sudo ufw allow from SERVER_IP
sudo ufw allow from 10.42.0.0/16 to any
sudo ufw allow from 10.43.0.0/16 to any
sudo ufw enable
curl -sfL https://get.k3s.io | K3S_URL=https://SERVER_IP:6443 K3S_TOKEN=PASTE_NODE_TOKEN sh -

با K3S_URL، اسکریپت سرویس k3s-agent را نصب می‌کند. kubectl get nodes روی سرور اول نود جدید را با ROLES برابر <none> و وضعیت Ready نشان می‌دهد.

هشدار: طبق مستندات k3s، هر کس توکن سرور را داشته باشد عملاً مدیر کلاستر است؛ آن را در اسکریپت یا گیت نگذارید. ترافیک بین نودها هم بدون wireguard-native گام ۱ رمزنگاری نمی‌شود.

حذف k3s

اسکریپت حذف، k3s، پادها، پایگاه‌دادهٔ کلاستر و داده‌های local-path را پاک می‌کند:

# on a server node
sudo /usr/local/bin/k3s-uninstall.sh
# on a worker (agent) node
sudo /usr/local/bin/k3s-agent-uninstall.sh

دستورات پرکاربرد kubectl

دستور کاربرد
kubectl get pods -A پادهای همهٔ Namespaceها
kubectl describe pod NAME جزئیات و رویدادها؛ اولین قدم عیب‌یابی
kubectl logs NAME --previous لاگ اجرای قبلی کانتینر ری‌استارت‌شده
kubectl exec -it NAME -- sh شل داخل کانتینر (اگر ایمیج شل دارد)
kubectl get events --sort-by=.metadata.creationTimestamp رویدادهای اخیر به ترتیب زمان
kubectl port-forward svc/web 8080:80 دسترسی موقت محلی به سرویس
kubectl top nodes مصرف CPU و رم نودها
kubectl delete -f app.yaml حذف منابع تعریف‌شده در فایل

کوبرنتیز روی سرورهای داخل ایران

Docker Hub آی‌پی‌های ایران را به استناد مقررات صادرات آمریکا مسدود می‌کند و این در کوبرنتیز دو اثر دارد: ایمیج بدون نام رجیستری از docker.io گرفته می‌شود و ایمیج‌های سیستمی خود k3s، از pause و coredns تا traefik، هم در docker.io/rancher هستند (فهرستشان در k3s-images.txt هر نسخه). پس بدون آمادگی، حتی اگر نصب تمام شود، پادهای سیستمی در ContainerCreating یا ImagePullBackOff می‌مانند.

ایمیج‌های رسمی کوبرنتیز (مثلاً برای kubeadm) روی registry.k8s.io هستند که ترافیک را به Google Cloud و AWS می‌فرستد و خیلی از ابزارها از ghcr.io و quay.io می‌آیند؛ دسترسی سرورهای ایران به این‌ها و به GitHub همیشه برقرار نیست. پیش از نصب بسنجید:

for u in https://get.k3s.io https://update.k3s.io/v1-release/channels \
  https://github.com/k3s-io/k3s/releases https://registry-1.docker.io/v2/ \
  https://docker.arvancloud.ir/v2/ https://registry.k8s.io/v2/ \
  https://ghcr.io/v2/ https://quay.io/v2/; do
  echo "$(curl -s -o /dev/null -m 10 -w '%{http_code}' "$u") $u"
done

کد 200 یا 401 یعنی در دسترس (401 برای رجیستری‌ها عادی است)، 403 یعنی مسدود و 000 یعنی تا ۱۰ ثانیه اتصالی برقرار نشد. اسکریپت نصب از update.k3s.io نسخه را می‌پرسد و فایل را از GitHub می‌گیرد.

میرور Docker Hub با registries.yaml

اگر سه نشانی اول باز است و Docker Hub نه، فایل registries.yaml گام ۱ کافی است: k3s آن را هنگام راه‌اندازی می‌خواند و containerd درخواست‌های docker.io را اول به میرور می‌فرستد. چند شرکت ایرانی میرور عمومی Docker Hub دارند. نمونهٔ شناخته‌شده‌اش میرور آروان‌کلاد با آدرس https://docker.arvancloud.ir است که در زمان نگارش این مطلب (آبان ۱۴۰۵) به درخواست ایمیج‌های rancher و traefik/whoami پاسخ می‌داد؛ وضعیت امروزش را با آزمون بالا بسنجید.

  • فایل را روی همهٔ نودها بسازید و اگر k3s نصب است، سرویس k3s یا k3s-agent را ری‌استارت کنید. آزمون: sudo k3s crictl pull traefik/whoami:v1.11.0.
  • containerd در آخر خود docker.io را هم امتحان می‌کند، پس خطای kubectl ممکن است 403 خود Docker Hub را نشان دهد حتی وقتی مشکل از میرور است؛ علت واقعی در /var/lib/rancher/k3s/agent/containerd/containerd.log نودی است که پاد رویش است.
  • این تنظیم فقط docker.io را پوشش می‌دهد. میرور واسطهٔ شخص ثالث است؛ فقط ایمیج رسمی با تگ مشخص بگیرید.

نصب آفلاین k3s (Air-gap)

اگر get.k3s.io یا GitHub باز نمی‌شود، فایل‌ها را روی سیستمی با دسترسی، مثلاً سرور لینوکسی خارج از ایران، بگیرید و منتقل کنید. با بستهٔ ایمیج‌های سیستمی، k3s برای اجزای خودش به Docker Hub نیاز ندارد. دستورها برای پردازندهٔ amd64 است. مقدار V را با نسخهٔ کانال stable در https://update.k3s.io/v1-release/channels یکی کنید (به‌جای + بنویسید %2B) و فایل‌های گام ۱ را پیش از اجرای install.sh بسازید:

# On a machine with internet access
V=v1.36.5%2Bk3s1
curl -LO https://github.com/k3s-io/k3s/releases/download/$V/k3s
curl -LO https://github.com/k3s-io/k3s/releases/download/$V/k3s-airgap-images-amd64.tar.zst
curl -LO https://github.com/k3s-io/k3s/releases/download/$V/sha256sum-amd64.txt
curl -Lo install.sh https://get.k3s.io
scp k3s k3s-airgap-images-amd64.tar.zst sha256sum-amd64.txt install.sh user@SERVER_IP:~/

# On the server
cd ~
grep -E ' (k3s|k3s-airgap-images-amd64.tar.zst)$' sha256sum-amd64.txt | sha256sum -c -
sudo mkdir -p /var/lib/rancher/k3s/agent/images/
sudo cp k3s-airgap-images-amd64.tar.zst /var/lib/rancher/k3s/agent/images/
sudo install -m 755 k3s /usr/local/bin/k3s
chmod +x install.sh
INSTALL_K3S_SKIP_DOWNLOAD=true ./install.sh

چک‌سام باید برای هر دو فایل OK بدهد. برای نود کارگر همین فایل‌ها را منتقل و دستور آخر را با K3S_URL و K3S_TOKEN اجرا کنید. ارتقا در این روش دستی است: فایل‌های نسخهٔ جدید را جایگزین و اسکریپت را دوباره اجرا کنید. ایمیج برنامه‌ها را هم می‌توانید جای دیگر با docker save ذخیره و روی نود با sudo k3s ctr images import وارد کنید.

رجیستری خصوصی یا نود خارج از ایران

برای تیم‌ها راه پایدارتر رجیستری خصوصی است که ایمیج‌های لازم را نگه می‌دارد و در registries.yaml به‌عنوان میرور docker.io، ghcr.io یا registry.k8s.io معرفی می‌شود. اگر کاربران بیشتر خارج از ایران‌اند یا کارتان مدام به GitHub وابسته است، نودها را روی سرور مجازی خارجی بگذارید.

رفع خطاهای رایج کوبرنتیز

اول kubectl describe pod NAME را بزنید و بخش Events انتهای خروجی را بخوانید.

نشانه علت محتمل راه‌حل
ImagePullBackOff با 403 رجیستری IP ایران را نمی‌پذیرد میرور یا نصب آفلاین
ImagePullBackOff با not found نام یا تگ ایمیج اشتباه بررسی تگ در رجیستری
ImagePullBackOff با 429 سقف دریافت Docker Hub ورود به حساب یا میرور
CrashLoopBackOff برنامه پس از شروع خارج می‌شود kubectl logs NAME --previous
OOMKilled مصرف رم بیشتر از limits افزایش limits یا رفع نشت حافظه
Pending با Insufficient cpu یا memory منابع آزاد کمتر از requests کم کردن requests یا افزودن منابع
سایت Nginx یا Apache خود سرور بعد از نصب k3s، 404 page not found می‌دهد ServiceLB پورت‌های 80 و 443 را با NAT به Traefik داده است خط disable: traefik در config.yaml و ری‌استارت k3s، یا انتقال سایت به کلاستر
نود NotReady k3s-agent متوقف یا فایروال بین نودها sudo journalctl -u k3s-agent و جدول پورت‌ها
404 page not found Host درخواست با Ingress جور نیست بررسی host و ingressClassName
permission denied روی k3s.yaml KUBECONFIG تنظیم نشده گام ۲

کوبرنتیز دریافت ایمیج و ری‌استارت کانتینر خراب را با فاصلهٔ رو به افزایش، تا سقف ۵ دقیقه، تکرار می‌کند؛ بعد از رفع علت، صبر کنید یا پاد را حذف کنید تا پاد تازه ساخته شود.

امنیت و نگهداری کلاستر

  • API را عمومی نکنید. برای kubectl روی کامپیوتر خودتان، kubeconfig گام ۲ را کپی کنید (با root، خود /etc/rancher/k3s/k3s.yaml را) و تونل SSH بزنید؛ آدرس داخل فایل https://127.0.0.1:6443 است و بدون تغییر کار می‌کند. نسخهٔ kubectl شما حداکثر یک نسخهٔ فرعی با سرور فاصله داشته باشد:
    mkdir -p ~/.kube
    scp user@SERVER_IP:.kube/config ~/.kube/k3s-server.yaml
    chmod 600 ~/.kube/k3s-server.yaml
    ssh -N -L 6443:127.0.0.1:6443 user@SERVER_IP
    # in a second terminal
    export KUBECONFIG=~/.kube/k3s-server.yaml
    kubectl get nodes
  • کمترین دسترسی با RBAC. k3s.yaml را به CI، برنامه‌ها یا هم‌تیمی‌ها ندهید؛ برای هر کدام یک ServiceAccount با Role محدود به Namespace خودش بسازید.
  • NodePort برای سرویس داخلی نه. مثل پورت‌های منتشرشدهٔ داکر، ترافیک NodePort و LoadBalancer با قانون‌های NAT پیش از قانون‌های ورودی UFW هدایت می‌شود و ufw deny معمولاً جلویش را نمی‌گیرد. سرویس داخلی را ClusterIP نگه دارید و ارتباط پادها را با NetworkPolicy، که k3s پشتیبانی می‌کند، محدود کنید.
  • بکاپ. در k3s تک‌سرور، پوشهٔ /var/lib/rancher/k3s/server/db/ را همراه فایل /var/lib/rancher/k3s/server/token نگه دارید؛ بدون توکن، بکاپ بازگردانی نمی‌شود. PVها و دیتابیس‌ها بکاپ جدا می‌خواهند؛ داده‌های StorageClass پیش‌فرض k3s (local-path) روی دیسک همان نود، زیر /var/lib/rancher/k3s/storage، ذخیره می‌شود و پاد را به همان نود می‌بندد.
  • ارتقا. اسکریپت نصب را با همان متغیرهای نصب اول دوباره اجرا کنید؛ روی کارگرها بدون K3S_URL و K3S_TOKEN، اسکریپت به‌جای کارگر یک سرور تازه نصب می‌کند. اول سرورها یکی‌یکی و بعد کارگرها را ارتقا دهید و از روی نسخهٔ فرعی نپرید (از 1.35 مستقیم به 1.37 نروید)؛ با کانال هر نسخه گام‌به‌گام بروید:
    curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=v1.37 sh -

چرخهٔ پشتیبانی نسخه‌ها

کوبرنتیز تقریباً سالی ۳ نسخهٔ فرعی می‌دهد و هر نسخه حدود ۱۴ ماه وصله می‌گیرد (۱۲ ماه عادی و ۲ ماه نگهداری). در زمان نگارش این مطلب (آبان ۱۴۰۵)، طبق صفحهٔ انتشارهای کوبرنتیز این سه نسخه پشتیبانی می‌شوند و پشتیبانی 1.34 در ۵ آبان ۱۴۰۵ تمام شد:

نسخه پایان پشتیبانی
1.37 ۶ آبان ۱۴۰۶ (۲۸ اکتبر ۲۰۲۷)
1.36 ۷ تیر ۱۴۰۶ (۲۸ ژوئن ۲۰۲۷)
1.35 ۹ اسفند ۱۴۰۵ (۲۸ فوریهٔ ۲۰۲۷)

سرور مناسب برای کوبرنتیز

برای یادگیری و کلاستر کوچک k3s، سرور مجازی لینوکس با ۲ هسته و ۲ تا ۴ گیگابایت رم کافی است. هاکان سرور، سرور مجازی را در ۵۲ لوکیشن ارائه می‌کند؛ در صفحهٔ خرید سرور مجازی لوکیشن نزدیک به کاربرانتان را انتخاب کنید و همهٔ نودهای یک کلاستر را در یک لوکیشن بگیرید.

با یک نود شروع کنید؛ ارتقای منابع سرویس با ثبت تیکت انجام می‌شود. IP سرویس تا زمانی که سرویس تمدید شود ثابت می‌ماند، پس K3S_URL و قانون‌های فایروال دست نمی‌خورند. برای کلاستر بزرگ‌تر خرید سرور اختصاصی را ببینید؛ سرور اختصاصی هاکان با لینوکس، ویندوز یا هر پلتفرم مجازی‌سازی دلخواه تحویل داده می‌شود و می‌توانید چند ماشین مجازی روی آن را نود کلاستر کنید؛ فقط خرابی همان سخت‌افزار همهٔ این نودها را با هم از کار می‌اندازد.

پرسش‌های متداول

کوبرنتیز به زبان ساده چیست؟

سیستمی که کانتینرهای شما را روی چند سرور اجرا و سالم نگه می‌دارد و جای اجرا، ری‌استارت، توزیع بار و به‌روزرسانی را خودش مدیریت می‌کند.

تفاوت k3s و k8s چیست؟

k3s خودِ کوبرنتیز است در قالب توزیعی سبک: اجزا در یک فایل اجرایی جمع شده‌اند و در حالت تک‌سرور به‌جای etcd از SQLite استفاده می‌شود. فایل‌های YAML و دستورهای kubectl همان‌اند.

آیا کوبرنتیز رایگان است؟

بله؛ کوبرنتیز و k3s متن‌باز و با مجوز Apache 2.0 هستند. هزینهٔ واقعی سرورها و زمان نگهداری کلاستر است.

یادگیری کوبرنتیز را از کجا شروع کنم؟

اول داکر و ساخت ایمیج را یاد بگیرید، بعد Pod، Deployment، Service و Ingress را با kind یا minikube روی لپ‌تاپ یا k3s روی یک سرور مجازی تمرین کنید.

آیا کوبرنتیز جای داکر را می‌گیرد؟

نه. داکر برای ساخت ایمیج و اجرای محلی رایج می‌ماند و کوبرنتیز همان ایمیج‌ها را روی کلاستر اجرا می‌کند؛ فقط روی نودها به‌جای Docker Engine، containerd کانتینرها را اجرا می‌کند.

آیا کوبرنتیز روی سرور ایران نصب می‌شود؟

بله، اما چون Docker Hub آی‌پی‌های ایران را مسدود می‌کند، پیش از نصب میرور را در registries.yaml تنظیم کنید و اگر GitHub هم باز نیست، k3s را آفلاین نصب کنید.

جمع‌بندی

کوبرنتیز اجرای کانتینرها روی چند سرور را خودکار می‌کند، اما سربار دارد؛ برای یک سایت یا اپ کوچک Docker Compose کافی است و کوبرنتیز وقتی می‌ارزد که چند سرویس، چند سرور و چند نفر درگیر باشند. از روز اول Secretها، پورت 6443، شبکهٔ بین نودها و ارتقای منظم را جدی بگیرید.

قدم بعدی: k3s را روی یک سرور آزمایشی نصب کنید، برنامهٔ نمونه را منتشر، به‌روز و بازگردانی کنید و بعد یکی از سرویس‌های خودتان را با YAML تعریف کنید. جزئیات در مستندات مفاهیم کوبرنتیز و مستندات k3s آمده است.