10 اشتباه رایج هنگام استفاده از Kubernetes

توجه داشته باشید. ترجمه: نویسندگان این مقاله مهندسانی از یک شرکت کوچک چک، pipetail هستند. آنها موفق شدند فهرستی شگفت انگیز از مشکلات [گاهی پیش پا افتاده، اما هنوز] بسیار مبرم و تصورات غلط مربوط به عملکرد خوشه های Kubernetes را گردآوری کنند.

10 اشتباه رایج هنگام استفاده از Kubernetes

در طول سال‌ها استفاده از Kubernetes، ما با تعداد زیادی خوشه (هم مدیریت‌شده و هم بدون مدیریت - در GCP، AWS و Azure) کار کرده‌ایم. با گذشت زمان، متوجه شدیم که برخی از اشتباهات دائما تکرار می شوند. با این حال، هیچ شرمی در این وجود ندارد: ما بیشتر آنها را خودمان انجام داده ایم!

این مقاله شامل رایج ترین خطاها و همچنین نحوه اصلاح آنها است.

1. منابع: درخواست ها و محدودیت ها

این مورد قطعاً سزاوار بیشترین توجه و رتبه اول در لیست است.

معمولا درخواست CPU یا اصلا مشخص نشده یا مقدار بسیار کمی دارد (برای قرار دادن هر چه بیشتر غلاف روی هر گره). بنابراین، گره ها بیش از حد بارگذاری می شوند. در زمان‌های بار بالا، قدرت پردازش گره به‌طور کامل مورد استفاده قرار می‌گیرد و یک حجم کاری خاص فقط آنچه را که «درخواست» می‌کند، دریافت می‌کند. گاز دادن به CPU. این منجر به افزایش تاخیر برنامه، وقفه های زمانی و سایر پیامدهای ناخوشایند می شود. (در این مورد در ترجمه اخیر ما بیشتر بخوانید:محدودیت های CPU و throttling تهاجمی در Kubernetes" - تقریبا ترجمه.)

بهترین تلاش (به شدت هیچ توصیه شده):

resources: {}

درخواست CPU بسیار کم (بسیار هیچ توصیه شده):

   resources:
      Requests:
        cpu: "1m"

از سوی دیگر، وجود محدودیت CPU می‌تواند منجر به پرش غیرمنطقی چرخه‌های ساعت توسط پادها شود، حتی اگر پردازنده گره به طور کامل بارگذاری نشده باشد. باز هم، این می تواند منجر به افزایش تاخیر شود. بحث در مورد پارامتر ادامه دارد سهمیه CPU CFS در هسته لینوکس و CPU throttling بسته به محدودیت های تعیین شده، و همچنین غیرفعال کردن سهمیه CFS... افسوس، محدودیت های CPU می تواند مشکلات بیشتری را نسبت به حل آنها ایجاد کند. اطلاعات بیشتر در این مورد را می توانید در لینک زیر بیابید.

انتخاب بیش از حد (تعهد بیش از حد) مشکلات حافظه می تواند منجر به مشکلات بزرگتر شود. رسیدن به محدودیت CPU مستلزم پرش از چرخه های ساعت است، در حالی که رسیدن به محدودیت حافظه مستلزم از بین بردن پاد است. آیا تا به حال مشاهده کرده اید OOMkill? بله، این دقیقاً همان چیزی است که ما در مورد آن صحبت می کنیم.

آیا می خواهید احتمال این اتفاق را به حداقل برسانید؟ حافظه را بیش از حد تخصیص ندهید و با تنظیم درخواست حافظه روی محدودیت (مانند مثال زیر) از QoS تضمین شده (کیفیت خدمات) استفاده کنید. در این مورد بیشتر بخوانید ارائه های هنینگ جاکوبز (مهندس ارشد در Zalando).

قابل ترکیدن (احتمال بالاتر برای کشته شدن OOM):

   resources:
      requests:
        memory: "128Mi"
        cpu: "500m"
      limits:
        memory: "256Mi"
        cpu: 2

تضمین:

   resources:
      requests:
        memory: "128Mi"
        cpu: 2
      limits:
        memory: "128Mi"
        cpu: 2

چه چیزی به طور بالقوه هنگام تنظیم منابع کمک خواهد کرد؟

با متریک-سرور شما می توانید مصرف فعلی منابع CPU و استفاده از حافظه توسط پادها (و کانتینرهای داخل آنها) را مشاهده کنید. به احتمال زیاد، شما در حال استفاده از آن هستید. فقط دستورات زیر را اجرا کنید:

kubectl top pods
kubectl top pods --containers
kubectl top nodes

با این حال، آنها فقط استفاده فعلی را نشان می دهند. می تواند به شما یک ایده تقریبی از ترتیب بزرگی بدهد، اما در نهایت به شما نیاز خواهید داشت تاریخچه تغییرات معیارها در طول زمان (برای پاسخ دادن به سؤالاتی مانند: "اوج بار CPU چقدر بود؟"، "بار دیروز صبح چقدر بود؟" و غیره). برای این شما می توانید استفاده کنید تیتان فرزند پاپتوس, DataDog و ابزارهای دیگر آنها به سادگی معیارها را از سرور متریک دریافت می کنند و آنها را ذخیره می کنند، و کاربر می تواند آنها را پرس و جو کرده و بر اساس آن رسم کند.

VerticalPodAutoscaler اجازه می دهد تا خودکار کردن این فرآیند. تاریخچه استفاده از CPU و حافظه را ردیابی می کند و درخواست ها و محدودیت های جدیدی را بر اساس این اطلاعات تنظیم می کند.

استفاده بهینه از توان محاسباتی کار آسانی نیست. مثل این است که همیشه تتریس بازی کنید. اگر برای توان محاسباتی با مصرف متوسط ​​کم (مثلاً 10 درصد) هزینه زیادی می‌پردازید، توصیه می‌کنیم محصولات مبتنی بر AWS Fargate یا Virtual Kubelet را مشاهده کنید. آنها بر اساس یک مدل صورت‌حساب بدون سرور/پرداخت به ازای استفاده ساخته شده‌اند، که ممکن است در چنین شرایطی ارزان‌تر باشد.

2. کاوشگرهای سرزندگی و آمادگی

به‌طور پیش‌فرض، بررسی‌های زنده بودن و آمادگی در Kubernetes فعال نیستند. و گاهی فراموش می کنند آنها را روشن کنند...

اما چگونه می توانید در صورت بروز خطای مهلک، سرویس را مجدداً راه اندازی کنید؟ و چگونه بار متعادل کننده متوجه می شود که یک غلاف آماده پذیرش ترافیک است؟ یا اینکه می تواند ترافیک بیشتری را مدیریت کند؟

این تست ها اغلب با یکدیگر اشتباه گرفته می شوند:

  • سرزندگی - بررسی "بقا"، که در صورت خرابی غلاف را دوباره راه اندازی می کند.
  • آمادگی - بررسی آمادگی، در صورت عدم موفقیت، پاد را از سرویس Kubernetes جدا می کند (این را می توان با استفاده از آن بررسی کرد kubectl get endpoints) و تا زمانی که بررسی بعدی با موفقیت انجام نشود ترافیک به آن نمی رسد.

هر دوی این چک ها در طول کل چرخه زندگی POD اجرا شد. این خیلی مهمه.

یک تصور غلط رایج این است که کاوشگرهای آمادگی فقط در هنگام راه اندازی اجرا می شوند تا متعادل کننده بداند که غلاف آماده است (Ready) و می تواند پردازش ترافیک را آغاز کند. با این حال، این تنها یکی از گزینه های استفاده از آنها است.

دیگری امکان پی بردن به اینکه ترافیک روی غلاف بیش از حد است و آن را بیش از حد بارگذاری می کند (یا غلاف محاسباتی با منابع فشرده انجام می دهد). در این مورد، بررسی آمادگی کمک می کند بار روی غلاف را کاهش دهید و آن را "خنک کنید".. تکمیل موفقیت آمیز یک بررسی آمادگی در آینده اجازه می دهد بار روی غلاف را دوباره افزایش دهید. در این صورت (اگر تست آمادگی ناموفق باشد)، شکست در تست زنده بودن بسیار نتیجه معکوس خواهد داشت. چرا یک پاد که سالم است و سخت کار می کند دوباره راه اندازی کنید؟

بنابراین، در برخی موارد، هیچ بررسی بهتر از فعال کردن آنها با پارامترهای نادرست پیکربندی شده است. همانطور که در بالا گفته شد، اگر چک زنده بودن کپی چک آمادگی، پس شما در دردسر بزرگی هستید. گزینه ممکن پیکربندی است فقط تست آمادگیو زندگی خطرناک کنار بگذار.

هر دو نوع چک نباید در صورت شکست وابستگی‌های رایج شکست بخورند، در غیر این صورت این امر منجر به شکست آبشاری (شبیه بهمن) همه غلاف‌ها می‌شود. به عبارت دیگر، به خودت آسیب نزن.

3. LoadBalancer برای هر سرویس HTTP

به احتمال زیاد، شما خدمات HTTP را در خوشه خود دارید که می خواهید آنها را به دنیای خارج ارسال کنید.

اگر سرویس را به عنوان باز کنید type: LoadBalancer، کنترل کننده آن (بسته به ارائه دهنده خدمات) یک LoadBalancer خارجی (که لزوماً در L7 اجرا نمی شود، بلکه حتی در L4) ارائه می دهد و با آن مذاکره می کند، و این ممکن است بر هزینه (آدرس IPv4 ثابت خارجی، قدرت محاسباتی، صورتحساب در هر ثانیه تأثیر بگذارد). ) به دلیل نیاز به ایجاد تعداد زیادی از این گونه منابع.

