Skip to content

فصل ۱۴ — ساخت کلاسترها به‌صورت کد

فصل ۳ کلاستر میزبانی برنامه را به‌عنوان سرویسی توصیف کرد که به‌صورت پویا نمونه‌های برنامه را در مجموعه‌ای از سرورها deploy و اجرا می‌کند («Compute Resources» در صفحه ۲۸). مثال‌های سیستم‌های کلاستر برنامه شامل Kubernetes، AWS ECS، HashiCorp Nomad، Mesos و Pivotal Diego است. این مدل نگرانی‌های orchestrate کردن برنامه‌ها را از نگرانی‌های provisioning و پیکربندی سرورهایی که روی آن‌ها اجرا می‌شوند جدا می‌کند (شکل ۱۴-۱ را ببینید).

شکل ۱۴-۱. کلاستر برنامه لایه‌ای بین منابع زیرساخت و برنامه‌های در حال اجرا روی آن‌ها ایجاد می‌کند

البته باید از کد برای تعریف و مدیریت کلاستر برنامه استفاده کنید. همان‌طور که در فصل ۱۰ توضیح داده شد، می‌توانید کلاستر برنامه را به‌عنوان یک یا چند application stack به‌صورت کد بسازید. در این فصل چند نمونه از شکل این کار را می‌دهم. چند topology stack مختلف نشان می‌دهم، از جمله یک stack واحد برای کل کلاستر و شکستن کلاسترها در چند stack («Stack Topologies for Application Clusters» در صفحه ۲۳۲). نمودارهایی برای pipelineهای تحویل تغییرات کد زیرساخت برای این topologyها هم می‌آورم.

همچنین استراتژی‌های اشتراک‌گذاری کلاسترها — یا عدم اشتراک — بین محیط‌ها و تیم‌ها را بحث می‌کنم («Sharing Strategies for Application Clusters» در صفحه ۲۴۱). فصل را با بحث زیرساخت برای برنامه‌های serverless FaaS می‌بندم («Infrastructure for FaaS Serverless» در صفحه ۲۴۶).

کانتینرها به‌صورت کد

یکی از نقاط قوت بسیار کانتینرها این است که به‌صورت کد تعریف می‌شوند. image کانتینر یک‌بار از فایل تعریف ساخته می‌شود، سپس برای ایجاد چند نمونه استفاده می‌شود. برای استفاده مؤثر از کانتینرها، ضروری است آن‌ها را immutable و stateless treat کنید.

محتوای نمونه کانتینر را تغییر ندهید؛ در عوض تعریف را تغییر دهید، image جدید بسازید و سپس نمونه را جایگزین کنید. و state را درون کانتینر ذخیره نکنید. در عوض state و داده را با منابع زیرساخت دیگر ذخیره کنید («Data Continuity in a Changing System» در صفحه ۳۸۲ در فصل ۲۱).

ماهیت immutable و stateless کانتینرها آن‌ها را کاملاً مناسب ماهیت پویا پلتفرم‌های cloud می‌کند، به همین دلیل با معماری‌های cloud native این‌قدر مرتبط‌اند («Cloud Native and Application-Driven Infrastructure» در صفحه ۱۵۶).

راه‌حل‌های کلاستر برنامه

دو رویکرد اصلی برای پیاده‌سازی و نگه‌داری کلاستر برنامه وجود دارد. یکی استفاده از managed cluster به‌عنوان سرویس است، معمولاً به‌عنوان بخشی از پلتفرم زیرساخت شما. دیگری deploy کردن راه‌حل کلاستر بسته‌بندی‌شده روی منابع زیرساخت سطح پایین‌تر است.

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

بیشتر پلتفرم‌های زیرساخت سرویس کلاستر managed ارائه می‌دهند. می‌توانید کلاستر را به‌صورت کد با ابزار پیکربندی stack تعریف، provision و تغییر دهید. استفاده از کلاستر به‌عنوان سرویس یعنی ایجاد stackی که کلاستر و عناصر پشتیبان را شامل شود.

بسیاری از این کلاسترها مبتنی بر Kubernetes هستند، از جمله EKS، AKS و GKE. برخی دیگر مبتنی بر سرویس کانتینر اختصاصی هستند، مثل ECS.

کلاسترهای Kubernetes مدیریت‌شده لایه abstraction cloud نیستند

در نگاه اول، کلاسترهای Kubernetes مدیریت‌شده توسط فروشنده راه‌حل عالی برای توسعه و اجرای برنامه‌ها به‌صورت شفاف در پلتفرم‌های cloud مختلف به نظر می‌رسند. حالا می‌توانید برای Kubernetes بسازید و روی هر cloudی که دوست دارید اجرا کنید!

در عمل، اگرچه کلاستر برنامه ممکن است بخشی مفید از لایه runtime برنامه شما باشد، کار بسیار بیشتری برای ایجاد پلتفرم runtime کامل لازم است. و دستیابی به abstraction واقعی از پلتفرم‌های cloud زیرین ساده نیست.

برنامه‌ها به منابع دیگری غیر از compute ارائه‌شده توسط کلاستر نیاز دارند، از جمله storage و networking. این منابع توسط پلتفرم‌های مختلف متفاوت ارائه می‌شوند، مگر راه‌حلی برای abstraction آن‌ها بسازید.

