Production-ready images for k8s

Гэтая гісторыя пра тое, як мы выкарыстоўваем кантэйнеры ў прадуктовым асяроддзі, асабліва пад Kubernetes. Артыкул прысвечаны збору метрык і логаў з кантэйнераў, а таксама білду вобразаў.

Production-ready images for k8s

Мы з фінтэх-кампаніі Exness, якая займаецца распрацоўкай сэрвісаў для анлайн-трэйдзінгу і фінтэх-прадуктаў для B2B і В2С. У нашым R & D шмат розных каманд, у аддзеле распрацоўкі 100 + супрацоўнікаў.

Мы прадстаўляем каманду, якая адказвае за платформу для збору і запуску кода нашымі распрацоўшчыкамі. У прыватнасці, мы адказваем за збор, захоўванне і прадастаўленне метрык, логаў, і падзей з прыкладанняў. У цяперашні час мы аперуем прыкладна трыма тысячамі Docker-кантэйнераў у прадуктовым асяроддзі, падтрымліваем наша big data-сховішча на 50 Тб і падаем архітэктурныя рашэнні, якія будуюцца вакол нашай інфраструктуры: Kubernetes, Rancher і розныя публічныя cloud-правайдэры. 

Наша матывацыя

Што гарыць? Ніхто не можа адказаць. Дзе ачаг? Зразумець цяжка. Калі загарэлася? Высветліць можна, але не адразу. 

Production-ready images for k8s

Чаму адны кантэйнеры стаяць, а іншыя ўпалі? Які кантэйнер стаў таму віной? Бо звонку кантэйнеры аднолькавыя, а ўсярэдзіне ў кожнага свой Neo.

Production-ready images for k8s

Нашы распрацоўшчыкі - пісьменныя хлопцы. Яны робяць добрыя паслугі, якія прыносяць прыбытак кампаніі. Але бываюць факапы, калі кантэйнеры з прыкладаннямі ідуць уразброд. Адзін кантэйнер спажывае занадта шмат CPU, іншы – сетка, трэці – аперацыі ўводу-вываду, чацвёрты наогул незразумела, што робіць з сокетамі. Усё гэта падае, і карабель тоне. 

агенты

Каб зразумець, што адбываецца ўнутры, мы вырашылі ставіць агентаў прама ў кантэйнеры.

Production-ready images for k8s

Гэтыя агенты - стрымальныя праграмы, якія падтрымліваюць кантэйнеры ў такім стане, каб яны не зламалі адзін аднаго. Агенты стандартызаваны, і гэта дазваляе стандартаваць падыход да абслугоўвання кантэйнераў. 

У нашым выпадку агенты павінны прадастаўляць логі ў стандартным фармаце, тэгіраваныя і з тратлінгам. Таксама яны павінны даваць нам стандартызаваныя метрыкі, якія пашыраюцца з пункту гледжання бізнэс-прыкладанняў.

Пад агентамі таксама маюцца на ўвазе ўтыліты для эксплуатацыі і абслугоўвання, якія ўмеюць працаваць у розных сістэмах аркестравання, якія падтрымліваюць розныя images (Debian, Alpine, Centos і т. д.).

Нарэшце, агенты павінны падтрымліваць просты CI/CD, улучальны ў сябе Docker-файлы. Інакш карабель разваліцца, таму што кантэйнеры пачнуць пастаўляцца па "крывых" рэйках.

Працэс зборкі і прылада мэтавага image

Каб усё было стандартызавана і кіравана, неабходна прытрымлівацца нейкага стандартнага працэсу зборкі. Таму мы вырашылі збіраць кантэйнеры кантэйнерамі - такая вось рэкурсія.

Production-ready images for k8s

Тут кантэйнеры прадстаўлены суцэльнымі контурамі. Заадно вырашылі пакласці ў іх дыстрыбутывы, каб "жыццё малінай не здавалася". Навошта гэта было зроблена, мы раскажам ніжэй.
 
У выніку атрымаўся інструмент для зборкі - кантэйнер пэўнай версіі, які спасылаецца на пэўныя версіі дыстрыбутываў і пэўныя версіі скрыптоў.

Як мы яго ўжываем? У нас ёсць Docker Hub, у якім ляжыць кантэйнер. Мы люструем яго ўнутр сваёй сістэмы, каб пазбавіцца ад вонкавых залежнасцяў. Атрымаўся кантэйнер, пазначаны жоўтым колерам. Мы ствараем шаблон, каб усталяваць у кантэйнер усе неабходныя нам дыстрыбутывы і скрыпты. Пасля гэтага мы збіраем гатовую да эксплуатацыі выяву: распрацоўнікі кладуць у яго код і нейкія свае адмысловыя залежнасці. 

