10 Ümumi Kubernetes Səhvləri

Qeyd. tərcümə.: Bu məqalənin müəllifləri kiçik bir Çex şirkətinin mühəndisləridir, pipetail. Onlar Kubernetes klasterlərinin işləməsi ilə bağlı [bəzən bayağı, lakin yenə də] çox aktual problemlər və yanlış təsəvvürlərin gözəl siyahısını toplamağa müvəffəq oldular.

10 Ümumi Kubernetes Səhvləri

Kubernetes-dən istifadə etdiyimiz illər ərzində biz çoxlu sayda klasterlə (həm idarə olunan, həm də idarə olunmayan – GCP, AWS və Azure-da) işləmişik. Zaman keçdikcə bəzi səhvlərin davamlı olaraq təkrarlandığını hiss etməyə başladıq. Ancaq bunda utanc yoxdur: onların çoxunu özümüz etmişik!

Məqalədə ən çox yayılmış səhvlər var və onları necə düzəltmək olar.

1. Resurslar: sorğular və məhdudiyyətlər

Bu maddə mütləq ən yaxın diqqətə və siyahıda birinci yerə layiqdir.

Adətən CPU tələbi ya ümumiyyətlə göstərilməyib, ya da çox aşağı qiymətə malikdir (hər node mümkün qədər çox pods yerləşdirmək üçün). Beləliklə, düyünlər həddindən artıq yüklənir. Yüksək yüklənmə zamanı qovşağın emal gücü tam istifadə olunur və müəyyən bir iş yükü yalnız onun "tələb etdiyi" şeyi alır. CPU tənzimləmə. Bu, tətbiqin gecikmə müddətinin artmasına, fasilələrə və digər xoşagəlməz nəticələrə gətirib çıxarır. (Bu barədə daha çoxunu digər son tərcüməmizdə oxuyun: "Kubernetes-də CPU məhdudiyyətləri və aqressiv tənzimləmə"- təqribən. tərcümə.)

Yükzək əzm (son dərəcə heç bir tövsiyə):

resources: {}

Çox aşağı CPU tələbi (son dərəcə heç bir tövsiyə):

   resources:
      Requests:
        cpu: "1m"

Digər tərəfdən, CPU limitinin olması, node prosessoru tam yüklənməsə belə, podlar tərəfindən saat dövrlərinin əsassız olaraq atlanmasına səbəb ola bilər. Yenə də bu, gecikmələrin artmasına səbəb ola bilər. Parametr ətrafında mübahisələr davam edir CPU CFS kvotası Linux nüvəsində və müəyyən edilmiş limitlərdən asılı olaraq CPU tənzimləməsi, həmçinin CFS kvotasının söndürülməsi... Təəssüf ki, CPU limitləri həll edə bildiklərindən daha çox problem yarada bilər. Bu barədə ətraflı məlumatı aşağıdakı linkdən əldə etmək olar.

Həddindən artıq seçim (həddindən artıq öhdəlik) yaddaş problemləri daha böyük problemlərə səbəb ola bilər. CPU limitinə çatmaq saat dövrlərini atlamağa, yaddaş limitinə çatmaq isə podun öldürülməsinə səbəb olur. Heç müşahidə etmisinizmi OOMkill? Bəli, söhbət məhz bundan gedir.

Bunun baş vermə ehtimalını minimuma endirmək istəyirsiniz? Yaddaşdan həddən artıq yer ayırmayın və yaddaş tələbini limitə təyin etməklə (aşağıdakı nümunədə olduğu kimi) Zəmanətli QoS (Xidmət Keyfiyyəti) istifadə etməyin. Bu barədə ətraflı oxuyun Henning jacobs təqdimatı (Zalandoda aparıcı mühəndis).

Burstable (OOMkilled almaq şansı daha yüksəkdir):

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

Zəmanətli:

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

Resursları qurarkən potensial olaraq nə kömək edəcək?

Ilə ölçülər-server podlar (və onların içərisindəki qablar) üzrə cari CPU resurs istehlakını və yaddaş istifadəsini görə bilərsiniz. Çox güman ki, siz artıq istifadə edirsiniz. Sadəcə aşağıdakı əmrləri yerinə yetirin:

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