همچنین باید سرویس‌هایی مثل monitoring، identity management و secrets management فراهم کنید. باز هم یا سرویس متفاوتی در هر پلتفرم cloud استفاده می‌کنید، یا سرویس یا لایه abstractionی می‌سازید که در هر cloud deploy و نگه دارید.

پس کلاستر برنامه در واقع بخش کوچکی از پلتفرم میزبانی برنامه کلی شماست. و حتی آن بخش هم تمایل دارد از cloudی به cloud دیگر متفاوت باشد — با version، پیاده‌سازی و ابزارهای مختلف برای سیستم هسته Kubernetes.

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

بسیاری تیم‌ها ترجیح می‌دهند کلاسترهای برنامه را خودشان نصب و مدیریت کنند به‌جای استفاده از کلاسترهای managed. Kubernetes محبوب‌ترین راه‌حل هسته کلاستر است.

می‌توانید از installerهایی مثل kops، Kubeadm و kubespray برای deploy Kubernetes روی زیرساختی که برای آن provision کرده‌اید استفاده کنید.

توزیع‌های Kubernetes بسته‌بندی‌شده هم هستند که سرویس‌ها و ویژگی‌های دیگر را bundle می‌کنند. ده‌ها مورد از این‌ها وجود دارد، از جمله:¹

  • HPE Container Platform (Hewlett Packard)
  • OpenShift (Red Hat)
  • Pivotal Container Services (PKS) (VMware/Pivotal)
  • Rancher RKE

برخی این محصولات با format کانتینر و سرویس‌های زمان‌بندی و orchestration برنامه خودشان شروع کردند. بسیاری تصمیم گرفتند هسته محصولاتشان را حول Docker و Kubernetes که به‌طور غالب محبوب شده‌اند بازسازی کنند به‌جای ادامه توسعه راه‌حل‌های خودشان.

اما تعداد کمی محصول مقاومت کرده‌اند در برابر جذب به borg Kubernetes. این‌ها شامل HashiCorp Nomad و Apache Mesos هستند که هر دو می‌توانند نمونه‌های کانتینر و همچنین برنامه‌های غیرکانتینری را در منابع compute مختلف orchestrate کنند. Cloud Foundry Application Runtime (CFAR) orchestration کانتینر خودش (Diego) را دارد، اگرچه می‌تواند با Kubernetes هم استفاده شود.²

Topologyهای stack برای کلاسترهای برنامه

کلاستر برنامه از قطعات متحرک مختلف تشکیل شده. یک مجموعه قطعات، برنامه‌ها و سرویس‌هایی‌اند که کلاستر را مدیریت می‌کنند. برخی این سرویس‌های مدیریت کلاستر:

  • Scheduler — تصمیم می‌گیرد چند نمونه از هر برنامه اجرا شود و کجا اجرا شوند
  • Monitoring — برای تشخیص مسائل نمونه‌های برنامه تا در صورت لزوم restart یا جابه‌جایی شوند
  • Configuration registry — برای ذخیره اطلاعات لازم مدیریت کلاستر و پیکربندی برنامه‌ها
  • Service discovery — به برنامه‌ها و سرویس‌ها امکان می‌دهد موقعیت فعلی نمونه‌های برنامه را پیدا کنند
  • Management API و UI — به ابزارها و کاربران امکان تعامل با کلاستر می‌دهد

بسیاری deploy کلاستر سرویس‌های مدیریت را روی سرورهای اختصاصی، جدا از سرویس‌هایی که نمونه‌های برنامه را host می‌کنند اجرا می‌کنند. این سرویس‌ها هم احتمالاً باید clustered اجرا شوند، برای تاب‌آوری.

قطعات اصلی دیگر کلاستر برنامه، nodeهای میزبانی برنامه هستند. این nodeها مجموعه‌ای از سرورها هستند که scheduler نمونه‌های برنامه را روی آن‌ها اجرا می‌کند. رایج است آن‌ها را به‌عنوان server cluster راه‌اندازی کنید («Compute Resources» در صفحه ۲۸) تا تعداد و موقعیت نمونه‌های سرور مدیریت شود. service mesh («Service Mesh» در صفحه ۲۴۴) ممکن است فرایندهای sidecar را روی nodeهای host، در کنار نمونه‌های برنامه اجرا کند.

یک کلاستر برنامه نمونه (شکل ۱۴-۲) شامل سرورهایی برای اجرای سرویس‌های مدیریت کلاستر، server cluster برای اجرای نمونه‌های برنامه و بلوک‌های آدرس شبکه است.

شکل ۱۴-۲. یک کلاستر برنامه نمونه

ساختارهای networking برای کلاستر برنامه ممکن است flat باشند. سرویس‌های کلاستر آدرس‌های شبکه را به نمونه‌های برنامه تخصیص می‌دهند. همچنین باید امنیت شبکه — از جمله رمزنگاری و مدیریت اتصال — را مدیریت کند، اغلب با service mesh برای این کار.

از stackهای زیرساخت برای provision این زیرساخت استفاده می‌کنید. فصل ۵ توضیح داد اندازه stack و دامنه محتوای آن برای سرعت و ریسک تغییرات پیامد دارد.

