Kubernetes пайдалану кезіндегі 10 жиі кездесетін қателер

Ескерту. аударма: Бұл мақаланың авторлары шағын чех компаниясының инженерлері, pipetail. Олар Kubernetes кластерлерінің жұмысына қатысты [кейде қарапайым, бірақ бәрібір] өте өзекті мәселелер мен қате түсініктердің тамаша тізімін құрастыра алды.

Kubernetes пайдалану кезіндегі 10 жиі кездесетін қателер

Kubernetes-ті пайдаланған жылдар ішінде біз көптеген кластерлермен (басқарылатын және басқарылмайтын – GCP, AWS және Azure жүйелерінде) жұмыс істедік. Уақыт өте келе кейбір қателіктердің үнемі қайталанатынын байқай бастадық. Дегенмен, бұл жерде ұят жоқ: біз олардың көпшілігін өзіміз жасадық!

Мақалада ең көп кездесетін қателер бар, сонымен қатар оларды қалай түзетуге болады.

1. Ресурстар: сұраныстар мен шектеулер

Бұл элемент ең мұқият назар аударуға және тізімдегі бірінші орынға лайық.

Әдетте CPU сұрауы не мүлде көрсетілмеген немесе өте төмен мәнге ие (әр түйінге мүмкіндігінше көп түйіршіктерді орналастыру үшін). Осылайша, түйіндер шамадан тыс жүктеледі. Жоғары жүктеме кезінде түйіннің өңдеу қуаты толығымен пайдаланылады және белгілі бір жұмыс жүктемесі ол «сұраған» нәрсені ғана алады. CPU тежеу. Бұл қолданбаның кешігуінің артуына, күту уақытының артуына және басқа да жағымсыз салдарға әкеледі. (Бұл туралы басқа соңғы аудармамыздан оқыңыз: «CPU шектеулері және Кубернетестегі агрессивті дроссельдер" - шамамен. аудар.)

BestEffort (өте емес ұсынылады):

resources: {}

Өте төмен CPU сұранысы (өте емес ұсынылады):

   resources:
      Requests:
        cpu: "1m"

Екінші жағынан, процессорлық шектеудің болуы түйін процессоры толық жүктелмеген болса да, тактілер арқылы тактілік циклдарды негізсіз өткізіп жіберуге әкелуі мүмкін. Тағы да, бұл кідірістердің артуына әкелуі мүмкін. Параметр төңірегінде даулар жалғасуда CPU CFS квотасы Linux ядросында және орнатылған шектеулерге байланысты орталық процессорды реттеу, сондай-ақ CFS квотасын өшіру... Өкінішке орай, процессорлық шектеулер шешуден гөрі көп мәселелерді тудыруы мүмкін. Бұл туралы толығырақ ақпаратты төмендегі сілтемеден табуға болады.

Шамадан тыс таңдау (артық міндеттеме) жад проблемалары үлкенірек мәселелерге әкелуі мүмкін. CPU шегіне жету сағат циклдерін өткізіп жіберуді талап етеді, ал жад шегіне жету подкастты өлтіруді талап етеді. Сіз байқап көрдіңіз бе OOMkill? Иә, дәл осы туралы айтып отырмыз.

Бұл орын алу ықтималдығын барынша азайтқыңыз келе ме? Жадты шамадан тыс бөлмеңіз және жад сұрауын шекке орнату арқылы Кепілдендірілген QoS (қызмет көрсету сапасы) пайдаланыңыз (төмендегі мысалдағыдай). Бұл туралы толығырақ бөлімде оқыңыз Хеннинг Джейкобс презентациялары (Заландодағы жетекші инженер).

Жарылғыш (OOMkilled алу мүмкіндігі жоғары):

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

Кепілдік:

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

Ресурстарды орнату кезінде не көмектеседі?

Көмегімен метрика-сервер процессордың ағымдағы ресурсын тұтынуды және блоктар (және олардың ішіндегі контейнерлер) бойынша жадты пайдалануды көре аласыз. Сірә, сіз оны пайдаланып жатырсыз. Тек келесі пәрмендерді іске қосыңыз:

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

Дегенмен, олар тек ағымдағы пайдалануды көрсетеді. Ол сізге шама реті туралы шамамен түсінік бере алады, бірақ сайып келгенде сізге қажет болады уақыт бойынша көрсеткіштердің өзгеру тарихы («Процессордың ең жоғары жүктемесі қандай болды?», «Кеше таңертең қандай жүктеме болды?» және т.б. сұрақтарға жауап беру үшін). Ол үшін пайдалануға болады Прометей, DataDog және басқа құралдар. Олар жай ғана метрика-серверден көрсеткіштерді алады және оларды сақтайды, ал пайдаланушы оларды сұрап, сәйкесінше сыза алады.

VerticalPodAutoscaler ол мүмкіндік береді автоматтандыру бұл процесс. Ол процессор мен жадты пайдалану тарихын бақылайды және осы ақпарат негізінде жаңа сұраулар мен шектеулерді орнатады.

Есептеу қуатын тиімді пайдалану оңай шаруа емес. Бұл үнемі Tetris ойнау сияқты. Орташа тұтынуы төмен есептеу қуаты үшін тым көп төлеп жатсаңыз (мысалы, ~10%), AWS Fargate немесе Virtual Kubelet негізіндегі өнімдерді қарауды ұсынамыз. Олар серверсіз/пайдалану үшін төлем үлгісінде жасалған, мұндай жағдайларда арзанырақ болуы мүмкін.

2. Жандылық пен дайындық зондтары

Әдепкі бойынша, Kubernetes жүйесінде белсенділік пен дайындықты тексеру қосылмаған. Ал кейде оларды қосуды ұмытып кетеді...

Бірақ қауіпті қате болған жағдайда қызметті қайта іске қосуды қалай бастауға болады? Жүктеме теңестіруші подводтың трафикті қабылдауға дайын екенін қайдан біледі? Немесе ол көбірек трафикті басқара алады ма?

Бұл сынақтар жиі бір-бірімен шатастырылады:

  • Өмір — «өмір сүру қабілеттілігін» тексеру, ол сәтсіз болған жағдайда подводты қайта іске қосады;
  • Дайындық — дайындықты тексеру, егер ол сәтсіз болса, ол подкастты Kubernetes қызметінен ажыратады (оны пайдалану арқылы тексеруге болады). kubectl get endpoints) және трафик келесі тексеру сәтті аяқталмайынша оған келмейді.