Чым добры такі падыход? 

  • Па-першае, поўны версійны кантроль інструментаў зборкі - кантэйнер зборкі, версіі скрыптоў і дыстрыбутываў. 
  • Па-другое, мы дабіліся стандартызацыі: аднолькавым чынам ствараем шаблоны, прамежкавыя і гатовыя да эксплуатацыі image. 
  • Па-трэцяе, кантэйнеры забяспечваюць нам партавальнасць. Сёння мы выкарыстоўваем Gitlab, а заўтра пяройдзем на TeamCity або Jenkins і сапраўды гэтак жа зможам запускаць нашы кантэйнеры. 
  • Па-чацвёртае, мінімізацыя залежнасцяў. Мы невыпадкова паклалі ў кантэйнер дыстрыбутывы, бо гэта дазваляе не спампоўваць іх кожны раз з Інтэрнэту. 
  • Па-пятае, павысілася хуткасць зборкі – наяўнасць лакальных копій выяў дазваляюць не марнаваць час на запампоўку, бо ёсць лакальная выява. 

Іншымі словамі, мы дабіліся кантраляванага і гнуткага працэсу зборкі. Мы выкарыстоўваем аднолькавыя сродкі для зборкі любых кантэйнераў з поўным версіяваннем. 

Як працуе наша працэдура зборкі

Production-ready images for k8s

Зборка запускаецца адной камандай, працэс выконваецца ў выяве (вылучаны чырвоным). У распрацоўніка ёсць Docker-файл (вылучаны жоўтым), мы яго рэндэрым, падмяняючы зменныя значэннямі. І адначасна дадаем header'ы і footer'ы - гэта нашы агенты. 

Header дадае дыстрыбутывы з адпаведных вобразаў. А footer усталёўвае ўнутр нашы сэрвісы, наладжвае запуск працоўнай нагрузкі, лагіраванні і іншых агентаў, падмяняе entrypoint і г.д. 

Production-ready images for k8s

Мы доўга думалі, ці ставіць супервізор. У рэшце рэшт, вырашылі, што ён нам патрэбен. Выбралі S6. Супервізор забяспечвае кіраванне кантэйнерам: дазваляе падлучацца да яго ў выпадку падзення асноўнага працэсу і забяспечвае ручное кіраванне кантэйнерам без яго перастварэння. Логі і метрыкі - гэта працэсы, якія выконваюцца ўнутры кантэйнера. Іх таксама трэба неяк кантраляваць, і мы гэта робім з дапамогай супервізара. Нарэшце, S6 бярэ на сябе выкананне housekeeping, апрацоўку сігналаў і іншыя задачы.

Паколькі ў нас ужываюцца розныя сістэмы аркестрацыі, пасля зборкі і запуску кантэйнер павінен зразумець, у якім асяроддзі ён знаходзіцца, і дзейнічаць па сітуацыі. Напрыклад:
Гэта дазваляе нам сабраць адну выяву і запускаць яго ў розных сістэмах аркестрацыі, прычым запускацца ён будзе з улікам спецыфікі гэтай сістэмы аркестрацыі.

 Production-ready images for k8s

Для аднаго і таго ж кантэйнера мы атрымліваем розныя працэсныя дрэвы ў Docker і Kubernetes:

Production-ready images for k8s

Карысная нагрузка выконваецца пад супервізарам S6. Звярніце ўвагу на collector і events - гэта нашы агенты, якія адказваюць за логі і метрыкі. У Kubernetes іх няма, а ў Docker ёсць. Чаму? 

Калі паглядзець спецыфікацыю пода (тут і далей Kubernetes pod), то мы ўбачым, што кантэйнер events выконваецца ў подзе, у якім ёсць асобны кантэйнер collector, які выконвае функцыю збору метрык і логаў. Мы можам выкарыстоўваць магчымасці Kubernetes: запуск кантэйнераў у адным подзе, у адзінай працэснай і/або сеткавай прасторах. Фактычна ўкараняць сваіх агентаў і выконваць нейкія функцыі. І калі гэты ж кантэйнер запусціцца ў Docker, ён атрымае на выхадзе ўсё тыя ж самыя магчымасці, гэта значыць зможа дастаўляць логі і метрыкі, бо агенты будуць запушчаны ўсярэдзіне. 

Метрыкі і логі

Дастаўка метрык і логаў - складаная задача. З яе вырашэннем звязана некалькі аспектаў.
Інфраструктура ствараецца для выканання карыснай нагрузкі, а не масавай дастаўкі логаў. Гэта значыць, гэты працэс павінен выконвацца з мінімальнымі патрабаваннямі да рэсурсаў кантэйнераў. Мы імкнемся дапамагчы нашым распрацоўшчыкам: "Вазьміце кантэйнер Docker Hub, запусціце, і мы зможам даставіць логі". 