«Patterns and Antipatterns for Structuring Stacks» در صفحه ۵۶ به‌ویژه الگوهایی برای چیدمان منابع در stackها فهرست می‌کند. مثال‌های زیر نشان می‌دهند این الگوها چگونه به زیرساخت کلاستر اعمال می‌شوند.

stack یکپارچه با کلاستر به‌عنوان سرویس

ساده‌ترین طراحی تعریف همه قطعات کلاستر در یک stack است، با پیروی از ضدالگوی stack یکپارچه («Antipattern: Monolithic Stack» در صفحه ۵۶). اگرچه monolith در مقیاس ضدالگو می‌شود، یک stack واحد وقتی با کلاستر کوچک و ساده شروع می‌کنید مفید است.

مثال ۱۴-۱ از کلاستر به‌عنوان سرویس استفاده می‌کند، مشابه AWS EKS، AWS ECS، Azure AKS و Google GKE. پس کد کلاستر را تعریف می‌کند، اما نیازی به provision سرور برای اجرای مدیریت کلاستر ندارد چون پلتفرم زیرساخت آن را پشت صحنه مدیریت می‌کند.

مثال ۱۴-۱. کد stack که همه چیز برای کلاستر را تعریف می‌کند

yaml
address_block:
  name: cluster_network
  address_range: 10.1.0.0/16"
  vlans:
    - vlan_a:
         address_range: 10.1.0.0/8
    - vlan_b:
         address_range: 10.1.1.0/8
    - vlan_c:
         address_range: 10.1.2.0/8

application_cluster:
  name: product_application_cluster
  address_block: $address_block.cluster_network

server_cluster:
  name: "cluster_nodes"
  min_size: 1
  max_size: 3
  vlans: $address_block.cluster_network.vlans
  each_server_node:
    source_image: cluster_node_image
    memory: 8GB

این مثال بسیاری چیزهایی که برای کلاستر واقعی دارید — مثل مسیرهای شبکه، سیاست‌های امنیتی و monitoring — را حذف کرده. اما نشان می‌دهد عناصر مهم networking، تعریف کلاستر و مجموعه سرور برای nodeهای host همه در یک پروژه‌اند.

stack یکپارچه برای راه‌حل کلاستر بسته‌بندی‌شده

کد مثال ۱۴-۱ از سرویس کلاستر برنامه ارائه‌شده توسط پلتفرم زیرساخت استفاده می‌کند. بسیاری تیم‌ها در عوض از راه‌حل کلاستر برنامه بسته‌بندی‌شده استفاده می‌کنند (همان‌طور که در «Packaged Cluster Distribution» در صفحه ۲۳۱ توضیح داده شد). این راه‌حل‌ها installerهایی دارند که نرم‌افزار مدیریت کلاستر را روی سرورها deploy می‌کنند.

وقتی از یکی از این راه‌حل‌ها استفاده می‌کنید، stack زیرساخت شما زیرساختی را که installer برای deploy و پیکربندی کلاستر نیاز دارد provision می‌کند. اجرای installer باید گام جدا باشد. این‌طور می‌توانید stack زیرساخت را جدا از کلاستر برنامه تست کنید. امیدوارانه می‌توانید پیکربندی کلاستر را به‌صورت کد تعریف کنید. اگر چنین است، می‌توانید آن کد را با تست و pipeline مناسب مدیریت کنید تا به‌روزرسانی‌ها و تغییرات را آسان و ایمن تحویل دهید.

ممکن است مفید باشد از کد پیکربندی سرور (همان‌طور که در فصل ۱۱) برای deploy سیستم مدیریت کلاستر روی سرورها استفاده کنید. بعضی محصولات بسته‌بندی‌شده از ابزارهای پیکربندی استاندارد — مثل Ansible برای OpenShift — استفاده می‌کنند، پس شاید بتوانید آن‌ها را در فرایند ساخت stack بگنجانید. مثال ۱۴-۲ snippetی است که به کد stack یکپارچه مثال ۱۴-۱ اضافه می‌کنید تا سروری برای برنامه مدیریت کلاستر بسازد.

مثال ۱۴-۲. کد ساخت سرور مدیریت کلاستر

yaml
virtual_machine:
  name: cluster_manager
  source_image: linux-base
  memory: 4GB
  provision:
    tool: servermaker
    parameters:
      maker_server: maker.shopspinner.xyz
      role: cluster_manager

کد سرور را با اجرای دستور خیالی servermaker پیکربندی می‌کند و نقش cluster_manager را اعمال می‌کند.

pipeline برای stack کلاستر برنامه یکپارچه

چون فقط یک stack وجود دارد، یک pipeline می‌تواند تغییرات کد را به نمونه‌های کلاستر برنامه تست و تحویل دهد. اما عناصر دیگری هم درگیرند، از جمله image سرور برای nodeهای host و خود برنامه‌ها.

شکل ۱۴-۳ طراحی بالقوه این pipelineها را نشان می‌دهد.

شکل ۱۴-۳. نمونه‌ای از pipelineها برای کلاستر با stack یکپارچه

pipeline بالایی (شکل ۱۴-۴) image سرور برای nodeهای host می‌سازد، همان‌طور که در «Using a Pipeline to Test and Deliver a Server Image» در صفحه ۲۲۱ توضیح داده شد. نتیجه این pipeline image سروری است که به‌صورت ایزوله تست شده. تست‌های آن image احتمالاً بررسی می‌کنند نرم‌افزار مدیریت کانتینر نصب شده و با سیاست‌های امنیتی مطابقت دارد.