Lakin onlar yalnız cari istifadəni göstərirlər. Bu sizə böyüklük sırası haqqında təxmini bir fikir verə bilər, amma nəticədə sizə lazım olacaq zamanla ölçülərdəki dəyişikliklərin tarixi (kimi suallara cavab vermək üçün: “Pek CPU yükü nə qədər idi?”, “Dünən səhər yükü nə idi?” və s.). Bunun üçün istifadə edə bilərsiniz Prometey, DataDog və digər alətlər. Onlar sadəcə olaraq metrik-serverdən ölçülər alır və onları saxlayır və istifadəçi onları sorğulaya və müvafiq olaraq tərtib edə bilər.

VerticalPodAutoscaler imkan avtomatlaşdırmaq bu proses. O, CPU və yaddaşdan istifadə tarixini izləyir və bu məlumat əsasında yeni sorğular və məhdudiyyətlər təyin edir.

Hesablama gücündən səmərəli istifadə etmək asan məsələ deyil. Bu, hər zaman Tetris oynamaq kimidir. Aşağı orta istehlakla (deyək ki, ~10%) hesablama gücü üçün çox pul ödəyirsinizsə, AWS Fargate və ya Virtual Kubelet əsasında məhsullara baxmağı tövsiyə edirik. Onlar serversiz/istifadəyə görə ödənişli hesablama modelində qurulub, belə şəraitdə daha ucuz ola bilər.

2. Canlılıq və hazırlıq zondları

Defolt olaraq, canlılıq və hazırlıq yoxlamaları Kubernetes-də aktiv deyil. Və bəzən onları açmağı unudurlar...

Ancaq ölümcül bir səhv halında xidmətin yenidən başlamasına başqa necə başlaya bilərsiniz? Yük balanslaşdırıcısı podun trafiki qəbul etməyə hazır olduğunu necə bilir? Yoxsa daha çox trafik idarə edə bilər?

Bu testlər çox vaxt bir-biri ilə qarışdırılır:

  • Canlılıq — uğursuz olduqda podu yenidən işə salan “sağ qalma qabiliyyəti” yoxlanışı;
  • Hazırlıq — hazırlıq yoxlanışı, uğursuz olarsa, podu Kubernetes xidmətindən ayırır (bunu istifadə edərək yoxlamaq olar kubectl get endpoints) və növbəti yoxlama uğurla başa çatana qədər ona trafik gəlmir.

Bu yoxlamaların hər ikisi PODUN BÜTÜN HƏYAT DÖVRÜ ƏRZİNDƏ İCRA EDİLİR. Bu çox vacibdir.

Ümumi bir yanlış fikir, hazırlıq zondlarının yalnız başlanğıcda işə salınmasıdır ki, balanslaşdırıcı podun hazır olduğunu bilsin (Ready) və trafiki emal etməyə başlaya bilər. Ancaq bu, onların istifadəsi variantlarından yalnız biridir.

Digəri, poddakı trafikin həddindən artıq və həddindən artıq olduğunu aşkar etmək imkanıdır həddindən artıq yükləyir (və ya pod resurs tutumlu hesablamaları yerinə yetirir). Bu vəziyyətdə hazırlıq yoxlaması kömək edir poddakı yükü azaldın və onu "sərinləyin". Gələcəkdə hazırlıq yoxlamasını uğurla başa çatdırmaq imkan verir poddakı yükü yenidən artırın. Bu halda (hazırlıq testi uğursuz olarsa), canlılıq testinin uğursuzluğu çox əks-məhsuldar olardı. Niyə sağlam və çox işləyən podu yenidən başladın?

Buna görə də, bəzi hallarda, heç bir yoxlama, onları səhv konfiqurasiya edilmiş parametrlərlə işə salmaqdan daha yaxşıdır. Yuxarıda qeyd edildiyi kimi, əgər canlılıq yoxlaması nüsxələri hazırlığın yoxlanılması, onda böyük bəladasınız. Mümkün seçim konfiqurasiya etməkdir yalnız hazırlıq testitəhlükəli canlılıq kənara buraxın.

