Русский
Русский
English
Статистика
Реклама

Ресурсы

Delphi 7 на костылях автоматизация подготовки ресурсов

31.03.2021 18:20:59 | Автор: admin

Эпиграф: Пусть это вдохновит Вас на подвиг! (Бел Кауфман, Вверх по лестнице, ведущей вниз).

О костылях и велосипедах, неотъемлемой части современной некромантии.

Это история интеграции в процесс разработки одного единственного решения. Решение доведено до конечного результата, ссылка на репозиторий будет далее по тексту.

Казалось бы, что может быть более простым и естественным, чем прозрачная, без нелепых телодвижений, работа с размещёнными в специально выделенной для этого папке ресурсами? А если среда разработки выпущена на границе тысячелетия?

Первым великим неудобством, с которым я столкнулся, подписавшись года четыре назад на сопровождение и активную доработку проекта на Delphi 7, было категорическое неудобство работы с входящими в проект относительно крупными SQL запросами. Проект обеспечивает отчётность перед поставщиками (десятки поставщиков, взаимодействие с которыми идёт через множество компаний-интеграторов), и этих запросов там, что гуталина у сторожа ну просто завались. Причём запросы эти изначально описывались прямо в тексте, вперемешку с кодом представьте мой восторг с учётом того, что запросы приходилось время от времени переносить в SSMS, исправлять и переносить обратно. А если вспомнить, что и Delphi, и в SQL используются одиночные кавычки, становится ещё печальнее.

Первая реакция на эту красоту была вполне предсказуемой: срочно отделить данные от кода! Идеальным (и очевидным) решением кажется создание структуры папок с файлами запросов, которые при компиляции автоматически попадали бы в ресурсы с соответствующими идентификаторами. При этом, однако, компилятору нужно явно предоставлять список ресурсов в виде отдельно сформированного *.rc файла с соответствующими именами для доступа, который надо ещё предварительно сформировать.

Однако, компиляция проекта из-под IDE Delphi 7 является чёрным ящиком без малейшей возможности прикрутить к ней хоть что-то своё. У неё просто нет ни одного хука, чтобы зацепить собственный обработчик. Современные версии работают с MS Build, но у меня-то этого нет! Конечно, для сборки продуктивной версии можно использовать батник и компилятор командной строки, где можно добавить любую предварительную обработку, но для запуска из-под IDE этот вариант не годится.

Ещё одна печалька оказалась в том, что файл ресурсов (*.rc) перекомпилируется только тогда, когда изменилась его собственная дата. То, что изменилась дата файла, на который он ссылается (то есть сам ресурс), компилятор не волнует никак. Плюс rc-файл ещё и создать надо! И очень, очень хочется делать это автоматически.

Но сначала появился костыль. До этого я работал с Дельфи лет восемь назад, и с ресурсами тогда совсем не сталкивался, зато свободно делал компоненты. Итак, для решения вопроса по-быстрому я набросал визуальный компонент, который можно было кинуть на форму и открыть текст в редакторе (в окончательной версии - вообще двойным кликом). Набросок был готов в течение пары часов, затем после нескольких подходов компонент был окончательно оформлен и разделён на две части (просто текст и SQL) ради синтаксической подсветки в редакторе кода. Ниже, на скриншоте, Вы можете увидеть аж четыре компонента (два из которых успели активно поработать), но Проект, хотя и обеспечил очень быстро возможность по-человечески работать с текстом запросов, был заброшен в силу присущих ему принципиальных недостатков.