شکل ۱۴-۴. pipeline برای image سرور nodeهای host

pipeline پایینی (شکل ۱۴-۵) برای برنامه‌ای است که روی کلاستر deploy می‌شود. در عمل برای هر برنامه deploy‌شده جدا یکی از این‌ها دارید. این pipeline حداقل یک مرحله زودهنگام برای ساخت و تست برنامه به‌تنهایی دارد. سپس مراحلی دارد که برنامه را در هر محیط به کلاستر deploy می‌کند. برنامه در این محیط‌ها تست، بررسی و برای استفاده production در دسترس قرار می‌گیرد. pipelineهای برنامه با pipelineهای نمونه‌های کلاستر خیلی loosely coupled هستند. ممکن است انتخاب کنید مراحل تست برنامه را بعد از به‌روزرسانی کلاستر trigger کنید. این کمک می‌کند مسائلی که تغییر کلاستر برای برنامه ایجاد می‌کند را با اجرای تست‌های مختص برنامه پیدا کنید.

شکل ۱۴-۵. pipelineها برای تحویل برنامه‌ها به کلاستر

pipeline برای stack کلاستر برنامه در شکل ۱۴-۶ با مرحله آفلاین («Offline Testing Stages for Stacks» در صفحه ۱۳۱) شروع می‌شود که بررسی syntax و اعمال کد stack به mock محلی پلتفرم زیرساخت («Testing with a Mock API» در صفحه ۱۳۳) را اجرا می‌کند. این تست‌ها مشکلات در سطح کدنویسی را بدون نیاز به منابع پلتفرم زیرساخت می‌گیرند، پس سریع اجرا می‌شوند.

شکل ۱۴-۶. pipeline برای کد stack کلاستر

مرحله دوم این pipeline مرحله آنلاین است («Online Testing Stages for Stacks» در صفحه ۱۳۴) و نمونه‌ای از stack روی پلتفرم زیرساخت ایجاد می‌کند. نمونه ممکن است persistent («Pattern: Persistent Test Stack» در صفحه ۱۴۲) یا ephemeral («Pattern: Ephemeral Test Stack» در صفحه ۱۴۳) باشد. تست‌های این مرحله می‌توانند بررسی کنند سرویس‌های مدیریت کلاستر درست ایجاد و در دسترس‌اند. همچنین می‌توانید مسائل امنیتی را تست کنید — مثلاً اطمینان از قفل بودن دسترسی به endpointهای مدیریت کلاستر.³

چون این stack کلاستر یکپارچه کد ایجاد سرورهای node host را شامل می‌شود، مرحله تست آنلاین می‌تواند آن‌ها را هم تست کند. تست می‌تواند برنامه نمونه را به کلاستر deploy کند و ثابت کند کار می‌کند. مزیت استفاده از برنامه نمونه به‌جای برنامه واقعی این است که می‌توانید آن را ساده نگه دارید. به حداقل وابستگی‌ها و پیکربندی‌ها کاهش دهید تا مطمئن شوید هر failure تست به‌خاطر مسائل provisioning کلاستر است، نه پیچیدگی deploy برنامه دنیای واقعی.

توجه کنید این مرحله pipeline سنگین است. هم پیکربندی کلاستر و هم server cluster nodeهای host را تست می‌کند. همچنین image سرور را در context کلاستر تست می‌کند. چیزهای مختلفی می‌توانند باعث fail این مرحله شوند که troubleshooting و رفع failure را پیچیده می‌کند.

بیشتر زمان سپری‌شده این مرحله تقریباً قطعاً صرف provision همه چیز می‌شود، خیلی بیشتر از زمان اجرای تست‌ها. این دو مسئله — تنوع چیزهای تست‌شده در یک مرحله و زمان provision — محرک‌های اصلی شکستن کلاستر به چند stack هستند.

نمونه چند stack برای کلاستر

شکستن کد زیرساخت کلاستر به چند stack می‌تواند قابلیت اطمینان و سرعت فرایند تغییرات را بهبود دهد. هدف طراحی هر stack طوری باشد که بتوانید آن را به‌صورت ایزوله provision و تست کنید، بدون نیاز به provision نمونه stackهای دیگر.

با جدا کردن مجموعه سرور nodeهای host به stack جدا شروع کنید، همان‌طور که در مثال ۱۴-۳ است.

مثال ۱۴-۳. کد stack که مجموعه سرور nodeهای host را تعریف می‌کند

yaml
server_cluster:
  name: "cluster_nodes"
  min_size: 1
  max_size: 3
  vlans: $address_block.host_node_network.vlans
  each_server_node:
    source_image: cluster_node_image
    memory: 8GB

address_block:
  name: host_node_network
  address_range: 10.2.0.0/16"
  vlans:
    - vlan_a:
        address_range: 10.2.0.0/8
    - vlan_b:
        address_range: 10.2.1.0/8
    - vlan_c:
        address_range: 10.2.2.0/8

