بلاگ/راه‌اندازی HashiCorp Consul برای Service Discovery بین چند سرور مجازی و اختصاصی
به‌روز شده

راه‌اندازی HashiCorp Consul برای Service Discovery بین چند سرور مجازی و اختصاصی

1405/08/070 بازدید
راه‌اندازی HashiCorp Consul برای Service Discovery بین چند سرور مجازی و اختصاصی

راه‌اندازی HashiCorp Consul برای Service Discovery بین چند سرور مجازی و اختصاصی

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

معماری کلاستر Consul روی چند سرور

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

فرض کنید سه سرور اپلیکیشن و یک سرور دیتابیس دارید. هر سرور اپلیکیشن باید بداند آدرس دیتابیس چیست، و اگر یک سرور اپلیکیشن جدید اضافه شد، بقیه باید آن را بشناسند. Consul روی هر سرور یک agent اجرا می‌کند؛ این agentها با هم صحبت می‌کنند، لیست سرویس‌های سالم را در یک کاتالوگ مشترک نگه می‌دارند و آن را از طریق DNS داخلی (مثلا web.service.consul) یا یک HTTP API در دسترس می‌گذارند. برنامه‌ها به‌جای IP ثابت، از این نام استفاده می‌کنند و دیگر لازم نیست کسی دستی چیزی را به‌روز کند.

پیش‌نیازها برای ساخت کلاستر

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

  • سه سرور با Ubuntu 22.04 یا 24.04 — ترکیبی از سرور مجازی و سرور اختصاصی هم مشکلی ندارد، Consul به نوع سخت‌افزار کاری ندارد.
  • یک شبکهٔ داخلی بین سرورها (شبکهٔ خصوصی یا حتی IP عمومی با فایروال محدودشده) که agentها از طریق آن با هم ارتباط بگیرند.
  • پورت‌های زیر باز بین سرورها:
پورتپروتکلکاربرد
8300TCPارتباط Server agentها با هم (Raft)
8301TCP/UDPSerf — عضویت و اطلاع‌رسانی داخل کلاستر
8302TCP/UDPSerf — ارتباط بین چند دیتاسنتر
8500TCPرابط HTTP و وب UI
8600TCP/UDPکوئری DNS

پورت 8500 را فقط روی شبکهٔ داخلی باز نگه دارید؛ باز بودنش رو به اینترنت یعنی هر کسی می‌تواند کاتالوگ سرویس‌های شما را ببیند. برای باز کردن دقیق همین پورت‌ها بین سرورها می‌توانید از راهنمای راه‌اندازی فایروال nftables روی سرور لینوکس کمک بگیرید.

نصب Consul با مخزن رسمی

روی هر سه سرور همین مراحل را تکرار کنید. اول کلید و مخزن رسمی HashiCorp را اضافه می‌کنیم:

sudo apt-get update
sudo apt-get install -y gnupg wget curl
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update
sudo apt-get install -y consul

با consul version مطمئن شوید نسخه نصب شده. تا این‌جا هر سه سرور فقط باینری Consul را دارند؛ هنوز agentی اجرا نشده.

پیکربندی کلاستر سه‌نودی

فایل اصلی کانفیگ در /etc/consul.d/consul.hcl قرار می‌گیرد. فرض کنید IP داخلی سرورها 10.0.0.11، 10.0.0.12 و 10.0.0.13 است. روی هر سه سرور این فایل را بسازید و فقط bind_addr را مطابق IP همان سرور عوض کنید:

datacenter = "arianet-dc1"
data_dir   = "/opt/consul"
server     = true
bootstrap_expect = 3
bind_addr  = "10.0.0.11"
client_addr = "0.0.0.0"
retry_join = ["10.0.0.11", "10.0.0.12", "10.0.0.13"]
ui_config {
  enabled = true
}

bootstrap_expect=3 به Consul می‌گوید منتظر بماند تا سه Server agent پیدا شوند و بعد رهبر Raft را انتخاب کند. retry_join باعث می‌شود هر agent خودش بقیه را پیدا کند، بدون این‌که نیاز باشد دستور join را دستی بزنید.

سرویس را روی هر سه سرور استارت کنید:

sudo systemctl enable --now consul

برای چک کردن وضعیت کلاستر:

consul members
consul operator raft list-peers

خروجی اول باید سه عضو با وضعیت alive نشان بدهد و خروجی دوم باید دقیقا یک leader معرفی کند. اگر یکی از agentها به بقیه نپیوست، معمولا دلیلش فایروال بسته روی پورت 8301 یا 8300 است.

ثبت یک سرویس با Health Check

حالا فرض کنید روی یکی از سرورها یک API روی پورت 8080 اجرا شده و می‌خواهید بقیه بتوانند آن را پیدا کنند. یک فایل تعریف سرویس بسازید، مثلا /etc/consul.d/web.json:

{
  "service": {
    "name": "web",
    "port": 8080,
    "check": {
      "http": "http://localhost:8080/health",
      "interval": "10s",
      "timeout": "2s"
    }
  }
}

بعد از ذخیره، کانفیگ را reload کنید:

consul reload
consul catalog services

اگر web در خروجی دیدید، سرویس ثبت شده. نکتهٔ مهم همین Health Check است: Consul هر 10 ثانیه آدرس /health را چک می‌کند و اگر جواب ندهد، آن instance را از لیست سرویس‌های سالم حذف می‌کند تا بقیهٔ سرورها سراغ یک instance خراب نروند.

ارتباط Consul با سرورهای مجازی و اختصاصی و علامت تیک سبز برای سرویس‌های سالم