Первым и самым важным из них оказался формат хранения контента в .dfm файле почти текстовый. Текст принудительно разбивался на строки, закавычивался, все символы не из базовой латиницы записывались многосимвольными кодами Представляете себе, как выглядели при этом диффы? Невозможным оказывался также контекстный поиск по всему проекту (тексты запросов в него не попадали). Поиск сторонними средствами по латинице мог споткнуться о размер строки и её принудительный перенос посреди слова.

  object SqlSALES: TSqlVar    SQL.Strings = (      'SET NOCOUNT ON'      ''      'IF OBJECT_ID(N'#39'tempdb..#Sales'#39', N'#39'U'#39') IS NOT NULL '      'DROP TABLE #Sales;'      ''      'IF OBJECT_ID(N'#39'tempdb..#ClientIDs'#39', N'#39'U'#39') IS NOT NULL '      'DROP TABLE #ClientIDs;'      ''      '-- '#1055#1072#1088#1072#1084#1077#1090#1088#1099': '#1076#1072#1090#1072' '#1086#1090', '#1076#1072#1090#1072' '#1076#1086', '#1075#1088#1091#1087#1087#1072      '-- '#1056#1077#1072#1083#1080#1079#1072#1094#1080#1103      'SELECT '              #9'OperDate,                                                  -- '#1044 +        #1072#1090#1072              ...

На это накладывался ещё один немаловажный недостаток, присущий самописным компонентам Дельфи в принципе: компонент не может быть зарегистрирован на уровне проекта, его надо явно и заранее устанавливать в IDE, но далеко не все это умеют. Если открыть проект в среде без соответствующих компонентов, то они, после гневного сообщения просто пропадут. В наше время, с сокращением количества опытных кадров, не гнушающихся работать с древнючей Delphi, это выглядит, как натуральная бас-факторная мина. Хотя и без того там этих мин хоть ведром черпай...

Еще одна существенная проблема заключалась в невозможности использовать для редактирования при таком подходе сторонние редакторы.

С учётом перечисленного, проект с компонентами замер на полушаге из-за потери целесообразности, а я начал исследовать возможность всё-таки перейти на использование текстовых файлов с автоматическим добавлением их в ресурсы.

Итак, я вернулся к идее хранить отдельные запросы в файлах. Предстояло решить следующие проблемы:

  1. Должен автоматически формироваться файл со списком ресурсов для компилятора

  2. ВАЖНО!!! изменение файла с запросом должно автоматически попасть в программу, при первой же компиляции (даже если не делать build)

  3. Обеспечить включение ресурсов в операцию контекстного поиска по проекту.

  4. Опционально ещё и шифровать для пущего пафоса. Требование проекта на уровне Очень желательно.

По первому пункту я решил использовать Gulp.js инструмент для сборки фронтенда, с которым мельком удалось познакомится незадолго до этого. Он умеет следить за изменением файлов в папке и обрабатывать это событие. Мне требовалась лишь возможность запустить по событию командный файл. Этот же файл используется и для билда продуктивной версии.

Обеспечение второго пункта разложилось на две половинки. Во-первых, при изменении исходных файлов требовалось сразу же, не дожидаясь перестроения списка, изменить дату .rc файла. Это инициирует запрос на перезагрузку файла при переключении в Delphi. Во-вторых, этот файл должен быть постоянно открыт в IDE, иначе компилятор не обращает внимания на то, что он изменился (он-то, наивный, предполагает, что я всё через IDE делаю). А так при переключении извне в IDE дата файла проверяется и задаётся вопрос о необходимости его перезагрузить.

Третий пункт (контекстный поиск) решается добавлением исходного файла в проект, до первого USES, в директиве компилятора вида:

{%File 'Res\SRC\SQL\Import\Sectors\leafSectors.sql'}

Четвёртый решается элементарно запуском отдельной утилитки для шифрования всё в том же пакетном файле, и расшифровкой непосредственно в основном проекте при обращении к ресурсу.

Ну, и собственно список файлов сформировать надо было. В результате шапка проекта стала выглядеть примерно так:

SomeProject.dpr

library SomeProject;{  Текст между тегами ниже генерируется и обновляется автоматически!  Этот фрагмент нужен для подключения исходных файлов ресурсов к поиску  текста по файлам проекта.   Для разового обновления запустить res/CompileRc/CompileAllResources.cmd  Для автоматического обновления запустить _Автообновление ресурсов.cmd  Пока работает автообновление, после каждого изменения исходных файлов в папке res\src  автоматически запускается res/CompileRc/CompileAllResources.cmd  Чтобы среда разработки автоматически подтягивала изменения, в ней должен быть  открыт в редакторе исходник 'Res\AutoGenerated.rc'. <= Можно поместить  курсор куда-нибудь сюда -----^^^^^^^^^^^^^^^^^^^^ и нажать Ctrl + Enter}{<AUTOGENERATED_RC>}{%File 'Res\SRC\SQL\DB_Updates.sql'}{%File 'Res\SRC\SQL\Foo\Sales.sql'}{%File 'Res\SRC\SQL\Foo\Stocks.sql'}...{$R 'Res\AutoGenerated.res' 'Res\AutoGenerated.rc'}{</AUTOGENERATED_RC>}uses...

AutoGenerated.rc (пример):

SQL_DB_Updates     RCDATA PREPARED\SQL_DB_UpdatesSQL_Foo_Sales     RCDATA PREPARED\SQL_Foo_SalesSQL_Foo_Stocks     RCDATA PREPARED\SQL_Foo_Stocks...

Галпфайл был простой до безобразия:

gulpfile.js

const { watch, series } = require('gulp');const spawn = require('child_process').spawn; function compileResources(cb) { var cmd = spawn('CompileRc\\CompileAllResources.cmd', [], {stdio: 'inherit'}); cmd.on('close', function (code) {   cb(code); });} exports.default = function() { compileResources(code=>{}) watch('Src/**', compileResources); // series(compileResources, ...)};

Простота связана с тем, что вся процедура подготовки ресурсов должна быть независимой от монитора изменений, и запускаться отдельно (в том числе при сборке приложения средствами командной строки). Галп только взял на себя запуск отдельно созданного и отлаженного пакетника по событию изменения исходных файлов.

Кстати, пришлось его радикально править, когда пришлось обновить Галп после обновления Ноды. Текущие версии у меня такие:

>gulp --versionCLI version: 2.3.0Local version: 4.0.2>node -vv12.20.0

Впрочем, это уже не важно от Галпа я буквально в процессе написания статьи избавился.

Основной пакетник:

  • сразу же меняет дату сгенерированного файла

  • составляет список файлов в обслуживаемой папке, за вычетом исключений

  • запускает программку на Perl, которая преобразует сырой список файлов во все виды, в которых он употребляется, в том числе генерирует rc-файл, и формирует задание на подготовку (шифрование) для изменённых файлов

  • запускает подготовку ресурсов

  • выделяет из dpr ранее добавленный туда список ссылок. Если он изменился, то заменяет его

  • компилирует сформированный rc-файл

  • Информирует о времени запуска и завершения и об обслуживаемой папке (на случай одновременного запуска нескольких экзкмпляров.

И всё это запускается из отслеживающего изменения монитора.

CompileAllResources.cmd

@Echo offset BatchDir=%~dp0cd %BatchDir%touch ..\AutoGenerated.rcFOR %%i IN ("%BatchDir%..") DO (set target=%%~fi)echo.echo [%TIME%] STARTING: ===== %target% =====echo.if not exist %BatchDir%..\prepared\*.* md %BatchDir%..\prepared > nulcall %BatchDir%..\AutoCompileRc.Config.cmdFOR %%i IN ("%DprFile%") DO (set DprFileOnly=%%~nxi)call %BatchDir%WaitWhileRunned.cmd gitcd %BatchDir%..%BatchDir%bin\find SRC -type f | %BatchDir%bin\grep -E -v --file=%BatchDir%excludes.lst>%BatchDir%ResFiles.lst%BatchDir%bin\perl %BatchDir%CreateRc.pl %BatchDir%ResFiles.lst AutoGenerated.rc %BatchDir%RcSources.lst %BatchDir%PrepareIt.cmdcd %BatchDir%echo {$R 'Res\AutoGenerated.res' 'Res\AutoGenerated.rc'}>>RcSources.lstcall between.cmd %DprFile% "\{<AUTOGENERATED_RC>\}\s*" "\{<\/AUTOGENERATED_RC>\}">RcSourcesOld.lstfc RcSources.lst RcSourcesOld.lst>nulif errorlevel 1 (call ReplaceBetween.cmd %DprFile% RcSources.lst "\{\<AUTOGENERATED_RC\>\}\s*" "\{\<\/AUTOGENERATED_RC\>\}">%DprFileOnly%.tmpcopy %DprFileOnly%.tmp %DprFile%>nuldel %DprFileOnly%.tmp)echo Preparing updated and new files...cd ..call %BatchDir%PrepareIt.cmdecho Compiling resources...brcc32 AutoGenerated.rccd %BatchDir%echo.echo [%TIME%] DONE: ===== %target% =====echo.

Внутри он содержит сборную солянку технологий, использует линуксовские find и grep (под Виндой они ставятся вместе с git) и даже Перл. Каюсь, побаловаться захотелось. Забавный опыт, хотя и немного травматичный. Своей лаконичностью и непрозрачностью (вроде наличия переменной по умолчанию) он напомнил мне ассемблер:

CreateRc.pl

#!c:/Perl/bin/perlopen (IN, "<".$ARGV[0]) || die $!;      # Список исходных файлов для ресурсовopen (RC_ENC, ">".$ARGV[1]) || die $!;  # Формируемый исходник (.rc)open (LST, ">".$ARGV[2]) || die $!;     # Формируемый файл со списком  # исходников, который будет вставлен в проект между тегами  # {<AUTOGENERATED_RC>} и {</AUTOGENERATED_RC>}open (ENC_CMD, ">".$ARGV[3]) || die $!; # Формируемый пакетный файл (.cmd)  # для подготовки каждого изменённого файла (например, щифрование)while(<IN>){  split /\n/;  $File = $_;                     # Для каждого из исходных файлов  $File =~ s/\//\\/g;             # - приводим разделитель каталогов  $File =~ s/\n//;                # - исключаем перевод строки  $Name = $File;                  # Имя ресурса  $Name =~ s/^Src\\//i;           # - исключаем префикс (папка)  $Name =~ s/\\/_/g;              # - вместо разделителя каталогов подчёркивание  $Name =~ s/\..*$//;             # - исключаем расширение  $Dest = "PREPARED\\".$Name."";  $_ = $File;  $EncryptIt = ! /\\Bin\\/i;      # Ресурсы из папок и подпапок bin не шифруем  print RC_ENC $Name    , substr("                                        ", 1, 40 - length($Name))    , "    RCDATA  "    , $Dest    , "\r\n";  $_ = $File;  if (! /\\Bin\\/i) {    # Добавляем в проект текстовые ресурсы (здесь: формируем вставку в dpr файл)    # Ресурсы из папок и подпапок bin не считаем текстом и в проект не включаем    print LST        "{\%File 'Res\\"      , $File      , "'}\r\n";  }  # Только для новых или обновлённых файлов: добавляем команду на подготовку  # (шифрование либо просто копирование)  if (! (-f $Dest) || ( (stat $File)[9] > (stat $Dest)[9] ) ) {    if ($EncryptIt) {      # Шифрование: encrypt.cmd <источник> <приёмник> <имя ресурса в нижнем регистре>      # имя ресурса может быть использовано для генерации пароля.      # Еncrypt.cmd определяете самостоятельно.      print ENC_CMD "call encrypt.cmd "        , $File        , substr("                                        ", 1, 40 - length($File))        , " "        , $Dest        , " \""        , lc $Name        , "\"\r\n";    } else {      print ENC_CMD "copy "        , $File        , substr("                                        ", 1, 40 - length($File))        , " "        , $Dest        , ">nul\r\n";    }  }}close IN;close RC_ENC;close LST;close ENC_CMD;

В процессе многолетней эксплуатации вылезли забавные особенности. Для примера, обновление git (с последующим обновлением линуксовских утилит) как-то раз мою автоматизацию сломало. Конкретно, более новый grep отказался воспринимать список исключений как список регэкспов, по одному на строку. Find тоже что-то такое подбрасывал (по крайней мере, тот, что установлен глобально сейчас, уже не отрабатывает именно так, как ожидается). В результате пришлось зафиксировать их версию банально кинуть бинарники в репозиторий, чтобы потом не плакать, благо, они не шибко большие, и изменять я их не планирую. Было ли что-то подобное в связи с Перлом не помню, но на всякий случай и его туда же пихнул.

Помню ещё, что добавление шифрования вынудило запоминать дату изменения файлов и шифровать только обновлённые, иначе просто долго получалось скрипт не успевал отработать до того, как я отвечал согласием на предложение перезагрузить исходные файлы в IDE.

И уже после того, как взялся за эту статью, решил всё-таки избавиться от Галпа. Зачем мне (или тому, кто попробует это за мной повторить) неконтролируемая глобальная внешняя зависимость, имеющая ещё одну неконтролируемую внешнюю зависимость (я по node.js), и из возможностей которой используется откровенный мизер?

Результат проект FolderMonitor, написанный на Delphi (https://bitbucket.org/danik-ik/foldermonitor/src/master/). Собственно, именно он прописан как монитор по умолчанию в инсталляторе предыдущего проекта (да, я не только сделал из этого отдельный проект, но даже сдалал инсталлятор в виде пакетного файла, см. https://bitbucket.org/danik-ik/compilerc/src/master/README.md).

Инсталлятор проекта CompileRc работает с использованием git. Он создаёт ветку в репозитории проекта и добавляет туда необходимые модули и настроечные файлы. Вместо шифрования по умолчанию используется заглушка (копирование), что опзволяет добавлять ресурсы как есть. Вот скриншот репозитория тестового проекта в SmartGit, после добавления в него CompileRc (все три коммита ветки CompileRc, как и сама ветка, сформированы инсталлятором), запуска монитора и добавления нескольких файлов ресурсов (в рабочем дереве):

В основу монитора изменений был положен широко известный в пример, с некоторыми доработками по результатам эксплуатации. Во что он там обёрнут, можете глянуть в репозитории, если интересно, там кода всего ничего. Консольное приложение, в режиме ожидания управляется с клавиатуры (пуск/пауза/принудительный запуск).

Основа монитора:

(******************************************************************************  Ожидание (в отдельном потоке) изменений в папке, формирование  соответствующего события.  На основании широко известного примера:  https://webdelphi.ru/2011/08/monitoring-izmenenij-v-direktoriyax-i-fajlax-sredstvami-delphi-chast-1/  Проверяются события:  - изменение имени файла или папки  - изменение размера  - изменение времени последней записи ******************************************************************************)unit FolderMonitorCore;interfaceuses Classes, Windows, SysUtils;type  TFolderMonitorCore = class(TThread)    private      FDirectory: string;      FScanSubDirs: boolean;      FOnChange   : TNotifyEvent;      procedure DoChange;    public      constructor Create(ASuspended: boolean; ADirectory:string; AScanSubDirs: boolean);      property OnChange: TNotifyEvent read FOnChange write FOnChange;    protected      procedure Execute; override;  end;implementation{ TFolderMonitorCore }constructor TFolderMonitorCore.Create(ASuspended: boolean; ADirectory: string;  AScanSubDirs: boolean);begin  inherited Create(ASuspended);  FDirectory:=ADirectory;  FScanSubDirs:=AScanSubDirs;  FreeOnTerminate:=true;end;procedure TFolderMonitorCore.DoChange;begin  if Assigned(FOnChange) then    FOnChange(Self);end;procedure TFolderMonitorCore.Execute;var ChangeHandle: THandle;begin  // инициируем ожидание изменений, получаем соответствующий хэндл  ChangeHandle:=FindFirstChangeNotification(PChar(FDirectory),                                            FScanSubDirs,                                            FILE_NOTIFY_CHANGE_FILE_NAME+                                            FILE_NOTIFY_CHANGE_DIR_NAME+                                            FILE_NOTIFY_CHANGE_SIZE+                                            FILE_NOTIFY_CHANGE_LAST_WRITE                                            );  // Проверяем корректность инициации, иначе выбрасывается исключение{$WARNINGS OFF}  Win32Check(ChangeHandle <> INVALID_HANDLE_VALUE);{$WARNINGS ON}  try    // выполняем цикл пока не получим запрос на завершение    while not Terminated do    begin      { Важное отличие от оригинального примера: ожидание НЕ бесконечно,        периодически проверяется флаг выхода }      case WaitForSingleObject(ChangeHandle, 1000) of        WAIT_FAILED: Terminate; {Ошибка, завершаем поток}        WAIT_OBJECT_0: // Дождались изменений          begin            // Задержка страховка от повторной реакции на несколько изменений подряд            // в процессе единственного сохранения            // (при сохранении исходника в Sublime Text выскакивало стабильно).            // Проблема была следствием ключевого правила: если изменение происходит            // ПОСЛЕ запуска приложения, то по окончании приложение запускается повторно.            // Величина задержки подобрана пальцем в небо.            sleep(5);            WaitForSingleObject(ChangeHandle, 1); // изменение уже было, поэтому результат не проверяется            // Ещё одно отличие: завершение имеет приоритет перед событием изменения            if not Terminated then              Synchronize(DoChange);          end;        WAIT_TIMEOUT: {DO NOTHING}; // идём на следующий круг,                                    // либо завершаем по условию цикла       end;      FindNextChangeNotification(ChangeHandle);    end;  finally    FindCloseChangeNotification(ChangeHandle);  end;end;end.

Итог.

На сегодня работа в ресурсами выглядит следующим образом. Запросы хранятся в отдельных файлах и сгруппированы по папкам. Когда я собираюсь их править, запускаю монитор. Всю папку с исходниками открываю в редакторе (например, VS Code). Исправляю то, что надо, принудительно сохраняю (если полагаться на автосохранение при потере фокуса, и переключиться из редактора прямо в Delphi, то изменения не успеют дойти до rc-файла). В Delphi заранее и всегда открыт AutoGenerated.rc. Когда я переключаюсь в Delphi, дата rc-файла уже изменена монитором, и среда задаёт запрос на его перезагрузку. Любая последующая компиляция подхватывает произведённые изменения с первого раза. То есть, если упростить, то при запущенном мониторе: изменил исходный запрос (или что там в ресурсах лежит) сохранил переключился в Delphi Reload? Yes! запустил. При этом риск запуска с устаревшим вариантом ресурса практически отсутствует.

Ссылка на репозиторий проекта: https://bitbucket.org/danik-ik/compilerc/

На мой взгляд, всё это преодоление позволило вопреки всем ретронеудобствам поддерживать постоянный интерес к работе, качественно разбавляя рутину и не позволяя затосковать по причине отсутствия каких-нибудь модных перламутровых пуговиц. Больше скажу, когда подобных вызовов стало меньше, а рутинные операции многократно ускорились (в смысле трудозатрат), даже как будто чего-то не хватать стало. Наверное, мне просто сложно работать на всём готовом.

Так что если Вы вдруг оказались на должности штатного некроманта просто помните о том, что не боги горшки обжигают, и у Вас есть шансик сделать себе хорошо и нескучно.

P.S.

Если честно,хотел в первую очередь рассказать о параметризованных модульных тестах и об автоматизации их запуска, но вот вылезла именно эта тема, не отвертишься: пиши меня, и всё тут.

Подробнее..

Перевод Как оптимизировать ограничения ресурсов Kubernetes

15.06.2021 10:13:02 | Автор: admin

Поиск оптимальных значений для ограничения ресурсов Kubernetes непростая задача, поскольку вам нужно найти золотую середину между слишком жесткими и недостаточными ограничениями.

В этой статье, которая является продолжением серии статей о рациональном использовании ресурсов в Kubernetes, вы узнаете, как выбрать правильные ограничения ресурсов Kubernetes: от обнаружения контейнеров без каких-либо ограничений до определения оптимальных параметров, которые вы должны установить в своем кластере.

Prometheus одно из самых популярных решений для мониторинга кластеров Kubernetes. Поэтому каждый шаг в этом руководстве содержит примеры запросов PromQL.

Обнаружение контейнеров без ограничения ресурсов

Первым шагом для выбора правильных лимитов является обнаружение контейнеров без каких-либо ограничений.

Отсутствие лимитов в контейнере может оказать негативное воздействие на узлы кластера. В лучшем случае узлы начнут выселять pods с учетом QoS. При этом также возникнут проблемы с производительностью из-за троттлинга процессора. Но в худшем случае узел может перестать работать из-за нехватки ресурсов.

Контейнеры без CPU Limit в каждом namespace

sum by (namespace)(count by (namespace,pod,container)(kube_pod_container_info{container!=""}) unless sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="cpu"}))

Контейнеры без Memory Limit в каждом namespace

sum by (namespace)(count by (namespace,pod,container)(kube_pod_container_info{container!=""}) unless sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="memory"}))

Допустим, вы нашли несколько контейнеров без ограничений ресурсов. Как определить потенциально опасные? Легко! Нужно найти контейнеры, которые используют больше всего ресурсов и при этом не имеют лимитов.

Топ-10 контейнеров без CPU Limits, потребляющих больше всего ресурсов CPU

topk(10,sum by (namespace,pod,container)(rate(container_cpu_usage_seconds_total{container!=""}[5m])) unless sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="cpu"}))