Другі аспект - абмежаванне аб'ёму логаў. Калі ў некалькіх кантэйнерах узнікае сітуацыя ўсплёску аб'ёму логаў (прыкладанне ў цыкле выводзіць stack-trace), узрастае нагрузка на CPU, каналы сувязі, сістэму апрацоўкі логаў, і гэта ўплывае на працу хаста ў цэлым і іншыя кантэйнеры на хасце, то часам гэта прыводзіць да "падзення" хаста. 

Трэці аспект неабходна са скрынкі падтрымліваць як мага больш методык збору метрык. Ад чытання файлаў і апытання Prometheus-endpoint да выкарыстання спецыфічных пратаколаў дадаткаў.

І апошні аспект - неабходна мінімізаваць спажыванне рэсурсаў.

Мы абралі open-source рашэнне на Go пад назовам Telegraf. Гэта ўніверсальны канектар, які падтрымлівае больш за 140 відаў уваходных каналаў (input plugins) і 30 відаў выходных (output plugins). Мы яго дапрацавалі і зараз мы раскажам, як ён выкарыстоўваецца ў нас на прыкладзе Kubernetes. 

Production-ready images for k8s

Дапушчальны, распрацоўнік разгортвае нагрузку, і Kubernetes атрымлівае запыт на стварэнне пода. У гэты момант для кожнага пода аўтаматычна ствараецца кантэйнер пад назвай Collector (мы выкарыстоўваем mutation webhook). Collector - гэта наш агент. На старце, гэты кантэйнер настройвае сябе на працу c Prometheus і сістэмай збору логаў.

  • Для гэтага ён выкарыстоўвае анатацыі пода, і ў залежнасці ад яе змесціва, стварае, скажам, канчатковую кропку end-point Prometheus; 
  • На падставе спецыфікацыі пода і спецыфічных налад кантэйнераў вырашае, як дастаўляць логі.

Логі мы збіраем праз Docker API: распрацоўнікам дастаткова пакласці іх у stdout ці stderr, а далей Collector разбярэцца. Логі збіраюцца chunk'амі з некаторай затрымкай, каб прадухіліць магчымую перагрузку хаста. 

Метрыкі збіраюцца па асобніках працоўнай нагрузкі (працэсам) у кантэйнерах. Усё пазначаецца тэгамі: namespace, пад і гэтак далей, а затым канвертуецца ў фармат Prometheus - і становіцца даступна для збору (акрамя логаў). Таксама, логі, метрыкі і падзеі мы адпраўляем у Kafka і далей:

  • Логі даступныя ў Graylog (для візуальнага аналізу);
  • Логі, метрыкі, падзеі адпраўляюцца ў Clickhouse для доўгатэрміновага захоўвання.

Гэтак жа ўсё працуе ў AWS, толькі мы заменны Graylog з Kafka на Cloudwatch. Адпраўляем туды логі, і ўсё атрымліваецца вельмі зручна: адразу зразумела, да каго кластару і кантэйнеру яны ставяцца. Тое ж самае дакладна і для Google Stackdriver. Гэта значыць, наша схема працуе як on-premise з Kafka, так і ў воблаку. 

Калі ж у нас няма Kubernetes з подамі, схема атрымліваецца крыху больш складана, але працуе па тых жа прынцыпах.

Production-ready images for k8s

Усярэдзіне кантэйнера выконваюцца такія ж працэсы, яны аркеструюцца з дапамогай S6. Усё тыя ж самыя працэсы запушчаны ўнутры аднаго кантэйнера.

У выніку

Мы стварылі суцэльнае рашэнне для зборкі і запуску выяў у эксплуатацыю, з опцыямі збору і дастаўкай логаў і метрык:

  • Распрацавалі стандартызаваны падыход да зборкі выяў, на яго аснове распрацавалі CI-шаблоны;
  • Агенты для збору дадзеных - гэта нашы пашырэння Telegraf. Мы іх добра абкаталі ў production;
  • Ужывальны mutation webhook для ўкаранення кантэйнераў з агентамі ў падах; 
  • Інтэграваліся ў экасістэму Kubernetes/Rancher;
  • Можам выконваць аднолькавыя кантэйнеры ў розных сістэмах аркестрацыі і атрымліваць чаканы намі вынік;
  • Стварылі цалкам дынамічную канфігурацыю кіравання кантэйнерамі. 

Суаўтар: Ілля Пруднікаў

Крыніца: habr.com

Дадаць каментар