در این مورد، بسیار منطقی تر است که از یک بار متعادل کننده خارجی، باز کردن خدمات به عنوان استفاده کنید type: NodePort. یا بهتر است، چیزی شبیه به آن را گسترش دهید nginx-ingress-controller (یا صفت) که تنها خواهد بود NodePort نقطه پایانی مرتبط با متعادل کننده بار خارجی است و با استفاده از ترافیک در خوشه را هدایت می کند وارد شدن-منابع Kubernetes

سایر سرویس‌های درون خوشه‌ای (ریز) که با یکدیگر تعامل دارند، می‌توانند با استفاده از خدماتی مانند «ارتباط» برقرار کنند. ClusterIP و مکانیزم کشف سرویس داخلی از طریق DNS. فقط از DNS/IP عمومی آنها استفاده نکنید، زیرا این می تواند بر تأخیر تأثیر بگذارد و هزینه خدمات ابری را افزایش دهد.

4. مقیاس خودکار یک خوشه بدون در نظر گرفتن ویژگی های آن

هنگام اضافه کردن گره ها و حذف آنها از یک خوشه، نباید به برخی معیارهای اساسی مانند استفاده از CPU در آن گره ها تکیه کنید. برنامه ریزی غلاف باید بسیاری را در نظر بگیرد محدودیت هایمانند قرابت pod/node، لکه‌ها و تحمل‌ها، درخواست‌های منابع، QoS و غیره. استفاده از اتواسکیل کننده خارجی که این تفاوت های ظریف را در نظر نمی گیرد می تواند منجر به مشکلاتی شود.