Топ-10 контейнеров без Memory Limits, потребляющих больше памяти

topk(10,sum by (namespace,pod,container)(container_memory_usage_bytes{container!=""}) unless sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="memory"}))

Обнаружение контейнеров со слишком строгими ограничениями

Обнаружение контейнеров со слишком строгими CPU Limits

Если утилизация контейнером ресурсов процессора приближается к установленному лимиту, то его производительность будет снижаться из-за троттлинга ЦП.

Выполните этот запрос, чтобы найти контейнеры, для которых использование ЦП близко к пределу:

(sum by (namespace,pod,container)(rate(container_cpu_usage_seconds_total{container!=""}[5m])) / sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="cpu"})) > 0.8

Обнаружение контейнеров со слишком строгими Memory Limits

Если контейнер превысит лимит по памяти, он будет убит.

На этой диаграмме показано, как при резком повышении потребления контейнером памяти достигнут установленный лимит и контейнер был убит.

Используйте этот запрос, чтобы найти контейнеры, для которых потребление памяти близко к установленному лимиту:

(sum by (namespace,pod,container)(container_memory_usage_bytes{container!=""}) / sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="memory"})) > 0.8

Как выбрать оптимальные значения для лимитов?

Один из способов выбрать оптимальные значения для лимитов наблюдение за утилизацией ресурсов контейнером в течение некоторого времени. Мы можем использовать две стратегии:

Консервативная

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

Находим оптимальный CPU Limit с помощью консервативной стратегии:

max by (namespace,owner_name,container)((rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[5m])) * on(namespace,pod) group_left(owner_name) avg by (namespace,pod,owner_name)(kube_pod_owner{owner_kind=~"DaemonSet|StatefulSet|Deployment"}))

Находим оптимальный Memory Limit с помощью консервативной стратегии:

max by (namespace,owner_name,container)((container_memory_usage_bytes{container!="POD",container!=""}) * on(namespace,pod) group_left(owner_name) avg by (namespace,pod,owner_name)(kube_pod_owner{owner_kind=~"DaemonSet|StatefulSet|Deployment"}))

Агрессивная

Задаем ограничение ресурсов по 99 квантилю. Это позволит не учитывать 1% наиболее высоких значений. Это хорошая стратегия, если есть редкие аномалии или пики, которые вы хотите игнорировать.

Находим оптимальный CPU Limit с помощью агрессивной стратегии:

quantile by (namespace,owner_name,container)(0.99,(rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[5m])) * on(namespace,pod) group_left(owner_name) avg by (namespace,pod,owner_name)(kube_pod_owner{owner_kind=~"DaemonSet|StatefulSet|Deployment"}))

Находим оптимальный Memory Limit с помощью агрессивной стратегии:

quantile by (namespace,owner_name,container)(0.99,(container_memory_usage_bytes{container!="POD",container!=""}) * on(namespace,pod) group_left(owner_name) avg by (namespace,pod,owner_name)(kube_pod_owner{owner_kind=~"DaemonSet|StatefulSet|Deployment"}))

Достаточно ли ресурсов в вашем кластере?

Узлы кластера гарантируют, что запланированные в них pods будут иметь достаточно ресурсов на основе параметра Requests контейнера каждого pods. К тому же, узлы резервируют за каждым контейнером указанный объем памяти и количество ядер ЦП.

Необходимо также контролировать, что сумма всех ограничений ресурсов Kubernetes не превышает ёмкость ресурсов в вашем кластере.

Когда вы утилизируете большую часть ресурсов кластера, контейнеры могут работать без проблем при обычной нагрузке, но в сценариях с высокой нагрузкой контейнеры могут начать использовать ЦП и память до предела. Это приведет к тому, что узел начнет выселять pods, а в критических ситуациях узел перестанет работать из-за нехватки ресурсов.

Как обнаружить превышение доступных ресурсов кластера?

Процент превышения доступных ресурсов по памяти:

100 * sum(kube_pod_container_resource_limits{container!="",resource="memory"} ) / sum(kube_node_status_capacity_memory_bytes)