Ümumi asılılıqlar uğursuz olduqda, hər iki növ yoxlama uğursuz olmamalıdır, əks halda bu, bütün podların kaskadlı (uçquna bənzər) uğursuzluğuna səbəb olacaqdır. Başqa sözlə, özünə zərər vermə.

3. Hər HTTP xidməti üçün LoadBalancer

Çox güman ki, klasterinizdə xarici dünyaya yönləndirmək istədiyiniz HTTP xidmətləri var.

Xidməti açsanız type: LoadBalancer, onun nəzarətçisi (xidmət provayderindən asılı olaraq) xarici LoadBalancer təmin edəcək və danışıqlar aparacaq (mütləq L7-də deyil, hətta L4-də işləyir) və bu, qiymətə təsir göstərə bilər (xarici statik IPv4 ünvanı, hesablama gücü, saniyədə hesablama ) belə resursların çoxlu sayda yaradılması zərurəti ilə əlaqədardır.

Bu vəziyyətdə, bir xarici yük balanslaşdırıcısından istifadə etmək, xidmətləri açmaq daha məntiqlidir type: NodePort. Və ya daha yaxşısı kimi bir şeyi genişləndirin nginx-ingress-nəzarətçisi (Və ya traefik), tək kim olacaq NodePort xarici yük balanslaşdırıcısı ilə əlaqəli son nöqtə və istifadə edərək klasterdəki trafiki yönləndirəcək giriş- Kubernetes resursları.

kimi xidmətlərdən istifadə edərək, bir-biri ilə qarşılıqlı əlaqədə olan digər klasterdaxili (mikro) xidmətlər "əlaqə saxlaya" bilər ClusterIP və DNS vasitəsilə daxili xidmət kəşf mexanizmi. Sadəcə onların ictimai DNS/IP-dən istifadə etməyin, çünki bu, gecikməyə təsir edə və bulud xidmətlərinin qiymətini artıra bilər.

4. Klasterin xüsusiyyətlərini nəzərə almadan avtomatik miqyasda dəyişdirilməsi

Düyünləri klasterə əlavə edərkən və onları çoxluqdan çıxararkən, bu qovşaqlarda CPU istifadəsi kimi bəzi əsas ölçülərə etibar etməməlisiniz. Pod planlaşdırma çoxunu nəzərə almalıdır məhdudiyyətlər, məsələn, pod/qovşaq yaxınlığı, ləkələr və dözümlər, resurs sorğuları, QoS və s. Bu nüansları nəzərə almayan xarici avtomiqyaslayıcıdan istifadə problemlərə səbəb ola bilər.

Təsəvvür edin ki, müəyyən bir pod planlaşdırılmalıdır, lakin bütün mövcud CPU gücü tələb olunur/sökülür və pod vəziyyətdə ilişib qalır Pending. Xarici avtomiqyaslayıcı orta cari CPU yükünü (tələb olunanı deyil) görür və genişləndirməyə başlamır (miqyaslı) - başqa node əlavə etmir. Nəticədə, bu pod planlaşdırılmayacaq.

Bu vəziyyətdə tərs miqyaslama (miqyaslı) — bir qovşağın klasterdən çıxarılmasını həyata keçirmək həmişə daha çətindir. Təsəvvür edin ki, sizdə statuslu bir pod var (davamlı yaddaş qoşulmuşdur). Davamlı həcmlər adətən aiddir xüsusi mövcudluq zonası və bölgədə təkrarlanmır. Beləliklə, əgər xarici avtomiqyaslayıcı bu pod ilə qovşağı silsə, planlaşdırıcı bu podu başqa qovşaqda planlaşdıra bilməyəcək, çünki bu, yalnız davamlı yaddaşın yerləşdiyi əlçatanlıq zonasında edilə bilər. Pod vəziyyətdə ilişib qalacaq Pending.