تصور کنید که یک پاد خاص باید برنامه ریزی شود، اما تمام توان CPU موجود درخواست/از هم جدا شود و پاد در یک حالت گیر می کند Pending. مقیاس خودکار خارجی میانگین بار فعلی CPU را می بیند (نه درخواستی) و توسعه را آغاز نمی کند (مقیاس کردن) - گره دیگری اضافه نمی کند. در نتیجه این پاد زمان بندی نمی شود.

در این مورد، مقیاس معکوس (مقیاس در مقیاس) - پیاده سازی یک گره از یک خوشه همیشه دشوارتر است. تصور کنید که یک غلاف حالت دار دارید (با حافظه دائمی متصل شده است). حجم های ماندگار معمولا متعلق به منطقه در دسترس بودن خاص و در منطقه تکرار نمی شوند. بنابراین، اگر یک خودکار مقیاس‌کننده خارجی یک گره را با این پاد حذف کند، زمان‌بندی‌کننده نمی‌تواند این غلاف را روی گره دیگری زمان‌بندی کند، زیرا این کار فقط در منطقه در دسترس بودن جایی که ذخیره‌سازی دائمی قرار دارد انجام می‌شود. Pod در حالت گیر می کند Pending.

در جامعه Kubernetes بسیار محبوب است Cluster-autoscaler. بر روی یک خوشه اجرا می شود، API های ارائه دهندگان اصلی ابر را پشتیبانی می کند، تمام محدودیت ها را در نظر می گیرد و می تواند در موارد فوق مقیاس پذیر باشد. همچنین می‌تواند با حفظ تمام محدودیت‌های تعیین‌شده، مقیاس را افزایش دهد، در نتیجه در هزینه‌ها صرفه‌جویی می‌شود (که در غیر این صورت صرف ظرفیت استفاده نشده می‌شود).