Процент превышения доступных ресурсов по ЦП:

100 * sum(kube_pod_container_resource_limits{container!="",resource="cpu"} ) / sum(kube_node_status_capacity_cpu_cores)

Как правило, не все контейнеры полностью утилизируют запрашиваемые ресурсы одновременно. Если заданные лимиты составляют 100% от ресурсов кластера это повлечет за собой дополнительные затраты на инфраструктуру, которая никогда не будет использоваться.

Лучшим решением будет выбрать консервативную стратегию, гарантирующую, что избыточное использование составляет менее 125%, или агрессивную стратегию, которая позволяет лимитам достичь 150% емкости вашего кластера.

Не менее важным будет проверка соответствия лимитов емкости каждого узла. Например, у нас есть контейнер с CPU Requests - 2 и CPU Limit - 8. Этот контейнер можно запланировать на узле с 4 ядрами, но лимиты не дадут нужного эффекта, потому что на узле недостаточно ядер.

Процент превышения доступных ресурсов узла по памяти:

sum by (node)(kube_pod_container_resource_limits{container!=,resource=memory} ) / sum by (node)(kube_node_status_capacity_memory_bytes)

Процент превышения доступных ресурсов узла по ЦП:

sum by (node)(kube_pod_container_resource_limits{container!=,resource=cpu} ) / sum by (node)(kube_node_status_capacity_cpu_cores)

Подведем итоги

В этой статье вы узнали, почему так важно правильно использовать Kubernetes Limits and Requests, как определять наличие неоптимальных параметров в вашем кластере и какие стратегии вы могли бы использовать, чтобы установить правильные ограничения ресурсов Kubernetes.

Если вы хотите узнать больше, рекомендуем прочитать статью рациональное использовании ресурсов в Kubernetes.

Подробнее..

Книги, которые повлияли на меня как на разработчика и управленца

18.06.2021 12:04:53 | Автор: admin

Общаться в профессиональной среде, ходить на конференции и митапы, просто посидеть вечерком в приятном баре с профессионалом высокого уровня и обсудить какие-то классные идеи: всё это может помочь в работе. Среди этих ресурсов одно из первых мест занимают книги.

Под катом я расскажу вам о литературе, которая оказала на меня влияние как на управленца и разработчика. И, как мне кажется, может быть полезна любому, кто хочет вырасти в этих областях.

За мою практику я прочитал немало книг, но некоторые оказали большее влияние на становление разработчиком, а затем управленцем. Я разбил книги по нескольким разделам.

Практика

Книги из практического блока можно просто читать, независимо от того, разработчик вы сейчас или руководитель. Они все классные. Я рекомендую их всем, и они довольно простые прочитали, и можно сразу использовать.

Specification by Example

