راهنمای جامع Ceph
Englishشروع کنید
در این صفحه
فصل ۱۹

راهبری و نگه‌داری روزمره: ارتقا، جایگزینی دیسک، ‏autoscaler‏ و ‏balancer‏

۳۵ دقیقه مطالعهویرایش این صفحه
حوصله ندارم این فصل در چند خط
  • ارتقای ‏cephadm‏ غلتان است: اول ‏mgr‏ها، سپس ‏MON‏ها یکی‌یکی، بعد ‏OSD‏ها به شرط فعال ماندن ‏PG‏ها و در آخر بقیه‌ی ‏daemon‏ها.
  • دیسک را با ‏--replace‏ عوض کنید تا شناسه و جای ‏OSD‏ در ‏CRUSH‏ بماند و فقط ‏PG‏های همان ‏OSD backfill‏ شوند.
  • حالت نگهداری میزبان بررسی می‌کند توقف میزبان امن است و ‏noout‏ را فقط برای همان میزبان می‌گذارد.
  • ‏pg_autoscaler‏ تعداد ‏PG‏های هر ‏pool‏ را تنظیم می‌کند و ‏balancer‏ با ‏upmap‏ پخش ‏PG‏ها را یکنواخت می‌کند؛ سلامت دستگاه‌ها و بررسی‌های دوره‌ای جزو کار روزمره‌اند.

۱۹-۱ پیش از شروع#

۱۹-۱-۱ این فصل به چه سؤال‌هایی جواب می‌دهد؟#

بیشتر عمر یک کلاستر ‏Ceph‏ را کارهای روزمره تشکیل می‌دهد: ارتقای نسخه، تعویض دیسک، افزودن و خارج کردن میزبان، تنظیم تعداد ‏PG‏ها و متوازن کردن داده. هر کدام از این کارها اگر درست انجام شود بی‌سروصداست و اگر نه، به حادثه تبدیل می‌شود. این فصل روال‌های امروزی را با ‏cephadm‏ مرور می‌کند و سپس به درون دو ماژول مهم ‏mgr‏ می‌رود: ‏pg_autoscaler‏ و ‏balancer‏.

  • ارتقا با ‏cephadm‏ به چه ترتیبی انجام می‌شود و ارتقای مرحله‌ای چیست؟
  • دیسک خراب را چگونه با حفظ شناسه‌ی ‏OSD‏ جایگزین کنیم؟
  • میزبان را چگونه برای نگه‌داری خارج یا برای همیشه حذف کنیم؟
  • ‏pg_autoscaler‏ تعداد ‏PG‏ را با چه فرمولی محاسبه می‌کند و چه چیزی در ‏Umbrella‏ تغییر کرد؟
  • ‏balancer‏ در حالت ‏upmap‏ چگونه تصمیم می‌گیرد کدام ‏PG‏ جابه‌جا شود؟
  • کدام پرچم‌ها و تنظیمات برای کارهای نگه‌داری لازم‌اند؟

۱۹-۲ ارتقای نسخه#

شکل ۱۹-۱: روال ارتقا در سه مرحله: آمادگی شامل سالم بودن کلاستر، خواندن یادداشت‌های انتشار و اطمینان از دسترسی میزبان‌ها به image ؛ ترتیب cephadm از mgr و mon تا OSD ها با بررسی ok-to-stop و سپس سایر daemon ها؛ و پایان با یکسان بودن نسخه‌ها و بررسی require_osd_release
شکل ۱۹-۱: روال ارتقا در سه مرحله: آمادگی شامل سالم بودن کلاستر، خواندن یادداشت‌های انتشار و اطمینان از دسترسی میزبان‌ها به ‏image‏؛ ترتیب ‏cephadm‏ از ‏mgr‏ و ‏mon‏ تا ‏OSD‏ها با بررسی ‏ok-to-stop‏ و سپس سایر ‏daemon‏ها؛ و پایان با یکسان بودن نسخه‌ها و بررسی ‏require_osd_release‏

‏cephadm‏ ارتقا را به‌صورت ‏rolling‏ انجام می‌دهد: ابتدا ‏mgr‏ها (تا ماژول ‏cephadm‏ جدید کار را ادامه دهد)، سپس ‏MON‏ها یکی‌یکی با حفظ ‏quorum‏، سپس ‏OSD‏ها با بررسی اینکه توقف آن‌ها ‏PG‏ها را غیرفعال نمی‌کند، و در پایان سایر سرویس‌ها.

bashReef+
ceph -s
ceph versions
ceph orch upgrade start --ceph-version 20.2.5          # یا --image quay.io/ceph/ceph:v20.2.5
ceph orch upgrade status
ceph -W cephadm                                        # پیگیری زنده
ceph orch upgrade pause | resume | stop
✎ یادداشت

نسخه‌های ذکرشده در مثال (‏Tentacle 20.2.5‏) آخرین نسخه‌ی نقطه‌ای ‏Tentacle‏ در زمان نگارش است. پیش از ارتقا، فهرست رسمی انتشارها در ‏docs.ceph.com/en/latest/releases‏ را بررسی و یادداشت‌های ارتقای همان نسخه را بخوانید؛ بعضی انتشارها پیش‌نیاز یا گام دستی دارند.

۱۹-۲-۱ ارتقای مرحله‌ای#

‏cephadm‏ امکان ارتقای بخشی از ‏daemon‏ها را می‌دهد (‏staggered upgrade‏)؛ برای مثال فقط ‏mgr‏ و ‏mon‏ روی چند میزبان، یا فقط سرویس‌های ‏RGW‏ مشخص با محدودیت تعداد:

bashReef+
ceph orch upgrade start --image quay.io/ceph/ceph:v20.2.5 --daemon-types mgr,mon --hosts mon1,mon2
ceph orch upgrade start --image quay.io/ceph/ceph:v20.2.5 --services rgw.s3main --limit 2
◆ عمیق‌تر

در مستندات ‏Umbrella‏، ارتقای ‏OSD‏ها می‌تواند بر اساس ‏bucket CRUSH‏ انجام شود: با ‏--daemon-types osd --crush_bucket_type rack‏ (و اختیاری ‏--crush_bucket_name‏)، ‏cephadm‏ برای هر ‏bucket‏ فرمان ‏MON‏ ‏ceph osd ok-to-upgrade‏ را با سقف ‏mgr/cephadm/max_parallel_osd_upgrades‏ صدا می‌زند و ‏OSD‏های آن ‏bucket‏ را با هم ارتقا می‌دهد؛ اگر پارامترهای ‏bucket‏ داده نشود، به دروازه‌ی پیش‌فرض ‏ok-to-stop‏ برمی‌گردد. انواع ‏bucket‏ پشتیبانی‌شده در مستندات: ‏host‏، ‏rack‏ و ‏chassis‏. این قابلیت زمان ارتقای کلاسترهای بزرگ را به‌شدت کم می‌کند، چون به‌جای یک ‏OSD‏ در هر زمان، یک دامنه‌ی خرابی کامل هم‌زمان ارتقا می‌یابد.

⚠ هشدار