Kubernetes icmasında çox populyardır klaster-avtomiqyaslayıcı. O, klasterdə işləyir, əsas bulud provayderlərinin API-lərini dəstəkləyir, bütün məhdudiyyətləri nəzərə alır və yuxarıda göstərilən hallarda miqyaslana bilər. O, həmçinin bütün müəyyən edilmiş limitləri qoruyarkən miqyasını genişləndirə bilir və bununla da pula qənaət edir (əks halda istifadə olunmamış gücə sərf olunacaq).

5. IAM/RBAC imkanlarına məhəl qoymamaq

Üçün davamlı sirləri olan IAM istifadəçilərindən istifadə etməkdən çəkinin maşınlar və tətbiqlər. Rollardan və xidmət hesablarından istifadə edərək müvəqqəti girişi təşkil edin (xidmət hesabları).

Biz tez-tez giriş düymələrinin (və sirrlərin) proqram konfiqurasiyasında sərt kodlaşdırıldığı, həmçinin Cloud IAM-a çıxışa malik olmasına baxmayaraq, sirlərin fırlanmasına məhəl qoymamaq faktı ilə qarşılaşırıq. Müvafiq yerlərdə istifadəçilər əvəzinə IAM rolları və xidmət hesablarından istifadə edin.

10 Ümumi Kubernetes Səhvləri

kube2iam haqqında unudun və birbaşa xidmət hesabları üçün IAM rollarına keçin (bölmədə təsvir olunduğu kimi). eyni adlı qeyd Štěpán Vraný):

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

Bir annotasiya. O qədər də çətin deyil, elə deyilmi?

Həmçinin, xidmət hesablarına və nümunə profillərinə imtiyazlar verməyin admin и cluster-adminehtiyac olmasa. Xüsusilə RBAC K8-lərdə bunu həyata keçirmək bir az daha çətindir, lakin mütləq səyə dəyər.

6. Podlar üçün avtomatik anti-yaxınlığa etibar etməyin

Təsəvvür edin ki, bir qovşaqda bəzi yerləşdirmənin üç nüsxəsi var. Düyün düşür və onunla birlikdə bütün replikalar. Xoşagəlməz vəziyyət, elə deyilmi? Bəs niyə bütün replikalar eyni node üzərində idi? Kubernetes yüksək əlçatanlığı (HA) təmin etməli deyilmi?!

Təəssüf ki, Kubernetes planlaşdırıcısı öz təşəbbüsü ilə ayrı mövcudluq qaydalarına uyğun gəlmir. (anti-yaxınlıq) podlar üçün. Onlar açıq şəkildə ifadə edilməlidir:

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

Hamısı budur. İndi podlar müxtəlif qovşaqlarda planlaşdırılacaq (bu vəziyyət yalnız planlaşdırma zamanı yoxlanılır, lakin onların işləməsi zamanı yox - buna görə də requiredDuringSchedulingIgnoredDuringExecution).

Burada söhbət gedir podAntiAffinity müxtəlif qovşaqlarda: topologyKey: "kubernetes.io/hostname", - və müxtəlif əlçatanlıq zonaları haqqında deyil. Tam hüquqlu HA tətbiq etmək üçün bu mövzunu daha dərindən öyrənməli olacaqsınız.

7. PodDisruptionBudgets-a məhəl qoymamaq

Təsəvvür edin ki, Kubernetes klasterində istehsal yükünüz var. Dövri olaraq qovşaqlar və klasterin özü yenilənməlidir (və ya istismardan çıxarılmalıdır). PodDisruptionBudget (PDB) klaster administratorları və istifadəçilər arasında xidmət zəmanəti müqaviləsi kimi bir şeydir.

PDB qovşaqların olmaması səbəbindən xidmət kəsilməsinin qarşısını almağa imkan verir:

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

Bu misalda siz klasterin istifadəçisi olaraq adminlərə deyirsiniz: “Hey, mənim zookeeper xidməti var və nə etsəniz də, bu xidmətin ən azı 2 nüsxəsinin həmişə mövcud olmasını istərdim.”

Bu barədə ətraflı oxuya bilərsiniz burada.

8. Ümumi klasterdə birdən çox istifadəçi və ya mühit