Бұл тексерулердің екеуі де ПОДТОРДЫҢ БАРЛЫҚ ӨМІРЛІК ЦИКЛІ БОЙЫНША ОРЫНДАЛАДЫ. Бұл өте маңызды.

Жалпы қате түсінік дайындық зондтары тек іске қосу кезінде іске қосылады, осылайша теңгеруші подкасттың дайын екенін біле алады (Ready) және трафикті өңдеуді бастауға болады. Дегенмен, бұл оларды пайдалану нұсқаларының бірі ғана.

Тағы бір нәрсе - трафиктің шамадан тыс екенін анықтау мүмкіндігі оны шамадан тыс жүктейді (немесе подвод ресурстарды көп қажет ететін есептеулерді орындайды). Бұл жағдайда дайындықты тексеру көмектеседі бағандағы жүктемені азайтып, оны «салқындату».. Болашақта дайындықты тексеруді сәтті аяқтау мүмкіндік береді бағандағы жүктемені қайтадан арттырыңыз. Бұл жағдайда (дайындық сынағы сәтсіз аяқталса), өмірлік сынақтың сәтсіздігі өте кері нәтиже береді. Неліктен сау және көп жұмыс істейтін подводты қайта іске қосыңыз?

Сондықтан, кейбір жағдайларда дұрыс емес конфигурацияланған параметрлермен қосудан гөрі, мүлде тексерулер жақсырақ. Жоғарыда айтылғандай, егер жандылықты тексеру көшірмелері дайындықты тексеру, онда сіз үлкен қиындыққа тап боласыз. Мүмкін опция конфигурациялау болып табылады тек дайындық сынағымен қауіпті тіршілік шетке қалдырыңыз.

Жалпы тәуелділіктер сәтсіз болған кезде тексерудің екі түрі де сәтсіздікке ұшырамауы керек, әйтпесе бұл барлық түйіндердің каскадты (көшкін тәрізді) істен шығуына әкеледі. Басқа сөзбен, өзіңе зиян тигізбе.

3. Әрбір HTTP қызметі үшін LoadBalancer