این کد VLANهای جدا برای nodeهای host اضافه می‌کند، برخلاف کد قبلی stack یکپارچه (مثال ۱۴-۱ را ببینید). practice خوب است nodeهای host و مدیریت کلاستر را در segmentهای شبکه مختلف تقسیم کنید — که می‌توانستید در stack یکپارچه هم انجام دهید. شکستن stackها ما را به این کار وادار می‌کند، اگر فقط برای کاهش coupling بین دو stack.

شکستن stackها pipeline جدیدی برای stack کلاستر nodeهای host اضافه می‌کند، همان‌طور که در شکل ۱۴-۷ نشان داده شده.

شکل ۱۴-۷. pipeline اضافه‌شده برای مجموعه nodeهای host

اگرچه چند مرحله بیشتر در این pipeline ترکیبی هستند، سبک‌تر و سریع‌ترند. مرحله تست آنلاین برای stack مدیریت کلاستر (highlight شده در شکل ۱۴-۸) فقط زیرساخت مدیریت کلاستر را provision می‌کند که سریع‌تر از مرحله آنلاین در pipeline stack یکپارچه است. این stack دیگر به pipeline image سرور nodeهای host وابسته نیست و nodeهای سرور را شامل نمی‌شود. پس تست‌های این مرحله می‌توانند روی بررسی پیکربندی و امنیت صحیح مدیریت کلاستر متمرکز شوند.

شکل ۱۴-۸. مراحل تست آنلاین برای pipelineهای کلاستر

این طراحی بازنگری‌شده pipeline stack سرور nodeهای host را با pipeline stack مدیریت کلاستر در مرحله stack integration به هم می‌چسباند، همان‌طور که در شکل ۱۴-۹ نشان داده شده.

شکل ۱۴-۹. مرحله تست stack integration برای کلاستر

این مرحله تست آنلاین است که نمونه‌های هر دو stack را با هم provision و تست می‌کند. این تست‌ها می‌توانند روی مسائلی متمرکز شوند که فقط با این ترکیب ظاهر می‌شوند، پس نباید فعالیت‌های تست مراحل قبلی را تکرار کنند. این مرحله‌ای است که برنامه نمونه deploy می‌کنید و ثابت می‌کنید روی کلاستر درست اجرا می‌شود. همچنین می‌توانید تاب‌آوری و scaling را با trigger کردن failure در برنامه تست و ایجاد شرایط لازم برای افزودن نمونه‌های اضافی تست کنید.

ممکن است تصمیم بگیرید به stackهای بیشتری تقسیم کنید؛ مثلاً جدا کردن زیرساخت networking مشترک از stack مدیریت. فصل‌های ۱۵ و ۱۷ جزئیات بیشتری درباره decompose و یکپارچه‌سازی زیرساخت در stackها می‌دهند.

استراتژی‌های اشتراک‌گذاری برای کلاسترهای برنامه

چند کلاستر باید اجرا کنید، هر کدام چقدر بزرگ باشند و چقدر روی هر کدام اجرا کنید؟

در تئوری می‌توانید یک کلاستر واحد اجرا کنید و محیط‌ها و مرزهای برنامه دیگر را درون نمونه کلاستر manifest کنید. اما دلایل زیادی هست که یک کلاستر واحد عملی نباشد:⁴

مدیریت تغییرات باید کلاستر را به‌روز، upgrade، fix و تغییر دهید. پس حداقل جایی برای تست این تغییرات نیاز دارید که سرویس‌ها را قطع نکند. برای تغییرات disruptive — مثل آن‌هایی که downtime می‌خواهند یا ریسک آن را دارند — زمان‌بندی زمانی که نیاز همه تیم‌ها، برنامه‌ها و منطقه‌ها را برآورده کند چالش‌برانگیز است. اجرای چند کلاستر زمان‌بندی پنجره‌های نگهداری را آسان‌تر و اثر تغییر ناموفق را کمتر می‌کند.

جداسازی (Segregation) بسیاری پیاده‌سازی‌های clustering segregation کافی بین برنامه‌ها، داده و پیکربندی ارائه نمی‌دهند. ممکن است regimeهای حاکمیت متفاوت برای پیاده‌سازی کلاستر بر اساس سرویس‌های روی آن داشته باشید. مثلاً سرویس‌هایی که شماره کارت اعتباری را handle می‌کنند ممکن است الزامات انطباق سخت‌گیرانه‌تری داشته باشند، پس اجرای آن‌ها روی کلاستر جدا الزامات کلاسترهای دیگر را ساده می‌کند.

قابلیت پیکربندی (Configurability) برخی برنامه‌ها یا تیم‌ها الزامات پیکربندی متفاوتی برای کلاسترهایی که استفاده می‌کنند دارند. دادن نمونه کلاستر جدا به آن‌ها تعارض پیکربندی را کاهش می‌دهد.

کارایی و مقیاس‌پذیری راه‌حل‌های clustering ویژگی‌های scaling متفاوتی دارند. بسیاری با latency بالاتر کنار نمی‌آیند که اجرای یک کلاستر واحد در مناطق جغرافیایی را غیرعملی می‌کند. برنامه‌ها ممکن است به محدودیت منابع یا contention با یکدیگر هنگام scale up روی یک کلاستر برخورد کنند.

دسترس‌پذیری (Availability) یک کلاستر واحد نقطه شکست واحد است. اجرای چند کلاستر می‌تواند در سناریوهای failure مختلف کمک کند.

چند استراتژی بالقوه برای اندازه و اشتراک‌گذاری نمونه‌های کلاستر وجود دارد. برای انتخاب استراتژی درست برای سیستم خود، الزامات جداسازی تغییر، قابلیت پیکربندی، کارایی، مقیاس، توزیع و دسترس‌پذیری را در نظر بگیرید. سپس راه‌حل clustering برنامه را در برابر آن الزامات تست کنید.

یک کلاستر بزرگ برای همه چیز

یک کلاستر واحد می‌تواند ساده‌تر از چند کلاستر مدیریت شود. استثنای محتمل مدیریت تغییرات است. پس حداقل باید حداقل یک نمونه کلاستر جدا برای تست تغییرات داشته باشید و از pipeline برای deploy و تست تغییرات پیکربندی کلاستر آنجا قبل از اعمال به کلاستر production استفاده کنید.

کلاسترهای جدا برای مراحل تحویل

می‌توانید کلاسترهای مختلف برای بخش‌های مختلف فرایند software delivery اجرا کنید. این می‌تواند به‌سادگی یک کلاستر برای هر محیط باشد (شکل ۱۴-۱۰ را ببینید).

شکل ۱۴-۱۰. pipelineها که یک کلاستر برای هر محیط deploy برنامه مدیریت می‌کنند

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

تغییری از جداسازی کلاسترها بر اساس مرحله تحویل، اشتراک کلاسترها در چند مرحله است. مثلاً ممکن است کلاسترهای مختلف بر اساس الزامات حاکمیت استفاده کنید. در شکل ۱۴-۱۱ سه کلاستر هست. کلاستر DEV برای توسعه است، نمونه‌هایی که مردم مجموعه داده‌های مختلف برای سناریوهای تست اکتشافی‌تر می‌سازند و استفاده می‌کنند. کلاستر NON-PROD برای مراحل تحویل سخت‌گیرانه‌تر با مجموعه داده‌های تست مدیریت‌شده. کلاستر PROD محیط‌های PREPROD و PROD را host می‌کند که هر دو داده مشتری دارند و پس الزامات حاکمیت سخت‌گیرانه‌تری دارند.

شکل ۱۴-۱۱. نمونه‌های کلاستر مشترک در چند محیط

وقتی چند محیط را در کلاستر مشترک host می‌کنید، باید هدف داشته باشید هر محیط تا حد امکان جدا نگه داشته شود. ایده‌آل این است برنامه‌ها و سرویس‌های عملیاتی نتوانند نمونه‌های محیط‌های دیگر را ببینند یا با آن‌ها تعامل کنند. بسیاری از مکانیزم‌هایی که راه‌حل‌های clustering برنامه برای جداسازی برنامه‌ها ارائه می‌دهند «نرم» هستند. مثلاً ممکن است بتوانید نمونه‌ها را tag کنید تا محیط را نشان دهند، اما این صرفاً قرارداد است. باید روش‌های قوی‌تری برای جداسازی برنامه‌ها جستجو کنید.

کلاسترها برای حاکمیت

یکی از مزایای داشتن کلاسترهای جدا برای بخش‌های مختلف فرایند تحویل این است که الزامات حاکمیت معمولاً برای مراحل مختلف فرایند متفاوت است. production الزامات سخت‌گیرانه‌تری دارد چون سرویس‌های آنجا business-criticalترین‌اند و داده حساس‌ترین است.

اغلب بخش‌های مختلف سیستم الزامات حاکمیت و انطباق متفاوتی دارند که مراحل تحویل را قطع می‌کنند. رایج‌ترین مثال سرویس‌هایی است که شماره کارت اعتباری را handle می‌کنند و مشمول استانداردهای PCI هستند. مثال‌های دیگر سرویس‌هایی با داده شخصی مشتری که ممکن است مشمول regimeهایی مثل GDPR باشند.

host کردن سرویس‌های مشمول استانداردهای سخت‌گیرانه‌تر روی کلاسترهای اختصاصی می‌تواند انطباق و auditing را ساده و تقویت کند. می‌توانید کنترل‌های قوی‌تری روی این کلاسترها، برنامه‌های روی آن‌ها و تحویل تغییرات کد به آن‌ها اعمال کنید. کلاسترهایی که سرویس‌های با الزامات انطباق کمتر سخت‌گیرانه host می‌کنند می‌توانند فرایندها و کنترل‌های حاکمیت ساده‌شده داشته باشند.

به‌عنوان مثال می‌توانید دو کلاستر داشته باشید، یکی برای توسعه، تست و production hosting سرویس‌های تنظیم‌شده و یکی برای سرویس‌های غیرتنظیم‌شده. یا نمونه‌های کلاستر را بر اساس مرحله تحویل و الزامات تنظیم‌گری تقسیم کنید، همان‌طور که در شکل ۱۴-۱۲ نشان داده شده.

شکل ۱۴-۱۲. کلاسترهای جدا برای مرحله تحویل و الزامات تنظیم‌گری

کلاسترها برای تیم‌ها

عامل دیگر سازمان‌دهی چند کلاستر مالکیت تیمی است. اغلب تیم‌های مختلف مسئول تحویل و اجرای انواع مختلف برنامه‌ها و سرویس‌ها هستند که ممکن است الزامات میزبانی متفاوتی داشته باشند. مثلاً تیمی که سرویس‌های customer-facing دارد ممکن است الزامات حاکمیت و دسترس‌پذیری متفاوتی از تیمی داشته باشد که سرویس‌های بخش داخلی را مالک است. کلاستر اختصاص‌یافته به تیم می‌تواند برای الزامات آن تیم و برنامه‌هایش بهینه شود.

Service Mesh

service mesh شبکه‌ای غیرمتمرکز از سرویس‌هاست که connectivity بین بخش‌های سیستم توزیع‌شده را به‌صورت پویا مدیریت می‌کند. قابلیت‌های networking را از لایه زیرساخت به لایه runtime برنامه در مدل توصیف‌شده در «The Parts of an Infrastructure System» در صفحه ۲۳ منتقل می‌کند. در پیاده‌سازی معمول service mesh، هر نمونه برنامه ارتباط با نمونه‌های دیگر را به فرایند sidecar واگذار می‌کند (شکل ۱۴-۱۳ را ببینید).

شکل ۱۴-۱۳. sidecarها ارتباط با فرایندهای دیگر در service mesh را ممکن می‌کنند

برخی سرویس‌هایی که service mesh می‌تواند به برنامه‌ها ارائه دهد:

Routing ترافیک را به مناسب‌ترین نمونه برنامه داده‌شده هدایت کند، هر جا در حال اجرا باشد. routing پویا با service mesh سناریوهای deploy پیشرفته مثل blue-green و canary را ممکن می‌کند، همان‌طور که در «Changing Live Infrastructure» در صفحه ۳۶۸ توضیح داده شده.

دسترس‌پذیری قوانین محدود کردن تعداد درخواست‌ها را enforce کند؛ مثلاً circuit breakerها.

امنیت رمزنگاری را handle کند، از جمله گواهی‌ها.

احراز هویت (Authentication) قوانین اینکه کدام سرویس‌ها به کدام متصل شوند enforce کند. گواهی‌ها را برای peer-to-peer authentication مدیریت کند.

مشاهده‌پذیری، monitoring و troubleshooting اتصالات و رویدادهای دیگر را ثبت کند تا مردم درخواست‌ها را در سیستم‌های توزیع‌شده پیچیده trace کنند.

service mesh در ترکیب با کلاستر میزبانی برنامه خوب کار می‌کند. کلاستر برنامه به‌صورت پویا منابع compute جدا از منابع سطح پایین‌تر فراهم می‌کند. service mesh ارتباط برنامه را جدا از منابع networking سطح پایین‌تر به‌صورت پویا مدیریت می‌کند. مزایای این مدل:

  • توسعه برنامه را ساده می‌کند، با انتقال نگرانی‌های مشترک از برنامه به sidecar.
  • ساخت و بهبود نگرانی‌های مشترک در estate را آسان‌تر می‌کند، چون فقط به‌روزرسانی sidecar را deploy می‌کنید بدون نیاز به تغییر کد همه برنامه‌ها و سرویس‌ها.
  • ماهیت پویای deploy برنامه را handle می‌کند، چون همان سیستم orchestration و scheduling که نمونه‌های برنامه را deploy و پیکربندی می‌کند (مثلاً در کانتینرها) می‌تواند نمونه‌های sidecar را همراه با آن‌ها deploy و پیکربندی کند.

برخی مثال‌های service mesh شامل HashiCorp Consul، Envoy، Istio و Linkerd هستند.

service meshها بیشتر با سیستم‌های کانتینری مرتبط‌اند. اما می‌توانید مدل را در سیستم‌های غیرکانتینری پیاده‌سازی کنید؛ مثلاً با deploy فرایندهای sidecar روی ماشین‌های مجازی.

service mesh پیچیدگی اضافه می‌کند. مانند مدل‌های معماری cloud native مثل microservices، service mesh جذاب است چون توسعه برنامه‌های فردی را ساده می‌کند. اما پیچیدگی ناپدید نمی‌شود؛ فقط به زیرساخت منتقل کرده‌اید. پس سازمان شما باید آماده مدیریت این باشد، از جمله آماده بودن برای فرایند یادگیری شیب‌دار.

ضروری است مرزهای واضح بین networking پیاده‌سازی‌شده در سطح زیرساخت و networking پیاده‌سازی‌شده در service mesh حفظ شود. بدون طراحی و انضباط پیاده‌سازی خوب، ممکن است نگرانی‌ها را duplicate و درهم آمیزه کنید. سیستم شما سخت‌تر فهمیده می‌شود، پرریسک‌تر برای تغییر و سخت‌تر برای troubleshooting.

زیرساخت برای FaaS Serverless

فصل ۳ FaaS serverless را یکی از روش‌هایی فهرست کرد که پلتفرم می‌تواند منابع compute را به برنامه‌ها ارائه دهد («Compute Resources» در صفحه ۲۸). مدل معمول برای کد برنامه اجرای مداوم آن در کانتینر یا سرور است. FaaS کد برنامه را on demand، در پاسخ به رویداد یا زمان‌بندی اجرا می‌کند.

کد FaaS برای actionهای کوتاه‌مدت و تعریف‌شده‌خوب مفید است که کد سریع شروع می‌شود. مثال‌های معمول handle کردن درخواست HTTP یا پاسخ به رویدادهای خطا در message queue است. پلتفرم وقتی لازم است چند نمونه کد را به‌صورت موازی launch می‌کند، مثلاً برای handle کردن چند رویداد همزمان.

FaaS می‌تواند برای workloadهایی که تقاضا خیلی متغیر است بسیار کارآمد باشد — scale up در اوج‌ها و اصلاً اجرا نشدن وقتی لازم نیست.

«Serverless» دقیق‌ترین اصطلاح برای این نیست، چون البته کد روی سرور اجرا می‌شود. فقط سرور برای شما به‌عنوان توسعه‌دهنده effectively نامرئی است. همین با کانتینرها هم صادق است، پس آنچه serverless را متمایز می‌کند سطح abstraction از سرورها نیست. تمایز واقعی serverless این است که فرایند کوتاه‌مدت است نه long-running.

به همین دلیل بسیاری اصطلاح FaaS را به serverless ترجیح می‌دهند. این هم از کاربردهای دیگر serverless — که می‌تواند Backend as a Service (BaaS) یعنی سرویس میزبانی‌شده خارجی — تفکیک می‌کند.⁵

runtimeهای FaaS همان مدل‌های کلاستر برنامه را دنبال می‌کنند — runtime FaaS ارائه‌شده به‌عنوان سرویس توسط پلتفرم زیرساخت شما، و FaaS بسته‌بندی‌شده که نیاز به provision و پیکربندی زیرساخت و ابزارهای مدیریت دارد.

مثال‌های runtime FaaS ارائه‌شده به‌عنوان سرویس:

  • AWS Lambda
  • Azure Functions
  • Google Cloud Functions

مثال‌های راه‌حل runtime FaaS بسته‌بندی‌شده:

  • Fission
  • Kubeless
  • OpenFaaS
  • Apache OpenWhisk

می‌توانید همان استراتژی‌های توضیح‌داده‌شده قبلاً در این فصل برای provision زیرساخت راه‌حل FaaS بسته‌بندی‌شده — مثل مجموعه سرورها و سرویس‌های مدیریت — استفاده کنید. مطمئن شوید عمیقاً می‌فهمید راه‌حل FaaS شما چگونه کار می‌کند تا آگاه باشید آیا و چگونه کد ممکن است داده «leak» کند. مثلاً ممکن است فایل‌های موقت و باقیمانده دیگر در مکان‌هایی بگذارد که برای کد FaaS دیگر در دسترس باشد، که مسائل امنیتی و انطباق ایجاد می‌کند. اینکه راه‌حل FaaS چقدر نیازهای شما برای جداسازی داده را برآورده می‌کند و آیا می‌تواند scale کند باید تصمیم‌گیری شما درباره اجرای چند نمونه runtime FaaS را هدایت کند.

سرویس‌های FaaS ارائه‌شده توسط فروشندگان cloud معمولاً چیز کمتری برای پیکربندی نسبت به کلاسترهای برنامه به شما می‌گذارند. مثلاً معمولاً نیازی به مشخص کردن اندازه و ماهیت سرورهای host که کد روی آن‌ها اجرا می‌شود ندارید. این مقدار زیرساختی که باید تعریف و مدیریت کنید را به‌شدت کاهش می‌دهد.

با این حال، بیشتر کد FaaS با سرویس‌ها و منابع دیگر تعامل دارد. ممکن است networking برای درخواست‌های inbound که برنامه FaaS را trigger می‌کنند و درخواست‌های outbound که کد می‌فرستد تعریف کنید. کد FaaS اغلب داده و پیام را به دستگاه‌های ذخیره‌سازی، پایگاه داده‌ها و message queue می‌خواند و می‌نویسد. همه این‌ها نیاز به تعریف و تست منابع زیرساخت دارند. و البته کد FaaS باید با pipeline تحویل و تست شود، مانند هر کد دیگر. پس هنوز به همه رویه‌ها درباره تعریف و promote کردن کد زیرساخت و یکپارچه‌سازی آن با فرایندهای تست برنامه نیاز دارید.

جمع‌بندی

زیرساخت compute برای پشتیبانی از سرویس‌ها وجود دارد. سرویس‌ها توسط نرم‌افزار برنامه ارائه می‌شوند که روی محیط runtime اجرا می‌شود. این فصل توضیح داد چگونه از کد برای تعریف زیرساختی استفاده کنید که محیط‌های runtime برای برنامه‌های سازمان شما فراهم می‌کند.


¹ فهرست توزیع‌های Kubernetes certified را در وب‌سایت Kubernetes ببینید.

² برای جزئیات بیشتر «CF Container Runtime» را ببینید.

³ Kubernetes تاریخاً مسائل اجازه استفاده از Management API بدون authentication داشته است. راهنماها را دنبال کنید تا مطمئن شوید اقدامات امن‌سازی کلاستر را انجام می‌دهید و تست بنویسید تا تغییرات کد و پیکربندی که تصادفاً راهی برای مهاجمان باز می‌کند متوقف شود.

⁴ Rob Hirschfeld trade-offهای بین اندازه و اشتراک‌گذاری کلاستر را در مقاله «The Optimal Kubernetes Cluster Size? Let's Look at the Data» بررسی می‌کند.

⁵ برای اطلاعات بیشتر مقاله قطعی Mike Roberts «Serverless Architectures» را ببینید.