Kubernetes ad boşluqları (ad boşluqları) güclü izolyasiya təmin etməyin.

Ümumi yanlış fikir ondan ibarətdir ki, əgər siz bir ad sahəsinə qeyri-məhsul yükünü, digərinə məhsul yükünü yerləşdirsəniz, o zaman onlar heç bir şəkildə bir-birinə təsir etməyəcəklər... Bununla belə, resurs sorğuları/məhdudiyyətləri, kvotaların təyin edilməsi və prioritet siniflərinin təyin edilməsi ilə müəyyən bir izolyasiya səviyyəsinə nail olmaq olar. Məlumat müstəvisində bəzi "fiziki" izolyasiya yaxınlıqlar, dözümlülüklər, ləkələr (və ya qovşaq seçiciləri) ilə təmin edilir, lakin bu cür ayırma kifayət qədərdir. çətin həyata keçirmək.

Hər iki növ iş yükünü eyni klasterdə birləşdirməli olanlar mürəkkəbliklə məşğul olmalı olacaqlar. Əgər belə bir ehtiyac yoxdursa və birinə sahib ola bilərsiniz daha bir klaster (məsələn, ictimai buludda), onda bunu etmək daha yaxşıdır. Bu, daha yüksək izolyasiya səviyyəsinə nail olacaqdır.

9. Xarici TrafficPolicy: Klaster

Çox vaxt görürük ki, klaster daxilində bütün trafik standart siyasətin təyin olunduğu NodePort kimi bir xidmət vasitəsilə gəlir. externalTrafficPolicy: Cluster... Bu o deməkdir NodePort klasterdəki hər qovşaqda açıqdır və istədiyiniz xidmətlə (podlar dəsti) qarşılıqlı əlaqə yaratmaq üçün onlardan hər hansı birini istifadə edə bilərsiniz.

10 Ümumi Kubernetes Səhvləri

Eyni zamanda, yuxarıda qeyd olunan NodePort xidməti ilə əlaqəli real podlar adətən yalnız müəyyən bir şəbəkədə mövcuddur. bu qovşaqların alt çoxluğu. Başqa sözlə, mən tələb olunan qovluğa malik olmayan bir qovşaqla əlaqə qursam, o, trafiki başqa bir node-a yönləndirəcək, hop əlavə edir və artan gecikmə (qovşaqlar müxtəlif əlçatanlıq zonalarında/məlumat mərkəzlərində yerləşirsə, gecikmə kifayət qədər yüksək ola bilər; əlavə olaraq, çıxış trafiki xərcləri artacaq).

Digər tərəfdən, müəyyən bir Kubernetes xidmətinin siyasət dəsti varsa externalTrafficPolicy: Local, sonra NodePort yalnız tələb olunan podların həqiqətən işlədiyi qovşaqlarda açılır. Vəziyyəti yoxlayan xarici yük balanslayıcısından istifadə edərkən (sağlamlığın yoxlanılması) son nöqtələr (necə edir AWS ELB), O trafiki yalnız lazımi qovşaqlara göndərəcəkgecikmələrə, hesablama ehtiyaclarına, çıxış hesablarına faydalı təsir göstərəcək (və sağlam düşüncə də bunu diktə edir).

Artıq buna bənzər bir şey istifadə etdiyiniz yüksək şans var traefik və ya nginx-ingress-nəzarətçisi HTTP giriş trafikini yönləndirmək üçün NodePort son nöqtəsi (və ya NodePort-dan da istifadə edən LoadBalancer) kimi və bu seçimin qurulması belə sorğular üçün gecikməni əhəmiyyətli dərəcədə azalda bilər.

В bu nəşrin Siz externalTrafficPolicy, onun üstünlükləri və mənfi cəhətləri haqqında daha çox öyrənə bilərsiniz.

10. Çoxluqlara bağlanmayın və idarəetmə müstəvisindən sui-istifadə etməyin

Əvvəllər serverləri müvafiq adlarla çağırmaq adət idi: Anton, HAL9000 və Colossus... Bu gün onlar təsadüfi yaradılan identifikatorlarla əvəz olunub. Ancaq vərdiş qaldı və indi xüsusi adlar çoxluqlara gedir.

Tipik bir hekayə (real hadisələrə əsaslanaraq): hər şey konsepsiyanın sübutu ilə başladı, buna görə də klasterin qürurlu adı var idi. test… İllər keçdi və HƏLƏ istehsalda istifadə olunur və hamı ona toxunmağa qorxur.

Klasterlərin ev heyvanlarına çevrilməsində əyləncəli heç nə yoxdur, ona görə də məşq edərkən onları vaxtaşırı çıxarmağı tövsiyə edirik. fəlakətin bərpası (bu kömək edəcək xaos mühəndisliyi - təqribən. tərcümə.). Bundan əlavə, nəzarət təbəqəsi üzərində işləmək zərər verməz (idarəetmə təyyarəsi). Ona toxunmaqdan qorxmaq yaxşı əlamət deyil. və s. ölü? Uşaqlar, həqiqətən də probleminiz var!

Digər tərəfdən, onu manipulyasiya etməklə məşğul olmamalısınız. Zamanla nəzarət təbəqəsi yavaşlaya bilər. Çox güman ki, bu, çoxlu sayda obyektin fırlanmadan yaradılması ilə bağlıdır (Helm-dən standart parametrlərlə istifadə edərkən ümumi vəziyyət, buna görə konfiqurasiya xəritələrində/sirrlərdə onun vəziyyəti yenilənmir - nəticədə minlərlə obyekt toplanır. nəzarət təbəqəsi) və ya kube-api obyektlərinin daimi redaktəsi ilə (avtomatik miqyas üçün, CI/CD üçün, monitorinq üçün, hadisə qeydləri, nəzarətçilər və s.).

Bundan əlavə, idarə olunan Kubernetes provayderi ilə SLA/SLO müqavilələrini yoxlamağı və zəmanətlərə diqqət yetirməyi tövsiyə edirik. Satıcı zəmanət verə bilər təbəqənin mövcudluğuna nəzarət (və ya onun alt komponentləri), lakin ona göndərdiyiniz sorğuların p99 gecikməsi deyil. Başqa sözlə, daxil ola bilərsiniz kubectl get nodes, və yalnız 10 dəqiqədən sonra cavab alın və bu, xidmət müqaviləsinin şərtlərinin pozulması olmayacaq.

11. Bonus: ən son etiketdən istifadə etməklə

Amma bu artıq klassikdir. Son vaxtlar bu texnikaya daha az rast gəlirik, çünki çoxları acı təcrübədən öyrənərək etiketdən istifadə etməyi dayandırıblar. :latest və versiyaları bərkitməyə başladı. Yaşasın!

ECR şəkil teqlərinin dəyişməzliyini qoruyur; Bu əlamətdar xüsusiyyətlə tanış olmağı tövsiyə edirik.

Xülasə

Hər şeyin bir gecədə işləyəcəyini gözləməyin: Kubernetes panacea deyil. Pis proqram hətta Kubernetesdə belə qalacaq (və yəqin ki, daha da pisləşəcək). Diqqətsizlik nəzarət təbəqəsinin həddindən artıq mürəkkəbliyinə, yavaş və gərgin işinə səbəb olacaqdır. Bundan əlavə, fəlakətin bərpası strategiyası olmadan qalma riskiniz var. Kubernetes-in qutudan kənarda izolyasiya və yüksək əlçatanlıq təmin edəcəyini gözləməyin. Tətbiqinizi həqiqətən buludda yerli etmək üçün bir az vaxt sərf edin.

Müxtəlif komandaların uğursuz təcrübələri ilə tanış ola bilərsiniz bu hekayələr toplusu Henning Jacobs tərəfindən.

Bu yazıda verilən səhvlər siyahısına əlavə etmək istəyənlər Twitter-də bizimlə əlaqə saxlaya bilərlər (@MarekBartik, @MstrsObserver).

Tərcüməçidən PS

Bloqumuzda da oxuyun:

Mənbə: www.habr.com

Добавить комментарий