Книга понравилась мне настолько, что побудила написать первую статью на Хабре. Гойко Аджич автор книги сам описывает ее как книгу о разработке ПО без единой строчки кода. Ее фокус находится на пересечении управления требованиями, проектного менеджмента, DevOps и тестирования (в том числе автоматизированного). Если DevOps часто описывают как infrastructure as code, то Specification by Example это своего рода requirements as code. Проработав некоторое время в корпоративном сегменте индустрии любой разработчик рано или поздно узнает о том, насколько неполными, неточными, противоречивыми и устаревшими бывают требования и насколько сложно, долго и дорого бывает переделывать программы, написанные по таким требованиям. Существуют тяжелые методы борьбы с этим недугом. Например ГОСТ 34 до сих пор используется в госсекторе, несмотря на то, что он безнадежно устарел.

Specification by Example гораздо более гибкая и менее формальная техника, позволяющая, впрочем, заказчику и исполнителю говорить на одном языке, понятном обоим. Кроме того, ГОСТы описывают форму проектной документации, но не дают конкретных советов по проектному управлению и никак не поощряют коммуникацию и совместную работу по улучшению требований и нахождению лучших (более быстрых, качественных и дешевых) способов решения проблем. Примеры переформулированных требований из книги гарантированно не оставят вас равнодушными. Техникой контрольных примеров мы пользуемся уже восемь лет, и она позволяет экономить какое-то невероятное количество времени и избегать недопониманий.

На основе техники, описанной в книге, даже разработан продукт SpecFlow. Нам он показался излишне громоздким. Но вам, возможно, подойдет. О связи требований и автоматизированного теста на примере SpecFlow можно почитать в этой статье.

Event Storming

Это даже не книга, а своего рода комикс. Если вы любите стикеры, доски и kanban, то event storming скорее всего тоже зайдет. Со временем мы пришли к тому, что большинство web-проектов сразу создаем на основе CQRS-архитектуры, даже если на старте хранилище данных всего одно. Это позволяет по мере развития проектов независимо оптимизировать стеки чтения и записи. И в момент, когда запросы к БД становятся уже совершенно безобразными, воткнуть очередь с денормализоваными хранилищами.

Подробно о всех преимуществах CQRS перед классической n-layer- и onion-архитектурой я рассказывал в докладе Быстрорастворимое проектирование.

Причем здесь Event Storming? Это техника специфицирования в терминах DDD, CQRS и Event Sourcing в форме увлекательной игры со стикерами, фломастерами и доской (доска может быть физической или виртуальной, но с физической гораздо веселее). С точки зрения наглядности, метод не успевает за Activity и BPMN-диаграммами. Но он гораздо более легковесный и прост в освоении и понимании.

Impact Mapping

И снова книга Гойко Аджича. Часть идей в ней пересекается со Specification by Example, но у книг разные целевые аудитории. Spec by Example лучше подойдет для разработчиков, архитекторов, тестировщиков, аналитиков и менеджеров среднего звена. Impact Mapping инструмент, в первую очередь, для бизнеса: владельцев продукта (или даже компании), маркетинга и топ-менеджмента. Spec by Example лишь поощряет общение с целью поиска оптимальных решений. Impact Mapping это формальный процесс для стратегического планирования. Его можно использовать не только в разработке ПО, но и для стратегического планирования, в целом. Например, в этом году мы использовали Impact Mapping для приоритизации и планирования задач в HR.

Теория + практика

Теоретически-практические книжки чуть более сложные. Я бы рекомендовал начать с DDD это очень холиварная тема! Возможно, DDD это не то, что вам нужно на этапе создания стартапа, но попробуйте обратить внимание не на технические аспекты, а на высокоуровневые паттерны. На то, как DDD предлагает общаться с экспертами, выделять главное, и на то, что продукт порой важнее используемых технологий. Если вам это зайдет, то дальше начнется протоптанная другими тропа: DDD -> CQRS -> Event Sourcing. Чаще всего все эти три темы обсуждаются в одном комьюнити. Как только вы разберетесь, что собой представляет каждая из концепций, вы поймете почему.

Немного особняком стоит книга Скотта Влашина про DDD в мире функционального программирования. Во-первых, ФП в изложении Влашина это не сложно. Обратите на книгу внимание хотя бы поэтому. Во-вторых, даже если в ближайшие десятилетия вы не собираетесь никуда сворачивать с тропинки объектно-ориентированного программирования, изучение других способов решения знакомых проблем может быть точкой роста. Я большой фанат гипотезы лингвистической относительности (и фильма Прибытие удачно выигрывающего эту гипотезу). В каком-то смысле знание языков программирования может влиять на ваше мировоззрение также, как знание естественных языков.

Теория

Факты и заблуждения профессионального программирования

Если эти книги вам знакомы или показались неинтересными, а вы хотите прочесть что-то более фундаментальное, рекомендую книгу Роберта Гласса Факты и заблуждения профессионального программирования. Она в свое время помогла мне перестать проваливать сроки реализации проектов, потому что я понял, что некоторые числа, которые были в моей голове, в три раза отличались от реальности. Книга хороша тем, что Роберт Гласс всю свою жизнь фактически проработал в аэрокосмической отрасли и собирал реальную статистику о том, сколько времени занимает анализ, разработка, тестирование, как неточны оценки, как часто меняются требования и как на самом деле сложно адаптироваться к таким изменениям.

Мифический человеко-месяц