5. نادیده گرفتن قابلیت های IAM/RBAC

مراقب استفاده از کاربران IAM با اسرار دائمی باشید ماشین آلات و برنامه های کاربردی. با استفاده از نقش‌ها و حساب‌های سرویس، دسترسی موقت را سازماندهی کنید (حساب خدمات).

ما اغلب با این واقعیت روبرو می شویم که کلیدهای دسترسی (و اسرار) در پیکربندی برنامه هاردکد هستند و همچنین با وجود دسترسی به Cloud IAM از چرخش اسرار غفلت می کنیم. در صورت لزوم از نقش‌های IAM و حساب‌های خدماتی به جای کاربران استفاده کنید.

10 اشتباه رایج هنگام استفاده از Kubernetes

Kube2iam را فراموش کنید و مستقیماً به نقش‌های IAM برای حساب‌های سرویس بروید (همانطور که در توضیح داده شد یادداشتی به همین نام اشتپان ورانی):

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-app-role
  name: my-serviceaccount
  namespace: default

یک حاشیه. آنقدر سخت نیست، درست است؟

همچنین، به حساب‌های سرویس و نمایه‌های نمونه امتیازی اعطا نکنید admin и cluster-adminاگر آنها به آن نیاز ندارند پیاده سازی این کار به خصوص در RBAC K8 کمی دشوارتر است، اما قطعا ارزش تلاش را دارد.

6. به ضد قرابت خودکار برای غلاف ها تکیه نکنید

تصور کنید که سه کپی از برخی استقرارها روی یک گره دارید. گره سقوط می کند، و همراه با آن همه کپی ها. وضعیت ناخوشایند، درست است؟ اما چرا همه کپی ها روی یک گره قرار داشتند؟ آیا Kubernetes قرار نیست دسترسی بالا (HA) را ارائه دهد؟!

متأسفانه، زمانبندی Kubernetes، به ابتکار خود، با قوانین وجود جداگانه مطابقت ندارد (ضد قرابت) برای غلاف آنها باید به صراحت بیان شوند:

// опущено для краткости
      labels:
        app: zk
// опущено для краткости
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - zk
              topologyKey: "kubernetes.io/hostname"

همین. اکنون غلاف ها بر روی گره های مختلف برنامه ریزی می شوند (این شرایط فقط در زمان برنامه ریزی بررسی می شود، اما نه در حین عملکرد آنها - بنابراین requiredDuringSchedulingIgnoredDuringExecution).

در اینجا ما در مورد صحبت می کنیم podAntiAffinity در گره های مختلف: topologyKey: "kubernetes.io/hostname"، - و نه در مورد مناطق مختلف در دسترس بودن. برای اجرای یک HA تمام عیار، باید در این موضوع عمیق تر شوید.

7. نادیده گرفتن PodDisruptionBudgets

تصور کنید که یک بار تولید در یک خوشه Kubernetes دارید. به طور دوره ای، گره ها و خود خوشه باید به روز شوند (یا از کار افتاده). PodDisruptionBudget (PDB) چیزی شبیه به قرارداد تضمین خدمات بین مدیران و کاربران خوشه است.

PDB به شما امکان می دهد از وقفه های سرویس ناشی از کمبود گره ها جلوگیری کنید:

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: zookeeper

در این مثال، شما به عنوان کاربر خوشه به ادمین ها می گویید: "سلام، من یک سرویس باغ وحش دارم، و مهم نیست که شما چه کاری انجام می دهید، من دوست دارم حداقل 2 نمونه از این سرویس همیشه در دسترس باشد."

می توانید در این مورد بیشتر بخوانید اینجا.

8. چندین کاربر یا محیط در یک خوشه مشترک

فضاهای نام Kubernetes (فضاهای نام) عایق قوی ایجاد نمی کند.

یک تصور اشتباه رایج این است که اگر شما یک بار غیر پرود را در یک فضای نام و یک بار را در فضای دیگر قرار دهید، آن‌ها به هیچ وجه بر یکدیگر تأثیر نخواهند گذاشت... با این حال، سطح مشخصی از انزوا را می توان با استفاده از درخواست ها/محدودیت های منابع، تعیین سهمیه ها و تعیین اولویت کلاس ها به دست آورد. برخی از انزوای "فیزیکی" در صفحه داده توسط قرابت ها، تحمل ها، آلودگی ها (یا انتخابگرهای گره) ارائه می شود، اما چنین جدایی کاملاً است. دشوار است پیاده سازی.

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

9. خارجی TrafficPolicy: خوشه

اغلب ما می بینیم که تمام ترافیک داخل کلاستر از طریق سرویسی مانند NodePort می آید که خط مشی پیش فرض برای آن تنظیم شده است. externalTrafficPolicy: Cluster... این به آن معناست که NodePort روی هر گره در خوشه باز است و می توانید از هر یک از آنها برای تعامل با سرویس مورد نظر (مجموعه ای از pods) استفاده کنید.

10 اشتباه رایج هنگام استفاده از Kubernetes

در عین حال، پادهای واقعی مرتبط با سرویس NodePort ذکر شده در بالا معمولاً فقط در یک مکان خاص در دسترس هستند. زیر مجموعه این گره ها. به عبارت دیگر، اگر به گره ای متصل شوم که پاد مورد نیاز را ندارد، ترافیک را به گره دیگری ارسال می کند. اضافه کردن یک هاپ و افزایش تأخیر (اگر گره ها در مناطق/مراکز داده های مختلف در دسترس قرار گیرند، تأخیر می تواند بسیار زیاد باشد؛ علاوه بر این، هزینه های ترافیک خروجی افزایش خواهد یافت).

از طرف دیگر، اگر یک سرویس Kubernetes خاص دارای یک مجموعه سیاست باشد externalTrafficPolicy: Local، سپس NodePort فقط در گره هایی باز می شود که پادهای مورد نیاز واقعاً در آنجا اجرا می شوند. هنگام استفاده از متعادل کننده بار خارجی که وضعیت را بررسی می کند (بررسی سلامت) نقاط پایانی (چگونه انجام می شود AWS ELBاو ترافیک را فقط به گره های ضروری ارسال می کند، که تأثیر مفیدی بر تأخیرها، نیازهای محاسباتی، صورتحسابهای خروج خواهد داشت (و عقل سلیم همین را حکم می کند).

احتمال زیادی وجود دارد که قبلاً از چیزی شبیه به آن استفاده می کنید صفت یا nginx-ingress-controller به عنوان یک نقطه پایانی NodePort (یا LoadBalancer، که از NodePort نیز استفاده می کند) برای مسیریابی ترافیک ورودی HTTP، و تنظیم این گزینه می تواند تأخیر چنین درخواست هایی را به میزان قابل توجهی کاهش دهد.

В این انتشارات می‌توانید درباره خارجی TrafficPolicy، مزایا و معایب آن بیشتر بدانید.

10. به خوشه ها گره نخورید و از هواپیمای کنترل سوء استفاده نکنید

قبلاً مرسوم بود که سرورها را با نام های مناسب فراخوانی می کردند: آنتون، HAL9000 و Colossus... امروزه با شناسه های تولید شده به صورت تصادفی جایگزین شده اند. با این حال، این عادت باقی ماند و اکنون نام های مناسب به خوشه ها می روند.

یک داستان معمولی (بر اساس وقایع واقعی): همه چیز با اثبات مفهوم شروع شد، بنابراین خوشه نامی مغرور داشت. تست... سال ها می گذرد و هنوز هم در تولید استفاده می شود و همه از دست زدن به آن می ترسند.

هیچ چیز جالبی در مورد تبدیل خوشه ها به حیوانات خانگی وجود ندارد، بنابراین توصیه می کنیم آنها را به طور دوره ای در حین تمرین حذف کنید. بازیابی فاجعه (این کمک خواهد کرد مهندسی آشوب - تقریبا ترجمه.). علاوه بر این، کار روی لایه کنترل ضرری ندارد (کنترل هواپیما). ترس از دست زدن به او نشانه خوبی نیست. و غیره مرده؟ بچه ها، شما واقعاً در مشکل هستید!

از طرف دیگر، شما نباید با دستکاری آن غافل شوید. با زمان لایه کنترل ممکن است کند شود. به احتمال زیاد، این به دلیل ایجاد تعداد زیادی از اشیاء بدون چرخش آنها است (وضعیت رایج هنگام استفاده از Helm با تنظیمات پیش فرض، به همین دلیل است که وضعیت آن در configmaps/secrets به روز نمی شود - در نتیجه، هزاران شی در انباشته می شوند. لایه کنترل) یا با ویرایش مداوم اشیاء kube-api (برای مقیاس‌بندی خودکار، برای CI/CD، برای نظارت، گزارش‌های رویداد، کنترل‌کننده‌ها و غیره).

علاوه بر این، توصیه می‌کنیم قراردادهای SLA/SLO را با ارائه‌دهنده مدیریت‌شده Kubernetes بررسی کنید و به تضمین‌ها توجه کنید. فروشنده می تواند تضمین کند در دسترس بودن لایه کنترل (یا اجزای فرعی آن)، اما نه تاخیر p99 درخواست هایی که برای آن ارسال می کنید. به عبارت دیگر می توانید وارد شوید kubectl get nodes، و تنها پس از 10 دقیقه پاسخ دریافت کنید و این امر نقض شرایط قرارداد خدمات نخواهد بود.

11. پاداش: با استفاده از آخرین برچسب

اما این در حال حاضر یک کلاسیک است. اخیراً کمتر به این تکنیک برخورد کرده ایم، زیرا بسیاری از آنها با آموختن از تجربه تلخ، استفاده از برچسب را متوقف کرده اند. :latest و شروع به پین ​​کردن نسخه ها کرد. هورا!

ECR تغییرناپذیری تگ های تصویر را حفظ می کند; توصیه می کنیم با این ویژگی قابل توجه آشنا شوید.

خلاصه

انتظار نداشته باشید همه چیز یک شبه کار کند: Kubernetes یک دارو نیست. برنامه بد حتی در Kubernetes نیز به همین شکل باقی خواهد ماند (و احتمالا بدتر خواهد شد). بی دقتی منجر به پیچیدگی بیش از حد، کار کند و پر استرس لایه کنترل می شود. علاوه بر این، شما در معرض خطر باقی ماندن بدون استراتژی بازیابی فاجعه هستید. از Kubernetes انتظار نداشته باشید که انزوا و در دسترس بودن بالا را خارج از جعبه ارائه دهد. مدتی را صرف ساختن اپلیکیشن خود واقعاً ابری کنید.

می توانید با تجربیات ناموفق تیم های مختلف در داخل آشنا شوید این مجموعه داستان توسط هنینگ جیکوبز

کسانی که مایل به اضافه کردن به لیست خطاهای ارائه شده در این مقاله هستند می توانند با ما در توییتر تماس بگیرند (@MarekBartik, @MstrsObserver).

PS از مترجم

در وبلاگ ما نیز بخوانید:

منبع: www.habr.com

اضافه کردن نظر