اگر میزبانی ‏offline‏ یا در حالت نگه‌داری باشد، ارتقا متوقف و منتظر می‌ماند. پیش از شروع، ‏ceph orch host ls‏ را بررسی کنید. ارتقا را در زمان ‏backfill‏ سنگین یا وجود ‏PG‏های غیرفعال شروع نکنید.

۱۹-۳ جایگزینی دیسک#

شکل ۱۹-۲: جایگزینی دیسک خراب با حفظ شناسه‌ی OSD در دو مرحله: خارج کردن با orch osd rm -- replace که PG ها را تخلیه و OSD را destroyed علامت می‌زند، و جایگزینی که پس از تعویض فیزیکی و در صورت نیاز zap ، مشخصات سرویس OSD دیسک جدید را می‌گیرد و OSD با همان شناسه ساخته و backfill می‌شود
شکل ۱۹-۲: جایگزینی دیسک خراب با حفظ شناسه‌ی ‏OSD‏ در دو مرحله: خارج کردن با ‏orch osd rm‏ --‏replace‏ که ‏PG‏ها را تخلیه و ‏OSD‏ را ‏destroyed‏ علامت می‌زند، و جایگزینی که پس از تعویض فیزیکی و در صورت نیاز ‏zap‏، مشخصات سرویس ‏OSD‏ دیسک جدید را می‌گیرد و ‏OSD‏ با همان شناسه ساخته و ‏backfill‏ می‌شود
bashReef+
ceph osd tree | grep -E "down|destroyed"
ceph orch osd rm 17 --replace          # شناسه حفظ و OSD در CRUSH باقی می‌ماند
ceph orch osd rm status
# پس از تعویض دیسک
ceph orch device ls stor-b3 --refresh
ceph orch device zap stor-b3 /dev/sdk --force      # فقط اگر دیسک قبلاً استفاده شده
ceph orch ps --daemon-type osd | grep osd.17
💡 نکته

‏--replace‏ باعث می‌شود ‏OSD‏ در وضعیت ‏destroyed‏ بماند، نه حذف کامل؛ بنابراین موقعیت ‏CRUSH‏ و شناسه حفظ می‌شود و پس از ساخت ‏OSD‏ جدید، فقط ‏PG‏های همان ‏OSD backfill‏ می‌شوند، نه یک بازتوزیع کلی. بدون ‏--replace‏، حذف ‏OSD‏ و افزودن ‏OSD‏ جدید دو بار داده را جابه‌جا می‌کند.

⚠ هشدار

‏ceph orch osd rm‏ تأیید نمی‌خواهد و بلافاصله شروع می‌کند؛ مستندات این را صریحاً گوشزد می‌کند. شناسه را دوبار بررسی کنید. برای توقف: ‏ceph orch osd rm stop <id>‏.

۱۹-۴ نگه‌داری و حذف میزبان#

bashReef+
ceph orch host maintenance enter stor-b3        # توقف همه‌ی daemonهای Ceph میزبان
# ... به‌روزرسانی هسته، تعمیر سخت‌افزار، راه‌اندازی دوباره ...
ceph orch host maintenance exit stor-b3
# حذف دائمی
ceph orch host drain stor-b3                    # برچسب _no_schedule و _no_conf_keyring؛ خروج daemonها
ceph orch osd rm status
ceph orch host rm stor-b3
✎ یادداشت

‏maintenance enter‏ پیش از توقف، بررسی می‌کند توقف ‏daemon‏های میزبان ایمن است (مثلاً ‏PG‏ها فعال می‌مانند) و در صورت ناامنی امتناع می‌کند؛ طبق مستندات، ‏--force‏ از هشدارها (نه ‏alert‏ها) عبور می‌کند و ‏--force --yes-i-really-mean-it‏ همه‌ی بررسی‌های ایمنی را دور می‌زند و می‌تواند به از دست رفتن دسترسی داده یا ‏quorum‏ منجر شود. در کد ‏cephadm‏ (‏pybind/mgr/cephadm/module.py‏)، ورود به نگه‌داری با فرمان ‏osd set-group‏ پرچم ‏noout‏ را برای زیردرخت ‏CRUSH‏ همان میزبان تنظیم می‌کند تا داده بی‌دلیل بازتوزیع نشود، و خروج آن را برمی‌دارد.

۱۹-۵ از درون کد: ‏pg_autoscaler‏#

۱۹-۵-۱ مسئله#

تعداد ‏PG‏ هر ‏pool‏ دو اثر متضاد دارد: ‏PG‏ کم یعنی توزیع ناهموار داده و موازی‌سازی کم؛ ‏PG‏ زیاد یعنی مصرف حافظه و ‏CPU‏ بیشتر در ‏OSD‏ها و ‏peering‏ سنگین‌تر. ماژول ‏pg_autoscaler‏ در ‏mgr‏ (‏src/pybind/mgr/pg_autoscaler/module.py‏) این تعادل را خودکار می‌کند. هدف آن این است که هر ‏OSD‏ حدود ‏mon_target_pg_per_osd‏ نسخه‌ی ‏PG‏ میزبانی کند.

شکل ۱۹-۳: مراحل محاسبه‌ی pg_autoscaler : ابتدا بودجه‌ی PG هر ریشه‌ی CRUSH از تعداد OSD ها ضرب در mon_target_pg_per_osd ، سپس سهم هر pool از مصرف واقعی یا نسبت هدف و تبدیل آن به pg_target با در نظر گرفتن bias و size ، و در نهایت گرد کردن به توان ۲ و تغییر فقط وقتی تفاوت از آستانه بیشتر باشد
شکل ۱۹-۳: مراحل محاسبه‌ی ‏pg_autoscaler‏: ابتدا بودجه‌ی ‏PG‏ هر ریشه‌ی ‏CRUSH‏ از تعداد ‏OSD‏ها ضرب در ‏mon_target_pg_per_osd‏، سپس سهم هر ‏pool‏ از مصرف واقعی یا نسبت هدف و تبدیل آن به ‏pg_target‏ با در نظر گرفتن ‏bias‏ و ‏size‏، و در نهایت گرد کردن به توان ۲ و تغییر فقط وقتی تفاوت از آستانه بیشتر باشد
⚠ هشدار

وابسته به نسخه. مقدار پیش‌فرض ‏mon_target_pg_per_osd‏ در ‏src/common/options/mgr.yaml.in‏ در برچسب‌های ‏v19.2.0‏ و ‏v20.2.0‏ برابر ۱۰۰ و در ‏v21.2.0‏ (Umbrella) برابر ۲۰۰ است. یعنی پس از ارتقا به ‏Umbrella‏، ‏autoscaler‏ ممکن است برای ‏pool‏های موجود ‏PG‏ بیشتری پیشنهاد کند و تقسیم ‏PG‏ (و جابه‌جایی داده) آغاز شود. پیش از ارتقا ‏ceph osd pool autoscale-status‏ را ذخیره کنید و پس از ارتقا مقایسه کنید؛ در صورت لزوم مقدار قبلی را صریحاً با ‏ceph config set global mon_target_pg_per_osd 100‏ تنظیم کنید.