کشف سرویس از طریق DNS داخلی Consul

ساده‌ترین راه کشف سرویس، کوئری DNS روی پورت 8600 است:

dig @127.0.0.1 -p 8600 web.service.consul

این دستور فقط IPهای instanceهای سالم سرویس web را برمی‌گرداند (اگر با مفهوم DNS آشنا نیستید، DNS چیست؟ را بخوانید). برای این‌که برنامه‌ها بدون نوشتن -p 8600 و @127.0.0.1 از این DNS استفاده کنند، باید Consul را به‌عنوان forwarder به systemd-resolved معرفی کنید؛ یعنی هر کوئری با پسوند .consul را به پورت 8600 بفرستد و بقیه را مثل همیشه به DNS معمولی. بعد از این تنظیم، کافی است در کانفیگ برنامه به‌جای IP ثابت دیتابیس، آدرس db.service.consul را بنویسید — با هر تغییر سرور، این آدرس همیشه به instanceهای زندهٔ همان لحظه اشاره می‌کند.

Server agent در برابر Client agent

روی کلاسترهای بزرگ‌تر از سه سرور، همهٔ ماشین‌ها لازم نیست Server agent باشند. تفاوت دو نوع agent این‌طور است:

ویژگیServer agentClient agent
شرکت در رای‌گیری Raftبلهخیر
تعداد توصیه‌شده در یک دیتاسنتر3 یا 5به تعداد سرورهای اپلیکیشن
نگهداری کاتالوگ کاملبله، روی دیسکفقط کش محلی
مصرف منابعکمی بیشتر (I/O برای Raft log)سبک

برای یک دیتاسنتر معمولی سه Server agent کافی است؛ باقی سرورهای اپلیکیشن به‌عنوان Client agent با server=false به همین کلاستر وصل می‌شوند و فقط کوئری می‌زنند.

نکاتی برای محیط Production

قبل از این‌که این کلاستر را به بار واقعی وصل کنید، چند مورد را چک کنید:

  • رمزنگاری gossip: با consul keygen یک کلید بسازید و در encrypt همهٔ کانفیگ‌ها بگذارید تا ترافیک بین agentها رمزنگاری شود.
  • ACL: پیش‌فرض Consul بدون ACL است، یعنی هر agentی که به شبکه وصل شود می‌تواند سرویس ثبت کند. برای Production این گزینه را فعال کنید.
  • بک‌آپ Raft snapshot: با consul snapshot save backup.snap یک نسخهٔ پشتیبان از وضعیت کلاستر بگیرید، به‌خصوص قبل از آپدیت نسخه.
  • تعداد فرد Server agent: همیشه 3، 5 یا 7 — عدد زوج باعث مشکل در رای‌گیری رهبر می‌شود؛ همین قانون در کلاستر‌های دیگر مبتنی بر رای‌گیری هم صدق می‌کند، مثل صف‌های Quorum در راه‌اندازی RabbitMQ روی سرور مجازی و اختصاصی.
  • مانیتورینگ کلاستر: برای دیدن وضعیت واقعی این agentها در طول زمان، یک ابزار مانیتورینگ مثل Prometheus و Grafana کنار آن راه بیندازید.

برای این کلاستر سه‌نودی، شبکهٔ داخلی پایدار بین سرورها شرط اول کار کردن درست Raft است. اگر هنوز زیرساخت را انتخاب نکرده‌اید، سرورهای ابری آریانت شبکهٔ خصوصی بین سرورها و IP ثابت می‌دهند که دقیقا همین را نیاز دارید:

خرید سرور مجازی برای ساخت کلاستر Consul

سؤالات متداول

آیا Consul روی سرور مجازی معمولی هم کار می‌کند یا باید سرور اختصاصی داشت؟ روی سرور مجازی هم به‌خوبی کار می‌کند. Consul به منابع زیادی نیاز ندارد؛ یک سرور با 1 تا 2 گیگابایت رم برای Server agent کافی است. سرور اختصاصی فقط وقتی لازم می‌شود که تعداد سرویس‌ها یا ترافیک کوئری DNS خیلی بالا برود.

برای یک پروژه با یک یا دو سرویس هم باید کلاستر سه‌نودی بسازم؟ نه لزوما. اگر فقط یک سرویس دارید و IPها تقریبا ثابت هستند، Consul پیچیدگی اضافه است. ارزشش را وقتی نشان می‌دهد که تعداد سرورها بیشتر از دو یا سه تا می‌شود یا سرورها به‌طور مرتب اضافه و کم می‌شوند.

اگر یکی از نودهای Consul از دسترس خارج شود چه می‌شود؟ اگر نودی که از دست می‌رود Client agent باشد، فقط همان سرور دسترسی به کاتالوگ را از دست می‌دهد. اگر یک Server agent باشد و باقی سه (یا پنج) نود سالم بمانند، کلاستر همچنان کار می‌کند چون اکثریت Raft برقرار است؛ مشکل واقعی وقتی پیش می‌آید که بیشتر از نیمی از Server agentها هم‌زمان از دست بروند.

تفاوت Consul با ابزارهایی مثل etcd یا ZooKeeper چیست؟ هر سه از Raft برای توافق بین نودها استفاده می‌کنند، اما Consul از ابتدا برای Service Discovery طراحی شده و DNS داخلی، Health Check و رابط وب را آماده دارد. etcd و ZooKeeper بیشتر یک key-value store عمومی هستند که Service Discovery رویش پیاده‌سازی می‌شود، نه ویژگی اصلی‌شان.