Сірә, сіздің кластеріңізде сыртқы әлемге жібергіңіз келетін HTTP қызметтері бар.

Қызметті ретінде ашсаңыз type: LoadBalancer, оның контроллері (қызмет провайдеріне байланысты) сыртқы LoadBalancer қамтамасыз етеді және келіседі (міндетті түрде L7-де емес, тіпті L4-те жұмыс істейді) және бұл бағаға әсер етуі мүмкін (сыртқы статикалық IPv4 мекенжайы, есептеу қуаты, секундтық төлем ) осындай ресурстардың көп санын құру қажеттілігіне байланысты.

Бұл жағдайда қызметтерді ашатын бір сыртқы жүктеме теңестіргішін пайдалану әлдеқайда қисынды type: NodePort. Немесе жақсырақ, келесідей нәрсені кеңейтіңіз nginx-кіру контроллері (немесе трейфик), кім жалғыз болады NodePort сыртқы жүктеме теңестірушісімен байланысты соңғы нүкте және кластердегі трафикті пайдалану арқылы бағыттайды кіру-Кубернет ресурстары.

Бір-бірімен өзара әрекеттесетін басқа кластер ішілік (микро) қызметтер сияқты қызметтерді пайдаланып «байланысуға» болады ClusterIP және DNS арқылы кірістірілген қызметті табу механизмі. Тек олардың жалпыға қолжетімді DNS/IP мекенжайын пайдаланбаңыз, себебі бұл кідіріске әсер етіп, бұлттық қызметтердің құнын арттыруы мүмкін.

4. Кластерді оның ерекшеліктерін есепке алмай автомасштабтау

Түйіндерді кластерге қосқанда және оларды кластерге жою кезінде сол түйіндерде CPU пайдалану сияқты кейбір негізгі көрсеткіштерге сенбеу керек. Подты жоспарлау көп нәрсені ескеруі керек шектеулер, мысалы, қосқыш/түйін ұқсастығы, ақаулар мен рұқсаттар, ресурс сұраулары, QoS және т.б. Осы нюанстарды ескермейтін сыртқы автомасштабты пайдалану проблемаларға әкелуі мүмкін.

Белгілі бір подкастты жоспарлау керек деп елестетіңіз, бірақ барлық қолжетімді процессор қуаты сұралады/бөлшектелген және подкаст күйде қалып қояды Pending. Сыртқы автомасштабтаушы процессордың орташа ағымдағы жүктемесін (сұралған емес) көреді және кеңейтуді бастамайды (кеңейту) - басқа түйінді қоспайды. Нәтижесінде бұл қосқыш жоспарланбайды.

Бұл жағдайда кері масштабтау (масштабтау) — кластерден түйінді жою әрқашан іске асыру қиынырақ. Сізде күйі бар подкаст бар деп елестетіңіз (тұрақты жад қосылған). Тұрақты көлемдер әдетте тиесілі арнайы қолжетімділік аймағы және аймақта қайталанбайды. Осылайша, егер сыртқы автомасштабтаушы осы подкольмен түйінді жойса, жоспарлаушы бұл подкастты басқа түйінге жоспарлай алмайды, себебі мұны тек тұрақты жад орналасқан қолжетімділік аймағында ғана жасауға болады. Pod күйінде тұрып қалады Pending.

Кубернетес қауымдастығында өте танымал кластер-автомасштабтауыш. Ол кластерде жұмыс істейді, негізгі бұлттық провайдерлердің API интерфейстерін қолдайды, барлық шектеулерді ескереді және жоғарыда аталған жағдайларда масштабтауға болады. Ол сондай-ақ барлық белгіленген шектеулерді сақтай отырып, ауқымды кеңейте алады, осылайша ақшаны үнемдейді (ол басқа жағдайда пайдаланылмаған қуатқа жұмсалады).

5. IAM/RBAC мүмкіндіктерін елемеу

үшін тұрақты құпиялары бар IAM пайдаланушыларын пайдаланудан сақ болыңыз машиналар мен қосымшалар. Рөлдер мен қызмет тіркелгілерін пайдаланып уақытша кіруді ұйымдастырыңыз (қызметтік шоттар).

Қолданба конфигурациясында қатынау кілттерінің (және құпиялардың) қатты кодталғанын, сондай-ақ Cloud IAM рұқсатына қарамастан құпияларды айналдыруды елемейтін фактілерді жиі кездестіреміз. Қажет болған жағдайда пайдаланушылардың орнына IAM рөлдері мен қызмет тіркелгілерін пайдаланыңыз.

Kubernetes пайдалану кезіндегі 10 жиі кездесетін қателер

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. Қоспалар үшін автоматты анти-апфиниттілікке сенбеңіз

Түйінде кейбір орналастырудың үш көшірмесі бар деп елестетіңіз. Түйін құлайды және онымен бірге барлық көшірмелер. Жағымсыз жағдай, солай ма? Бірақ неге барлық көшірмелер бір түйінде болды? Кубернетес жоғары қолжетімділікті (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", - және әртүрлі қолжетімділік аймақтары туралы емес. Толық ХА енгізу үшін сізге осы тақырыпты тереңірек зерттеу керек болады.

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 аттар кеңістігі (аттар кеңістігі) күшті оқшаулауды қамтамасыз етпеңіз.

Жалпы қате түсінік, егер сіз бір аттар кеңістігіне өнім емес жүктемені және басқасына өнім жүктемесін орналастырсаңыз, онда олар бір-біріне ешқандай әсер етпейді... Дегенмен, белгілі бір оқшаулау деңгейіне ресурс сұрауларын/шектеулерін, квоталарды орнату және priorityClasses орнату арқылы қол жеткізуге болады. Деректер жазықтығындағы кейбір «физикалық» оқшаулау ұқсастықтармен, төзімділіктермен, сызаттармен (немесе түйіндерді таңдау арқылы) қамтамасыз етіледі, бірақ мұндай бөлу айтарлықтай қиын іске асыру.

Бір кластерде жұмыс жүктемесінің екі түрін біріктіруді қажет ететіндер күрделілікпен күресуге мәжбүр болады. Егер мұндай қажеттілік болмаса және сізде оны алуға мүмкіндігіңіз болса тағы бір кластер (мысалы, жалпыға ортақ бұлтта), онда мұны істеген дұрыс. Бұл оқшаулаудың әлдеқайда жоғары деңгейіне жетеді.

9. externalTrafficPolicy: Кластер

Біз кластер ішіндегі барлық трафик әдепкі саясат орнатылған NodePort сияқты қызмет арқылы келетінін жиі көреміз. externalTrafficPolicy: Cluster... Бұл дегеніміз NodePort кластердегі әрбір түйінде ашық және сіз олардың кез келгенін қалаған қызметпен (подтар жинағы) әрекеттесу үшін пайдалана аласыз.

Kubernetes пайдалану кезіндегі 10 жиі кездесетін қателер

Сонымен қатар, жоғарыда аталған NodePort қызметімен байланысты нақты бөтелкелер әдетте белгілі бір жерде ғана қол жетімді. осы түйіндердің ішкі жиыны. Басқаша айтқанда, егер мен қажетті подкаст жоқ түйінге қосылсам, ол трафикті басқа түйінге бағыттайды, хоп қосу және кідірістің жоғарылауы (егер түйіндер әртүрлі қолжетімділік аймақтарында/деректер орталықтарында орналасса, кідіріс айтарлықтай жоғары болуы мүмкін; сонымен қатар, шығу трафигінің шығындары артады).

Екінші жағынан, белгілі бір Kubernetes қызметінде саясат жинағы болса externalTrafficPolicy: Local, содан кейін NodePort тек қажетті қосқыштар нақты іске қосылған түйіндерде ашылады. Күйін тексеретін сыртқы жүктеме балансын пайдаланған кезде (денсаулықты тексеру) соңғы нүктелер (ол қалай істейді AWS ELB), Ол трафикті тек қажетті түйіндерге жібереді, бұл кідірістерге, есептеу қажеттіліктеріне, шығыс шоттарына жақсы әсер етеді (және жалпы мағына да солай етеді).

Осы сияқты бірдеңені пайдаланып жатқаныңыздың ықтималдығы жоғары трейфик немесе nginx-кіру контроллері HTTP кіру трафигін бағыттау үшін NodePort соңғы нүктесі (немесе NodePort пайдаланатын LoadBalancer) ретінде және бұл опцияны орнату осындай сұраулар үшін кідіріс уақытын айтарлықтай азайтуы мүмкін.

В осы жарияланымның Сіз externalTrafficPolicy, оның артықшылықтары мен кемшіліктері туралы көбірек біле аласыз.

10. Кластерлерге байланбаңыз және басқару жазықтығына қиянат жасамаңыз

Бұрын серверлерді тиісті атаулармен шақыру әдеттегідей болды: Антон, HAL9000 және Colossus... Бүгінде олар кездейсоқ құрылған идентификаторлармен ауыстырылды. Дегенмен, әдет қалды, енді жалқы есімдер кластерлерге барады.

Кәдімгі оқиға (нақты оқиғаларға негізделген): бәрі тұжырымдаманы дәлелдеуден басталды, сондықтан кластердің мақтанарлық атауы болды. тестілеу...Жылдар өтті, ол Өндірісте ӘЛІ ҚОЛДАНЫЛАДЫ, оған қол тигізуге бәрі қорқады.

Кластерлердің үй жануарларына айналуында қызық ештеңе жоқ, сондықтан жаттығу кезінде оларды мезгіл-мезгіл алып тастауды ұсынамыз. апатты қалпына келтіру (бұл көмектеседі хаос инженериясы - шамамен. аудар.). Сонымен қатар, басқару қабатында жұмыс істеу зиян тигізбейді (басқару ұшағы). Оған қол тигізуге қорқу жақсы белгі емес. т.б өлді? Жігіттер, сендер шынымен қиыншылықтасыңдар!

Екінші жағынан, сіз оны манипуляциялаумен айналыспауыңыз керек. Уақытпен басқару қабаты баяу болуы мүмкін. Бұл, ең алдымен, олардың айналуынсыз жасалған көптеген нысандарға байланысты (Helm-ді әдепкі параметрлермен пайдалану кезіндегі жалпы жағдай, сондықтан оның конфигматикалық карталардағы/құпиялардағы күйі жаңартылмайды - нәтижесінде мыңдаған нысандар жинақталады. басқару деңгейі) немесе kube-api нысандарын тұрақты өңдеумен (автоматты масштабтау үшін, CI/CD үшін, бақылау үшін, оқиғалар журналдары, контроллерлер және т.б.).

Бұған қоса, басқарылатын Kubernetes провайдерімен SLA/SLO келісімдерін тексеруді және кепілдіктерге назар аударуды ұсынамыз. Сатушы кепілдік бере алады деңгейдің қолжетімділігін бақылау (немесе оның ішкі құрамдас бөліктері), бірақ сіз оған жіберген сұраулардың p99 кідірісі емес. Басқаша айтқанда, енгізуге болады kubectl get nodes, және жауапты 10 минуттан кейін ғана алыңыз және бұл қызмет көрсету келісімінің шарттарын бұзу болып табылмайды.

11. Бонус: соңғы тегті пайдалану

Бірақ бұл қазірдің өзінде классика. Соңғы уақытта біз бұл әдісті сирек кездестіреміз, өйткені көптеген адамдар ащы тәжірибеден сабақ алып, тегті пайдалануды тоқтатты. :latest және нұсқаларды бекітуді бастады. Ура!

ECR сурет тегтерінің өзгермейтіндігін сақтайды; Сізге осы тамаша мүмкіндікпен танысуды ұсынамыз.

Резюме

Барлығы бір түнде жұмыс істейді деп күтпеңіз: Кубернетес панацея емес. Нашар қолданба тіпті Кубернетесте де осылай қалады (және ол нашарлауы мүмкін). Абайсыздық бақылау қабатының шамадан тыс күрделілігіне, баяу және стресстік жұмысына әкеледі. Бұған қоса, апатты қалпына келтіру стратегиясынсыз қалу қаупі бар. Kubernetes қораптан тыс оқшаулауды және жоғары қолжетімділікті қамтамасыз етеді деп күтпеңіз. Қолданбаңызды шынымен бұлттыққа айналдыруға біраз уақыт бөліңіз.

Сіз әртүрлі командалардың сәтсіз тәжірибелерімен таныса аласыз бұл әңгімелер жинағы Хеннинг Джейкобс жазған.

Осы мақалада келтірілген қателер тізіміне қосқысы келетіндер бізбен Twitter арқылы байланыса алады (@MarekBartik, @MstrsObserver).

Аудармашыдан PS

Біздің блогта да оқыңыз:

Ақпарат көзі: www.habr.com

пікір қалдыру