۱۹-۵-۲ الگوریتم#

text
pseudocode: pg_autoscaler (بازنویسی این کتاب)
  for root in crush_roots:
      budget[root] = osds_in(root) * mon_target_pg_per_osd
  for pool:
      root      = root_of(pool.crush_rule)
      ratio     = max(actual_used / root_capacity,
                      target_size_bytes / root_capacity,
                      normalized target_size_ratio)          # نسبت‌ها نرمال می‌شوند
      pg_target = ratio * budget[root] * pool.bias / pool.size
      if pool.bulk:     start near full share
      else:             start small, grow with usage
      pg_final  = round_to_power_of_two(pg_target)            # Umbrella: گرد کردن بهینه (knapsack)
      pg_final  = clamp(pg_final, pg_num_min, pg_num_max)
      threshold = dynamic_threshold(pg_final) if scaling up else threshold   # پیش‌فرض 3.0
      if pg_final > pg_num_target * threshold or pg_final < pg_num_target / threshold:
          if pool.mode == 'on':   set pg_num_target = pg_final
          elif pool.mode == 'warn': raise POOL_TOO_FEW_PGS / POOL_TOO_MANY_PGS

آستانه جلوی نوسان را می‌گیرد: ‏autoscaler‏ فقط وقتی ‏pg_num‏ را تغییر می‌دهد که مقدار ایده‌آل دست‌کم سه برابر (پیش‌فرض ‏threshold=3.0‏) بیشتر یا کمتر از مقدار فعلی باشد. حداقل مقدار مجاز آستانه ۱.۰ است (‏ceph osd pool set threshold‏).

در کد جاری (و ‏Umbrella‏)، آستانه برای افزایش در چند اندازه‌ی رایج پویا است:

python
# from ceph/ceph, LGPL — src/pybind/mgr/pg_autoscaler/module.py (excerpt)
def get_dynamic_threshold(self, final_pg_num: int, default_threshold: float) -> float:
    if final_pg_num in (512, 1024):
        return 1.0
    elif final_pg_num == 2048:
        return 2.0
    return default_threshold

یعنی رسیدن به ۵۱۲ یا ۱۰۲۴ ‏PG‏ بدون نیاز به اختلاف سه‌برابری انجام می‌شود (هر افزایشی کافی است) و برای ۲۰۴۸ اختلاف دوبرابری کافی است. برای کاهش، همان آستانه‌ی پیش‌فرض اعمال می‌شود. در ‏Umbrella‏، گرد کردن ‏pg_target‏ به توان ۲ هم دیگر برای هر ‏pool‏ جداگانه انجام نمی‌شود: تابع ‏_find_optimal_pg_distribution‏ با برنامه‌نویسی پویای کوله‌پشتی تصمیم می‌گیرد کدام ‏pool‏ها رو به بالا و کدام رو به پایین گرد شوند تا مجموع خطای گرد کردن کمینه و بودجه‌ی ‏PG‏ ریشه رعایت شود (این تابع در برچسب ‏v20.2.0‏ وجود ندارد).

bashReef+
ceph osd pool autoscale-status
ceph osd pool set vm-fast target_size_ratio 0.4       # پیش‌بینی سهم آینده
ceph osd pool set archive bulk true                   # pool بزرگ: سهم کامل از ابتدا
ceph osd pool set archive pg_num_min 256
ceph osd pool get threshold
ceph osd pool set noautoscale                          # توقف موقت سراسری
ceph osd pool unset noautoscale
💡 نکته

برای ‏pool‏هایی که می‌دانید بزرگ خواهند شد (داده‌ی ‏RGW‏ یا ‏RBD‏ اصلی)، از ابتدا ‏bulk‏ را فعال کنید. در غیر این صورت ‏autoscaler‏ با ‏PG‏ کم شروع می‌کند و همزمان با پر شدن ‏pool‏، چند بار ‏PG‏ها را تقسیم می‌کند که هر بار جابه‌جایی داده دارد.

۱۹-۶ از درون کد: ‏balancer‏#

۱۹-۶-۱ حالت‌ها#

حالتسازوکارپیش‌نیاز
‏upmap‏ (پیش‌فرض)افزودن ‏pg_upmap_items‏ برای جابه‌جایی تک‌تک ‏PG‏هاکلاینت‌های ‏Luminous‏ به بعد
‏crush-compat‏تنظیم وزن‌های جایگزین در یک ‏weight-set‏ سازگارسازگار با کلاینت‌های قدیمی
‏read‏ و ‏upmap-read‏متعادل کردن ‏primary‏ها (‏pg_upmap_primary‏) برای بار خواندنکلاینت‌های ‏Reef‏ به بعد
شکل ۱۹-۴: عملکرد balancer در حالت upmap : ماژول mgr در هر بازه‌ی sleep_interval (پیش‌فرض ۶۰ ثانیه) و در صورت آرام بودن کلاستر do_upmap را اجرا می‌کند؛ OSDMap::calc_pg_upmaps تعداد PG هر OSD را با مقدار هدف وزن‌دار مقایسه و برای OSD های با انحراف بیش از max_deviation ، ورودی‌های pg_upmap_items با رعایت قانون CRUSH می‌سازد؛ نتیجه backfill فقط برای PG های منتخب است
شکل ۱۹-۴: عملکرد ‏balancer‏ در حالت ‏upmap‏: ماژول ‏mgr‏ در هر بازه‌ی ‏sleep_interval‏ (پیش‌فرض ۶۰ ثانیه) و در صورت آرام بودن کلاستر ‏do_upmap‏ را اجرا می‌کند؛ ‏OSDMap::calc_pg_upmaps‏ تعداد ‏PG‏ هر ‏OSD‏ را با مقدار هدف وزن‌دار مقایسه و برای ‏OSD‏های با انحراف بیش از ‏max_deviation‏، ورودی‌های ‏pg_upmap_items‏ با رعایت قانون ‏CRUSH‏ می‌سازد؛ نتیجه ‏backfill‏ فقط برای ‏PG‏های منتخب است

۱۹-۶-۲ الگوریتم ‏upmap‏#

‏Module.do_upmap()‏ در ‏src/pybind/mgr/balancer/module.py‏ با گزینه‌های ‏upmap_max_optimizations‏ (پیش‌فرض ۱۰، بیشینه‌ی تغییر در هر دور) و ‏upmap_max_deviation‏ (پیش‌فرض ۵ ‏PG‏) کار را به ‏OSDMap::calc_pg_upmaps()‏ در ‏C++‏ می‌سپارد. منطق آن:

text
pseudocode: calc_pg_upmaps (خلاصه‌ی این کتاب از OSDMap.cc)
  for osd: target[osd] = total_pgs * weight[osd] / total_weight      # سهم وزن‌دار
           deviation[osd] = pgs[osd] - target[osd]
  repeat up to max_optimizations:
      over  = OSDs with deviation >  max_deviation (پرترین اول)
      under = OSDs with deviation < -max_deviation
      if none: break
      for pg on over[0]:
          candidate = an OSD in under that keeps CRUSH rule valid
                      (همان دامنه‌ی خرابی، بدون تکرار در up set)
          if found: add pg_upmap_items[pg] += (over[0] → candidate); update counts; break
      also: remove existing upmap items that no longer help
  return pending increment
◆ عمیق‌تر

‏pg_upmap_items‏ نگاشت ‏CRUSH‏ را دور نمی‌زند، بلکه روی خروجی ‏CRUSH‏ اعمال می‌شود: ‏CRUSH up set‏ را حساب می‌کند و سپس جفت‌های (‏from‏ → ‏to‏) جایگزین می‌شوند. اگر بعداً تغییر ‏CRUSH‏ باعث شود ‏upmap‏ قانون را نقض کند (مثلاً دو نسخه در یک میزبان)، ‏OSDMap‏ هنگام اعمال آن را نادیده می‌گیرد و ‏MON‏ آن را پاک می‌کند (‏clean_pg_upmaps‏). به همین دلیل ‏upmap‏ ایمن‌تر از تغییر دستی وزن‌هاست.

bashReef+
ceph balancer status
ceph balancer mode upmap
ceph balancer on
ceph config set mgr mgr/balancer/upmap_max_deviation 1     # توزیع دقیق‌تر در کلاستر بزرگ
ceph balancer eval
ceph osd df tree | sort -nk17 | tail                      # ستون‌های VAR و PGS
✎ یادداشت

‏balancer‏ فقط وقتی کار می‌کند که درصد ‏PG‏های ‏misplaced‏ کمتر از ‏target_max_misplaced_ratio‏ باشد (پیش‌فرض ۰.۰۵)؛ بنابراین در میانه‌ی ‏backfill‏ سنگین، کار تازه‌ای شروع نمی‌کند. حالت‌های ‏read balancer‏ به کلاینت‌های ‏Reef‏ به بعد نیاز دارند (‏ceph osd set-require-min-compat-client reef‏).

۱۹-۷ سه الگوریتم نگه‌داری با عدد#

بخش‌های قبل ‏autoscaler‏ و ‏balancer‏ را در سطح مفهوم توضیح دادند. این بخش هر دو را تا سطح حلقه و عدد باز می‌کند. چون الگوریتم گرد کردن ‏autoscaler‏ در ‏Umbrella‏ عوض شده است، هر دو نسخه را جداگانه آورده‌ایم.

۱۹-۷-۱ گرد کردن به توان دو و آستانه‌ی ۳ برابری#

∑ الگوریتم: ‏pg_autoscaler‏ سه‌گذره (تا ‏v20.2.0‏)

منبع در کد: src/pybind/mgr/pg_autoscaler/module.py :: PgAutoscaler._calc_final_pg_target، nearest_power_of_two (برچسب v20.2.0)

پیچیدگی: ‏O‏(P) برای ‏P pool‏ در هر ریشه‌ی ‏CRUSH‏؛ گرد کردن ‏O‏(۱) با شیفت بیتی

text
pseudocode
budget[root] = Σ_osd mon_target_pg_per_osd / (تعداد ریشه‌های آن OSD) ; pg_left = budget
pass 1 (pool غیر bulk): used = capacity_ratio × pg_left ; pg_left −= used ; target = used / size × bias
pass 2 (bulk با ratio > even = 1/(pools − used_pools)): ratio = max(used, even) ; همان محاسبه
pass 3 (بقیه‌ی bulk): ratio = 1/(باقی) ; target = ratio × pg_left / size × bias
final = max(pg_num_min=32, nearest_power_of_two(target)) ; final = min(final, pg_num_max)
adjust = (final > current × 3) or (final < current / 3)       # threshold پیش‌فرض 3.0

مثال عددی. ده ‏OSD‏ در یک ریشه با ‏mon_target_pg_per_osd = 100‏ (پیش‌فرض ‏v20.2.0‏) بودجه‌ی ۱۰۰۰ نسخه‌ی ‏PG‏ می‌دهند. ‏pool‏ غیر ‏bulk‏ به نام ‏rbd‏ با ‏size 3‏ و ‏capacity_ratio‏ = ۰.۳ دارای ‏used‏ = ۳۰۰ است و ‏target‏ = ۳۰۰/۳ = ۱۰۰. تابع ‏nearest_power_of_two‏(۱۰۰) کران‌های ۶۴ و ۱۲۸ را می‌سازد (با ‏OR‏ کردن شیفت‌ها: ۹۹ → ۱۲۷ → ۱۲۸). چون ۱۲۸ − ۱۰۰ = ۲۸ < ۱۰۰ − ۶۴ = ۳۶، نتیجه ۱۲۸ است. اگر ‏pg_num‏ فعلی ۳۲ باشد، ۱۲۸ > ۹۶ است و تغییر اعمال می‌شود. اگر ‏pg_num‏ فعلی ۶۴ بود، ۱۲۸ < ۱۹۲ بود و ‏autoscaler‏ فقط هشدار می‌داد و چیزی را تغییر نمی‌داد. این هیسترزیس جلوی ‏split/merge‏ پشت سر هم را می‌گیرد. نقطه‌ی تصمیم گرد کردن، ۱.۵ برابر هر توان دو است.

شکل ۱۹-۵: سمت چپ تابع پله‌ای nearest_power_of_two است: هدف هر pool به نزدیک‌ترین توان دو گرد می‌شود و مرز تصمیم (نقطه‌چین نارنجی) ۱.۵ برابر توان پایین‌تر است. نقطه‌ی قرمز مثال متن است. سمت راست قاعده‌ی آستانه با threshold = ۳ و pg_num فعلی ۳۲ است: فقط مقادیر سبز، یعنی بیش از ۹۶ یا کمتر از ۱۰.۷، تغییر واقعی ایجاد می‌کنند
شکل ۱۹-۵: سمت چپ تابع پله‌ای ‏nearest_power_of_two‏ است: هدف هر ‏pool‏ به نزدیک‌ترین توان دو گرد می‌شود و مرز تصمیم (نقطه‌چین نارنجی) ۱.۵ برابر توان پایین‌تر است. نقطه‌ی قرمز مثال متن است. سمت راست قاعده‌ی آستانه با ‏threshold‏ = ۳ و ‏pg_num‏ فعلی ۳۲ است: فقط مقادیر سبز، یعنی بیش از ۹۶ یا کمتر از ۱۰.۷، تغییر واقعی ایجاد می‌کنند

۱۹-۷-۲ گرد کردن سراسری با کوله‌پشتی (‏Umbrella‏)#

∑ الگوریتم: گرد کردن بهینه‌ی ‏PG‏ با برنامه‌ریزی پویا

منبع در کد: src/pybind/mgr/pg_autoscaler/module.py :: PgAutoscaler._find_optimal_pg_distribution، _calculate_final_pool_pg_target، get_dynamic_threshold، PoolGroup.update (برچسب v21.2.0)

پیچیدگی: طبق ‏docstring‏ کد ‏O‏(n·‏log2‏(budget))؛ فضای حالت = مجموع‌های ممکن ‏PG‏ اضافه

text
pseudocode
برای هر گروه pool (هم‌هدف، هم‌size، هم‌bias): down = pow2_down(t)×size ، up = pow2_up(t)×size
    cost_down = |down − t×size| ، cost_up = |up − t×size| ، extra = up − down
base = Σ down ; budget = pg_left − base
parent[0] = {0: (Σ cost_down)}
for group i: برای هر مجموع s در parent[i]:
    s' = s + extra_i ; c' = c − cost_down_i + cost_up_i
    if s' ≤ budget and (s' جدید یا c' کمتر): parent[i+1][s'] = (c', s)
opt = کمترین هزینه؛ در تساوی، بیشترین PG ; سپس عقب‌گرد برای یافتن گروه‌های «up»
threshold پویا برای افزایش: final ∈ {512, 1024} ⇒ 1.0 ، final = 2048 ⇒ 2.0 ، وگرنه threshold

مثال عددی. ‏pg_left‏ = ۱۰۰۰. ‏pool A‏ هدف ۱۰۰ با ‏size 3‏ دارد و ‏pool B‏ هدف ۱۸۰ با ‏size 3‏.

  • ‏A‏: ‏down‏ = ۶۴×۳ = ۱۹۲، ‏up‏ = ۱۲۸×۳ = ۳۸۴، هزینه‌ها ۱۰۸ و ۸۴، ‏extra‏ = ۱۹۲.
  • ‏B‏: ‏down‏ = ۱۲۸×۳ = ۳۸۴، ‏up‏ = ۲۵۶×۳ = ۷۶۸، هزینه‌ها ۱۵۶ و ۲۲۸، ‏extra‏ = ۳۸۴.

‏base‏ = ۵۷۶ و ‏budget‏ = ۴۲۴. چهار گزینه وجود دارد:

  • هر دو پایین: هزینه ۲۶۴.
  • فقط ‏B‏ بالا: ۳۳۶.
  • فقط ‏A‏ بالا: ۲۴۰.
  • هر دو بالا: ۵۷۶ ‏PG‏ اضافه، بیش از بودجه.

بنابراین ‏A‏ = ۱۲۸ و ‏B‏ = ۱۲۸ انتخاب می‌شود. در این مثال نتیجه با گرد کردن محلی یکی است. تفاوت وقتی پیدا می‌شود که گرد کردن محلی هر دو را بالا ببرد و بودجه‌ی ریشه را بشکند. نسخه‌ی سه‌گذره چنین چیزی را نمی‌دید. آستانه‌ی پویا هم تغییر از ۲۵۶ به ۵۱۲ را بدون شرط ۳ برابری مجاز می‌کند.

شکل ۱۹-۶: چهار انتخاب ممکن برای گرد کردن دو pool در مثال متن. ارتفاع هر ستون مجموع فاصله‌ی مقادیر گردشده از هدف است. گزینه‌ی خاکستری از بودجه‌ی ۴۲۴ نسخه‌ی PG اضافه بیشتر است و حذف می‌شود. گزینه‌ی سبز کمترین هزینه را دارد و انتخاب می‌شود. برنامه‌ریزی پویا به‌جای امتحان همه‌ی ۲ⁿ ترکیب، فقط مجموع‌های ممکن PG اضافه را نگه می‌دارد
شکل ۱۹-۶: چهار انتخاب ممکن برای گرد کردن دو ‏pool‏ در مثال متن. ارتفاع هر ستون مجموع فاصله‌ی مقادیر گردشده از هدف است. گزینه‌ی خاکستری از بودجه‌ی ۴۲۴ نسخه‌ی ‏PG‏ اضافه بیشتر است و حذف می‌شود. گزینه‌ی سبز کمترین هزینه را دارد و انتخاب می‌شود. برنامه‌ریزی پویا به‌جای امتحان همه‌ی ۲ⁿ ترکیب، فقط مجموع‌های ممکن ‏PG‏ اضافه را نگه می‌دارد
⚠ هشدار

وابسته به نسخه. این الگوریتم در برچسب ‏v20.2.0‏ وجود ندارد و در ‏v21.2.0‏ هست. در همان نسخه پیش‌فرض ‏mon_target_pg_per_osd‏ هم از ۱۰۰ به ۲۰۰ رسیده است، پس پس از ارتقا هم بودجه و هم روش گرد کردن تغییر می‌کند. در شاخه‌ی ‏main‏، کف ‏pg_num_min‏ به‌جای ثابت ‏PG_NUM_MIN‏ = ۳۲ از ‏osd_pool_default_pg_num‏ خوانده می‌شود. پیش از تکیه بر آن، نسخه‌ی خودتان را بررسی کنید.

۱۹-۷-۳ انحراف و امتیاز توازن در ‏upmap‏#

∑ الگوریتم: انحراف وزن‌دار و ‏bal_score‏ در ‏calc_pg_upmaps‏

منبع در کد: src/osd/OSDMap.cc :: OSDMap::calc_pg_upmaps، calc_deviations، fill_overfull_underfull

پیچیدگی: هر تکرار ‏O‏(OSD + ‏PG‏ روی ‏OSD‏ پرتر × هزینه‌ی ‏CRUSH‏)؛ حداکثر ‏upmap_max_optimizations‏ = ۱۰ تغییر در هر دور

text
pseudocode
pgs_per_weight = total_pg_replicas / Σ weight
for osd: target = weight × pgs_per_weight ; dev = pgs − target
         bal_score += (dev/target)^2 × weight ; max_dev = max(|dev|)
if max_dev ≤ max_deviation (5): return 0
loop (max بار): overfull = {dev > 5} ، underfull = {dev < −5}
    if هر دو خالی: break ; if overfull خالی: از more_overfull (0 < dev ≤ 5) استفاده کن
    از پرترین OSD: یک PG پیدا کن که جابه‌جایی‌اش به underfull قانون CRUSH را نشکند ⇒ pg_upmap_items
    انحراف‌ها را دوباره حساب کن ؛ فقط اگر bal_score بهتر شد بپذیر

مثال عددی. شش ‏OSD‏ با وزن‌های ۱، ۱، ۱، ۱، ۲ و ۲ (مجموع ۸) و ۳۸۴ نسخه‌ی ‏PG‏ (۱۲۸ PG × ‏size 3‏) داریم، پس ‏pgs_per_weight‏ = ۴۸. ‏OSD‏‌های وزن ۱ هدف ۴۸ دارند و وزن ۲ هدف ۹۶. شمارش فعلی ۵۵، ۴۱، ۵۰، ۴۶، ۱۰۰ و ۹۲ است، پس انحراف‌ها +۷، −۷، +۲، −۲، +۴ و −۴.

  • ‏bal_score‏ = ‏2×(7/48)2+2×(2/48)2+4×(4/96)2=0.05302 \times (7/48)^2 + 2 \times (2/48)^2 + 4 \times (4/96)^2 = 0.0530‏.
  • حرکت اول، یک ‏PG‏ از ‏osd.0‏ به ‏osd.1‏: انحراف ±۶ و امتیاز ۰.۰۴۱۷.
  • حرکت دوم: ±۵ و امتیاز ۰.۰۳۲۱.

اکنون هیچ ‏OSD‏ انحراف بیش از ۵ ندارد و حلقه متوقف می‌شود. در عمل، انتخاب ‏PG‏ به قانون ‏CRUSH‏ محدود است. اگر ‏osd.0‏ و ‏osd.1‏ در یک میزبان باشند و قانون یک نسخه در هر میزبان را بخواهد، جابه‌جایی مستقیم ممکن نیست و الگوریتم سراغ ‏OSD‏ کم‌بار دیگری می‌رود. کد ‏bal_score‏ را عمداً در ‏double‏ جمع می‌کند، چون در ‏float‏ تغییر یک ‏PG‏ در کلاسترهای بزرگ کمتر از دقت عدد می‌شد و ‏balancer‏ متوقف می‌ماند.

شکل ۱۹-۷: انحراف تعداد PG هر OSD از هدف وزن‌دارش در مثال متن، پیش از upmap و پس از هر upmap . خط‌چین‌ها مرز upmap_max_deviation = ۵ هستند. هر upmap یک واحد از پرترین OSD کم و به کم‌بارترین اضافه می‌کند. امتیاز bal_score که مجموع وزن‌دار مربع انحراف نسبی است، با هر حرکت کمتر می‌شود. OSD ‌های وزن ۲ با انحراف ±۴ دست نخورده می‌مانند، چون درون مرزند
شکل ۱۹-۷: انحراف تعداد ‏PG‏ هر ‏OSD‏ از هدف وزن‌دارش در مثال متن، پیش از ‏upmap‏ و پس از هر ‏upmap‏. خط‌چین‌ها مرز ‏upmap_max_deviation‏ = ۵ هستند. هر ‏upmap‏ یک واحد از پرترین ‏OSD‏ کم و به کم‌بارترین اضافه می‌کند. امتیاز ‏bal_score‏ که مجموع وزن‌دار مربع انحراف نسبی است، با هر حرکت کمتر می‌شود. ‏OSD‏‌های وزن ۲ با انحراف ±۴ دست نخورده می‌مانند، چون درون مرزند
💡 نکته

‏ceph balancer eval‏ همین امتیاز را برای کل کلاستر یا یک ‏pool‏ گزارش می‌کند. ‏ceph osd df tree‏ ستون ‏PGS‏ را نشان می‌دهد که می‌توانید انحراف را با آن دستی محاسبه کنید. برای توزیع یکنواخت‌تر از پیش‌فرض، ‏ceph config set mgr mgr/balancer/upmap_max_deviation 1‏ را امتحان کنید، اما این کار جابه‌جایی بیشتری ایجاد می‌کند.

۱۹-۸ ‏balancer‏ و ‏split‏ با نگاشت واقعی#

دو آزمایش این بخش روی همان نقشه‌ی ۱۲۰ ‏OSD‏ (۱۰ میزبان × ۱۲، ‏‏straw2‏، ‏‏chooseleaf host‏، ‏‏size‏ = ۳) انجام شده است که در فصل ۱ ساختیم. ابزارها ‏crushtool‏ و ‏osdmaptool‏ از ‏Ceph 18.2.7‏ بودند.

۱۹-۸-۱ ‏upmap balancer‏ روی ۱۰۲۴ و ۸۱۹۲ ‏PG‏#

∑ الگوریتم: مسیر ‏balancer‏ در حالت ‏upmap‏

منبع در کد: src/osd/OSDMap.cc :: calc_pg_upmaps؛ src/pybind/mgr/balancer/module.py؛ همان کد در osdmaptool --upmap

پیچیدگی: هر دور ‏O‏(pg_num × ‏size‏) برای شمارش و انتخاب

text
pseudocode
برای هر OSD: target = pg_num × size × (وزن OSD / وزن کل pool)
deviation(o) = PGهای o − target(o)
تا وقتی max |deviation| > upmap_max_deviation و تعداد تغییرها < upmap_max:
    o_over = بیشترین deviation مثبت ؛ o_under = بیشترین deviation منفی، با همان failure domain مجاز
    یک PG از o_over بردار که قاعده‌ی CRUSH را نقض نکند و به o_under ببر
    ← ورودی pg-upmap-items: pg  o_over  o_under

اندازه‌گیری. دستور ‏osdmaptool om --mark-up-in --upmap out.txt --upmap-deviation 1 --upmap-max 10000 --upmap-pool rbd --save‏ روی دو ‏osdmap‏ اجرا شد.

با ۸۱۹۲ ‏PG‏، تنها ‏CRUSH‏ بین ۱۷۲ و ۲۳۴ ‏PG‏ به هر ‏OSD‏ می‌دهد (انحراف معیار ۱۳.۲۴ در برابر میانگین ۲۰۴.۸). بعد از ۶۱۸ ورودی ‏pg-upmap-items‏ (۶۳۰ جفت ‏OSD‏، یعنی ۲.۶٪ ‏replica‏ها) بازه به ۲۰۴ تا ۲۰۶ و انحراف معیار به ۰.۵۴ رسید.

با ۱۰۲۴ ‏PG‏، بازه از ۱۳ تا ۴۲ به ۲۵ تا ۲۶ رسید. این کار ۲۲۶ ورودی و ۲۴۶ جفت لازم داشت که ۸.۰٪ ‏replica‏هاست. یعنی سهم جابه‌جایی لازم برای یکنواخت شدن در ‏pg_num‏ کم بیشتر است.

چون ‏CRUSH‏ با ‏pg_num‏ بالا یکنواخت‌تر است، ‏balancer‏ هم کار کمتری دارد. اما در هر دو حالت برطرف کردن انحراف چند درصد داده را جابه‌جا می‌کند و ‏balancer‏ آن را با همان سقف ۵٪ (‏target_max_misplaced_ratio‏) قسط‌بندی می‌کند.

شکل ۱۹-۸: توزیع تعداد PG روی ۱۲۰ OSD پیش از upmap (نارنجی، فقط CRUSH ) و پس از upmap (آبی)، برای ۱۰۲۴ و ۸۱۹۲ PG ، با osdmaptool -- upmap و انحراف مجاز ۱. عنوان هر نمودار تعداد ورودی‌های pg-upmap-items و سهم replica های جابه‌جاشده را نشان می‌دهد
شکل ۱۹-۸: توزیع تعداد ‏PG‏ روی ۱۲۰ ‏OSD‏ پیش از ‏upmap‏ (نارنجی، فقط ‏CRUSH‏) و پس از ‏upmap‏ (آبی)، برای ۱۰۲۴ و ۸۱۹۲ ‏PG‏، با ‏osdmaptool‏ --‏upmap‏ و انحراف مجاز ۱. عنوان هر نمودار تعداد ورودی‌های ‏pg-upmap-items‏ و سهم ‏replica‏های جابه‌جاشده را نشان می‌دهد

۱۹-۸-۲ دو برابر کردن ‏pg_num‏: نیمی از داده جابه‌جا می‌شود#

∑ الگوریتم: کنترل‌گر ‏pg_num‏ و ‏pgp_num‏ در ‏mgr‏

منبع در کد: src/mgr/DaemonServer.cc :: adjust_pgs؛ گزینه‌های target_max_misplaced_ratio = 0.05 (global.yaml.in) و mgr_max_pg_num_change = 128 (mgr.yaml.in)

پیچیدگی: ‏O‏(تعداد ‏pool‏) در هر دور

text
pseudocode
اگر همه‌ی PGهای pool فعال‌اند و pg_num − pgp_num < 128:
    pg_num += min(128 − (pg_num − pgp_num), pg_num_target − pg_num)      # split، هنوز بدون جابه‌جایی
target = min(pg_num_pending, pgp_num_target)
اگر inactive یا degraded یا unknown > 0  یا  misplaced > 0.05: صبر
اگر pool تقریباً خالی است (اشیا ≤ pgp_num_target): pgp_num = target یک‌جا
وگرنه: room = min(0.05 − misplaced, 0.025) ؛ estmax = max(⌊pg_num × room⌋, 1)
       pgp_num = clamp(target, pgp_num − estmax, pgp_num + estmax)       # جابه‌جایی واقعی اینجاست

اندازه‌گیری. برای هر دو برابر شدن، نگاشت ‏PG‏ فرزند ‏ps + n‏ با نگاشت ‏PG‏ والد ‏ps‏ در ‏osdmap‏ قبلی مقایسه شد (‏pgp_num‏ برابر ‏pg_num‏). در همه‌ی گام‌ها از ۲۵۶ به ۵۱۲ تا ۳۲۷۶۸ به ۶۵۵۳۶، حدود ۹۲٪ فرزندها روی هر سه ‏OSD‏ جدید نشستند و بقیه تقریباً همه روی دو ‏OSD‏ جدید. در مجموع ۴۸.۶ تا ۴۹.۲ درصد کل داده جابه‌جا شد. هیچ ‏PG‏ والدی جای خود را عوض نکرد.

این عدد با یک برآورد ساده می‌خواند. نیمی از داده به فرزندها می‌رود. احتمال اینکه یک ‏replica‏ فرزند تصادفاً روی یکی از ‏OSD‏های والد بنشیند حدود ۳/۱۲۰ است. پس ۰.۵ × (۱ − ۳/۱۲۰) ≈ ۴۸.۷۵٪.

تا وقتی ‏pgp_num‏ بالا نرفته، فرزند با ‏ceph_stable_mod(ps, pgp_num, mask)‏ به همان جای والد نگاشت می‌شود و ‏split‏ فقط فراداده است. جابه‌جایی واقعی با بالا رفتن ‏pgp_num‏ رخ می‌دهد.

مدل کنترل‌گر نشان می‌دهد که ‏mgr‏ این جابه‌جایی را در گام‌هایی به اندازه‌ی حدود ۲.۵٪ ‏pg_num‏ پخش می‌کند. شبیه‌سازی ۱۰۲۴ به ۲۰۴۸ با فرض پایان ‏backfill‏ پیش از هر دور، ۲۷ گام می‌دهد که نخستینشان ۱۰۲۴ به ۱۰۵۲ است. پس افزایش ‏pg_num‏ روی ‏pool‏ پر، معادل جابه‌جایی نیمی از داده‌ی ‏pool‏ است و بسته به حجم چند ساعت تا چند روز طول می‌کشد.

شکل ۱۹-۹: چپ: پس از دو برابر شدن pg_num و pgp_num ، چند درصد PG های فرزند روی ۰، ۱، ۲ یا ۳ OSD تازه می‌نشینند، و سهم کل داده‌ی جابه‌جاشده (حدود ۴۸.۷٪)، اندازه‌گیری‌شده با osdmaptool روی ۱۲۰ OSD . راست: مدل کنترل‌گر adjust_pgs در mgr برای ۱۰۲۴ به ۲۰۴۸، با سقف فاصله‌ی ۱۲۸ بین pg_num و pgp_num و گام pgp برابر pg_num × min (۰.۰۵ − misplaced, 0.025 )، با فرض پایان backfill پیش از هر دور
شکل ۱۹-۹: چپ: پس از دو برابر شدن ‏pg_num‏ و ‏pgp_num‏، چند درصد ‏PG‏های فرزند روی ۰، ۱، ۲ یا ۳ ‏OSD‏ تازه می‌نشینند، و سهم کل داده‌ی جابه‌جاشده (حدود ۴۸.۷٪)، اندازه‌گیری‌شده با ‏osdmaptool‏ روی ۱۲۰ ‏OSD‏. راست: مدل کنترل‌گر ‏adjust_pgs‏ در ‏mgr‏ برای ۱۰۲۴ به ۲۰۴۸، با سقف فاصله‌ی ۱۲۸ بین ‏pg_num‏ و ‏pgp_num‏ و گام ‏pgp‏ برابر ‏pg_num‏ × ‏min‏(۰.۰۵ − ‏misplaced, 0.025‏)، با فرض پایان ‏backfill‏ پیش از هر دور

۱۹-۹ مدیریت پیکربندی#

از ‏Mimic‏، پیکربندی مرکزی در پایگاه داده‌ی ‏MON‏ نگه‌داری می‌شود و ‏ceph.conf‏ روی میزبان‌ها فقط برای یافتن ‏MON‏ها لازم است. این یعنی تغییرات پیکربندی قابل ردیابی، قابل بازگشت و یکسان روی همه‌ی ‏daemon‏ها هستند.

bashReef+
ceph config dump | head
ceph config get osd.12 osd_memory_target
ceph config show osd.12 | grep -E "osd_memory_target|osd_max_backfills"   # مقدار مؤثر و منبع آن
ceph config set osd/class:hdd osd_memory_target 6G                       # mask بر اساس device class
ceph config set osd.12 debug_osd 10/10                                   # موقت برای عیب‌یابی
ceph config rm osd.12 debug_osd
ceph config log 20                                                        # تاریخچه‌ی تغییرات
ceph config reset 1234                                                    # بازگشت به نسخه‌ی مشخص
ceph config help osd_op_queue
💡 نکته

‏ceph config log‏ و ‏ceph config reset <num>‏ ابزار بازگشت سریع پس از تغییر اشتباه هستند. پیش از هر تغییر گسترده، شماره‌ی آخرین ورودی ‏log‏ را یادداشت کنید.

⚠ هشدار

تنظیماتی که با ‏ceph tell osd.* injectargs‏ یا ‏ceph daemon ... config set‏ اعمال می‌شوند موقتاند و پس از راه‌اندازی دوباره از بین می‌روند. برای ماندگاری، ‏ceph config set‏ به کار ببرید؛ برای تغییر موقت در حادثه، آگاهانه از ‏tell‏ استفاده کنید و در لاگ حادثه ثبت کنید.

۱۹-۱۰ پرچم‌های نگه‌داری#

پرچماثرکاربرد
‏noout‏‏OSD‏های ‏down‏ به ‏out‏ نمی‌روندنگه‌داری کوتاه (ترجیحاً ‏set-group‏ برای یک میزبان)
‏norebalance‏جابه‌جایی برای متعادل‌سازی متوقفتغییرات پی‌درپی ‏CRUSH‏
‏nobackfill‏ / ‏norecover‏‏backfill‏ یا ‏recovery‏ متوقفکاهش بار در زمان اوج (موقت و خطرناک)
‏noscrub‏ / ‏nodeep-scrub‏‏scrub‏ جدید شروع نمی‌شودارتقا یا بار سنگین
‏pause‏همه‌ی خواندن و نوشتن متوقففقط شرایط اضطراری خاص
bashReef+
ceph osd set-group noout stor-b3          # فقط OSDهای یک میزبان
ceph osd unset-group noout stor-b3
ceph osd set norebalance && ceph osd unset norebalance

۱۹-۱۱ کارهای دوره‌ای#

بازهکار
روزانه‏ceph -s‏، هشدارهای تازه، ‏ceph crash ls-new‏، پری (‏ceph df‏)
هفتگی‏ceph osd df tree‏ (‏VAR‏ و ‏PGS‏)، ‏deep scrub‏های عقب‌افتاده، وضعیت ‏mirroring‏ و ‏multisite‏
ماهانهبررسی نسخه‌ها و انتشارهای نقطه‌ای، بازبینی ‏SMART‏ دیسک‌ها (‏ceph device ls‏)، آزمون بازیابی
فصلیتمرین ‏failover‏، بازبینی ظرفیت و پیش‌بینی رشد، بازبینی ‏cap‏ها و کلیدها
✎ یادداشت

ماژول ‏devicehealth‏ در ‏mgr‏ داده‌ی ‏SMART‏ دیسک‌ها را جمع می‌کند: ‏ceph device ls‏، ‏ceph device get-health-metrics <devid>‏ و پیش‌بینی خرابی با ‏ceph device predict-life-expectancy <devid>‏؛ پیش‌بینی به‌صورت پیش‌فرض خاموش است (‏device_failure_prediction_mode=none‏) و برای حالت ‏local‏ باید ماژول ‏diskprediction_local‏ را فعال کنید. با ‏mgr/devicehealth/mark_out_threshold‏ می‌توان ‏OSD‏ دیسک رو به خرابی را پیش از خرابی خودکار ‏out‏ کرد.

نکات ‏SRE‏ این فصل
  • ارتقا را فقط روی کلاستر سالم و پس از خواندن یادداشت‌های انتشار شروع کنید.
  • پس از ارتقا به ‏Umbrella‏، تغییر پیش‌فرض ‏mon_target_pg_per_osd‏ (۱۰۰ به ۲۰۰) را مدیریت کنید.
  • برای جایگزینی دیسک همیشه ‏--replace‏ را به کار ببرید.
  • ‏noout‏ را با ‏set-group‏ برای یک میزبان و موقت تنظیم کنید.
  • ‏pool‏های بزرگ را از ابتدا ‏bulk‏ کنید.
  • همه‌ی تغییرات پیکربندی را با ‏ceph config‏ و قابل بازگشت انجام دهید.

۱۹-۱۲ تکمیلی و به‌روز#

  • ارتقای ‏OSD‏ بر اساس ‏bucket CRUSH‏ و فرمان ‏ceph osd ok-to-upgrade‏ در مستندات ‏Umbrella‏ آمده است.
  • در ‏Umbrella‏، پیش‌فرض ‏mon_target_pg_per_osd‏ به ۲۰۰ رسیده و گرد کردن ‏PG‏ها با بهینه‌سازی سراسری انجام می‌شود.
  • ‏ceph-deploy‏ بایگانی شده و همه‌ی روال‌ها با ‏cephadm‏ انجام می‌شوند؛ ‏ceph-ansible‏ همچنان «فعلاً» نگه‌داری می‌شود و مهاجرت به ‏cephadm‏ توصیه شده است (فصل ۱۱).
  • ‏read balancer‏ از ‏Reef‏ برای متوازن کردن ‏primary‏ها در دسترس است.

۱۹-۱۳ تمرین عملی#

  1. ۱. یک ارتقای نقطه‌ای در کلاستر آزمایشی انجام دهید و ترتیب ارتقای ‏daemon‏ها را از ‏ceph -W cephadm‏ ثبت کنید.
  2. ۲. یک ‏OSD‏ را با ‏--replace‏ حذف و دوباره بسازید؛ مقدار داده‌ی ‏backfill‏‌شده را با حذف بدون ‏--replace‏ مقایسه کنید.
  3. ۳. یک میزبان را به حالت نگه‌داری ببرید و پرچم ‏noout‏ گروهی را در ‏ceph osd dump‏ ببینید.
  4. ۴. خروجی ‏ceph osd pool autoscale-status‏ را پیش و پس از تنظیم ‏bulk‏ و ‏target_size_ratio‏ مقایسه کنید.
  5. ۵. ‏upmap_max_deviation‏ را به ۱ کاهش دهید و تغییر ستون ‏PGS‏ در ‏ceph osd df‏ را دنبال کنید.
  6. ۶. در ‏pg_autoscaler/module.py‏ جای اعمال ‏pg_num_min‏ و ‏pg_num_max‏ را پیدا کنید.

۱۹-۱۴ پرسش‌های مرور#

  1. ۱. ترتیب ارتقای ‏daemon‏ها در ‏cephadm‏ چیست و چرا ‏mgr‏ اول است؟
  2. ۲. ارتقای ‏OSD‏ بر اساس ‏bucket CRUSH‏ چه مزیتی دارد؟
  3. ۳. چرا ‏--replace‏ جابه‌جایی داده را کم می‌کند؟
  4. ۴. ‏maintenance enter‏ چه کاری با پرچم ‏noout‏ انجام می‌دهد؟
  5. ۵. فرمول پایه‌ی ‏pg_target‏ در ‏autoscaler‏ چیست؟
  6. ۶. آستانه‌ی ‏autoscaler‏ چه مشکلی را حل می‌کند و آستانه‌ی پویا چه زمانی اعمال می‌شود؟
  7. ۷. تغییر پیش‌فرض ‏mon_target_pg_per_osd‏ در ‏Umbrella‏ چه پیامدی دارد؟
  8. ۸. ‏upmap balancer‏ چگونه ‏PG‏ی را برای جابه‌جایی انتخاب می‌کند؟
  9. ۹. چرا ‏upmap‏ ایمن‌تر از تغییر دستی وزن‌هاست؟
  10. ۱۰. تفاوت ‏ceph config set‏ و ‏injectargs‏ چیست؟

پاسخ این پرسش‌ها در پیوست ه: پاسخ پرسش‌ها آمده است. پاسخ پرسش‌های این فصل →

۱۹-۱۵ منابع این فصل#

راهنمای جامع Ceph · ۱٫۶ · آبان ۱۴۰۵
© 2026 Ramin Najarbashi · CC BY-NC-SA 4.0

حریم خصوصی: این سایت کوکی نمی‌گذارد. برای شمارش بازدیدها از Cloudflare Web Analytics استفاده می‌شود که کوکی ندارد و افراد را دنبال نمی‌کند.