Книга Фредерика Брукса, несмотря на то, что ей уже 100500 лет, и вы можете встретить в тексте что-то про перфокарты, это фундаментальный труд. Закон Брукса никуда не делся и, кажется, не денется. Понимание этого закона (девять матерей не родят дитя за один месяц) поможет принимать критические и зачастую контринтуитивные управленческие решения. Юбилейное издание включает в себя статью Серебряной пули нет, с которой тоже не грех ознакомиться всем и каждому.

Сколько стоит программный продукт

Большинство знает другую книгу МакКонела Совершенный код. Для кого-то она даже стала своеобразной Библией программирования. Если вы уже программируете хорошо и хотите научиться лучше оценивать трудозатраты на разработку, прочтите Software Estimation: Demystifying the Black Art (Сколько стоит программный продукт; в оригинале название звучит точнее, не находите?:). Книжка сложная, со статистикой, но ничего лучшего об оценке я не видел. Гарантирую, качество оценки тех, кто использует методы и советы из книги, многократно превосходит качество оценки тех, кто делает это по наитию.

Лютая теория и даже философия

Но если этого вам мало, и вы хотите улучшить свое умение думать о процессе, в целом, понять разницу между управлением, организацией и даже не прочь почитать что-то философское, то Г. П. Щедровицкий Оргуправленческое мышление это то, что вам нужно. Книга очень сложно читается, это конспект лекций для руководителей стройки атомных электростанций в СССР. На момент строительства никакой методологии Как строить атомные АС просто не существовало. Стройки велись по всему СССР, что делало каждый проект уникальным. В этих условиях успех строительства напрямую зависел от качества организации и от управления стройкой. В терминологии Щедровицкого эти два слова значат совсем не одно и тоже. В ходе лекций автор пытается найти баланс между первым и вторым. Труд просто фундаментальный и где-то философский, предназначенный для организаторов и руководителей с большой буквы.

Цель. Процесс непрерывного улучшения

Производственный роман и по совместительству введение в теорию ограничений Элияху Голдратта иллюстрирует изменчивость реального мира и наивность планов, игнорирующих случайные события. После прочтения книги вы научитесь видеть картину в целом и больше не дадите частностям запутать вас.

На этом мой список книг подходит к концу. Выбирайте полезные для себя и enjoy!

TechLead Conf 2021 конференция, полностью посвященная инженерным процессам и практикам откроет свои двери уже совсем скоро: 30 июня и 1 июля она пройдет в Radisson Slavyanskaya (Москва).Расписаниеуже готово.Билетыв продаже. А ещё у нас открытдоступк докладам TechLead Conf 2020.

До встречи в офлайне!

Подробнее..

Ресурсы для поиска удаленной работы для нетехнарей

29.12.2020 00:19:38 | Автор: admin

Возможно у вас тоже есть друзья-нетехнари, которые терзают вас вопросами "где искать постоянную удаленную работу?" и "как попасть в айти?". У меня на этот случай есть заготовленный списочек ресурсов с вакансиями, который уже сэкономил мне много часов на таких вопросах. Хочу поделиться им с вами и попробую его обновлять, если Хабр позволяет обновлять публикации.

Тем, у кого уровень английского "London is the capital of Great Britain", я советую идти на всем известные российские ресурсы и искать там по фильтру "удаленная работа". А тем, чей уровень английского позволяет, кто хочет получать з/п в долларах и готов заморочиться с оформлением ИП или самозанятости, можно спокойно предлагать поискать иностранную компанию. Для технарей этот список тоже будет актуален.

Это, конечно, не исчерпывающий список, и будет круто, если вы дополните его в комментариях. Удачи в поиске!

  • WeWorkRemotely
    Один из самых старых сайтов с удаленными вакансиями от создателей Basecamp
    Фильтры: Copywriting, Business & Management, Customer Support, Finance and Legal, Sales and Marketing

  • AngleList
    Американские и канадские стартапы, здесь я нашла свою текущую работу
    Фильтры: Operations, Marketing, Sales, Management, Other

  • F6s
    Европейские стартапы
    Фильтры: Operations, Marketing, Financial, Accounting

  • Workable
    Сайт агрегатор, публикации напрямую от компаний

  • NODESK
    Фильтр: "non-tech"

  • Revolution Remote
    Только удаленные вакансии поддержки Support, Service, Helpdesk, Tech Support

  • People-First Jobs
    Публикуют только вакансии от компаний, которые ценят своих сотрудников
    Фильтры: Business management, Copywriting, Customer success & support, Design, Finance & legal, Operations, Product, Project management, Sales & marketing, Others

  • REMOTIVE
    фильтр: All Other

  • RemoteOK
    Фильтр: Non-tech

  • EU Remote Jobs
    Фильтры: Customer Support, Human Resources, Legal, Marketing, Sales

  • Europe Remotely
    Фильтры: Marketing & Sales, Customer Support

  • Workingтоmads
    Фильтры: Administration, Human Resources, Education, Legal, Sales, Writing, Sales filters

  • Skip the Drive
    Фильтры: Administrative, Consulting, Editor, Entry Level, Human Resources

  • Twitter
    Не самый очевидный ресурс, но именно в Твиттер дублируют вакансии как сами компании, так и сайты агрегаторы.
    Искать по "должность" или "скилл" + remote job

Фото: Jen Theodore on Unsplash

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru