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

Серверное администрирование

Как я искал нормальный RDP-клиент и нашел целых три

27.01.2021 16:20:11 | Автор: admin


Remote Desktop Protocol один из самых распространенных протоколов для удаленного управления, потому что он используется для работы с операционными системами Windows, которые часто незаменимы в корпоративной среде. Естественно, самый распространенный способ подключения к удаленной системе использование средств встроенных в саму систему, но он не единственный и, более того, совершенно неприменимый, если используется другая ОС или сильно устаревшая Windows.

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


MobaXterm


Эта программа для Windows. Немного неправильно называть MobaXterm RDP-клиентом, потому что это целый комбайн. Список поддерживаемых протоколов впечатляет: SSH, Telnet, Rlogin, RDP, VNC, XDMCP, FTP, SFTP и Serial.

Почему я рекомендую этот клиент? Меня уже давно не радует Putty. Громоздкий и запутанный интерфейс из времен W95, не вызывающий ностальгию, если приходится часто с ним работать, плохая поддержка экранов высокого разрешения, собственный формат ключей, отсутствие поддержки вкладок и прочее. MobaXterm лишен всех этих недостатков, это удобная и современная программа. Портативная версия состоит из одного единственного exeшника и файла настроек, интерфейс интуитивный, а если нужна помощь, то, в отличии от Putty, в самой программе есть исчерпывающая документация.

Кроме соединения через перечисленные протоколы можно локально поднимать некоторые сервисы для удаленного доступа, такие как: FTP, SSH/SFTP, HTTP и другие. Если вы не любите консольные nano и vi, то в программе есть текстовый редактор с удобным графическим интерфейсом. В терминале есть настраиваемая подсветка синтаксиса и автодополнение.
Сразу после запуска программа нашла ранее используемые мной подключения, импортировала настройки из Putty и обнаружила установленную в системе WSL-Ubuntu:



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

Apache Guacamole




Современные тенденции DevOps предполагают перенос окружения для разработки с локальной машины на сервер компании или к облачному провайдеру. Один из простых примеров ранее описывался в статье: Установка Visual Studio Code в облаке, приложения для удаленного подключения этого тоже не избежали.

Apache Guacamole, это клиентский шлюз для удаленного подключения, работающий на HTML5, позволяет пользоваться протоколами: VNC, Telnet, RDP, Kubernetes и SSH / SFTP через web-интерфейс. Не требуется установки никаких программ, подписок на сторонние сервисы, все работает прямо в браузере, независимо от того, какой операционной системой пользуется разработчик. Все что требуется: установить и настроить службы на сервере. По сути, это web-интерфейс для FreeRDP бесплатной реализации протокола RDP, с открытым исходным кодом.

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

Настройка сервиса подробнейшим образом документирована, мануал впечатляет своими размерами. Установка возможна несколькими способами: из репозиториев, компиляция исходников и разворачивание образа Docker. К счастью, как это часто бывает, один прошаренный DevOps-инженер решил автоматизировать процесс установки с наиболее типичными настройками и выложил готовый скрипт на github: guac-install. Из его кода легко понять, что он пошел по пути установки образа Docker, и все действия сводятся к вводу всего нескольких команд.

Начнем с того, что настроим виртуальный сервер для установки AG. Его характеристики будут зависеть от количества пользователей, но разработчики рекомендуют не меньше 2 гигабайт оперативной памяти. Размещение сервера выберем в Москве, для минимального пинга, что критично для работы с удаленными компьютерами.



В качестве тестовой машины я выбрал такие параметры :



После того, как будет создана виртуальная машина, подключимся к ней (используя MobaXterm, конечно же). Теперь можно приступать к работе.

Сначала надо скачать скрипт установки:

wget https://git.io/fxZq5 -O guac-install.sh

Выдать ему разрешение на исполнение:

chmod +x guac-install.sh

И запустить:

./guac-install.sh

В процессе работы будут установлены нужные образы и задано несколько вопросов о настройке паролей для MySQL. В конце скрипт выдаст сообщение о том, что установка завершена, напишет адрес для подключения к сервису и сообщит пароль/логин, который настоятельно порекомендует потом поменять:

Installation Complete- Visit: http://localhost:8080/guacamole/- Default login (username/password): guacadmin/guacadmin***Be sure to change the password***.


Все готово, надо только заменить localhost на внешний айпи-адрес нашего сервера и ввести пару логин/пароль в форму логина на сайте:



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

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

В качестве примера подключимся к серверу под управлением Windows по протоколу RDP. Для этого надо зайти в Настройки и выбрать опцию Подключения. Интерфейс переведен на несколько языков, и сложностей при работе с ним ни у кого не возникнет.



Дальше надо заполнить следующие поля (я перечислю минимально необходимые):
В разделе РЕДАКТИРОВАНИЕ ПОДКЛЮЧЕНИЯ заполнить поле Название и в поле Протокол выбрать RDP
В разделе СОВМЕСТНОЕ ИСПОЛЬЗОВАНИЕ поставить требуемые числа в поля Максимальное число соединений и Максимальное число соединений на пользователя. Любое необходимое, но не меньше 1.
В разделе НАСТРОЙКИ и подразделе Сеть ввести айпи-адрес удаленного сервера под управлением Windows и Порт: 3389.
Далее заполнить поля Имя пользователя и Пароль. В моем случае еще потребовалось отметить опцию Игнорировать сертификат сервера.
Остальное настройки заполняются по необходимости, в зависимости от специфики серверов, к которым требуется подключаться.
В итоге выглядит это примерно так:



В самом низу страницы нажимаем кнопку СОХРАНИТЬ и можно подключаться с главной страницы панели управления:



Все работает, мы видим рабочий стол нашего виртуального сервера:



Myrtille


На основе FreeRDP разрабатывается еще один проект: , аналогичный Apache Guacamole, но работающий на системе Windows. Его установка традиционный Windows-way, надо всего лишь скачать файл инсталлятора с и запустить его. Приложение поддерживает двухфакторную авторизацию и позволяет настроить ее в процессе установки:


В следующем диалоговом окне можно настроить работу с Active Directory:



А затем порты для подключения:



Далее следует диалог с выбором опций для установки сертификата, драйвера для PDF-принтера и разрешения множественных подключений:



Потом выбирается директория, куда будет устанавливаться программа и запускается процесс установки. На этом все, сервисом можно пользоваться, перейдя по ссылке: , где вместо ip-address надо подставить адрес сервера и web-клиент готов к подключению:



Надо заметить, что он не позволяет управлять группами пользователей и подключениями как AG и довольно аскетичен в настройках. Меню сервиса хоть и не блещет красотой, но вполне функционально:



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

Подробнее..

Перевод Концепции nginx, о которых мне хотелось бы знать много лет назад

29.01.2021 16:08:57 | Автор: admin
Nginx это веб-сервер, в котором используется архитектура Master-Slave. В nginx имеются обратный прокси-сервер, балансировщик нагрузки, почтовый прокси-сервер и HTTP-кеш.

Определение это сложное, полное специальных терминов. Если вы тоже так думаете значит, эта статья написана специально для вас. Сначала мы разберёмся с основными концепциями и понятиями nginx, а потом поговорим о том, как его устанавливать и настраивать.



Для того чтобы вам было легче просто помните о том, что nginx это отличный веб-сервер.

Веб-сервер, если описать его простыми словами, это нечто вроде посредника. Предположим, вам нужно посетить сайт dev.to. Вы вводите а адресной строке браузера следующее: dev.to. Браузер (клиент) находит адрес веб-сервера, а затем делается запрос к бэкенд-серверу, который возвращает клиенту ответ.

Прокси-сервер и обратный прокси-сервер


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

Прокси-сервер


Итак, у нас имеется как минимум один клиент, веб-сервер, являющийся системой-посредником (в данном случае мы будем называть его прокси-сервером), и обычный сервер. Во взаимодействии всех этих систем самое главное то, что обычный сервер не знает о том, какой именно клиент осуществляет к нему запрос. Звучит не очень понятно? Давайте взглянем на следующую схему.


Прокси-сервер

В данном случае Клиент 1 и Клиент 2 отправляют Запрос 1 и Запрос 2 к серверу через прокси-сервер. Этот сервер не знает о том, от какого именно клиента исходит тот или иной запрос, но, всё равно, выполняет то, что от него требуется.

Обратный прокси-сервер


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


Обратный прокси-сервер

В данном случае клиент отправляет запрос через веб-сервер. А веб-сервер обращается к одному из множества серверов, выбирая конкретный сервер с использованием особого алгоритма. Например, с помощью очень приятного циклического (round-robin) алгоритма. Ответ на запрос отправляют клиенту через веб-сервер. В результате в данном случае клиент не знает о том, с каким именно бэкенд-сервером взаимодействует.

Балансировка нагрузки


Балансировка нагрузки это ещё одно понятие, которое надо освоить для понимания nginx. Но с тем, что это такое, разобраться будет уже не особенно сложно, так как балансировщик нагрузки это всего лишь один из экземпляров приложения, реализующего возможности обратного прокси-сервера.

Разберёмся с отличиями балансировщика нагрузки от обратного прокси-сервера. Для работы балансировщика нагрузки нужно как минимум 2 бэкенд-сервера. А вот для работы обычного обратного прокси-сервера это необязательно. Он может работать и с одним бэкенд-сервером.

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

Приложения, хранящие и не хранящие состояние


Мы пока ещё обсуждаем общие понятия, но обещаю, что очень скоро мы перейдём к работе с nginx. А сначала, всё же, давайте разберёмся с основами.

Приложения, хранящие состояние


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


Приложение, хранящее состояние

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

Приложения, не хранящие состояние


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


Приложение, не хранящее состояние

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

Что такое nginx?


Nginx это веб-сервер. Это понятие использовалось в данном материале до сих пор. Это, в сущности, посредник.


Nginx

Если вам кажется, что эта схема переусложнена, то знайте, что это не так. На ней просто собрано всё то, о чём мы до сих пор разговаривали. Тут имеются 3 бэкенд-сервера, работающих на портах 3001, 3002 и 3003. Все эти серверы используют одну и ту же базу данных, работающую на порте 5432.

Когда клиент отправляет запрос GET /employees к https://localhost (по умолчанию тут используется порт 433) этот запрос будет, на основе определённого алгоритма, отправлен одному из бэкенд-серверов. Сервер получит информацию из базы данных и отправит JSON-ответ nginx-серверу, после чего ответ попадёт клиенту.

Если для распределения задач по обработке запросов использовался бы некий алгоритм (вроде циклического), то, например, если Клиент 2 отправил бы запрос к https://localhost, то nginx-сервер переадресовал бы этот запрос на порт 3001, а потом отправил бы ответ клиенту. А другой запрос он мог бы передать на сервер, работающий на порте 3002 и так далее.

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

Установка nginx


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

Процесс установка nginx до крайности прост. В любой системе этот веб-сервер можно установить с помощью простой однострочной команды. Я пользуюсь macOS. Поэтому тут будут приведены команды, рассчитанные на эту систему. Но примерно такие же команды сработают и в Ubuntu, и в других дистрибутивах Linux, и в Windows.

Итак, вот команда для установки nginx:

$ brew install Nginx

Это всё, что нужно для установки nginx. Как по мне так это просто замечательно.

Запуск nginx


Запустить nginx не сложнее, чем установить:

$ nginx# или$ sudo nginx

После выполнения этой команды откройте свой любимый браузер и перейдите по адресу http://localhost:8080/. Если всё работает как надо вы увидите сообщение, напоминающее то, которое показано на следующем рисунке.


Nginx готов к работе

Основы настройки nginx


Разберём пошаговый пример настройки nginx. Для начала создадим на локальном компьютере следующую структуру директорий:

. nginx-demo  content   first.txt   index.html   index.md  main   index.html temp-nginx outsider index.html

Нужно, кроме того, поместить какие-нибудь данные в HTML- и MD-файлы.

Чего мы пытаемся добиться?


Тут имеются две папки nginx-demo и temp-nginx. В каждой из них содержатся статические HTML-файлы. Мы собираемся организовать доступ к этим двум папкам, используя один порт и настроить правила работы nginx.

Теперь вернёмся к nginx. Для того чтобы внести изменения в стандартные настройки nginx нужно отредактировать файл nginx.conf, который находится в папке usr/local/etc/nginx. Я для решения подобных задач использую vim, но вы вполне можете пользоваться любым другим редактором.

$ cd /usr/local/etc/nginx$ vim nginx.conf

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

$ cp nginx.conf copy-nginx.conf$ rm nginx.conf && vim nginx.conf

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

Шаг 1


Для начала выполним базовые настройки.

http {server {listen 5000;root /path/to/nginx-demo/main/;}}events {}

Обратите внимание на то, что тут необходима конструкция events {}, так как она обычно используется для описания количества рабочих процессов nginx. Здесь используется ключевое слово http, которое сообщает nginx о том, что мы собираемся работать на 7 уровне модели OSI.

Мы предлагаем nginx прослушивать порт 5000 и указываем путь к корневой директории main, в которой находится HTML-файл.

Шаг 2


Теперь настроим дополнительные правила для URL /content и /outsider. При этом URL /outsider будет соответствовать директории, находящейся за пределами пути к корневой директории, упомянутой на первом шаге настройки nginx.

http {server {listen 5000;root /path/to/nginx-demo/main/;location /content {root /path/to/nginx-demo/;}location /outsider {root /path/temp-nginx/;}}}events {}

Здесь конструкция location /content указывает на то, что к объявленному в ней root-пути будет добавлен дополнительный URL content. В результате то, что корневая директория для /content задана в виде root /path/to/nginx-demo/, означает, что мы сообщаем nginx о том, что при обращении по адресу http://localhost:5000/path/to/nginx-demo/content/ нужно выдать данные, хранящиеся в соответствующей папке.

Но возможности nginx не ограничены лишь настройкой корневых директорий, соответствующих неким URL. Nginx позволяет, кроме того, запрещать клиентам просмотр некоторых файлов.

Шаг 3


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

location ~ .md {return 403;}

Шаг 4


Изучим популярное правило proxy_pass, используемое при настройке nginx. Мы уже разобрались с тем, что такое прокси-сервер, что такое обратный прокси-сервер, и с тем, какое отношение к ним имеют бэкенд-серверы. Опишем в настройках ещё один бэкенд-сервер, работающий на порте 8888. В результате у нас будет два бэкенд-сервера. Одному соответствует порт 5000, а второму порт 8888.

server {listen 8888;location / {proxy_pass http://localhost:5000/;}location /new {proxy_pass http://localhost:5000/outsider/;}}

В результате получается, что если клиент обращается к порту 8888 через nginx, то мы перенаправляем запрос к порту 5000 и отправляем клиенту ответ.

Полный файл настроек nginx


А вот как выглядит полный файл с нашими настройками nginx:

http {server {listen 5000;root /path/to/nginx-demo/main/;location /content {root /path/to/nginx-demo/;}location /outsider {root /path/temp-nginx/;}location ~ .md {return 403;}}server {listen 8888;location / {proxy_pass http://localhost:5000/;}location /new {proxy_pass http://localhost:5000/outsider/;}}}events {}

Эти настройки будут использованы при запуске nginx командой sudo nginx.

Некоторые команды, используемые при работе с nginx


Первый запуск nginx:

$ nginx#или$ sudo nginx

Перезагрузка работающего nginx-сервера:

$ nginx -s reload#или$ sudo nginx -s reload

Остановка работающего nginx-сервера:

$ nginx -s stop#или$ sudo nginx -s stop

Выяснение того, какие процессы nginx работают в системе:

$ ps -ef | grep Nginx

Эта команда важна в тех случаях, когда при попытке выполнения других команд появляются сообщения об ошибках. А именно, речь идёт о том, что с помощью этой команды можно выяснить PID работающих процессов nginx, остановить их и снова запустить nginx.

Для остановки процесса, при условии знания его PID, можно воспользоваться такой командой:

$ kill -9 <PID>#или$ sudo kill -9 <PID>

Итоги


Теперь вы, в общих чертах, знакомы с сервером nginx и с его настройками. А значит можете продолжить изучение этой системы, например, обратившись к официальной документации.

Пользуетесь ли вы nginx?

Подробнее..

GlobalSign выпустила первый в мире кроссплатформенный агент для управления сертификатами под Windows, macOS и Linux

28.01.2021 02:19:40 | Автор: admin


19 января 2021 года компания GlobalSign объявила о выходе AEG 6.4 новой версии шлюза автоматической регистрации Auto Enrollment Gateway, вместе с которым представлена маленькая, но уникальная программка: кроссплатформенный агент для автоматической выдачи и управления сертификатами под Windows, Mac OS и Linux. Компания заявляет, что это первое такое предложение от любого удостоверяющего центра в мире.

Агент регистрации


Кроссплатформенный агент регистрации небольшая программа, которая устанавливается на устройстве и использует протокол ACME или SCEP для связи с AEG. Во многих случаях агент также обеспечивает соблюдение определённых отраслевых правил или национальных нормативных актов. Кроме того, агент устраняет барьеры для S/MIME, поскольку работает на любой платформе и операционной системе, что также повышает масштабируемость. Например, если из компании увольняется сотрудник, то его ключи автоматически архивируются.

Агент регистрации легко устанавливается на любом клиенте или сервере Windows, macOS и Linux. Утилита помогает устанавливать политики управления сертификатами и управлять с помощью интуитивно понятной панели мониторинга AEG.



Кроме того, агент автоматически выдаёт и контролирует сертификаты. Это великолепно масштабируемый метод развёртывания сертификатов на устройствах, машинах, клиентах S/MIME и серверах организации.

Установка агентов на своих конечных точках даёт организации больший охват и контроль над всей своей сетью, говорит Лила Ки, генеральный директор отдела операций в Северной и Южной Америке GlobalSign. Это также означает, что пользователям и администраторам больше не нужно полагаться на сложные методы регистрации сертификатов, что в конечном итоге улучшает управление сертификатами. Мы действительно ставим последнюю точку в автоматизации этого процесса. AEG 6.4 идеально подходит для организаций, которые хотят начать или оптимизировать удалённую работу, обеспечить безопасность сетей BYOD и автоматизировать функции PKI, которые потребляют время и ресурсы в ручном управлении.

Что такое Auto Enrollment Gateway


Auto Enrollment Gateway это полностью автоматизированное PKI-решение, которое интегрирует PKI непосредственно с Active Directory, поэтому в среде Windows можно автоматизировать выпуск сертификатов и управление ими без необходимости поддерживать собственный удостоверяющий центр. Поддержка протоколов SCEP и ACME v2 расширяет использование сертификатов за пределы домена Windows, позволяя автоматизировать сертификацию для серверов Linux, а также мобильных, сетевых и других устройств.



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

Если требуются публичные доверенные сертификаты (например, для отправки за пределы компании зашифрованных или скреплённых электронной подписью электронных писем), можно получить такой сертификат не через приватный корневой удостоверяющий центр, а через публичный доверенный корневой удостоверяющий центр GlobalSign.

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

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

  • Вход в систему с помощью смарт-карт
  • Электронные подписи в документах Microsoft Office,
  • Подпись кода
  • Защита электронных сообщений
  • SSL/TLS
  • Система шифрования данных Encrypted File System (EFS) на уровне файлов в операционных системах
  • Аутентификация пользователей
  • Аутентификация устройств
  • Мобильная аутентификация
  • и т.д.

Шлюз AEG идеально подходит для любой компании с более чем 500 сотрудниками и/или устройствами, а также для тех, кто использует Microsoft Active Directory. Управление PKI и автоматизация особенно востребованы в нынешних условиях, которые требуют от сотрудников удалённой работы.

AEG 6.4 также реализует опции безопасности, в которых сейчас нуждаются компании: S/MIME для безопасной электронной почты, удалённая сетевая аутентификация и инструменты для управления всем этим. Это снижает нагрузку на IT-отдел, экономит время и деньги ресурсов, а также значительно повышает уровень безопасности компании.
Подробнее..

Перевод Примеры грамотного применения SSH-шаблонов

17.02.2021 20:19:33 | Автор: admin


SSH-сертификаты очень мощный инструмент. Первоначально в удостоверяющем центре step-ca мы реализовали только минимальный набор функций для аутентификации по сертификатам пользователя и хоста. Затем добавили шаблоны сертификатов X.509, а ещё в августе прошлого года и SSH-шаблоны, в версии 0.15.2. Наконец, мы задокументировали эту функцию и готовы о ней рассказать.

Шаблоны для сертификатов SSH действуют аналогично шаблонам X.509: это JSON-файлы, написанные в Go text/template. Они применяются для настройки SSH-сертификатов, которые выдаёт step-ca. Давайте посмотрим, что представляют собой эти шаблоны и как их можно использовать.

По умолчанию шаблон пользовательского SSH-сертификата выглядит так:

{"type": {{ toJson .Type }},"keyId": {{ toJson .KeyID }},"principals": {{ toJson .Principals }},"extensions": {{ toJson .Extensions }},"criticalOptions": {{ toJson .CriticalOptions }}}

А вот SSH-сертификат, выданный по этому шаблону:

$ step ssh inspect id_ct-cert.pubid_ct-cert.pub:        Type: ecdsa-sha2-nistp256-cert-v01@openssh.com user certificate        Public key: ECDSA-CERT SHA256:iczSh1XiBBE36yfJcDidgp6fqY3qWx1RtEwFfAN9jDs        Signing CA: ECDSA SHA256:MKwRQ/SDKk/pCJbbCk5bfhZACjSjv7uZXLyc5n4Wx6k        Key ID: "carl@smallstep.com"        Serial: 2831574724231262409        Valid: from 2020-11-17T16:48:11 to 2020-11-18T08:49:11        Principals:                carl                carl@smallstep.com        Critical Options: (none)        Extensions:                permit-X11-forwarding                permit-agent-forwarding                permit-port-forwarding                permit-pty                permit-user-rc

Он позволяет юзеру carl (или carl@smallstep.com) пройти аутентификацию на любом SSH-хосте, который доверяет моему SSH CA. Сертификат включает в себя некоторые основные расширения:

  • permit-x11-forwarding: Разрешает переадресацию X11 (с помощью ssh -X) для запуска удалённых программ X11 на локальном дисплее.
  • permit-agent-forwarding: Разрешает переадресацию агента (с помощью ssh -A) для пересылки ключей из локального агента SSH на удалённый хост (подробнее про агента SSH см. здесь).
  • permit-port-forwarding: Разрешает переадресацию портов (туннель) с локального на удалённый порт (ssh -L) или с удалённого на локальный (ssh -R).
  • permit-pty: Очень важное расширение. Если хотите открыть интерактивную сессию в консоли, хост должен выделить вам pty (псевдо-tty). В противном случае не предусмотрено никакой интерактивности. Например, для проверки SSH-аутентификации на GitHub можно запустить ssh -T git@github.com (-T отключает запрос на pty).
  • permit-user-rc: Запуск личного RC-файла после подключения (находится в ~/.ssh/rc на удалённом хосте).

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

Примеры шаблонов сертификатов


Внесём несколько изменений в дефолтный шаблон.

Запрещаем переадресацию агента и портов

Если пользователи подключаются к внутренним хостам через хост-бастион, то хорошо бы запретить перенаправление портов по соображениям безопасности. Вы же не хотите, чтобы юзеры перенаправили трафик с продакшн-сервера MySQL на свой localhost. Так же и переадресация агента сопряжена с риском для безопасности. Вот шаблон, который просто удаляет эти два расширения из сертификатов SSH:

{"type": {{ toJson .Type }},"keyId": {{ toJson .KeyID }},"principals": {{ toJson .Principals }},"extensions": {           "permit-x11-forwarding": "",           "permit-pty": "",           "permit-user-rc": ""  },"criticalOptions": {{ toJson .CriticalOptions }}}

Встраиваем директиву force-command

ForceCommand это серверная директива конфигурации SSHD, которая вместо интерактивного терминала запускает на хосте альтернативную команду. Но с тем же эффектом можно встроить force-command прямо в сертификат в раздел Critical Options:. Может пригодиться для служебных аккаунтов, которым необходимо выполнить только одну команду, например, запустить задание в удалённой системе.

Ограничиваем соединения по адресам

Чтобы ограничить область использования сертификата, в него можно встроить список разрешённых IP-адресов (блоков CIDR).

Вот шаблон сертификата, который использует и source-address, и force-command.

{"type": {{ toJson .Type }},"keyId": {{ toJson .KeyID }},"principals": {{ toJson .Principals }},"extensions": {{ toJson .Extensions }},"criticalOptions": {"force-command": "echo \"Hello World\"","source-address": "10.20.30.0/24,1.1.1.1/32"}}

Это нормальный пример, но здесь список IP жёстко зафиксирован и не изменяется. А нам обычно хочется использовать разные списки адресов для разных пользователей. Давайте попробуем

Вставляем разные значения для разных юзеров

Очевидно, пользователям нельзя давать право редактировать диапазон адресов. Следовательно, динамические значения должны поступать из надёжного источника.

Для этого в step-ca можно через поставщика OpenID Connect (OIDC) настроить провайдера OAuth на добавление к токену нестандартных требований (custom claim), содержащих блоки адресов CIRD, которые мы хотим добавить в сертификат этого пользователя.

Поставщик OIDC представляет собой идеальный способ выдачи SSH-сертификатов в step-ca. В статье DIY Single Sign-On for SSH я рассказывал, как настроить SSH CA, чтобы он выдавал краткосрочные SSH-сертификаты по ID-токенам от доверенного провайдера OAuth. Если step-ca настроен как доверенный клиент OAuth, он будет считывать поле email из токена ID и извлекать оттуда список участников SSH-сертификата (например, по полю carl@smallstep.com сгенерируются сертификаты для carl и carl@smallstep.com).

Но OIDC позволяет через шаблоны считать из токенов ID и другие поля. Вот где начинается настоящая магия. Таким образом, добавляем в каталог пользователей на стороне провайдера идентификации отдельное поле source_address и отражаем его в нашем ID-токене. Затем через шаблон SSH можно ввести значение из токена в сертификат. Вот шаблон:

{"type": {{ toJson .Type }},"keyId": {{ toJson .KeyID }},"principals": {{ toJson .Principals }},"extensions": {{ toJson .Extensions }},{{ if .Token.source_address }}"criticalOptions": {"source-address": "{{ .Token.source_address }}"}{{ else }}"criticalOptions": {{ toJson .CriticalOptions }}{{ end }}}

Аутентификация на GitHub по сертификату

Рассмотрим ещё один пример custom claim. С помощью GitHub Enterprise Cloud или GitHub Enterprise Server можно настроить GitHub на использование SSH-сертификатов. В частности, GitHub будет доверять вашему центру сертификации SSH. Но чтобы всё заработало, нужно создать для каждого пользователя отдельный SSH-сертификат с расширением login@github.com, в котором прописывается имя пользователя на GitHub. С помощью этого расширения сертификат аутентифицирует пользователя на GitHub Enterprise. И это здорово: один и тот же сертификат позволяет и подключиться к вашему серверу по SSH, и запушить код на GitHub.

Вот шаблон сертификата с поддержкой индивидуального расширения GitHub:

{"type": {{ toJson .Type }},"keyId": {{ toJson .KeyID }},"principals": {{ toJson .Principals }},"criticalOptions": {{ toJson .CriticalOptions }},{{ if .Token.ghu }}"extensions": {  "login@github.com": {{ toJson .Token.ghu }}}{{ else }}"extensions": {{ toJson .Extensions }}{{ end }}}

Для использования шаблона нужно добавить к токенам идентификации OIDC индивидуальное требование ghu (GitHub Username). Давайте подробно рассмотрим, как создать этот custom claim с помощью вашего провайдера OAuth.

Регистрация заявления у провайдера идентификации

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

  1. Добавьте приложение OAuth в Okta и установите доверие к нему у поставщика OIDC в step-ca, как описано в статье DIY SSO for SSH.


  2. Добавьте новое поле в каталог пользователей Okta (например, GitHub Username)
  3. Добавьте к OIDC-токену индивидуальное требование, например, с сокращённым названием ghu
  4. Теперь заполняем поле для тестового юзера и проверяем требование. В Okta есть инструмент тестирования токена ID. Или можно использовать step для проверки всего потока OAuth:

    OIDC_ENDPOINT="http://personeltest.ru/aways/[your organization].okta.com/oauth2/default/.well-known/openid-configuration"CLIENT_ID="[your OAuth client ID]"CLIENT_SECRET="[your OAuth client secret]"step oauth --oidc --provider $OIDC_ENDPOINT \    --client-id $CLIENT_ID --client-secret $CLIENT_SECRET \    --listen=":10000" --bare |step crypto jwt inspect --insecure
    

  5. Наконец, настройте step-ca для использования этого шаблона. Конфигурация поставщика должна ссылаться на файл шаблона:

    {  "provisioners": [    {      "type": "OIDC",      "name": "Okta",      "clientID": "[your OAuth client ID]",      "clientSecret": "[your OAuth client secret]",      "configurationEndpoint": "https://[your organization].okta.com/oauth2/default/.well-known/openid-configuration",      "listenAddress": ":10000",      "options": {        "ssh": {            "templateFile": "templates/certs/ssh/github.tpl"        }      }    },      ...  ]}
    

Что дальше


Мы добавили в документацию раздел о шаблонах SSH, где более подробно рассматриваются все параметры и переменные.

Если есть вопросы не стесняйтесь задавать.
Подробнее..

Аудит событий Active Directory и других решений Microsoft в Quest Change Auditor анонс вебинара

22.02.2021 12:20:43 | Автор: admin
Change Auditor инструмент для автоматизации аудита изменений в AD, Azure AD, SQL Server, Exchange, Exchange Online, Sharepoint, Sharepoint Online, Windows File Server, OneDrive for Business, Skype for Business, VMware, NetApp, EMC, FluidFS. Есть предустановленные отчёты на различные виды угроз, а также на соответствие стандартам GDPR, SOX, PCI, HIPAA, FISMA, GLBA.

Change Auditor значительно снижает трудозатраты на аудит в сравнении с использованием встроенных средств аудита или PowerShell-скриптов. В ситуации, когда авторы систем аудита, основанных на скриптах, увольняются (а мы сталкивались с такой ситуацией у одного из заказчиков), наличие промышленной системы аудита играет новыми красками.

image

Приглашаем вас зарегистрироваться на вебинар, который состоится 24 февраля в 12 часов дня по московскому времени. Вы узнаете о возможностях решения, кейсах использования, лицензировании и сможете задать интересующие вопросы. Под катом ссылки на наши предыдущие статьи с описанием Change Auditor и других решений от Quest по информационной безопасности.


А кто это сделал? Автоматизируем аудит информационной безопасности

Что полезного можно вытащить из логов рабочей станции на базе ОС Windows

Управление доступом и формирование отчётов безопасности для окружения Microsoft в Quest Enterprise Reporter

Сравним инструменты для аудита изменений в Active Directory: Quest Change Auditor и Netwrix Auditor

Sysmon теперь может записывать содержимое буфера обмена

Включаем сбор событий о запуске подозрительных процессов в Windows и выявляем угрозы при помощи Quest InTrust

Как InTrust может помочь снизить частоту неудачных попыток авторизаций через RDP

Как снизить стоимость владения SIEM-системой и зачем нужен Central Log Management (CLM)

Выявляем атаку вируса-шифровальщика, получаем доступ к контроллеру домена и пробуем противостоять этим атакам

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

А ещё у нас есть:

Группа в Facebook

Канал в Youtube.
Подробнее..

Как получить субтитрированный поток в RTMP из SDI

15.02.2021 12:06:03 | Автор: admin

Возникла задача получить из SDI сигнала трансляцию с субтитрами и отдать её на CDN в формате RTMP потока. Пару недель мучения и мытарств изложу в кратком содержании всех серий для коллекции. Возможно, кому пригодится.

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

Для захвата потока с SDI и транскодирования использовался сервер со следующей конфигурацией:

  1. Плата захвата, тестировалось две платы, Blackmagic DeckLink Duo 2 и DeckLink Quad 2, обе оправдали наши ожидания.

  2. Видеокарта с аппаратной поддержкой х264 кодека Nvidia Quadro P4000

  3. Сервер на базе процессора Intel(R) Xeon(R) Silver 4114

  4. Память 64Гб

Для отправки потока в сторону CDN использовался:

Wowza Streaming Engine сервер версии не ниже 8.5.

Сам захват с карты и передачу потока на Wowza было решено осуществлять средствами опенсорц проекта FFmpeg. Данный продукт хорошо себя зарекомендовал ранее и одно неоспоримое преимущество среди прочих он бесплатен.
Но для того чтобы все заработало нам необходимо собрать FFmpeg с необходимым перечнем модулей, а именно:

  • Поддержка DeckLink.

    Для этого необходимо скачать с сайта производителя Blackmagic_DeckLink_SDK желательно версии не ниже 10.7, на текущий момент присутствует версия 12. https://blackmagicdesign.com Blackmagic_DeckLink_SDK_12.0.zip
    Скачиваем распаковываем в дальнейшем нам потребуется указать путь к библиотекам при сборке нашего FFmpeg.

  • Поддержка аппаратного декодирования

    Необходимо зайти на сайт Nvidia и в разделе для разработчиков скачать CUDA под свою операционную систему.

    wget https://developer.download.nvidia.com/compute/cuda/11.2.0/local_installers/cuda_11.2.0_460.27.04_linux.runsudo sh cuda_11.2.0_460.27.04_linux.run
    
  • Декодирование Subtitles из SDI потока ZVBI

    В большинстве репозиториев уже присутствует данная библиотека в случае отсутствия её можно взять на https://sourceforge.net/projects/zapping/files/zvbi/0.2.35/

  • По необходимости другие библиотеки в частности, поддержка кодирования аудио в acc формат libfdk-aac и др.

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

Собрали до кучи все необходимые библиотеки и можем приступить к сборке самого FFmpeg со всеми необходимыми нам модулями.

В моем случае это примерно выглядело следующим образом:

--enable-cuda --enable-cuvid --enable-nvenc --enable-nonfree --enable-libnpp --extra-cflags=-I//cuda/include --extra-ldflags=-L//cuda/lib64 --enable-libfdk-aac --extra-cflags=-I//BlackmagicSDK/Linux/include --extra-ldflags=-L//BlackmagicSDK/Linux/include --enable-decklink --enable-libzvbi

Более подробно о том что и зачем, можно посмотреть на странице проекта FFmpeg, но это необходимый и достаточный минимум для сборки FFmpeg с требуемым функционалом под нашу задачу.

После сборки тщательно обработать напильником, чем мы и займемся

Для захвата потока запустим FFmpeg со следующими ключами:

ffmpeg


-hwaccel cuvid использовать аппаратное кодирование (задействовать видеокарту)
-f decklink подключить драйвера для работы с картой захвата
-thread_queue_size 16384 задаем длину очереди потока по умолчанию 8 у Вас может отличаться
-teletext_lines all указываем где искать телетекст
-i DeckLink Quad (1) используем первый вход с платы захвата
-c:v h264_nvenc устанавливаем аппаратный кодек
-aspect 16:9 -s 1024x576 -filter:v yadif -profile:v main -level 3.1 -preset llhq -gpu any -rc cbrldhq
-g 50 -r 25 -minrate 2000k -b:v 2000k -maxrate 2000k -bufsize 4000k -pixfmt yuv420p
-c:a libfdk-aac -ar 44100 -ac 2 -ab 128k -af volume=10dB -loglevel warning

-metadata:s:s:0 language=rus если при захвате потока не идентифицируется язык то необходимо, обязательно, его прописать, в моем случае это был единственны субтитрированный поток и он не идентифицировался - имел язык und
-f mpegts udp://ХХХ.ХХХ.ХХ.12:6970?pkt_size=1316 таргетируем захваченный поток по направлению к серверу в формате mpegts (данный формат позволяет передавать несколько субпотоков и он поддерживается FFmpeg), так же возможно использование мультикаст адресов в случае необходимости одновременной обработки с одного потока.

В результате мы получим поток с тремя субпотоками (Video, Audio, Subtitles) что мы и добивались!

Теперь для захвата и отправки данного потока на стороне WOWZA сервера необходимо в нужном приложении создать Stream File со следующим содержимым:
по средствам веб или руками в [wowza]/content/

{uri: udp://XXX.XXX.XXX.12:6970?pkt_size=1316,  адрес потока mpegtsDVBTeletextType: 1,2,3,4,5,  типы субтитров, я указал все, но можно указать только 2 и 5 если не ошибаюсь.mpegtsDVBTeletextPageNumber: 88,  страница субтитров 888 (здесь нет опечатки)reconnectWaitTime: 3000,  время через которое необходимо осуществить переподключение в мсstreamTimeout: 5000  время ожидания при обрыве потока в мс}

Далее подключаемся к данному потоку и если все сделали правильно, то увидим его в Incoming Streams вашего приложения.

После чего можем перейти в Stream Targets вашего приложения и отправить поток по назначению, в формате RTMP в котором будет три субпотока (Video, Audio и Data).

На этом все пинайте, не сильно, за объективную критику, Спасибо!

Подробнее..

Тиражирование Fedora из-под Fedora

04.02.2021 18:19:53 | Автор: admin

Многие руководства по установке слишком переусложнены из-за использования специфических утилит типа anaconda, livecd-tools, Fedora Media Writer и других, или создания файла сценария kickstart. В системе Fedora уже имеются необходимые средства для настраиваемой установки. Эта статья покажет пример для установки на USB флешку и на жёсткий диск

Внимание! Всё, что вы делаете, вы делаете на свой страх и риск, т.к. операции из этого руководства могут привести к частичной или полной потере данных.

Примечание: Предположительно используется базовая система, установленная на /dev/sda, а целевой диск или флешка подключены к /dev/sdb. В вашем случае это может быть другой диск, к примеру SSD M.2 нкаопитель, распознанный системой как /dev/nvme0n1

Разметка диска

GPT для жёсткого диска большого размера

sgdisk --zap-all /dev/sdbsgdisk -o /dev/sdbsgdisk -a 4096 -n 1:0:+1M --typecode=1:ef02 /dev/sdb # BIOS Bootsgdisk -a 4096 -n 2:0:+1G --typecode=2:8300 /dev/sdb # /bootsgdisk -a 4096 -n 3:0:+8G --typecode=3:8200 /dev/sdb # swapsgdisk -a 4096 --largest-new=4 --typecode=4:8300 /dev/sdb # XFSsgdisk -A 1:set:2 /dev/sdb

MBR для USB флешки

sfdisk /dev/sdb << EOFlabel: dosdevice: /dev/sdbunit: sectorssector-size: 512/dev/sdb1 : start=        2048, type=83, bootableEOF

Форматирование разделов

XFS для жёсткого диска

Почему XFS? Потому, что динамической выделение inode, удобно для большого количества мелких файлов, например если у вас много git проектов

mkfs.ext4 -F /dev/sdb2mkswap --force /dev/sdb3mkfs.xfs -f /dev/sdb4

EXT4 для USB флешки

mkfs.ext4 -b 1024 /dev/sdb1

Монтируем файловые системы

Для жёсткого диска

mount /dev/sdb4 /mntmkdir /mnt/{boot,dev,sys,proc}mount /dev/sdb2 /mnt/boot

Для USB флешки

mount /dev/sdb1 /mntmkdir /mnt/{boot,dev,sys,proc}

Установка базовой системы

Мой джентльменский набор содержит немного вспомогательных утилит для системного администрирования

dnf -y --installroot=/mnt --releasever=33 group install standard core \hardware-support development-libs development-toolsdnf -y --installroot=/mnt install iptables gpart gdisk rsync nano tcpdump \tcsh grub2-pc net-tools bind-utils sysstat xfsprogs

Устанавливаем загрузчик

mount --bind /dev /mnt/devmount --bind /sys /mnt/sysmount --bind /proc /mnt/proccp /etc/resolv.conf /mnt/etcchroot /mnt /bin/tcshdnf -y install kernelgrub2-install /dev/sdbgrub2-mkconfig -o /boot/grub2/grub.cfgexit

Внимание! С копированием resolv.conf будьте внимательны после, т.к. на текущий момент есть особенности использования с демоном systemd-resolved

Создание файла fstab

uuid очень удобен и хорош для поиска разделов в "мутной водице" среди правильно или неправильного распознания дисков в системе.

Для жёсткого диска

blkid --output export /dev/sdb2 | grep ^UUID= | xargs -I '{}' echo {} /boot ext4 rw,relatime 1 2 > /mnt/etc/fstabblkid --output export /dev/sdb4 | grep ^UUID= | xargs -I '{}' echo {} / xfs rw,relatime 0 0 > /mnt/etc/fstabblkid --output export /dev/sdb3 | grep ^UUID= | xargs -I '{}' echo {} swap swap defaults 0 0 > /mnt/etc/fstab

Для USB флешки

blkid --output export /dev/sdb1 | grep ^UUID= | xargs -I '{}' echo {} / ext4 rw,relatime 0 0 > /mnt/etc/fstab

Дорисовываем сову

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

echo 'root:123' | chpasswd --root /mnt

Размонтируем файловые системы

Для жёсткого диска

umount /mnt/devumount /mnt/sysumount /mnt/procumount /mnt/bootumount /mnt

Для USB флешки

umount /mnt/devumount /mnt/sysumount /mnt/procumount /mnt

Заключение

Такой вариант установки может подойти для bare-metall установки, подготовки инструмента для восстановления систем

Подробнее..

Создание общей архитектуры для высокопроизводительных вычислений, искусственного интеллекта и анализа данных

27.01.2021 16:20:11 | Автор: admin
Сегодня высокопроизводительные вычисления (HPC), искусственный интеллект (AI) и анализ данных (DA) пересекаются всё чаще и чаще. Дело в том, что для решения сложных проблем требуется комбинация различных методик. Сочетание AI, HPC и DA в традиционных технологических процессах может ускорить научные открытия и инновации.

Учёные и исследователи в области обработки данных разрабатывают новые процессы решения проблемы в массовом масштабе, требующие вычислительных ресурсов, таких как HPC-системы. Рабочие нагрузки, связанные с AI и анализом данных, выигрывают от использования HPC-инфраструктуры, которая способна масштабироваться для улучшения производительности. О тенденциях этого рынка и подходах к созданию архитектуры для DA, AI и HPC сегодня и поговорим под катом.



Тенденция к конвергенции современных рабочих нагрузок требует использования более унифицированной архитектуры. Для традиционных рабочих нагрузок HPC (скажем, моделирования) нужно больших вычислительных мощностей, а также быстрых сетевых соединений и высокопроизводительных файловых систем. Например, создание модели пласта месторождения полезных ископаемых может занимать от нескольких часов до нескольких дней.

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

Разница в рабочих нагрузках HPC, AI и DA может создавать впечатление, что для них потребуются три отдельные инфраструктуры, однако это не так. Унифицированная архитектура подойдет как аналитикам данных, так и учёным, работающим с искусственным интеллектом, без переучивания и приспособления к новой операционной модели.

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

  • Навыки пользователей HPC, AI или DA различаются.
  • Системы управления ресурсами и планировщики нагрузок не являются взаимозаменяемыми.
  • Не всё программное обеспечение и не все фреймворки интегрированы в единую платформу.
  • Экосистемы требуют различных инструментов и функций.
  • Нагрузки и их требования к производительности отличаются.

Основа готовых решений Dell Technologies


Готовые решения Dell Technologies для искусственного интеллекта и анализа данных это единая среда, соответствующая требованиям всех трёх нагрузок. Они строятся с учётом четырёх основных принципов:

  1. Доступность данных.
  2. Простое планирование заданий и управление ресурсами.
  3. Оптимизация рабочих нагрузок.
  4. Интегрированные оркестрация и контейнеризация.

Доступность данных


Пользователи нуждаются в быстром доступе к своим данным независимо от рабочей нагрузки. Перемещение данных должно быть ограничено между разрозненными средами хранения. Наборы данных для HPC, AI и для DA должны быть объединены в единую среду для повышения операционной эффективности, особенно если рабочий процесс совмещает несколько техник.

Например, продвинутые системы помощи водителю используют модели экстремальных погодных условий для предотвращения аварийных ситуаций в условиях реального движения машины в плохую погоду. Затем новые данные используются для обучения глубокой нейронной сети: выход становится входом для обучения модели. Далее результаты загружаются в Spark, который используется для подключения к текущему набору данных заказчика и для отбора лучших данных для последующих тренировок модели. Для лучшей производительности данные, получаемые от рабочего процесса, должны быть как можно ближе к уже имеющимся данным.



Планирование заданий и управление ресурсами


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

При анализе данных используются такие планировщики заданий, как Spark Standalone и Mesos. Готовая архитектура для высокопроизводительных вычислений и искусственного интеллекта использует Kubernetes для оркестровки Spark и управления ресурсами для выполняемых задач. Так как ни один планировщик заданий не обращается к обеим средам, то архитектура должна поддерживать и то, и другое. Dell Technologies разработала архитектуру, которая удовлетворяет обоим требованиям.

Готовая архитектура Dell EMC для высокопроизводительных вычислений, анализа данных и искусственного интеллекта создает единый пул ресурсов. Ресурсы могут быть динамически назначены любой HPC-задаче, которая управляется с помощью менеджера ресурсов HPC или для контейнеризированных рабочих нагрузок искусственного интеллекта или анализа данных, которые, в свою очередь, управляются из контейнерной системы Kubernetes.

Оптимизация рабочих нагрузок


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



Оркестрация и контейнеризация


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

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

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

Аппаратные блоки архитектуры


Выбор правильного сервера


Dell EMC PowerEdge DSS 8440 это двухпроцессорный сервер (4U), оптимизированный для высокопроизводительных вычислений. В один DSS 8440 может быть установлено 4, 8 или 10 графических ускорителей NVIDIA V100 для распознавания изображений или NVIDIA T4 для обработки естественного языка (NLP). Десять NVMe накопителей обеспечивают быстрый доступ к обучающим данным. Этот сервер обладает как производительностью, так и гибкостью, чтобы быть идеальным решением для машинного обучения, а также других ресурсоёмких рабочих нагрузок. Например, моделирования и прогностического анализа в инженерной и научной среде.



Dell EMC PowerEdge C4140 обеспечивает потребности в масштабируемых серверных решениях, необходимых для обучения нейронных сетей. Глубокое обучение процесс, требующий серьёзных вычислительных ресурсов, в том числе быстрых графических процессоров, особенно на этапе обучения. Каждый сервер C4140 поддерживает до четырёх графических процессоров NVIDIA Tesla V100 (Volta). Подключенные через фабрику NVIDIA NVLINK 20 восемь и более C4140 могут быть кластеризованы для более масштабных моделей, обеспечивая производительность до 500 Пфлопс.



Dell EMC PowerEdge R740xd это классический двухпроцессорный сервер, который подходит для большинства проектов по машинному обучению. Этот 2U-сервер общего назначения обладает перспективой для дальнейшего его использования для задач глубокого обучения, так как поддерживает установку графических ускорителей и большого количества накопителей.



Выбор правильной сети


Dell EMC PowerSwitch S5232F-ON: высокопроизводительный Ethernet Dell EMC S5235F-ON S5235F-ON имеет 32 порта QSFP28 каждый из который поддерживает 100 GbE или 10/25/40/50 GbE с помощью кабелей-разветвителей. Шина коммутатора имеет пропускную способностью 64 Тбит/с, обеспечивая высокую производительность при низких задержках.

Mellanox SB7800 подходящее решение для для множества одновременных нагрузок. Производительная, неблокируемая шина на 72 Тбит/c с задержкой между двумя любыми точками коммутации в 90 нс обеспечивает высокую производительность решения.

Сервисы и системы хранения данных


Выбор правильного сервиса хранения данных


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

  1. Сервис хранения встроен в программное обеспечение и является его составной частью. В качестве примера можно привести Apache Hadoop с файловой системой HDFS, либо No SQL БД Apache Cassandra.
  2. Сервис хранения предоставляется либо специализированными решениями (например, Dell EMC PowerScale), либо корпоративными системами хранения данных.
  3. Доступ к облачным ресурсам: как к частным Dell EMC ECS, Cloudian, Ceph, так и публичным Amazon, Google, MS Azure. Доступ к данным, как правило, осуществляется на базе REST протоколов Amazon S3, Openstack Swift и т.д. Это один из наиболее активно развивающихся сегментов рынка хранения для Big Data.

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

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



Требования к функциональности


К сервису хранения данных можно предъявить следующие требования:

  • Линейная масштабируемость как по ёмкости, так и производительности.
  • Возможность эффективно работать в многопоточной среде.
  • Толерантность к массированным сбоям компонентов системы.
  • Простота модернизации и расширения системы.
  • Возможности по созданию оперативных и архивных уровней хранения.
  • Расширенный функционал по работе с данными (аудит, средства DR, защита от несанкционированных изменений, дедупликация, поиск по метаданным и т.д.).

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

Ассортимент систем хранения Dell EMC включает высокопроизводительные СХД PowerScale (HDFS, NFS/SMB) и ECS (S3, Opensatck Swift, HDFS), а также распределенные СХД, работающие по протоколам NFS и Lustre.

Пример специализированной системы


В качестве примера специализированной системы, которая позволяет эффективно работать в проектах, связанных c большими данными, можно привести Dell EMC PowerScale. Она позволяет построить корпоративное озеро данных. СХД не содержит контроллеров и дисковых полок, а представляет собой набор равнозначных узлов, объединённых с помощью выделенной дублированной сети. Каждый узел содержит диски, процессоры, память и сетевые интерфейсы для клиентского доступа. Вся дисковая ёмкость кластера формирует единый пул хранения и единую файловую систему, доступ к которой возможен через любой из узлов.

Dell EMC PowerScale это система хранения с параллельным доступом по различным файловым протоколам. Все узлы формируют единый пул ресурсов и единую файловую систему. Все узлы равноправны, любой из узлов может обработать любой запрос без дополнительных накладных расходов. Система расширяется до 252 узлов. В рамках одного кластера мы можем использовать пулы узлов с разной производительностью. Для оперативной обработки применять производительные узлы с SSD/NVMe и производительным сетевым доступом 40 либо 25 GbE, а для архивных данных узлы с ёмкими SATA дисками на 8-12 терабайт. Дополнительно появляется возможность перемещения наименее используемых данных в облако: как частное, так и публичное.



Проекты и сферы применения


Использование системы Dell EMC PowerScale позволило реализовать ряд интересных проектов, связанных с технологиями больших данных. Например, систему идентификации подозрительных действий для Mastercard. Также с её помощью успешно решаются задачи, связанные с автоматическим управлением автомобиля (ADAS) компании Zenuity. Одним из важных моментов является возможность выделения сервиса хранения данных в отдельный уровень с возможностью его отдельного масштабирования.

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

Вторым важным моментом является то, что PowerScale предоставляет доступ именно к файловой системе. То есть, по сравнению с традиционными решениями здесь нет жёсткого ограничения на объём анализируемой информации. Кластерная архитектура обеспечивает отличную производительность для задач машинного обучения даже при использовании ёмких SATA-дисков. Отличной иллюстрацией являются задачи по ML / DL где точность полученной модели может зависит от объёма и качества данных.

Традиционные системы


В качестве базовой системы хранения можно использовать Dell EMC PowerVault ME4084 (DAS). Она расширяется до объёма в 3 петабайта и способна обеспечить пропускную способность 5500 Мб/с и 320 000 IOPS.

Типовая схема готового решения для HPC, AI и анализа данных




Типовые сценарии применения ИИ по отраслям




Резюме


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

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

Автор материала Александр Коряковский, инженер-консультант департамента вычислительных и сетевых решений Dell Technologies в России
Подробнее..

Перевод Проблемные поды эскалация привилегий подов в Kubernetes

01.02.2021 12:14:39 | Автор: admin


Что будет, если разрешить лишнее при создании подов в Kubernetes? Зависит от того, какие неймспейсы хоста и контексты безопасности разрешены. Здесь мы поговорим о восьми небезопасных конфигурациях подов и методах эскалации привилегий. Эта статья и созданный для нее репозиторий помогут пентестерам и администраторам разобраться в распространенных ошибках конфигурации.


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


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


Краткий обзор


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


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


Защита подов: что может натворить один атрибут?


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


Администратор Kubernetes может реализовать принцип наименьших привилегий с помощью контроллеров допуска. Это может быть, допустим, встроенный контроллер PodSecurityPolicy или популярный сторонний контроллер OPA Gatekeeper. Контроллеры допуска запрещают поду доступ в кластер, если у него больше разрешений, чем предписано политикой.


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


Пентестеры часто получают доступ к созданию подов на кластере, где не действует никакая политика. Это я называю легким уровнем сложности. Используем этот манифест от Рори МакКьюна (Rory McCune) (@raesene), эту команду от Даффи Кули (Duffie Cooley) (@mauilion) или плагин node-shell krew и вот уже можно интерактивно выполнять код в привилегированном режиме на хосте. Проще уже не придумаешь.


А что если создавать поды можно только с hostNetwork, hostPID, hostIPC, hostPath или privileged? Что будет в каждом случае? Сейчас узнаем.



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


Я расположил проблемные поды по мере убывания рисков. Атаки, которым подвержены любые поды Kubernetes (например, проверка доступа пода к сервису метаданных облачного провайдера или поиск неправильно настроенного Kubernetes RBAC) описаны в разделе Проблемный под 8: все запрещено.


Проблемные поды:


Поды


Проблемный под 1: все разрешено


Проблемный под 2: Privileged и hostPid


Проблемный под 3: только Privileged


Проблемный под 4: только hostPath


Проблемный под 5: только hostPid


Проблемный под 6: только hostNetwork


Проблемный под 7: только hostIPC


Проблемный под 8: все запрещено.


Проблемный под 1: все разрешено



Что произойдет в худшем случае?


Много всего.


Как?


Созданный под монтирует файловую систему хоста к поду. Проще всего будет создать под в ноде control-plane с помощью селектора nodeName в манифесте. Потом можно выполнить в поде exec и сделать chroot для каталога, где примонтирована файловая система хоста. Теперь у нас есть права root в ноде, где запущен наш под.


  • Читаем секреты из etcd. Если мы запускаем под на ноде control-plane с помощью селектора nodeName в спецификации пода, мы легко получаем доступ к базе данных etcd, где хранится вся конфигурация кластера, включая секреты.
  • Ищем токены привилегированных учеток сервисов. Даже если удалось запустить под только на рабочей ноде, мы все равно можем получить доступ к секретам всех подов на этой ноде. В продакшен-кластере даже на рабочей ноде всегда есть хотя бы один под с токеном, который привязан к учетке сервиса, связанной с clusterrolebinding, так что мы можем, например, создавать поды или просматривать секреты во всех неймспейсах.

Больше схем эскалации привилегий см. в файле README (ниже) и в разделе Проблемный под 4: hostPath.


Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/everything-allowed


Дополнительные материалы



Проблемный под 2: privileged и hostpid



Что произойдет в худшем случае?


Много всего.


Как?


Единственное отличие от предыдущего варианта способ получения root-доступа к хосту. Там мы делали chroot для файловой системы хоста, а здесь используем nsenter, чтобы получить права root для ноды, где запущен наш под.


Почему это работает?


  • Privileged. Контекст безопасности privileged: true на уровне контейнера ломает почти любые преграды, которые по идее должен давать контейнер для защиты от атак. Остается разве что неймспейс PID. Без hostPID nsenter сможет входить только в неймспейсы процесса, который запущен в контейнере. Больше примеров действий, которые можно совершить с privileged: true, см. в следующем разделе Проблемный под 3: только Privileged.


  • Privileged + hostPID. Если одновременно задать hostPID: true и privileged: true, поду будут доступны все процессы на хосте, и мы сможем войти в систему init (PID 1) на хосте. А там уже можно запустить shell на ноде.



С root-доступом на хосте у нас есть те же пути эскалации привилегий, о которых мы говорили в разделе Проблемный под 1: все разрешено.


Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/priv-and-hostpid


Дополнительные материалы



Проблемный под 3: только privileged



Что произойдет в худшем случае?


Много всего.


Как?


С privileged: true у нас два пути:


  • Примонтировать файловую систему хоста. В привилегированном режиме /dev на хосте будет доступен нашему поду. Мы можем примонтировать к нашему поду диск с файловой системой хоста командой mount. По моему опыту, полной свободы действий нам это не даст. Некоторые файлы и пути эскалации привилегий недоступны из привилегированного пода, если только мы не эскалируем его до полноценной shell. Зато можно легко примонтировать диск и посмотреть, что мы там увидим.
  • Использовать уязвимость cgroup в user mode с помощью специальных программ. Лучше всего получить интерактивный root-доступ к ноде, но тут придется повозиться. Можем использовать прототип эксплойта Феликса Уилхелма (Felix Wilhelm) undock.sh, чтобы выполнять по команде за раз, или вариант, который Брэндон Эдвадрс (Brandon Edwards) и Ник Фриман (Nick Freeman) предложили в своем выступлении Краткое руководство по выходу из контейнера. В этом варианте мы заставляем хост подключиться к listener на поде для эскалации до интерактивного root-доступа на хосте. Еще один вариант взять модуль Metasploit Docker Privileged Container Escape, где используется тот же эксплойт для апгрейда shell на контейнере до shell на хосте.

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


Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/priv


Дополнительные материалы



Проблемный под 4: только hostpath



Что произойдет в худшем случае?


Много всего.


Как?


Допустим, у нас нет доступа к хостовым process- и network- неймспейсам, но администраторы не ограничили возможности монтирования. Тогда можно примонтировать всю файловую систему хоста к поду и получить к ней доступ на чтение и запись. Теперь можем использовать те же пути эскалации привилегий, что и раньше. Этих путей столько, что Иен Колдуотер (Ian Coldwater) и Даффи Кули (Duffie Cooley) посвятили им целое выступление на Black Hat 2019: Неизведанный путь: атака на Kubernetes с параметрами по умолчанию.


Вот несколько путей эскалации привилегий, которые можно использовать, когда у нас есть доступ к файловой системе ноды Kubernetes:


  • Ищем файлы kubeconfig в файловой системе хоста. Если повезет, можно даже найти конфигурацию cluster-admin с полным доступом вообще ко всему.
  • Ищем токены во всех подах на ноде. Возьмем что-то типа kubectl auth can-i --list или access-matrix и посмотрим, есть ли в подах токены, которые дадут нам больше разрешений. Ищем токены, с которыми можно получать секреты или создавать поды, деплойменты и т. д. в kube-system или создавать clusterrolebinding.
  • Добавляем свой SSH-ключ. Если у нас есть сетевой доступ к SSH-соединению с нодой, добавим к ноде свой публичный ключ и подключимся к ней по SSH, чтобы получить полный интерактивный доступ.
  • Ломаем хэшированные пароли. Взламываем хэши в /etc/shadow и пытаемся использовать их для доступа к другим нодам.

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostpath


Дополнительные материалы



Проблемный под 5: только hostpid



Что произойдет в худшем случае?


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


Как?


С одним только hostPID не так просто получить root-доступ к ноде, но кое-что натворить можно.


  • Смотрим процессы на хосте. Если запустим ps в поде с hostPID: true, увидим все процессы на хосте, включая процессы на каждом поде.
  • Ищем пароли, токены, ключи и тому подобное.Если повезет, найдем что-нибудь для эскалации привилегий и доберемся до кластера, до сервисов, поддерживаемых кластером, или до сервисов, которые общаются с приложениями на кластере. Придется повозиться, но можно найти токен для учетки сервиса в Kubernetes или что-то подобное, чтобы раздобыть доступ к другим пространствам имен и в итоге получить привилегии cluster-admin.
  • Завершаем процессы. Можно завершить на ноде любой процесс, чтобы вызвать отказ в обслуживании (не советую пентестерам экспериментировать с этим пунктом).

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostpid


Проблемный под 6: только hostnetwork



Что произойдет в худшем случае?


Риск компрометации кластера.


Как?


Если у нас есть только hostNetwork: true, напрямую выполнить код в привилегированном режиме на хосте мы не можем, но если сильно повезет, шанс добраться до cluster-admin все же есть. Путей эскалации может быть три:


  • Прослушиваем трафик. С tcpdump можно прослушивать незашифрованный трафик на любом интерфейсе хоста. Если звезды сложатся, нам попадутся токены учетки сервиса или другая конфиденциальная информация, которая передается по незашифрованным каналам.
  • Получаем доступ к сервисам, связанным с localhost. Мы можем получить доступ к сервисам, которые принимают трафик только через loopback интерфейс хоста или как-то еще ограничены сетевыми политиками. Оттуда можно найти какие-нибудь интересные пути эскалации привилегий.
  • Обходим сетевую политику. Если пространство имен ограничено сетевой политикой, можно задеплоить под с атрибутом hostNetwork: true, чтобы обойти эти ограничения. Суть в том, что мы привязываемся к сетевым интерфейсам хоста, а не подам.

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostnetwork


Проблемный под 7: только hostipc



Что произойдет в худшем случае?


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


Как?


Если какой-то процесс на хосте или процессы в поде используют механизмы межпроцессного взаимодействия (IPC) хоста (общая память, массивы семафоров, очереди сообщений и т. д.), можно использовать эти механизмы для чтения/записи. Сначала ищем /dev/shm, общий для всех подов с атрибутом hostIPC: true и хоста. Можно проверить и другие механизмы IPC с помощью ipcs.


  • Проверяем /dev/shm. Ищем файлы в общей памяти.
  • Проверяем существующие объекты IPC. С помощью /usr/bin/ipcs можно узнать, используются ли какие-нибудь объекты IPC.

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostipc


Проблемный под 8: все запрещено



Что произойдет в худшем случае?


Много всего.


Как?


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


  • Доступные облачные метаданные. Если под размещен в облаке, пытаемся получить доступ к облачному сервису метаданных. Там можно найти учетные данные IAM, связанные с нодой, или хотя бы облачные учетные данные IAM, созданные специально для этого пода. В обоих случаях можно добраться до кластера, до облачной среды или и туда, и туда.
  • Учетки сервисов с лишними разрешениями. Если учетка сервиса по умолчанию в пространстве имен примонтирована к /var/run/secrets/kubernetes.io/serviceaccount/token в поде и позволяет слишком многое, с этим токеном можно эскалировать привилегии в кластере.
  • Компоненты Kubernetes с неправильной конфигурацией. Если у apiserver или kubelet'ов для anonymous-auth задано true и никакие сетевые политики нам не мешают, можно взаимодействовать с ними напрямую без аутентификации.
  • Эксплойты в ядре, движке контейнера или Kubernetes. Эксплойт в этих компонентах можно использовать для выхода из контейнера или доступа к кластеру Kubernetes без дополнительных разрешений.
  • Уязвимые сервисы. Если смотреть на сетевые сервисы кластера через под, скорее всего, мы увидим больше, чем с машины, где создали этот под. Можем поискать уязвимые сервисы и приложения, направляя трафик через под.

Примеры использования
https://github.com/BishopFox/badPods/tree/main/manifests/nothing-allowed


Дополнительные материалы


Защита Kubernetes KubeCon NA 2019 CTF
Kubernetes Goat
Атака на Kubernetes через Kubelet
Подробный обзор угроз для Kubernetes в реальном мире
Краткое руководство по выходу из контейнера
CVE-2020-8558 POC


Заключение


Если не считать проблемный под номер 8, где все и так запрещено, все пути эскалации привилегий в этом посте (и репозитории к нему) можно перекрыть политиками безопасности.


Администраторы Kubernetes могут использовать и другие методы глубокой защиты, чтобы снизить или полностью устранить риски некоторых путей атак, даже если у злоумышленника есть доступ к некоторым или ко всем неймспейсам и возможностям на хосте (отключить автоматическое монтирование токенов учеток сервисов или запретить подам запуск с правами root, указав MustRunAsNonRoot=trueи allowPrivilegeEscalation=false). Как это обычно и бывает с пентестами, для взлома может потребоваться больше или меньше усилий.


Админам часто приходится применять методы защиты без примеров последствий, к которым может привести та или иная рискованная конфигурация. Надеюсь, примеры в этом посте и манифестах в репозитории Bad Pods помогут вам применять принцип наименьших привилегий при создании подов Kubernetes в вашей компании.


От редакции: подробнее о безопасности в K8s можно узнать на интенсиве Kubernetes Мега. Интенсив пройдет в онлайн-формате с 17 по 19 мая 2021.
Подробнее..

Настройка отказоустойчивого кластера Kubernetes на серверах с публичной и приватной сетью с помощью Kubeadm

01.02.2021 14:09:27 | Автор: admin

Эта статья написана потому, что я бы хотел иметь такую статью перед глазами, когда развертывал кластер по документации. Сразу хочу сказать, что не являюсь экспертом в K8S, однако имел опыт с развертыванием продуктовых установок DC/OS (экосистемы, основанной на Apache Mesos). Долгое время K8S меня отпугивал тем, что, при попытке его изучения, тебя закидывают кучей концепций и терминов, отчего мозг взрывается.

Тем не менее, у меня возникла задача настроить отказоустойчивый Bare Metal кластер для комплексного приложения, в связи с чем и возникла данная статья. В процессе руководства я затрону следующие аспекты:

  • корректная установка с помощью kubeadm на узлах с несколькими NIC;

  • реализация отказоустойчивого Control Plane с доступом по общему IP и DNS-имени;

  • реализация Ingress контроллера на базе Nginx на выделенных узлах с доступом из публичной сети;

  • проброс K8S API в публичную сеть;

  • проброс K8S Dashboard UI в публичную сеть.

Я выполнял установку в среде Ubuntu 18.04, в связи с чем часть из шагов может не работать в вашем дистрибутиве. В тексте могут встречаться фразы "как я понял..." и "я не до сих пор не вполне понял...".

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

Отличительной особенностью в моем кластере является то, что у всех узлов имеется два сетевых интерфейся - в моем случае, на eth0 всегда находится публичный адрес, а на eth1 - адрес из сети 10.120.0.0/16.

Стоит отметить, что K8S исключительно проще настраивать в случае, если ваши машины имеют по одному NIC. Если ваша инфраструктура позволяет вам использовать машины с одним сетевым устройством и иметь внешний балансировщик нагрузки - однозначно так необходимо делать.

В случае моей же инфраструктуры такая топология хотя и возможна, но я понял насколько K8S становится проще при использовании машин с одной NIC уже после того, как начал развертывание, поэтому решил "победить" проблемы, в рамках данной топологии, сохранив преимущества доступа к каждой машине напрямую.

Еще, kubeadm при развертывании считает, что что правильный IP-адрес - это тот, который находится в сети, где шлюз "по-умолчанию", если не переопределить, ничего хорошего не выйдет.

Тем не менее, в случае использования Enterprise решений, машины с несколькими сетевыми картами и доступом к ним из разных сетей - достаточно рядовая история, поэтому данная модель развертывания имеет право на существование.

Хочу отметить, что я использую Ansible, но в качестве упрощения не буду в статье демонстрировать playbook-и, ориентируясь на настройку руками. Итак, приступим.

Замена DNS-рекурсора

Я хочу обеспечить доступность всех узлов кластера через DNS-имена по внутренним IP-адресам, при этом сохранив доступность разрешения обычных имен узлов в интернете. Для этого, на серверах gw-1, gw-2 я разверну pdns-recursor и укажу его в качестве рекурсора на всех узлах кластера.

Базовая настройка pdns-recursor на gw-1, gw-2 включает указание следующих директив:

allow-from=10.120.0.0/8, 127.0.0.0/8etc-hosts-file=/etc/hosts.resolvexport-etc-hosts=onexport-etc-hosts-search-suffix=cluster

Сам файл /etc/hosts.resolv генерируется с помощью ansible и выглядит следующим образом:

# Ansible managed10.120.29.231  gw-1 gw-110.120.28.23  gw-2 gw-210.120.29.32  video-accessors-1 video-accessors-110.120.29.226  video-accessors-2 video-accessors-210.120.29.153  mongo-1 mongo-110.120.29.210  mongo-2 mongo-210.120.29.220  mongo-3 mongo-310.120.28.172  compute-1 compute-110.120.28.26  compute-2 compute-210.120.29.70  compute-3 compute-310.120.28.127  zk-1 zk-110.120.29.110  zk-2 zk-210.120.29.245  zk-3 zk-310.120.28.21  minio-1 minio-110.120.28.25  minio-2 minio-210.120.28.158  minio-3 minio-310.120.28.122  minio-4 minio-410.120.29.187  k8s-1 k8s-110.120.28.37  k8s-2 k8s-210.120.29.204  k8s-3 k8s-310.120.29.135  kafka-1 kafka-110.120.29.144  kafka-2 kafka-210.120.28.130  kafka-3 kafka-310.120.29.194  clickhouse-1 clickhouse-110.120.28.66  clickhouse-2 clickhouse-210.120.28.61  clickhouse-3 clickhouse-310.120.29.244  app-1 app-110.120.29.228  app-2 app-210.120.29.33  prometeus prometeus10.120.29.222  manager manager10.120.29.187 k8s-cp
Шаблон Ansible для генерации конфига
# {{ ansible_managed }}{% for item in groups['all'] %}{% set short_name = item.split('.') %}{{ hostvars[item]['host'] }}  {{ item }} {{ short_name[0] }}{% endfor %}10.120.0.1 k8s-cp

Теперь, необходимо сделать так, чтобы все узлы вместо DNS-рекурсоров, получаемых из настроек DHCP, использовали данные DNS-ы. В Ubuntu 18.04 используется systemd-resolved, поэтому необходимо ему указать требуемые серверы gw-1, gw-2. Для этого определим манифест, переопределяющий поведение systemd-resolved с помощью файла /etc/systemd/network/0-eth0.network на каждом хосте кластера:

[Match]Name=eth0[Network]DHCP=ipv4DNS=10.120.28.23 10.120.29.231Domains=cluster[DHCP]UseDNS=falseUseDomains=false

Делает он следующее, для DHCP-записи, полученной через eth0 будут игнорироваться DNS-серверы и поисковые домены. Вместо этого будут использоваться серверы 10.120.28.23, 10.120.29.231 и использоваться поисковый домен *.cluster. После создания данного файла требуется перезагрузить узел или сеть узла, поскольку простой перезапуск systemd-resolved не инициирует повторное получение данных по DHCP. Я перезагружаю для того, чтобы убедиться в корректном поведении при старте узла.

При успешной инициализации systemd-resolve --status выдаст следующий листинг:

Global          DNSSEC NTA: 10.in-addr.arpa                      16.172.in-addr.arpa                      168.192.in-addr.arpa                      17.172.in-addr.arpa                      18.172.in-addr.arpa                      19.172.in-addr.arpa                      20.172.in-addr.arpa                      21.172.in-addr.arpa                      22.172.in-addr.arpa                      23.172.in-addr.arpa                      24.172.in-addr.arpa                      25.172.in-addr.arpa                      26.172.in-addr.arpa                      27.172.in-addr.arpa                      28.172.in-addr.arpa                      29.172.in-addr.arpa                      30.172.in-addr.arpa                      31.172.in-addr.arpa                      corp                      d.f.ip6.arpa                      home                      internal                      intranet                      lan                      local                      private                      testLink 3 (eth1)      Current Scopes: none       LLMNR setting: yesMulticastDNS setting: no      DNSSEC setting: no    DNSSEC supported: noLink 2 (eth0)      Current Scopes: DNS       LLMNR setting: yesMulticastDNS setting: no      DNSSEC setting: no    DNSSEC supported: no         DNS Servers: 10.120.28.23                      10.120.29.231          DNS Domain: cluster

Это действие необходимо выполнить на всех узлах кластера. При корректном выполнении каждый узел сможет выполнить ping gw-1.cluster, ping gw-2.cluster и получить ответ от данных узлов по внутренним ip-адресам.

Отключение раздела подкачки

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

sudo -- sh -c "swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab"

Для пущей уверенности удалите swap-раздел с помощью fdisk.

Внесение изменений в сетевые настройки ядра

Выполняется на всех узлах. Я буду использовать Flannel - простейший оверлейный сетевой провайдер для K8S. Обратите внимание, что довольно много провайдеров используют VXLAN. Это накладывает определенные особенности для сетевой инфраструктуры.

В простейшем случае, вам требуется обеспечить работоспособность multicast, поскольку VXLAN использует multicast-группы, для своей работы. Если multicast - не ваш вариант, но вы хотите использовать провайдер, основанный на VXLAN, можно настроить работу VXLAN через BGP или другими способами. Однако, сможет ли жить с этим выбранный вами провайдер сетевой инфраструктуры Kubernetes - это большой вопрос. В общем, Flannel поддерживает VXLAN через multicast. В моем случае это VXLAN+multicast over VXLAN+multicast over Ethernet, поскольку в моей сети виртуальные машины имеют VXLAN-бэкбон, работающий поверх Ethernet с использованием multicast - так тоже работает.

В /etc/modules добавьте br_netfilter, overlay.

Выполните modprobe br_netfilter && modprobe overlay, чтобы загрузить модули.

В /etc/sysctl.conf добавьте:

net.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1net.ipv4.ip_forward = 1

Выполните sysctl -p для применения изменений.

Установка containerd

Выполняется на всех узлах. Kubernetes рекомендует использовать containerd (впрочем, новые версии docker тоже используют containerd), поэтому установим его:

sudo apt-get updatesudo apt install containerdsudo sh -- -c "containerd config default | tee /etc/containerd/config.toml"sudo service containerd restart

Установим kubeadm, kubelet, kubectl

Выполняется на всех узлах. Здесь прям из руководства по установке K8S:

sudo apt-get update && sudo apt-get install -y apt-transport-https curlcurl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.listdeb https://apt.kubernetes.io/ kubernetes-xenial mainEOFsudo apt-get updatesudo apt-get install -y kubelet kubeadm kubectlsudo apt-mark hold kubelet kubeadm kubectl

Инициализация первого узла K8S

Выполняется на узлах, которые будут обслуживать Control Plane K8S - в моем случае k8s-{1,2,3}. Здесь уже есть нюансы, специфичные для моего развертывания:

kubeadm init --pod-network-cidr=10.244.0.0/16 \      --control-plane-endpoint=k8s-cp \      --apiserver-advertise-address=10.120.29.187

Для Flannel категорически важно использовать --pod-network-cidr=10.244.0.0/16. С другим адресным пространством для POD-ов K8S он не запустится.

--control-plane-endpoint string Specify a stable IP address or DNS name for the control plane.

Здесь Вы должны указать тот DNS или IP, который будет использоваться для связи всех шурушков K8S-а с Control Plane. Я решил использовать доменное имя k8s-cp, привязанное к отказоустойчивому ip-адресу 10.120.0.1 (см. далее, на текущий момент, k8s-cp указывает на один из серверов Control Plane: 10.120.29.187 k8s-cp).

Важный аргумент --api-server-advertise-address. Важно, что он влияет не только на api-server, но и на Etcd, что нигде не сказано, но очень важно для отказоустойчивой топологии. Если ничего не указать, то kubeadm возьмет адрес с той сети, в которой шлюз по-умолчанию, что не всегда верно. В моем случае это приводит к тому, что Etcd стартует на публичном интерфейсе, а кластер Etcd хочет работать по публичной сети, что меня не устраивает. Если этот адрес не указать правильно, то Flannel тоже не сможет корректно инициализироваться, будет падать с ошибками, что не может связаться с Control Plane (будет использовать тот же IP-адрес из сети со шлюзом по умолчанию для связи).

В общем, этот параметр привносит много геморроя и ведет к некорректной работе всего, что только может некорректно работать.

Теперь, если все хорошо, то Kubeadm развернет K8S на данном узле. Я рекомендую выполнить перезагрузку узла для того, чтобы убедиться что Control Plane стартует как надо. Убедитесь в этом, запросив список выполняемых задач:

ps xa  | grep -E '(kube-apiserver|etcd|kube-proxy|kube-controller-manager|kube-scheduler)'

Теперь можно скопmkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/configировать настройки конфигурации для доступа администратора к кластеру в домашний каталог:

mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config

Для проверки запросите задачи, выполняемые на данном настроенном контроллере посредством команды kubectl get pods --all-namespaces. Вы должны получить вывод, примерно соответствующий следующему:

NAMESPACE              NAME                                         READY   STATUS      RESTARTS   AGEkube-system            etcd-k8s-1                                   1/1     Running     0          2d23hkube-system            kube-apiserver-k8s-1                         1/1     Running     0          2d23hkube-system            kube-controller-manager-k8s-1                1/1     Running     1          2d23hkube-system            kube-scheduler-k8s-1                         1/1     Running     1          2d23h

Я рекомендую посмотреть вывод этой команды еще пару раз, с перерывом 1 минуту, чтобы убедиться, что RESTARTS не растут, а статус Running.

Сам Kubernetes никакой сети не предоставляет, делегируя это плагинам CNI. Мы будем использовать простой CNI - Flannel. Его установка производится элементарно следующей командой:

kubectl apply -f https://github.com/coreos/flannel/raw/master/Documentation/kube-flannel.yml

Опять же, выполните kubectl get pods --all-namespaces несколько раз, чтобы убедиться, что Flannel выполняется без ошибок и RESTARTS не растут. Если что-то пошло не так, посмотрите журнал событий flannel следующим способом (только используйте настоящее имя POD-а Flannel:

kubectl logs -n kube-system kube-flannel-ds-xn2j9

Теперь вы можете подключить два других узла Control Plane с помощью команды, выполненной на каждом из них:

# ssh k8s-2sudo kubeadm join k8s-cp:6443 --apiserver-advertise-address=10.120.28.37 --token tfqsms.kiek2vk129tpf0b7 --discovery-token-ca-cert-hash sha256:0c446bfabcd99aae7e650d110f8b9d6058cac432078c4fXXXXX6055b4bd --control-planemkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config# ssh k8s-3sudo kubeadm join k8s-cp:6443 --apiserver-advertise-address=10.120.29.204 --token tfqsms.kiek2vk129tpf0b7 --discovery-token-ca-cert-hash sha256:0c446bfabcd99aae7e650d110f8b9d6058cac432078c4fXXXXXec6055b4bd --control-planemkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config

Если вдруг --token "протух", используйте команду kubeadm token create, чтобы сгенерировать новый.

После подключения узла смотрите внимательно за состоянием Etcd:

kubectl get pods --all-namespaces | grep etcdkube-system            etcd-k8s-1                                   1/1     Running     0          2d23hkube-system            etcd-k8s-2                                   1/1     Running     1          2d22hkube-system            etcd-k8s-3                                   1/1     Running     1          2d22h

Состояние должно быть Running, увеличение счетчика перезагрузок не должно происходить. Команда kubectl get pods --all-namespaces должна отображать трехкратный набор процессов на всех узлах Control Plane:

NAME                            READY   STATUS    RESTARTS   AGEcoredns-74ff55c5b-h2zjq         1/1     Running   0          2d23hcoredns-74ff55c5b-n6b49         1/1     Running   0          2d23hetcd-k8s-1                      1/1     Running   0          2d23hetcd-k8s-2                      1/1     Running   1          2d22hetcd-k8s-3                      1/1     Running   1          2d22hkube-apiserver-k8s-1            1/1     Running   0          2d23hkube-apiserver-k8s-2            1/1     Running   1          2d22hkube-apiserver-k8s-3            1/1     Running   1          2d22hkube-controller-manager-k8s-1   1/1     Running   1          2d23hkube-controller-manager-k8s-2   1/1     Running   1          2d22hkube-controller-manager-k8s-3   1/1     Running   1          2d22hkube-flannel-ds-2f6d5           1/1     Running   0          2d3hkube-flannel-ds-2p5vx           1/1     Running   0          2d3hkube-flannel-ds-4ng99           1/1     Running   3          2d22hkube-proxy-22jpt                1/1     Running   0          2d3hkube-proxy-25rxn                1/1     Running   0          2d23hkube-proxy-2qp8r                1/1     Running   0          2d3hkube-scheduler-k8s-1            1/1     Running   1          2d23hkube-scheduler-k8s-2            1/1     Running   1          2d22hkube-scheduler-k8s-3            1/1     Running   1          2d22h

Следующим шагом настроим отказоустойчивый IP-адрес, который будет использоваться для доступа к Control Plane. В моем случае было три варианта:

  1. Keepalived;

  2. Pacemaker;

  3. kube-vip.

Здесь я потратил достаточно много времени, чтобы все завести. Начал я с Keepalived, который прекрасно работает в других моих серверных системах. В общем, здесь он у меня не завелся, не знаю в чем проблема - в Ubuntu 18.04 или в VXLAN-сети, которую я использую в качестве Underlay. Tcpdump показывал веселые VRRP-пакетики, летящие между k8s-{1,2,3}, но IP-адрес вешался всеми 3мя узлами, все считали себя MASTER-ами. Поскольку debug ничего полезного не дал, я отказался от Keepalived и выполнил настройку на Pacemaker. Тут меня ждала очередная неприятность - corosync и pacemaker не взлетали самостоятельно при старте, несмотря на:

sudo systemctl enable corosyncsudo systemctl enable pacemaker

Я придерживаюсь такого мнения, что корневые компоненты или работают или не надо их использовать, в /etc/rc.local прописывать эти службы не хотелось. В итоге, я познакомился со специализированным решением по предоставлению отказоустойчивого IP-адреса kube-vip, разработанным специально для Kubernetes.

Нам понадобится создать три манифеста, каждый для запуска kube-vip на одном из узлов Control Plane:

apiVersion: v1kind: Podmetadata:  creationTimestamp: null  name: kube-vip-cp-k8s-1         # поменять имя, соответственно узлу  namespace: kube-systemspec:  nodeName: k8s-1                 # будет запускаться именно на этом узле  containers:  - args:    - start    env:    - name: vip_arp      value: "true"    - name: vip_interface      value: eth1    - name: vip_leaderelection      value: "true"    - name: vip_leaseduration      value: "5"    - name: vip_renewdeadline      value: "3"    - name: vip_retryperiod      value: "1"    - name: vip_address      value: 10.120.0.1          # указать реальный IP, который будет использоваться    image: plndr/kube-vip:0.3.1  # проверить актуальную версию    imagePullPolicy: Always    name: kube-vip-cp    resources: {}    securityContext:      capabilities:        add:        - NET_ADMIN        - SYS_TIME    volumeMounts:    - mountPath: /etc/kubernetes/admin.conf      name: kubeconfig    - mountPath: /etc/ssl/certs      name: ca-certs      readOnly: true  hostNetwork: true  volumes:  - hostPath:      path: /etc/kubernetes/admin.conf    name: kubeconfig  - hostPath:      path: /etc/ssl/certs    name: ca-certsstatus: {}

Данный манифест необходимо сформировать для каждого из серверов Control Plane и выполнить их:

kubectl apply -f cluster_config/vip-1.ymlkubectl apply -f cluster_config/vip-2.ymlkubectl apply -f cluster_config/vip-3.yml

В результате вы должны получить три нормально выполняющихся POD-а, каждый на своем узле, при этом адрес 10.120.0.1 должен нормально пинговаться. Проверьте, что только один из kube-vip владеет IP:

sudo arping 10.120.0.1ARPING 10.120.0.142 bytes from 1e:01:17:00:01:22 (10.120.0.1): index=0 time=319.476 usec42 bytes from 1e:01:17:00:01:22 (10.120.0.1): index=1 time=306.360 msec42 bytes from 1e:01:17:00:01:22 (10.120.0.1): index=2 time=349.666 usec

Чем хорош kube-vip? Он не только предоставляет отказоустойчивый IP, но и определяет когда сервер на хосте, где он выполняется становится недоступен, переставая балансировать на него трафик.

Теперь, когда kube-vip предоставляет отказоустойчивый доступ к Kubernetes необходимо на хостах-рекурсорах gw-1, gw-2 в /etc/hosts.resolv обновить записи для k8s-cp:

10.120.0.1 k8s-cp

Выполните перезагрузку pdns-recursor командой sudo service pdns-recursor restart и проверьте, что k8s-cp отвечает со всех узлов IP адресом 10.120.0.1. Проверьте, что kubectl все еще корректно работает с узла k8s-1, он будет соединяться по k8s-cp, но использовать уже другой IP-адрес.

На данном этапе у нас есть реализация отказоустойчивого Control Plane K8S. Я рекомендую несколько раз поочередно перезагружать k8s-{1,2,3}, чтобы проверить, что кластер остается в работоспособном состоянии.

Добавление узла Worker-а

В нашей топологии предполагается использование двух узлов gw-1, gw-2, на которых будет размещен Nginx Ingress и один узел общего назначения (compute-1).

Все эти узлы в кластер можно добавить следующим образом:

kubeadm token create --print-join-command kubeadm join k8s-cp:6443 --token rn0s5p.y6waq1t6y2y6z9vw     --discovery-token-ca-cert-hash sha256:0c446bfabcd99aae7e650d110f8b9d6058cac432078c4fXXXe22ec6055b4bd# ssh gw-1sudo kubeadm join k8s-cp:6443 --token rn0s5p.y6waq1t6y2y6z9vw     --discovery-token-ca-cert-hash sha256:0c446bfabcd99aae7e650d110f8b9d6058cac432078c4fXXXe22ec6055b4bd# ssh gw-2...# ssh compute-1

После добавления kubectl get pds --all-namespaces должен показать расширенный набор выполняющихся POD-ов, а kubectl get nodes должен вывести все узлы кластера:

kubectl get nodesNAME                STATUS   ROLES                  AGE     VERSIONcompute-1           Ready    compute                2d23h   v1.20.2gw-1                Ready    gateway                2d4h    v1.20.2gw-2                Ready    gateway                2d4h    v1.20.2k8s-1               Ready    control-plane,master   2d23h   v1.20.2k8s-2               Ready    control-plane,master   2d23h   v1.20.2k8s-3               Ready    control-plane,master   2d23h   v1.20.2

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

Назначение ролей узлам

Роль можно присвоить просто:

kubectl label node gw-1 node-role.kubernetes.io/gateway=truekubectl label node gw-2 node-role.kubernetes.io/gateway=truekubectl label node compute-1 node-role.kubernetes.io/compute=true# если надо удалить рольkubectl label node compute-1 node-role.kubernetes.io/compute-

Настройка Ingress

Сейчас все готово для того, чтобы можно было выполнить развертывание Nginx Ingress на узлах gw-1, gw-2. Воспользуемся манифестом Nginx Ingress, но внесем в него ряд изменений:

  • запускать будем с сетью hostNetwork;

  • запускать будем в виде Deployment с фактором масштабирования "2";

  • запускать будем на узлах с ролью gateway.

Разберем подробнее про hostNetwork. Дело в том, что при использовании K8S в рамках какого-то облачного провайдера, последний через API назначает каждому узлу External IP, который может быть использован приложениями для связи с внешним миром. Так вот, у нас в bare metal кластере никаких External IP нет:

kubectl get nodes --output wideNAME                STATUS   ROLES                  AGE     VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIMEcompute-1           Ready    compute                3d      v1.20.2   10.120.28.172   <none>        Ubuntu 18.04.5 LTS   4.15.0-135-generic   containerd://1.3.3gw-1                Ready    gateway                2d4h    v1.20.2   10.120.29.231   <none>        Ubuntu 18.04.5 LTS   4.15.0-135-generic   containerd://1.3.3gw-2                Ready    gateway                2d4h    v1.20.2   10.120.28.23    <none>        Ubuntu 18.04.5 LTS   4.15.0-135-generic   containerd://1.3.3k8s-1               Ready    control-plane,master   3d      v1.20.2   10.120.29.187   <none>        Ubuntu 18.04.5 LTS   4.15.0-135-generic   containerd://1.3.3k8s-2               Ready    control-plane,master   2d23h   v1.20.2   10.120.28.37    <none>        Ubuntu 18.04.5 LTS   4.15.0-135-generic   containerd://1.3.3k8s-3               Ready    control-plane,master   2d23h   v1.20.2   10.120.29.204   <none>        Ubuntu 18.04.5 LTS   4.15.0-135-generic   containerd://1.3.3

Собственно, назначить этот External IP можно только через API, при этом он сбрасывается самим Kubernetes время от времени и требует постоянной установки. В общем, это неудобно и использоваться нормально не может. Я читал длинную переписку на GitHub, которая закончилась ничем вразумительным, еще советуют использовать metallb, который тоже непонятно в каком состоянии. В общем, я решил просто завести Nginx Ingress, используя hostNetworking, поскольку это обеспечивает привязку данного Ingress с адресам 0.0.0.0:443, 0.0.0.0:80 и решает мою задачу.

Собственно, манифест для запуска Nginx Ingress выглядит так:

Очень большой фрагмент YAML
apiVersion: v1kind: Namespacemetadata:  name: ingress-nginx  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx---# Source: ingress-nginx/templates/controller-serviceaccount.yamlapiVersion: v1kind: ServiceAccountmetadata:  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: controller  name: ingress-nginx  namespace: ingress-nginx---# Source: ingress-nginx/templates/controller-configmap.yamlapiVersion: v1kind: ConfigMapmetadata:  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: controller  name: ingress-nginx-controller  namespace: ingress-nginxdata:---# Source: ingress-nginx/templates/clusterrole.yamlapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm  name: ingress-nginxrules:  - apiGroups:      - ''    resources:      - configmaps      - endpoints      - nodes      - pods      - secrets    verbs:      - list      - watch  - apiGroups:      - ''    resources:      - nodes    verbs:      - get  - apiGroups:      - ''    resources:      - services    verbs:      - get      - list      - watch  - apiGroups:      - extensions      - networking.k8s.io   # k8s 1.14+    resources:      - ingresses    verbs:      - get      - list      - watch  - apiGroups:      - ''    resources:      - events    verbs:      - create      - patch  - apiGroups:      - extensions      - networking.k8s.io   # k8s 1.14+    resources:      - ingresses/status    verbs:      - update  - apiGroups:      - networking.k8s.io   # k8s 1.14+    resources:      - ingressclasses    verbs:      - get      - list      - watch---# Source: ingress-nginx/templates/clusterrolebinding.yamlapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm  name: ingress-nginxroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: ingress-nginxsubjects:  - kind: ServiceAccount    name: ingress-nginx    namespace: ingress-nginx---# Source: ingress-nginx/templates/controller-role.yamlapiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: controller  name: ingress-nginx  namespace: ingress-nginxrules:  - apiGroups:      - ''    resources:      - namespaces    verbs:      - get  - apiGroups:      - ''    resources:      - configmaps      - pods      - secrets      - endpoints    verbs:      - get      - list      - watch  - apiGroups:      - ''    resources:      - services    verbs:      - get      - list      - watch  - apiGroups:      - extensions      - networking.k8s.io   # k8s 1.14+    resources:      - ingresses    verbs:      - get      - list      - watch  - apiGroups:      - extensions      - networking.k8s.io   # k8s 1.14+    resources:      - ingresses/status    verbs:      - update  - apiGroups:      - networking.k8s.io   # k8s 1.14+    resources:      - ingressclasses    verbs:      - get      - list      - watch  - apiGroups:      - ''    resources:      - configmaps    resourceNames:      - ingress-controller-leader-nginx    verbs:      - get      - update  - apiGroups:      - ''    resources:      - configmaps    verbs:      - create  - apiGroups:      - ''    resources:      - events    verbs:      - create      - patch---# Source: ingress-nginx/templates/controller-rolebinding.yamlapiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: controller  name: ingress-nginx  namespace: ingress-nginxroleRef:  apiGroup: rbac.authorization.k8s.io  kind: Role  name: ingress-nginxsubjects:  - kind: ServiceAccount    name: ingress-nginx    namespace: ingress-nginx---# Source: ingress-nginx/templates/controller-service-webhook.yamlapiVersion: v1kind: Servicemetadata:  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: controller  name: ingress-nginx-controller-admission  namespace: ingress-nginxspec:  type: ClusterIP  ports:    - name: https-webhook      port: 443      targetPort: webhook  selector:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/component: controller---# Source: ingress-nginx/templates/controller-deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata:  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: controller  name: ingress-nginx-controller  namespace: ingress-nginxspec:  replicas: 2  selector:    matchLabels:      app.kubernetes.io/name: ingress-nginx      app.kubernetes.io/instance: ingress-nginx      app.kubernetes.io/component: controller  revisionHistoryLimit: 10  minReadySeconds: 0  template:    metadata:      labels:        app.kubernetes.io/name: ingress-nginx        app.kubernetes.io/instance: ingress-nginx        app.kubernetes.io/component: controller    spec:      hostNetwork: true      dnsPolicy: ClusterFirst      containers:        - name: controller          image: k8s.gcr.io/ingress-nginx/controller:v0.43.0@sha256:9bba603b99bf25f6d117cf1235b6598c16033ad027b143c90fa5b3cc583c5713          imagePullPolicy: IfNotPresent          lifecycle:            preStop:              exec:                command:                  - /wait-shutdown          args:            - /nginx-ingress-controller            - --election-id=ingress-controller-leader            - --ingress-class=nginx            - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller            - --validating-webhook=:8443            - --validating-webhook-certificate=/usr/local/certificates/cert            - --validating-webhook-key=/usr/local/certificates/key          securityContext:            capabilities:              drop:                - ALL              add:                - NET_BIND_SERVICE            runAsUser: 101            allowPrivilegeEscalation: true          env:            - name: POD_NAME              valueFrom:                fieldRef:                  fieldPath: metadata.name            - name: POD_NAMESPACE              valueFrom:                fieldRef:                  fieldPath: metadata.namespace            - name: LD_PRELOAD              value: /usr/local/lib/libmimalloc.so          livenessProbe:            httpGet:              path: /healthz              port: 10254              scheme: HTTP            initialDelaySeconds: 10            periodSeconds: 10            timeoutSeconds: 1            successThreshold: 1            failureThreshold: 5          readinessProbe:            httpGet:              path: /healthz              port: 10254              scheme: HTTP            initialDelaySeconds: 10            periodSeconds: 10            timeoutSeconds: 1            successThreshold: 1            failureThreshold: 3          ports:            - name: http              containerPort: 80              protocol: TCP            - name: https              containerPort: 443              protocol: TCP            - name: webhook              containerPort: 8443              protocol: TCP          volumeMounts:            - name: webhook-cert              mountPath: /usr/local/certificates/              readOnly: true          resources:            requests:              cpu: 100m              memory: 90Mi      nodeSelector:        node-role.kubernetes.io/gateway: "true"      serviceAccountName: ingress-nginx      terminationGracePeriodSeconds: 300      volumes:        - name: webhook-cert          secret:            secretName: ingress-nginx-admission---# Source: ingress-nginx/templates/admission-webhooks/validating-webhook.yaml# before changing this value, check the required kubernetes version# https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisitesapiVersion: admissionregistration.k8s.io/v1kind: ValidatingWebhookConfigurationmetadata:  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: admission-webhook  name: ingress-nginx-admissionwebhooks:  - name: validate.nginx.ingress.kubernetes.io    matchPolicy: Equivalent    rules:      - apiGroups:          - networking.k8s.io        apiVersions:          - v1beta1        operations:          - CREATE          - UPDATE        resources:          - ingresses    failurePolicy: Fail    sideEffects: None    admissionReviewVersions:      - v1      - v1beta1    clientConfig:      service:        namespace: ingress-nginx        name: ingress-nginx-controller-admission        path: /networking/v1beta1/ingresses---# Source: ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yamlapiVersion: v1kind: ServiceAccountmetadata:  name: ingress-nginx-admission  annotations:    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: admission-webhook  namespace: ingress-nginx---# Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yamlapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: ingress-nginx-admission  annotations:    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: admission-webhookrules:  - apiGroups:      - admissionregistration.k8s.io    resources:      - validatingwebhookconfigurations    verbs:      - get      - update---# Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yamlapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:  name: ingress-nginx-admission  annotations:    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: admission-webhookroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: ingress-nginx-admissionsubjects:  - kind: ServiceAccount    name: ingress-nginx-admission    namespace: ingress-nginx---# Source: ingress-nginx/templates/admission-webhooks/job-patch/role.yamlapiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:  name: ingress-nginx-admission  annotations:    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: admission-webhook  namespace: ingress-nginxrules:  - apiGroups:      - ''    resources:      - secrets    verbs:      - get      - create---# Source: ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yamlapiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:  name: ingress-nginx-admission  annotations:    helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: admission-webhook  namespace: ingress-nginxroleRef:  apiGroup: rbac.authorization.k8s.io  kind: Role  name: ingress-nginx-admissionsubjects:  - kind: ServiceAccount    name: ingress-nginx-admission    namespace: ingress-nginx---# Source: ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yamlapiVersion: batch/v1kind: Jobmetadata:  name: ingress-nginx-admission-create  annotations:    helm.sh/hook: pre-install,pre-upgrade    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: admission-webhook  namespace: ingress-nginxspec:  template:    metadata:      name: ingress-nginx-admission-create      labels:        helm.sh/chart: ingress-nginx-3.21.0        app.kubernetes.io/name: ingress-nginx        app.kubernetes.io/instance: ingress-nginx        app.kubernetes.io/version: 0.43.0        app.kubernetes.io/managed-by: Helm        app.kubernetes.io/component: admission-webhook    spec:      containers:        - name: create          image: docker.io/jettech/kube-webhook-certgen:v1.5.1          imagePullPolicy: IfNotPresent          args:            - create            - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc            - --namespace=$(POD_NAMESPACE)            - --secret-name=ingress-nginx-admission          env:            - name: POD_NAMESPACE              valueFrom:                fieldRef:                  fieldPath: metadata.namespace      restartPolicy: OnFailure      serviceAccountName: ingress-nginx-admission      securityContext:        runAsNonRoot: true        runAsUser: 2000---# Source: ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yamlapiVersion: batch/v1kind: Jobmetadata:  name: ingress-nginx-admission-patch  annotations:    helm.sh/hook: post-install,post-upgrade    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded  labels:    helm.sh/chart: ingress-nginx-3.21.0    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/instance: ingress-nginx    app.kubernetes.io/version: 0.43.0    app.kubernetes.io/managed-by: Helm    app.kubernetes.io/component: admission-webhook  namespace: ingress-nginxspec:  template:    metadata:      name: ingress-nginx-admission-patch      labels:        helm.sh/chart: ingress-nginx-3.21.0        app.kubernetes.io/name: ingress-nginx        app.kubernetes.io/instance: ingress-nginx        app.kubernetes.io/version: 0.43.0        app.kubernetes.io/managed-by: Helm        app.kubernetes.io/component: admission-webhook    spec:      containers:        - name: patch          image: docker.io/jettech/kube-webhook-certgen:v1.5.1          imagePullPolicy: IfNotPresent          args:            - patch            - --webhook-name=ingress-nginx-admission            - --namespace=$(POD_NAMESPACE)            - --patch-mutating=false            - --secret-name=ingress-nginx-admission            - --patch-failure-policy=Fail          env:            - name: POD_NAMESPACE              valueFrom:                fieldRef:                  fieldPath: metadata.namespace      restartPolicy: OnFailure      serviceAccountName: ingress-nginx-admission      securityContext:        runAsNonRoot: true        runAsUser: 2000

Запустив его с помощью kubectl apply -f nginx-ingress.yaml, мы получим два POD-а Nginx, выполняющихся на узлах gw-1, gw-2 и слушающих 443-й и 80-й порты:

kubectl get pods --all-namespaces | grep nginxingress-nginx          ingress-nginx-admission-create-4mm9m         0/1     Completed   0          46hingress-nginx          ingress-nginx-admission-patch-7jkwg          0/1     Completed   2          46hingress-nginx          ingress-nginx-controller-b966cf6cd-7kpzm     1/1     Running     1          46hingress-nginx          ingress-nginx-controller-b966cf6cd-ckl97     1/1     Running     0          46h

На узлах gw-1, gw-2:

sudo netstat -tnlp | grep -E ':(443|80)'tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      2661/nginx: master  tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      2661/nginx: master  tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      2661/nginx: master  tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      2661/nginx: master  tcp6       0      0 :::443                  :::*                    LISTEN      2661/nginx: master  tcp6       0      0 :::443                  :::*                    LISTEN      2661/nginx: master  tcp6       0      0 :::80                   :::*                    LISTEN      2661/nginx: master  tcp6       0      0 :::80                   :::*                    LISTEN      2661/nginx: master  

Можно постучаться на публичные адреса gw-1, gw-2 по 80-му порту и получить приветственную страницу Nginx. Далее, Вы можете использовать публичные адреса gw-1, gw-2 для создания записей DNS, использования в CDN и т.п.

Протестировать работу inress можно, создав сервис, на который Ingress будет проксировать трафик (взято отсюда) - echo1.yaml:

apiVersion: v1kind: Servicemetadata:  name: echo1spec:  ports:  - port: 80    targetPort: 5678  selector:    app: echo1---apiVersion: apps/v1kind: Deploymentmetadata:  name: echo1spec:  selector:    matchLabels:      app: echo1  replicas: 2  template:    metadata:      labels:        app: echo1    spec:      containers:      - name: echo1        image: hashicorp/http-echo        args:        - "-text=echo1"        ports:        - containerPort: 5678

Выполните данный манифест с помощью kubectl apply -f echo1.yaml. Теперь создадим правило Ingress (ingress-echo1.yaml):

apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata:  name: echo-ingressspec:  rules:  - host: echo1.example.com    http:      paths:      - backend:          serviceName: echo1          servicePort: 80

Выполним данный манифест kubectl apply -f ingress-echo1.yaml. Теперь, если на локальном компьютере в /etchosts внести запись для echo1.example.com:

127.0.0.1localhost127.0.1.1manager# The following lines are desirable for IPv6 capable hosts::1     localhost ip6-localhost ip6-loopbackff02::1 ip6-allnodesff02::2 ip6-allroutersX.Y.Z.C echo1.example.com

То можно получить проксирование трафика через Nginx Ingress. Проверим с помощью curl:

curl echo1.example.comecho1

Установка K8S Dashboard

Для установки Dashboard необходимо выполнить следующую команду:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml

Dashboard имеет ряд ограничений, например, он не работает через http, если обращение осуществляется не с localhost. В целом, не рекомендуется как-либо предоставлять доступ к Dashboard извне кластера через Ingress. Кроме того, Dashboard использует встроенную систему RBAC Kubernetes, поэтому требуется создать пользователя и дать ему права на Dashboard. Инструкция взята с этой страницы, здесь приводится для простоты восприятия.

Создадим аккаунт:

cat <<EOF | kubectl apply -f -apiVersion: v1kind: ServiceAccountmetadata:  name: admin-user  namespace: kubernetes-dashboardEOF

Определим роль пользователя:

cat <<EOF | kubectl apply -f -apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:  name: admin-userroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: cluster-adminsubjects:- kind: ServiceAccount  name: admin-user  namespace: kubernetes-dashboardEOF

Получим токен, с помощью которого пользователь сможет войти в Dashboard:

kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"

Если на вашей машине уже настроен kubect и есть $HOME/.kube/config, а сама машина "видит" k8s-cp, то вы можете запустить kubectl proxy и получить доступ к Dashboard по ссылке: http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/.

Если же ваша машина с браузером находится вне кластера, то переходим к следующему шагу, где мы настроим проброс API Kubernetes наружу через HAProxy.

Доступ к API K8S из внешней сети

На узлах gw-1, gw-2 необходимо установить haproxy. После установки измените конфигурационный файл /etc/haproxy/haproxy.cfg так, чтобы далее секции defaults он выглядел следующим образом:

defaults    # mode is inherited by sections that follow    mode tcpfrontend k8s    # receives traffic from clients    bind :6443    default_backend kubernetesbackend kubernetes    # relays the client messages to servers    server k8s k8s-cp:6443

Теперь вы можете обратиться к API K8S извне, указав в /etc/hosts своей локальной машины адрес gw-1 или gw-2 в качестве k8s-cp. Вам должны быть доступны с локальной машины все команды kubectl, включая kubectl proxy:

kubectl proxyStarting to serve on 127.0.0.1:8001

Можно открыть в браузере http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/ и насладиться видом приглашения авторизации Dashboard K8S:

Вводим токен, полученный с помощью:

kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"eyJhbGciOiJSUzI1NiIsImtpZCI6IlFkcGxwMTN2YlpyNS1TOTYtUnVYdsfadfsdjfksdlfjm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWd6anprIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJjM2RiOWFkMS0yYjdmLTQ3YTYtOTM3My1hZWI2ZjJkZjk0NTAiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.ht-RyqLXY4UzBnxIzJcnQn8Kk2iHWZzKVeAjUhKkJ-vOAtyqBu50rExgiRWsEHWfJp1p9xN8sXFKg62FFFbHWftPf6PmwfcBK2lXPy6OL9OaooP17WJVn75KKXIZHPWLO9VmRXPB1S-v2xFuG_J8jHB8pZHJlFjp4zIXfB--QwhrxeoTt5zv3CfXCl1_VYgCoqaxRsa7e892-vtMijBo7EZfJiyuAUQr_TsAIDY3zOWFJeHbwPFWzL_1fF9Y2o3r0pw7hYZHUoI8Z-3hbfOi10QBRyQlNZTMFSh7Z38RRbV1tw2ZmMvgSQyHa9TZFy2kYik6VnugNB2cilamo_b7hg

и переходим на главный экран Dashboard:

Вместо заключения

Как я писал в начале статьи, у меня уже есть опыт развертывания оркестраций на базе Docker, Apache Mesos (DC/OS), тем не менее, документация Kubernetes мне показалась сложной, запутанной и фрагментарной. Чтобы получить текущий результат я прошерстил довольном много сторонних руководств, Issue GitHub и, конечно, документацию Kubernetes. Надеюсь, что данное руководство поможет вам сэкономить свое время.

Подробнее..

Настраиваем Restic с systemd на Linux

31.01.2021 02:12:47 | Автор: admin

Restic хорошо известная программа для резервного копирования. Она достаточно проста, чтобы переноситься на любую ОС, и, вероятно, поэтому с ней не прилагается полноценный пример настройки на среднестатистической Linux-системе. Исправим это данным постом.


Поставим задачу следующим образом:


  1. Автоматический бэкап запускается ежедневно.
  2. Бэкап хранит только важные файлы и данные.
  3. Бэкап также включает в себя содержимое баз PostgreSQL, которое можно восстановить psql -f.

TL;DR поста

Пишем два юнита / таймера для systemd, запускаем restic под выделенным пользователем с CAP_DAC_READ_SEARCH, для PostgreSQL архивируем результат pg_dumpall.


Здесь предполагается, что бэкап производится на машине с Ubuntu Server 20.04 и выполняется на rest-server, работающий на 192.168.1.200. Тем не менее, конфигурация тривиально адаптируется к любому облачному провайдеру. Также предполагается, что репозиторий уже проинициализирован командой restic -r rest:http://192.168.1.200/your-repo/ init.


Бэкапим файлы/директории


Выполнять ПО с правами суперпользователя без особой надобности нежелательно, поэтому создадим для наших задач отдельного пользователя restic без группы и командной оболочки:


# useradd -m -N -s /usr/sbin/nologin restic

Нам понадобится следующий сервис systemd с параметром и таймер к нему:


/etc/systemd/system/restic@.service:


[Unit]# юнит активируется с параметром после @, то есть в#   systemctl start restic@your-repo.service# %I означает "your-repo"Description=Restic backup on %IAfter=syslog.targetAfter=network-online.target[Service]Type=oneshotUser=restic# читать список файлов к бэкапу будем из /etc/restic/your-repo.filesExecStart=/usr/local/bin/restic backup --files-from /etc/restic/%I.files# считаем репозиторий и пароль из /etc/restic/your-repo.envEnvironmentFile=/etc/restic/%I.env# выполняем restic с capability DAC_READ_SEARCH, дающей право# обходить права доступа ФС в Linux, это нужно для бэкапа# директорий, которые могут читать только другие пользователи# или суперпользовательAmbientCapabilities=CAP_DAC_READ_SEARCH[Install]WantedBy=multi-user.target

/etc/systemd/system/restic@.timer:


[Unit]# таймер, будучи запущенным с параметром после @# (restic@your-repo.timer), запустит restic@your-repo.serviceDescription=Run Restic at 12:00 AM[Timer]# запускаем restic ежедневно в 12 часов ночиOnCalendar=*-*-* 12:00:00[Install]WantedBy=timers.target

Адрес репозитория и пароль от него подаются на вход через файл с переменными среды в /etc/restic/your-repo.env. systemd читает их при старте юнита с правами root, поэтому имеет смысл задать разрешения директории /etc/restic/ соответствующим образом (т.е. 700 и владельцем установить root):


RESTIC_PASSWORD=your_repo_passwordRESTIC_REPOSITORY=rest:http://192.168.1.200/your-repo/

Нам также понадобится список файлов/директорий к бэкапу в /etc/restic/your-repo.files:


/var/lib/docker/etc/postgresql/etc/restic...

Бэкап PostgreSQL


Restic позволяет подачу данных для бэкапа через стандартный вход, так что мы можем скормить ему дамп, полученный pg_dumpall. Так как systemd запускает указанное директивой ExecStart вызовом execve(3), для использования перенаправления вывода и сжатия нам понадобится отдельный скрипт /usr/local/bin/pgdump.sh:


#!/usr/bin/env bashset -euo pipefail/usr/bin/sudo -u postgres pg_dumpall --clean \    | gzip --rsyncable \    | /usr/local/bin/restic backup --host $1 --stdin \        --stdin-filename postgres-$1.sql.gz

Сервис /etc/systemd/system/restic-pg@.service достаточно тривиален:


[Unit]Description=Restic PostgreSQL backup on %IAfter=syslog.targetAfter=network-online.targetAfter=postgresql.serviceRequires=postgresql.service[Service]Type=oneshotUser=resticExecStart=/usr/local/bin/pgdump.sh %IEnvironmentFile=/etc/restic/%I.env[Install]WantedBy=multi-user.target

Таймер /etc/systemd/system/restic-pg@.timer не отличается от виденного выше:


[Unit]Description=Run Restic on PostgreSQL at 12:00 AM[Timer]OnCalendar=*-*-* 0:00:00[Install]WantedBy=timers.target

Завершаем


Запустим таймеры и включим их автозагрузку:


# systemctl enable --now restic@your-repo.timer restic-pg@your-repo.timer

Проверим, работает ли построенная система:


# systemctl start restic@your-repo.service# systemctl start restic-pg@your-repo.service

Данный набор юнитов позволяет бэкапиться в неограниченное количество репозиториев, нужно лишь создать соответствующие /etc/restic/repo-name.{env,files}.


Ссылки


Подробнее..

Сколько CPU и RAM вам нужно, чтобы сделать бекап?

12.02.2021 10:14:08 | Автор: admin

Помните, как во второй половине 90-х один известный тогда профессор хрипло пел Бегут года, и грусть, печаль в твоих глазах, а я не знаю что тебе сказать. Так вот, года действительно бегут, а грусть-печаль в глазах из-за того, что гонка технологий уже достигла таких скоростей, что успеть за ними не может даже самый ловкий мангуст. Правда, некоторые вещи категорически отказываются меняться, и раз уж эта статья из блога компании, занимающейся бекапами, видимо, что-то не меняется в бекапах. А проблема, о которой хочется поговорить сегодня - это выбор сервера, который эти бекапы и будет делать. Все как-то привыкли думать только о размере стораджа, куда их предстоит складывать, а то, что процесс бекапа - это типичная задача обработки большого массива данных, которая жрёт RAM и CPU как не в себя, многие то ли забывают учесть, то ли по неопытности упускают этот момент. Так что сегодня учимся подбирать сервера для бекапов не только по размеру дисков. Или, как говорят зарубежные коллеги: backup server sizing best practices.

И да, в посте будет математика. Целых две формулы. Я предупредил.

Как и любое другое здравое современное приложение, Veeam Backup & Replication спроектирован таким образом, чтобы минимально загружать своему пользователю мозги и максимально эффективно справляться с поставленной задачей. На местах этот высокопарный посыл выражается в том, что независимо от масштаба вашей задачи устанавливается Veeam в три клика, ещё в пять делается первичная настройка и всё, полетели бекапы бекапироваться. Но как все мы отлично понимаем, это всего лишь радужная теория из мира с поняшками и бабочками. Ведь даже если самому приложению совершенно без разницы, бекапить ли ваш ноутбук на подключенный usb диск или гонять сотни терабайт снапшотов по FC фабрике (а ему действительно всё равно), то происходить это всё будет на вполне конкретном физическом железе, которому предстоит обработать все эти потоки данных. То есть, в то время, пока софтовая часть остаётся неизменной, архитектура решения в целом меняется до неузнаваемости.

Если скорость бекапа своего компа можно легко увеличить на порядок простой заменой USB 2.0 диска на USB 3.1, то имея задачу забекапить развесистую ферму серверов, да ещё и раскиданную по всему миру, можно столкнуться с тем, что в одном месте окажется слабый CPU, в другом процесс утыкается в объёмы доступной RAM, в третьем все ждут, когда контроллер дисковой полки соизволит записать очередную порцию данных, а в четвёртом так и вообще еле живой линк с внешним миром. Так что чем сложнее задача, тем проще и обиднее будет ошибиться с выбором любого из компонентов системы. И если за покупку слишком мощных серверов ругать вас не будут, то промашка в меньшую сторону скорее всего чревата большим числом неприятных разговоров в самом ближайшем будущем. Здесь - ты не поместился в бекапное окно, здесь - попытка сделать снепшот приводит к развалу кластера, а вот там просто нет ресурсов и придётся просить докупить новых железок. Так что тема планирования потребления CPU и RAM для бекапов не настолько и третьесортная задача, как к ней многие относятся.

Но прежде чем начать выписывать себе бюджеты на сотни CPU и тысячи гигабайт RAM, давайте освежим в памяти общую архитектуру Veeam Backup & Replication, чтобы точно не путаться в определениях и назначении компонентов.

  1. Сам VBR (Veeam Backup & Replication) сервер. Командный центр, оркестратор, ЦУП, разум улья, словом, называйте как хотите, но основная его роль - это синхронизация всех остальных компонентов и выдача команд на запуск разных увлекательных внутренних процессов, отслеживание расписания, и так далее. Технически ничего не мешает разместить вообще все компоненты на одной машине, и они даже будут работать. Однако такой сервер и ресурсов потребует соответствующих, и производительность его будет далека от совершенства. Так что лучше размещать всё остальное согласно назначению. Об этом ниже.

  2. База данных. Veeam - это классическое приложение, хранящее всю важную информацию в базе данных. Где и как вы расположите эту базу данных - его совершенно не волнует. Лишь бы до неё была связь и сервер стабильно работал. Хотите на одной машине с основной консолью? Пожалуйста! Для этого в установщике лежит Microsoft SQL Server 2016 SP2 Express Edition, который будет автоматически развёрнут и настроен самым лучшим образом. У вас уже есть своя инсталляция и вы хотите, чтобы база крутилась там? Без проблем! Просто укажите установщику адрес сервера и с какой учёткой туда идти. В процессе эксплуатации передумали и хотите перенести базу на другой сервер? Просто измените ключик в реестре или воспользуйтесь встроенной тулой. Всё для вас.

  3. Прокси сервер или просто прокся. Не знаю, почему когда-то давно было решено назвать их именно так, но точно знаю, что новичков это название иногда путает (именно путает, а не пугает). Но не будем искать виноватых, а просто зафиксируем, что прокси - это тот компонент инфраструктуры, который будет читать данные с бекапируемого объёкта и укладывать их в бекап. Это если упрощенно, потому что на самом деле данные будут сжиматься, дедуплицироваться, шифроваться, на их пути могут возникнуть другие прокси, нестабильные каналы связи и всякие хитрые хранилища. Не суть. Сейчас важно зафиксировать, что прокси - это то, что примет на себя основной удар по обработке данных. Они запускают пары data movers, один из которых что-то откуда-то читает, а второй что-то куда-то пишет. Чуете очевидную мораль? Чем ближе ваша прокся к бекапируемому объекту и чем ближе к ней хранилище бекапов, тем быстрее будет идти процесс. Но тут важно не увлекаться и помнить, что чудес не бывает. Ваши машины лежат на FC сторадже? Так будьте любезны и проксе предоставить FC подключение, иначе как ей данные получать? Ну не через managed интерфейс хоста же, ну честное слово. Хотя на самом деле с этой проблемой связана одна из самых частых ошибок при конфигурации - пользователь хочет, чтобы бекапы работали через Virtual Appliance, а работает через Network. Но не будем сейчас о грустном.

  4. Репозиторий. Он же бекапный сторадж. Может быть буквально чем угодно, к чему можно присоединиться, а ещё лучше, если там можно запустить наш дата мувер. Запустились на целевой системе - значит, можем контролировать процесс и часть операций проводить локально. Не можем запуститься на целевой системе - значит, приходится верить на слово, а каждый байт информации гонять взад-назад по сети. Так что во время любого синтетического трансформа бекапа, лежащего на сетевой шаре, ваша сеть будет вас ненавидеть. Поэтому Windows/Linux сервер - это твой бро, сетевые шары нет. Работать, конечно, будет, но медленно и не пойми как. Есть ещё целая россыпь вариантов вроде S3, дедуплицирующих систем и всяких специфических файловых систем вроде XFS, но это тема отдельного разговора. Просто помним, что репозиторий - это наше хранилище и гарант безопасного сна. Ну и особенно хорошо, если там можно запускать дата муверы.

  5. Enterprise Manager. Командир над командирами, в котором можно объединить управление несколькими VBR серверами и дать рядовым пользователям пользоваться частью функций через простенький веб-интерфейс. Например, можно выдать гранулярные права своему хелпдеску на восстановление определённых объектов на определённых машинах. Удалил пользователь письмо и корзину почистил, а хелпдеск ему хлоп - и вытаскивает это письмо из бекапа. Красота.

  6. И цифрой шесть давайте обозначим всё остальное, включая комбо-сервера, на которых крутится сразу по несколько ролей. Например, использовать один сервер в качестве и прокси, и репозитория - вполне нормальная идея, если серверу хватает ресурсов. Ну и помимо основных компонентов есть ещё целая россыпь вспомогательных: tape server, wan accelerator, cache repository и прочие gateway servers. Тут можно долго всё перечислять, тщательно объясняя, кто и зачем нужен, но мы здесь не за этим собрались. Лучше почитайте документацию, благо там всё очень понятно и подробно описано.

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

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

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

  1. Первым шагом будет проработка ваших RPO и RTO метрик, про которые уже было сказано очень много раз. Главное - запомнить основной посыл: не вы должны решать, с какой периодичностью делать бекапы и как быстро они должны восстанавливаться, а владельцы сервисов и те, кто называется на западе applications team. Вам надо собраться всех вместе и решить, для какого сервиса какой простой будет допустим и какой объём потерянных данных вы сможете пережить без того, что вас всех уволят, а компания закроется. Исходя из этого вы уже сможете построить вашу схему ротации бекапов, известную в англоязычной литературе как retention scheme.

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

  3. Посчитали свои терабайты? Отлично, теперь считаем, сколько у нас виртуальных машин/серверов. Совсем хорошо будет, если получится посчитать количество дисков на них, так как несколько дисков параллельно обрабатывать можно, а вот один в несколько потоков не получится. Соответственно, два диска по 500Гб забекапятся быстрее, чем один на терабайт, при прочих равных.

  4. Размер окна резервного копирования ака Backup window. Время, за которое должен состояться ваше бекап. Тут не всё так просто, как может показаться. Есть непосредственно бекап продакшена, который должен быть совершён вне времени основной офисной активности, чтобы не повлиять на сервисы. А есть некие побочные вещи, вроде бекап копи, синтетических трансформаций, записи бекапов на ленты и так далее. Если ваша инфраструктура резервного копирования находится на отдельном оборудовании и может спокойно заниматься своими делами, то вам повезло. Если нет, то ваша задача усложняется: надо, чтобы и сам бекап успел сделаться, и все последующие операции.

  5. И завершает наш парад вводных самая спорная метрика: сколько новых данных в день будет появляться на ваших серверах. Daily change rate, как называют на западе. К сожалению, тут нет единственно верного ответа, как посчитать этот параметр. Кто-то ограничивается примерными значениями, кто-то делает снапшоты и через сутки смотрит на их размеры. Вариантов много, и точного на сто процентов нет. Но вполне можно обойтись и средней температурой по больнице: для машин без высокой активности считается, что в день изменяется не более 5% диска, а в среднем по больнице принято считать, что 10% изменяющихся данных в день - это отличный показатель для дальнейших расчётов.

У пунктов 2 и 5 есть тонкий момент. Как вы прекрасно понимаете, требуемые мощности для того, чтобы успешно и вовремя забекапить весь прод, несколько отличаются от мощностей, необходимых для создания инкрементов. Иногда на порядок. То есть покупать супер-мощный сервер под прокси, который будет только раз в год (а вдруг вам достаточно) упаковывать все ваши петабайты за ночь, а все оставшиеся дни просто греть воздух, может статься и не очень разумным. Возможно, проще будет купить сервер в два раза меньше, но выделять под бекап не четыре часа, а восемь. Или вообще разбить процесс на несколько дней, делая полный бекап только части машин. Словом, момент тонкий и требует отдельного осмысления.

Зато теперь, когда у нас наконец-то есть все вводные данные, можно смело вооружаться калькулятором и начинать считать. При подсчётах мы будем исходить из того, что следуем рекомендациям VBR, и количество параллельно обрабатываемых тасок равно количеству имеющихся у процессора ядер. А одна таска - это один обрабатываемый диск. То есть если у нас на прокси CPU с четырьмя ядрами, то одновременно будут обрабатываться четыре диска с бекапируемых машин. И каждая таска, согласно всё тем же рекомендациям, для спокойной работы требует 2 Гб RAM.

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

Итак, берём вводные: у меня 640 Тб данных, я хочу делать Per-VM бекап (потому что могу), на бекап у меня есть 8 часов ночью, а мой change rate - классические 10%.

Шаг первый: делим объём данных на имеющееся время и получаем некую скорость обработки данных, которой нам надо достичь. В моём случае получается (640 Тб* 1024*1024)/(8 часов * 60* 60) = 23075 Мб/с - такова должна быть пропускная способность нашей системы.

Шаг второй. Пусть жизнь наша нелегка, и всё, что у нас есть - это сервера, которые могут выдать только 100 Мб/с. Делим желаемое на имеющееся и получаем 23075\100= 230. Округляем в большую сторону до 231. Получилось количество необходимых ядер. Да, блюстители размерностей и единиц измерений могут прибывать в ужасе от таких переходов, но куда деваться. Для примера давайте ещё представим, что наши сервера не настолько древние и от гигабита пропускной способности в обморок не падают. Получится, что нам вполне хватит 24 ядра. Более чем посильное число для современного оборудования.

На третьем шаге умножаем количество ядер на рекомендованные 2 Гб на таск и получаем 24*2 = 48 Гб RAM. Да в ноутбуки уже больше ставят, если честно. А вот у коллеги с более старым железом получится 2312 = 462 Гб RAM. Уже более интересное число, но чего только не сделаешь, дабы успеть забекапиться вовремя.

Затем просто делим это цифры на желаемое количество проксей, округляем в большую сторону и получаем искомые параметры. Повторюсь, никто не запрещает вам использовать хоть десять прокси, хоть один. Просто выдавайте им соответствующие ресурсы, и всё будет здорово. У вас по 12 ядер в сервере? Отлично, 231/12 = 20 серверов по 24 Гб оперативки в каждом. И так далее.

И вспоминаем нюанс с инкрементами. Мы договорились принять, что у нас будет меняться по 10% данных в день. Подставляем в наши формулы: (640 Тб*0,1% * 1024*1024)/(8 часов * 60* 60)= 2 331 Мб/c / 100 Мб/c = 24 ядра * 2 Гб RAM на таск = 48 Гб RAM. Значит, при прочих равных для инкрементальных бекапов нам будем достаточно двух серверов, по 24 гига оперативки в каждом.

Вот и вся математика. Как видите, никакой магии тут нет и всё считается довольно просто. Да, в своих подсчётах мы используем некую общую пропускную способность в вакууме, а не берём конкретные цифры по скорости сети, дисковых полок и так далее, но кто кроме вас знает вашу инфраструктуру, её слабые и сильные стороны?

На этом предлагаю на сегодня закончить. Мы рассмотрели только самых основных потребителей ресурсов, но если вам хочется узнать подробности про каждый аспект (база данных, сам VBR, сколько ресурсов нужно для побочных процессов и так далее), то недавно мой коллега Tim Smith целый час рассказывал про это на своё вебинаре. Крайне рекомендую к просмотру всем интересующимся темой, так как там всё разобрано действительно до костей.

Подробнее..

Продолжаем прокачивать Ansible

22.02.2021 06:06:33 | Автор: admin

Поводом для этой статьи послужил пост в чате @pro_ansible:

Vladislav ? Shishkov, [17.02.21 20:59]Господа, есть два вопроса, касаются кастомной долгой операции, например, бекапа: 1. Можно ли через ансибл прикрутить прогрессбар выполнения кастомного баша? (если через плагин, то пните в какой-нибудь пример или документацию плиз) 2. Вроде хочется для этого баша написать плагин, но встает вопрос, как быть и как решать моменты выполнения, которые идемпотентны?

Беглый поиск по задворкам памяти ничего подходящего не подсказал. Тем не менее, я точно вспомнил, что код Ansible легко читаемый, и искаропки поддерживает расширение как плагинами, так и обычными Python-модулями. А раз так, то ничего не мешает в очередной раз раздвинуть границы возможного. Hold my beer!...

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

Исходный вопрос можно свести к двум простейшим шагам:

  1. Захватить stdout команды на целевом хосте

  2. Передать его на управляющий хост.

Передаём данные на управляющий хост

Предлагаю начать с конца: с организации дополнительного канала передачи на управляющий хост. Решение этого вопроса выглядит достаточно очевидным: вспоминаем, что Ansible работает поверх ssh, и используем функцию обратного проброса порта:

Код на Python
# добавляем куда-нибудь сюда:# https://github.com/ansible/ansible/blob/5078a0baa26e0eb715e86c93ec32af6bc4022e45/lib/ansible/plugins/connection/ssh.py#L662self._add_args(    b_command,    (b"-R", b"127.0.0.1:33333:" + to_bytes(self._play_context.remote_addr, errors='surrogate_or_strict', nonstring='simplerepr') + b":33335"),    u"ANSIBLE_STREAMING/streaming set")

Как это работает? При сборке аргументов командной строки для установления ssh-соединения эта конструкция предоставит нам на целевом хосте порт 33333 по адресу 127.0.0.1, который будет туннелировать входящие соединения на контроллер - прямиком на порт 33335.

Для простоты используем netcat (ну правда, ну что за статья без котиков?): nc -lk 33335.

В этот момент, кстати, уже можно запустить Ansible и проверить, что туннель работает так, как следует: хотя пока по нему ничего и не передаётся, мы уже можем на целевом хосте зайти в консоль и выполнить nc 127.0.0.1 33333, введя какую-нибудь фразу и увидев её как результат работы команды выше.

Перехватываем stdout

Полдела сделано - идём дальше. Мы хотим перехватить stdout какой-то команды - по логике работы Ansible нам подойдёт модуль shell. Забавной, что он оказался пустышкой - в нём ни строчки кода, кроме документации и примеров, зато находим в нём отсылку к модулю command. С ним всё оказалось хорошо, кроме того факта, что нужная функция в нём напрямую не описана, хотя и использована. Но это уже было почти попадание в яблочко, потому что в итоге она нашлась в другом файле.

Под мысленное просто добавь воды просто добавляем щепотку своего кода:

Опять код
# в начале basic.py, рядом с прочими import'ами import socket# в функции run_command - где-нибудь тут:# https://github.com/ansible/ansible/blob/5078a0baa26e0eb715e86c93ec32af6bc4022e45/lib/ansible/module_utils/basic.py#L2447clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM);clientSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)clientSocket.connect(("127.0.0.1",33333));# в функции run_command - где-нибудь тут:# https://github.com/ansible/ansible/blob/5078a0baa26e0eb715e86c93ec32af6bc4022e45/lib/ansible/module_utils/basic.py#L2455clientSocket.send(b_chunk);# в функции run_command - где-нибудь тут# https://github.com/ansible/ansible/blob/5078a0baa26e0eb715e86c93ec32af6bc4022e45/lib/ansible/module_utils/basic.py#L2481clientSocket.close()

Собираем воедино и запускаем

Осталось сделать что? Правильно, определиться со способом подключения изменённых модулей в стоковый Ansible. На всякий случай напоминаю: мы поправили один connection plugin, и один модуль из стандартной библиотеки Ansible. Новичкам в этом деле могу рекомендовать статью хабраюзера chemtech с расшифровкой моего доклада на Стачке-2019 (там как раз в том числе объясняется, какие Python-модули куда складывать), ну а опытным бойцам эти пояснения вроде и не нужны :-)

Итак, время Ч. Результат в виде статичной картинки не очень показателен, поэтому я настроил tmux и запустил запись скринкаста.

Для внимательных зрителей скринкаста

В анимации можете увидеть два полезных побочных эффекта:

  • Теперь мы видим stdout всех не-Python процессов, которые запускаются Ansible'ом на целевом хосте - например, тех, что запускаются при сборе фактов;

  • Настройки переиспользования ssh-соединений из другой моей статьи позволяют получать этот самый stdout от удалённой команды уже после отключения Ansible от хоста.

Хотите ко мне на тренинг по Ansible?

Раз уж вы здесь - значит, вам как минимум интересно то, что я пишу об Ansible. Так вот, у меня есть опыт ведения такого тренинга внутри компании для коллег.

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

Подробнее..

Рамка (граница) окон в windows 10 и server 2016

25.02.2021 18:11:56 | Автор: admin

Наверно я не один такой, кто столкнулся с проблемой отсутствия границ окон в новых системах windows, ведь зачем-то их убрали с одним из обновлений. Спрашивают многие, а вот ответа нет однозначного нигде. С данной неожиданной неприятностью легко справиться, сменив руками настройки системы, а если это терминальный сервер и пользователей много? По умолчанию, пользователям выставляется наилучшее быстродействие, что отключает тени, в придачу по умолчанию в системе отключены границы окон, что приводит к полному сливанию окон друг с другом, в итоге невозможно отличить где кончается одно и начинается другое окно. Когда я решил централизованно решить эту проблему для всех пользователей, оказалось что найти решение не так уж и просто, поскольку нет ни одного ответа в интернете, дающего однозначное решение. В итоге перелопатив весь RU и EN сегменты сети, перепробовав разные варианты, я решил проблему. Если вас беспокоит та же проблема, прошу под кат.

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

Итак, вы имеете ситуацию как на картинке выше. Ваш путь лежит в редактор GPO, где надо сделать манипуляции, согласно следующей картинке:

Добавив данные изменения, требуется перезагрузка. Войдя в систему, появятся рамки и стандартные цвета системы:

В общем-то, на этом все, вы успешно избавились от безрамья и мелкомягкой, весьма странной "фичи".

Подробнее..

Блеск и нищета Virtual Tape Library

02.03.2021 10:09:04 | Автор: admin

VTL (они же Virtual Tape Library, если по паспорту) можно назвать одним из самых странных порождений IT индустрии. Родившись в эпоху расцвета ленточных накопителей как классический софтовый эмулятор настоящего железа, многими они были восприняты как ответ на главный вопрос жизни (Вселенной и всего такого), и теперь одни умудряются продавать их за деньги, а другие использовать в проде и считать, что всё нормально.

Я не буду кричать что первые плохие, а вторых надо гнать из профессии. Нет. Я только лишь предлагаю трезво взглянуть на суть VTL.

А в чём проблема?

Чтобы разобраться с вопросом о легитимности использовании VTL, давайте вспомним, зачем вообще нужны ленты. Это самое дешёвое, не самое быстрое, зато физически отчуждаемое устройство для хранения информации. Про дешевизну можем говорить, если посчитаем цену условного терабайта хранения. Прямо сейчас LTO-8 лента в режиме сжатия способна принять на себя 30 Терабайт данных, при цене около 9000 рублей. Для объективности можно даже откинуть маркетологов с их сжатием и записать только честные, физически наносимые 12,8 Тб. Для сравнения, за те же деньги можно взять SSD на один терабайт или обычный HDD на четыре. А тут сразу 12,8. Или даже 30, если повезёт. Да, для ленты ещё нужен привод, а лучше даже библиотека с роботом ценой в несколько сотен тысяч рублей, но там, где есть приличные объёмы данных, для которых встаёт вопрос о хранении на протяжении многих лет, это всё-таки дешевле, чем закупать дисковые полки и заниматься их обслуживанием.

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

И, конечно же, помним про возможность простого физического отключения. Вставили ленту в привод, записали на неё что-то, привод ленту выдал обратно, вы её убрали подальше, и голова ваша не болит. Лента лежит, собирает пыль, и ничего с ней не происходит. Диски так не умеют. Даже если и хочется вынуть диск сервера и убрать на полку, то придётся разбирать корпус и вырубать весь сервер. Если это дисковая полка, то корпус разбирать не придётся, но насиловать не рассчитанные на постоянное туда-сюда разъёмы тоже не очень хочется. А вот лентам для счастья ничего не надо. Ни электричества, чтобы постоянно крутить шпиндель, ни страха перед разболтавшимися разъёмами.

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

Все эти прекрасные особенности давно заприметили разного рода регулирующие гос.органы примерно всех стран. Если вы не знали, то есть довольно много компаний, от которых на законодательном уровне требуется хранить разного рода информацию по многу лет. Спросите, например, медиков, банки, страховщиков и так далее. Вам могут рассказать массу увлекательных историй про то, как они вынуждены обеспечивать сохранность данных своих клиентов на протяжении лет десяти-пятнадцати. Вы же не думаете, что кто-то в здравом уме будет покупать дисковую полку, задача которой будет заключаться в простаивании 99% времени? Да и диски придётся поменять не один раз за эти десять лет. Поэтому не только зарегулированные, но и обычные компании, где решили заняться архивным хранением, давно пришли к выводу, что ленты и только ленты.

Но есть тут один нюанс, который объяснит нам причины появления VTL почти тридцать лет назад. Представьте, что ваше основное боевое хранилище это дорогущий SAN, сделанный с использованием самых последних технологий своего времени. И вдруг выясняется, что к этому FiberChanel монстру надо подключить ленточную библиотеку по страшному и медленному SCSI интерфейсу. Полученная скорость работы вызовет у вас депрессию, не извольте сомневаться. И вот, после недельного запоя у вас появляется светлая мысль: А может ну их, эти ленты?. Но потом вы вспоминаете, что это Ну их может стоить многих денег вашей компании в виде штрафов от регулятора. Ну и весёлых приключений лично вам, если звёзды сойдутся особенно удачно. Поэтому у вас рождается очень хитрый план: а давайте вместо лент мы будем использовать всё те же диски, а чтобы рисовать красивые отчёты, мы напишем эмулятор, который будет подключаться к нашему софту, отвечающему за резервные копии, и будет тщательно кивать головой на все его команды к лентам.

И на тот момент это сработало. Появились эмуляторы, функциональность которых находилась на уровне архиватора: упаковать файлы в свой формат и радостно отчитаться по SCSI (или любому другому) порту о том, что ленточка старательно записана, робот её вынул и даже положил вот в такой вот слот в своей библиотеке. Самое натуральное переливание из пустого в порожнее под флагом имитации бурной деятельности. Но дабы не только ругать VTL на чём свет стоит, стоит всё же упомянуть и про их плюсы. Самый главный, действительно, это всё ещё скорость. Если вам совсем некуда девать деньги и ваш VTL пишет свои файлы на SSD, то вы победитель по жизни. Но если с деньгами не настолько всё хорошо, а весь фронт работ это записать буквально десяток плёнок, то диски будут дешевле, как ни крути. Если не верите, то просто посмотрите, сколько стоят современные LTO приводы. Ну и вишенка на торте - нет необходимости перематывать кассету на нужное место. Читай сразу откуда хочешь.

Поэтому главное что хочется сказать - не обманитесь заманчивыми плюсами VTL. Буква V значит Virtual, а все преимущества(и недостатки) лент исходят из их физической природы. Так что VTL может принести вам только моральное удовлетворение, но никак не решить задачу недорогого хранения отчуждаемых бекапов на случай аварии. Да и смысл интеграции с бекапным софтом уже давно пропал из-за наличия встроенных функций для перекладывания бекапов из одной корзины в другую. Например, в Veeam эта функция называется Backup Copy. Пользуйтесь на здоровье.

Да, есть ещё так называемые D2D2T системы, где VTL используется в виде кеша, а потом готовые файлы просто записываются на ленты. Правда, сейчас их будет правильнее называть D2D2C, где C это Cloud.

Препарируем VTL

Ну ладно, раз VTL это идеальная лаба, чтобы ознакомиться с функционалом ленточного бекапа, давайте таки развернём эту лабу и попробуем записать наши бекапы на ленту, хоть и виртуальную. Я долго выбирал между более хардкорным MHvtl и QUADstor с его симпатичным GUI, но в итоге остановился на втором исключительно из-за большей его популярности. Хотя оба проекта бесплатные и обеспечивают плюс-минус одни и те же функции. А производить все манипуляции я буду на CentOS.

Первым делом, конечно же, yum update && yum upgrade и ставим все необходимые пакеты:

yum install httpd gcc perl sg3_utils kernel-devel

Наверняка большая часть этих пакетов и так уже стоит, но вдруг вы такой же маньяк и начинаете с CentOS minimal. Также рекомендуется проверить, что установленные версии ядра и тулзов совпадают, а то в наших планах QUADstor компилировать, и лишние проблемы нам ни к чему. Так что сравниваем выводы uname -r и rpm -qa | grep kernel-devel

[root@centos ~]# uname -r3.10.0-1160.15.2.el7.x86_64[root@centos ~]# rpm -qa | grep kernel-develkernel-devel-3.10.0-1160.15.2.el7.x86_64

Если у вас циферки разошлись, то спасаемся yum upgrade kernel и ребутом.

С подготовкой закончено, и мы можем полноценно переходить к установке подопытного. В стандартных репозиториях его нет, поэтому на помощь нам приходит wget и официальный сайт. На момент февраля 2021 у меня получилось вот так:

wget https://quadstor.com/vtldownloads/quadstor-vtl-ext-3.0.51-rhel.x86_64.rpm

Теперь идём в директорию, куда скачался файл (если она у вас не стандартная), и устанавливаем пакет. Внимание: я это делают в чисто лабораторных целях и условиях, поэтому поэтому могу себе позволить делать всё от рута. А вы нет! Делайте все с правами рядового пользователя.

rpm -ivh quadstor.rpm

На что я получил отлуп по зависимостям (ох уж эти CentOS minimal)

rpm -ivh quadstor.rpmerror: Failed dependencies:libcrypto.so.10()(64bit) is needed by quadstor-vtl-ext-3.0.51-rhel.x86_64libcrypto.so.10(libcrypto.so.10)(64bit) is needed by quadstor-vtl-ext-3.0.51-rhel.x86_64libssl.so.10()(64bit) is needed by quadstor-vtl-ext-3.0.51-rhel.x86_64

Ладно, мы не гордые, идём и ставим compat-openssl10, так как это всё его библиотеки. И повторяем установку, которая в этот раз завершается успехом за пару минут, и мы становимся обладателями QUADstor, mini PostgreSQL сервера, где будут храниться данные конфигурации, и небольшого Apache Web Server для Web-GUI. Хотя никто не запрещает и дальше всё делать через консоль, но мы пойдём по более наглядному пути. Только перед этим нам надо запустить веб сервер и проверить, запустился ли демон VTL.

systemctl enable httpdservice httpd start/etc/rc.d/init.d/quadstorvtl start

Также установщик вас предупредит, что если хочется работать по FC, то надо обязательно перезагрузиться для корректной установки драйверов. Но в наши планы входит исключительно iSCSI, так что храним аптайм. На этом с консолью действительно всё, и мы можем открывать в любимом браузере WebGUI по IP нашей машины.

Первым делом надо зайти в Physical Storage и выбрать диски для работы. По умолчанию QUADstor выбирает первый диск, который обнаруживает. Читай, диск с системой. У меня на скриншоте виден второй диск, подключённый к этой виртуалке, так что смело выбираю его кнопкой Add.

Сразу предложат добавить этот диск в один из Storage Poolов, которые надо создать заранее. Это некая логическая единица для смыслового объединения лент по какому-то признаку. Как видите, ничего супер-необычного здесь нет, весь джентльменский набор: дедупликация для экономии места, WORM кассеты и репликация кассет. Но нам сейчас это всё не так интересно, поэтому ограничимся стандартным пулом.

Но самое интересное находится в секции Virtual Libraries. Здесь мы выбираем, хозяина какой именно железки мы будем из себя изображать. А то и нескольких сразу, ведь кто нам запретит? Так уж сложилось, что душой я за HP, поэтому хотел выбрать себе HP MSL 6000 с двумя приводами Ultrium 6250, но потом передумал и для наглядности выбрал ветерана ленточных боев - ESL 9000.

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

На этом с настройкой VTL всё, и хочется перейти в интерфейс Veeam, дабы скрестить его с библиотекой. Однако мы не ищем лёгких путёй и подключим библиотеку к другой Windows машине, которая будет работать у нас в качестве Tape Server. Для чего заходим на этот сервер, запускаем iSCSI сервис и iSCSI инициатор. Там находим нашу библиотеку любым из доступных способов и подключаемся к ней. По умолчанию будет использоваться порт 3260, так что может потребоваться добавить соответствующее правило на вашем фаерволе.

Тут наступает важный момент: надо обязательно открыть Device Manager и посмотреть как определились новые устройства. Крайне рекомендуется поставить драйвера, чтобы избежать проблем при работе с библиотекой. Veeam использует стандартные системные вызовы, поэтому если система может работать с библиотекой, Veeam тоже будет работать. А нет драйверов - нет мультиков. Так что если у вас старьё вроде того, что я добавил в свою лабу, система сама всё поставит. Если что-то новое, то качайте с сайта производителя. Технически, Veeam может работать и с универсальным Microsoft Tape Format (MTF), но оригинальные драйвера всегда в приоритете.

И теперь (наконец-то) можно идти на сервер Veeam и открывать вкладку Tape Infrastructure. Где первым делом запустим мастер добавления Tape Server.

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

Если всё было сделано правильно, то Veeam начнёт бодро двигать туда-сюда кассеты, проверяя и внося их в свой стандартный медиа пул.

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

Но мы отвлеклись, так что давайте вернёмся в Veeam и проверим, что всё добавилось верно.

Как мы видим на скриншоте, библиотека определилась верная, приводы на месте, а количество кассет совпадает с заданным. Все кассеты находятся в медиа пуле Free, так как мы провели инвентаризацию. Если её пропустить, то все неизвестные ленты попадут в пул Unrecognized. Можно принимать поздравления, ибо всё действительно работает как и должно.

Давайте же тогда посмотрим, как бекапы находят своё пристанище в недрах ленточных приводов! На самом деле про это уже были исчерпывающие посты от моих коллег. Вот этот и вот тот. Поэтому я здесь пробегусь по самым верхам, дабы не переписывать уже написанное.

Итак, запускаем мастер Backup to Tape, задаём имя джобе и на втором шаге добавляем бекап, который хотим хранить на ленте. Технически можно добавить не просто бекап, а хоть целый репозиторий с бекапами, но мы такого делать не будем. Просто берём один красивый бекапчик.

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

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


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

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

Ну а почему бы и нет? Имею право на мечты! Разве не для этого были придуманы VTL решения?

И на последок, ловите ссылку на раздел документации посвящённый работе с ленточными девайсами. Скорее всего там вы найдёте ответы на все свои вопросы.

Подробнее..

CentOS 7 и контроллер HPE B320i

17.02.2021 18:10:52 | Автор: admin

Понадобилось на днях установить старенький CentOS 7 на старенький ProLiant 360e Gen8. Задача уже экзотическая, но мало ли - вдруг кому пригодится, Maintenance updates для 7-ки обещаны еще до июня 2024, и gen8 еще могут послужить. Сперва опишу проблему, далее будет пошаговое руководство.

Intro

Итак, имеем CentOS/RHEL 7 и ProLiant Gen8 с Dynamic Smart Array B120i/B320i SATA RAID Controller. B120i и B320i очень похожи, отличаются количеством поддерживаемых физических дисков (6 и 8 соответственно) и опциональной поддержкой SAS дисков с дополнительной лицензией в B320i. Контроллеры являются "облегченными" и без проприетарного драйвера не работают, в отличие от полноценных Smart Array (без Dynamic). Руководство применимо ко всем моделям с этим контроллером.

Проблема описана на в статье Is the HP Smart Array B320i, B140i, B120i, B110i controller supported by RHEL or RHELOSP сайте Red Hat.

Issue: Some of the HP Gen8 and Gen9 systems are shipping with either a Smart Array B320i, B140i, B120i, B110i, or other Bxxxi controller that requires a closed source driver to make RAID functionality available to the OS.

Выхода здесь два:

  • переключить контроллер в SATA режим и собрать массив программно средствами ОС;

  • предоставить драйвер программе установки ОС.

Подробности есть в документе HP Dynamic Smart Array B120i and B320i Controllers - Driver Support and Configuration на сайте HPE, здесь же есть о переключении режима контроллера. Документация - QuickSpecs и User Guide для Dynamic Smart Array Controllers.

Нам же интересен 2-й вариант. Контроллер есть, уже куплен - надо использовать! Из очевидных плюсов - простота, никаких дополнительных шагов для загрузчика, boot раздела и т.д.

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

Пошаговое руководство.

  1. Загрузить тот самый драйвер. HPE Dynamic Smart Array B120i/B320i SATA RAID Controller Driver for Red Hat Enterprise Linux 7 (64-bit).

  2. Перейти в папку с загруженным файлом, распаковать его и изменить расширение на iso:
    $ gunzip hpvsa-1.2.16-136.rhel7u8.x86_64.dd.gz && \
    mv hpvsa-1.2.16-136.rhel7u8.x86_64.dd hpvsa-1.2.16-136.rhel7u8.x86_64.iso

  3. Создать образ флоппи-диска (шаг можно пропустить при наличии физического доступа к машине, записав iso-файл на отформатированный в fat32 USB-накопитель):
    $ mkfs.msdos -C hpvsa.rhel7.floppy.img 1440
    $ mkdir /tmp/hpvsa.rhel7.floppy
    $ sudo mount -o loop hpvsa.rhel7.floppy.img /tmp/hpvsa.rhel7.floppy
    $ sudo cp hpvsa-1.2.16-136.rhel7u8.x86_64.iso /tmp/hpvsa.rhel7.floppy
    $ sudo umount /tmp/hpvsa.rhel7.floppy
    $ rm -r /tmp/hpvsa.rhel7.floppy

  4. Подключаем в iLO Remote Console образы дистрибутива и флоппи-диска с драйвером, загружаемся с загрузочного диска, F11 Boot Menu.

  5. В параметры загрузчика дописываем (по нажатию Tab):
    (Прим.: в 5 и 6 было linux dd blacklist=ahci с добавлением vmalloc=384M для 32-битных ядер)
    modprobe.blacklist=ahci inst.dd

    Добавление параметров ядраДобавление параметров ядра
  6. Выбираем драйвер:

    Выбор драйвераВыбор драйвера
  7. Продолжаем обычную установку.

На этом все. К сожалению, не удалось найти действующий репозиторий с модулями ядра, чтобы автоматически поддерживать его актуальность. Последний в репозиториях - старый rhel7u5.

Дополнение

Для работы с контроллером и массивом непосредственно из ОС можно установить программу Command Line Smart Storage Administrator - ssacli.

  1. Импортируем публичный ключ HPE:
    rpm --import https://downloads.linux.hpe.com/SDR/hpePublicKey2048_key1.pub

  2. Создаем репозиторий

    vim /etc/yum.repos.d/mcp.repo
    [mcp] name=Management Component Pack
    baseurl=http://downloads.linux.hpe.com/repo/mcp/centos/$releasever/$basearch/current/
    enabled=1
    gpgkey=file:///etc/pki/rpm-gpg/GPG-KEY-mcp

  3. Установка:
    yum install amsd ssacli

  4. Использование:
    ssacli help

    Пример получения списка физических дисковПример получения списка физических дисков
Подробнее..

Почему линукс использует swap-файл

03.02.2021 02:16:03 | Автор: admin

Жажда тюнинга может завести в неведомые дебри. И, пожалуй, едва ли не самая частая неправильная оптимизация отключение swap-файла. Если прикинуть частоту, с которой эта ошибка встречается, то, наверное, она входит в негласный top-10 (а может и top-5) самых распространенных, самых бесполезных и самых вредных оптимизаций - потому что swap-файл это одна из самых интересных, сложно понимаемых и недооцененных сущностей в подсистеме управления виртуальной памятью.

Эта статья является обзорной и предназначена для того, чтобы дать представление об общих процессах, происходящих в системе, и объяснить, откуда берутся некоторые мифы, следование которым может доставить неприятные моменты

В начале был вопрос

Когда возникает необходимость в swap-файле? Самый частый ответ когда не хватает памяти. И, естественно, это ответ неправильный почти полностью. Правильный ответ - необходимость в использовании swap-файла возникает тогда, когда система не может удержать в памяти необходимый кэш и грязные страницы. А чтобы понять, что это значит, нам надо сделать маленький экскурс внутрь ядра операционной системы.

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

И когда процесс пытается получить доступ к какой-то странице своей памяти, MMU (memory management unit) процессора фактически производит обращение к той странице физической оперативной памяти, куда страница отображена.

А если страница не отображена ни в какую физическую страницу, то возникает page fault исключительная ситуация страница не найдена. При обработке этой ситуации система (ядро) проверяет, имеет ли процесс право получить доступ к своей логической странице: если не имеет (например эта страница заразервирована ядром или находится за хвостом кучи процесса) - то процессу придет сигнал SEGFAULT и процесс умрет.

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

Какие группы страниц памяти живут в системе?

Страницы физической памяти

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

  • Используемая страница, хранящая данные, не принадлежащие кэшу

  • Страница анонимного кэша (anonymous page cache) страница числится как принадлежащая кэшу, но не закрепленная ни за каким файлом. Очень похожа на используемую страницу (и в определенных ситуациях может превращаться в неё)

  • Чистая страница кэша (clean cache page)- страница, в которой хранятся закэшированные данные файла, которые не менялись.

  • Грязная страница кэща (dirty cache page) страница, в которой хранятся данные файла, которые были изменены (данные в кэше поменяли но на диск изменения не сохранили)

Страница процесса, в свою очередь, также может иметь несколько состояний

  • Недоступная процесс не имеет права на доступ к этой странице. Если процесс к ней обращается "неподобающим образом" то получает SEGFAULT

  • Доступная, сопоставленная физической странице, не принадлежащей кэшу. Процесс может работать с этой страницей

  • Доступная, сопоставленная физической странице кэша, в которую загружены данные файла. Процесс может работать с этой страницей.

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

И сейчас, когда мы более-менее определились с видами страниц, мы переходим к самой интересной части

Работа процесса

Чтобы понять как все эти механизмы связаны и работают, давайте рассмотрим запуск нового процесса. Мы запускаем новый процесс, и система загружает исполняемый файл. Как это происходит?

Система открывает бинарный файл с программой и Нет, она не читает его. Она отображает файл в адресное пространство процесса то есть создает записи (например)

  • Страница 0 ... 15 -> /usr/bin/filename сегмент 0 ... 65535

  • Страница 16 ... 31 -> /usr/bin/filename сегмент 65536 ... 131071

Ну да, там всё сложнее но нам сейчас главное понять идею.

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

MMU обнаруживает ошибку странице процесса не сопоставлена никакая физическая страница - ошибка, page fault! Ядро получает эту ошибку, смотрит на статус страницы:

  • процессу разрешен доступ

  • физической странице не сопоставлена (и это логично, иначе бы page fault не возник)

  • но сопоставлена сегменту файла

  • указанный фрагмент файла в кэше не обнаружен

В указанной ситуации, ядро берет свободную страницу, объявляет её страницей кэша и загружает в неё данные из файла с диска. Теперь это чистая страница кэша - clean page. Затем ядро добавляет ссылку этой странице процесса сопоставлена эта физическая страница, принадлежащая кэшу и взятая из указанного места файла. Управление возвращается процессу, а проблемная операция завершается успешно. Ну а если это была операция модификации данных (и модификация допустима), то после записи данных страница помечается как измененная и становится грязной страницей кэша - dirty page с точки зрения ядра.

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

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

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

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

Откуда (и когда) начинается использование swap-файла?

Представим, что мы загрузили с большой бинарник с большим количеством библиотек (привет, браузер!) в котором открыли сколько-то вкладок с документами, и исчерпали доступную физическую память. При этом, у нас образуется две больших группы страниц чистые страницы кэша, сопоставленные разделяемым библиотекам причем в этих страницах содержится использующийся код (мы ведь помним про то, что библиотеки загружаются по мере необходимости) и приватные страницы процесса или страницы anonymous page cache (этот механизм часто используется для предварительной аллокации памяти). Но, в обоих случаях, мы можем рассматривать их как данные процесса.

Свободных страниц у нас нет всё ушло на кэш и данные.

Теперь мы открываем еще одну вкладку, что при этом случается? Чтобы найти память, система вынуждена освободить часть чистых страниц кэша и отдать их под данные приложения ведь данные которые там лежали, можно снова загрузить с диска (это ведь "чистые" страницы!).

Но в этих страницах был ИСПОЛЬЗУЕМЙ код иначе бы они не подтянулись в кэш.

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

То есть фактически, в системе уже есть swap-файл, из которого постоянно ведется чтение и это разделяемые библиотеки. Но система не может использовать его эффективно, поскольку он ограничен и фактически неуправляем - и скатывается в трэшинг

А если бы у нас был настоящий swap-файл?

На основе учета частоты обращения к различным страницам, система скорей всего не освободила бы страницу с кодом, а поместила в swap данные наиболее давно не использовавшихся вкладок. И вместо постоянного чтения с диска, у нас случились бы одна запись и одно чтение причем именно в момент обращения к выгруженной в swap вкладке.

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

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

А если swap-файл маленький, то начинается веселье с постоянным записью-чтением в swap-файл.

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

Какие выводы можно сделать из всего вышеописанного?

Кэш (page cache) это не только кэш данных! Кэш - это очень существенный компонент в схеме организации виртуальной памяти - и теперь мы понимаем неправильность вопроса почему система ушла в свал а не освободила кэш. Ведь ответ очень прост - этот кэш на самом деле не просто кэш, а код. И если код используется чаще, чем данные - то в данном случае более важно сохранить в памяти код (сохранить кэш) чем удерживать в памяти данные!

Поэтому не надо бояться наличия swap-файла если статистика не покажет необходимости - система не полезет в свап.

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

Малый размер swap-файла вреден он не позволяет системе работать эффективно, поскольку увеличивает объем непродуктивного I/O

Резюме?

Это прекрасно, когда объем оперативной памяти достаточно велик, чтобы вместить и весь необходимый кэш, и данные. Но если у вас бюджетная система с8 16ГБ оперативной памяти (не говоря уж об ультрабюджетных ноутбуках с распаянными и нерасширяемыми 4GB), то swap достаточного объема (не менее 1 x ) это "то, что доктор прописал".

И достаточный размер swap-файла на быстром накопителе (кто сказал NVMe?) на бюджетном ноутбуке может очень хорошо увеличить производительность системы, особенно если вы любитель держать много открытых вкладок, документов, рисунков в графическом редакторе и т.д.

Не мешайте системе работать. Нет нужды бояться swap-файла. Если он не нужен он не будет использован. И то, что вы видите, что он якобы использован - на самом деле совсем не значит, что он использован. Просто нам показали картинку без подробностей.

Подробнее..

Почему линукс использует swap-файл, часть 2

07.02.2021 16:04:25 | Автор: admin
Первая часть маленького срывания покрова о работе подсистемы виртуальной памяти, связи механизмов mmap, разделяемых библиотек и кэшей вызвало такое бурное обсуждение, что я не смог удержаться от того, чтобы не продолжить исследование на практике

Поэтому, сегодня мы сделаем Крошечную лабораторную работу. В виде крошечной же программы на C, которую мы напишем, скомпилируем и проверим в деле со свапом и без свапа.

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

А вызов кода из этой библиотеки мы просто эмулируем чтением из такого mmap-нутого файла.

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

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

  • MEM_GBYTES размер оперативной памяти для теста
  • LIB_GBYTES размер кода

Объем данных у нас меньше объема физической памяти:

  • DATA_GBYTES = MEM_GBYTES 2

Суммарный объем кода и данных чуть больше объема физической памяти:

  • DATA_GBYTES + LIB_GBYTES = MEM_GBYTES + 1

Для теста на ноутбуке я взял MEM_GBYTES = 16, и получил следующие характеристики:

  • MEM_GBYTES = 16
  • DATA_GBYTES = 14 значит данных будет 14GB, то есть памяти достаточно
  • Swap size = 16GB

Текст программы


#include <sys/mman.h>#include <fcntl.h>#include <string.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#define GB       1073741824l#define MEM_SIZE    16#define LIB_GBYTES   3#define DATA_GBYTES   (MEM_SIZE - 2)long random_read(char * code_ptr, char * data_ptr, size_t size) {long rbt = 0;for (unsigned long i=0 ; i<size ; i+=4096) {rbt += code_ptr[(8l * random() % size)] + data_ptr[i];}return rbt;}int main() {size_t libsize = LIB_GBYTES * GB;size_t datasize = DATA_GBYTES * GB;int fd;char * dataptr;char * libptr;srandom(256);if ((fd = open("library.bin", O_RDONLY)) < 0) {printf("Required library.bin of size %ld\n", libsize);return 1;}if ((libptr = mmap(NULL, libsize,PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {printf("Failed build libptr due %d\n", errno);return 1;}if ((dataptr = mmap(NULL, datasize,PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,-1, 0)) == MAP_FAILED) {printf("Failed build dataptr due %d\n", errno);return 1;}printf("Preparing test ...\n");memset(dataptr, 0, datasize);printf("Doing test ...\n");unsigned long chunk_size = GB;unsigned long chunk_count = (DATA_GBYTES - 3) * GB / chunk_size;for (unsigned long chunk=0 ; chunk < chunk_count; chunk++) {printf("Iteration %d of %d\n", 1 + chunk, chunk_count);random_read(libptr, dataptr + (chunk * chunk_size), libsize);}return 0;}

Тест без использования swap


Запрещаем swap указав vm.swappines=0 и запускаем тест
$ time ./swapdemoPreparing test ...Killedreal 0m6,279suser 0m0,459ssys 0m5,791s


Что произошло? Значение swappiness=0 отключило свап анонимные страницы в него больше не вытесняются, то есть данные всегда в памяти. Проблема в том, что оставшихся 2GB не хватило для работающих в фоне Chrome и VSCode, и OOM-killer убил тестовую программу. А заодно нехватка памяти похоронила вкладку Chrome, в которой я писал эту статью. И мне это не понравилось пусть даже автоматическое сохранение сработало. Я не люблю когда мои данные хоронят.

Включенный swap


Выставляем vm_swappines = 60 (по умолчанию)
Запускаем тест:
$ time ./swapdemoPreparing test ...Doing test ...Iteration 1 of 11Iteration 2 of 11Iteration 3 of 11Iteration 4 of 11Iteration 5 of 11Iteration 6 of 11Iteration 7 of 11Iteration 8 of 11Iteration 9 of 11Iteration 10 of 11Iteration 11 of 11real 1m55,291suser 0m2,692ssys 0m20,626s

Фрагмент top:
Tasks: 298 total,  2 running, 296 sleeping,  0 stopped,  0 zombie%Cpu(s): 0,6 us, 3,1 sy, 0,0 ni, 85,7 id, 10,1 wa, 0,5 hi, 0,0 si, 0,0 stMiB Mem : 15670,0 total,  156,0 free,  577,5 used, 14936,5 buff/cacheMiB Swap: 16384,0 total, 12292,5 free,  4091,5 used.  3079,1 avail MemPID USER   PR NI  VIRT  RES  SHR S %CPU %MEM   TIME+ COMMAND10393 viking  20  0  17,0g 14,2g 14,2g D 17,3 93,0  0:18.78 swapdemo136 root   20  0    0   0   0 S  9,6  0,0  4:35.68 kswapd0


Плохой-плохой линукс!!! Он использует swap почти на 4 гигабайт хотя у него 14 гигабайт кэша и 3 гигабайта доступно! У линукса неправильные настройки! Плохой outlingo, плохие старые админы, они ничего не понимают, они сказали включить swap и теперь у меня из-за них система свапится и плохо работает. Надо отключить swap как советуют намного более молодые и перспективные интернет-эксперты, ведь они точно знают что делать!

Ну Пусть будет так. Давайте максимально отключим свап по советам экспертов?

Тест почти без swap


Выставляем vm_swappines = 1

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

Я верю Крису Дауну, поскольку считаю что он отличный инженер и знает что говорит, когда объясняет что swap-файл позволяет системе лучше работать. Поэтому, ожидая, что, что-то пойдет не так и возможно система будет ужасно неэффективно работать, я заранее подстраховался и запустил тестовую программу, лимитировав её таймером, чтобы увидеть хотя бы ее аварийное завершение.

Сначала рассмотрим вывод top:

Tasks: 302 total,  1 running, 301 sleeping,  0 stopped,  0 zombie%Cpu(s): 0,2 us, 4,7 sy, 0,0 ni, 84,6 id, 10,0 wa, 0,4 hi, 0,0 si, 0,0 stMiB Mem : 15670,0 total,  162,8 free,  1077,0 used, 14430,2 buff/cacheMiB Swap: 20480,0 total, 18164,6 free,  2315,4 used.  690,5 avail MemPID USER   PR NI  VIRT  RES  SHR S %CPU %MEM   TIME+ COMMAND6127 viking  20  0  17,0g 13,5g 13,5g D 20,2 87,9  0:10.24 swapdemo136 root   20  0    0   0   0 S 17,2  0,0  2:15.50 kswapd0

Ура?! Свап используется всего лишь на 2.5 гигабайт, что почти 2 в два раза меньше чем в тесте со включенным swap (и swappiness=60). Свапа используется меньше. Свободной памяти тоже меньше. И наверное, мы можем смело отдать победу молодым экспертам. Но вот что странно наша программа так и не смогла завершить даже 1 (ОДНОЙ!) итерации за 2 (ДВЕ!) минуты:
$ { sleep 120 ; killall swapdemo ; } &[1] 6121$ time ./swapdemoPreparing test Doing test Iteration 1 of 11[1]+ Done          { sleep 120; killall swapdemo; }Terminatedreal1m58,791suser0m0,871ssys0m23,998s


Повторим программа не смогла завершить 1 итерацию за 2 минуты хотя в предыдущем тесте она сделала 11 итераций за 2 минуты то есть с почти отключенным свапом программа работает более чем в 10(!) раз медленнее.

Но есть один плюс ни одной вкладки Chrome не пострадало. И это хорошо.

Тест с полным отключением swap


Но может быть, просто задавить свап через swappiness недостаточно, и его надо полностью отключать? Естественно, что надо проверить и эту теорию. Мы сюда тесты пришли провести, или что?

Это идеальный случай:

  • унас нет свопа и все наши данные будут гарантированно в памяти
  • свап не будет использоваться даже случайно, потому что его нет


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

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

Вывод top:
Tasks: 217 total,  1 running, 216 sleeping,  0 stopped,  0 zombie%Cpu(s): 0,0 us, 2,2 sy, 0,0 ni, 85,2 id, 12,6 wa, 0,0 hi, 0,0 si, 0,0 stMiB Mem : 15670,0 total,  175,2 free,  331,6 used, 15163,2 buff/cacheMiB Swap:   0,0 total,   0,0 free,   0,0 used.  711,2 avail MemPID USER   PR NI  VIRT  RES  SHR S %CPU %MEM   TIME+ COMMAND136 root   20  0    0   0   0 S 12,5  0,0  3:22.56 kswapd07430 viking  20  0  17,0g 14,5g 14,5g D  6,2 94,8  0:14.94 swapdemo

Почему это происходит


Объяснение очень простое сегмент кода который мы подключаем через mmap (libptr) лежит в кэше. Поэтому когда мы запрещаем (или почти запрещаем) swap тем или иным способом, не важно каким физическим ли отключением swap, или через vm.swappines=0|1 это всегда заканчивается одним и тем же сценарием вымыванием mmapнутого файла из кэша и последующей его загрузкой с диска. А библиотеки загружаются именно через mmap, и чтобы убедиться в этом, достаточно просто сделать ls -l /proc//map_files:

$ ls -l /proc/8253/map_files/ | head -n 10total 0lr-------- 1 viking viking 64 фев 7 12:58 556799983000-55679998e000 -> /usr/libexec/gnome-session-binarylr-------- 1 viking viking 64 фев 7 12:58 55679998e000-5567999af000 -> /usr/libexec/gnome-session-binarylr-------- 1 viking viking 64 фев 7 12:58 5567999af000-5567999bf000 -> /usr/libexec/gnome-session-binarylr-------- 1 viking viking 64 фев 7 12:58 5567999c0000-5567999c4000 -> /usr/libexec/gnome-session-binarylr-------- 1 viking viking 64 фев 7 12:58 5567999c4000-5567999c5000 -> /usr/libexec/gnome-session-binarylr-------- 1 viking viking 64 фев 7 12:58 7fb22a033000-7fb22a062000 -> /usr/share/glib-2.0/schemas/gschemas.compiledlr-------- 1 viking viking 64 фев 7 12:58 7fb22b064000-7fb238594000 -> /usr/lib/locale/locale-archivelr-------- 1 viking viking 64 фев 7 12:58 7fb238594000-7fb2385a7000 -> /usr/lib64/gvfs/libgvfscommon.solr-------- 1 viking viking 64 фев 7 12:58 7fb2385a7000-7fb2385c3000 -> /usr/lib64/gvfs/libgvfscommon.so

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

Заключение


Активное использование методики распространения программ всё свое везу с собой (flatpak, snap, docker image) приводит к тому, что количество кода, который подключается через mmap, существенно увеличивается.

Это может привести к тому, что использование экстремальных оптимизаций, связанных с настройкой/отключением swap, может привести к совершенно неожиданным эффектам, потому, что swap-файл это механизм оптимизации подсистемы виртуальной памяти в условиях memory pressure, а available memory это совсем не неиспользуемая память, а сумма размеров кэша и свободной памяти.

Отключая swap-файл, вы не убираете неправильный вариант, а не оставляете вариантов

Следует очень осторожно интерпретировать данные о потреблении памтяи процессом VSS и RSS. Они отображают текущее состояние а не оптимальное состояние.

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

P.S.: В обсуждениях регулярно задаются вопросы а вот если включить сжатие памяти через zram.... Мне стало интересно, и я провел соответствующие тесты: если включить zram и swap, как это сделано по умолчанию в Fedora, то время работы ускоряется примерно до 1 минуты.

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

Настройка собственного почтового сервера

26.02.2021 20:18:58 | Автор: admin

Есть три основных шага, чтобы установить и настроить собственный почтовый сервер.

  • Настройка IP и DNS

  • Выбор и запуск приложения почтового сервера

  • Добавление своего почтового сервера в белые списки

Настройка IP и DNS

Обеспечение внешнего статического IP-адреса, публичного домена и записи PTR

Это основные требования для запуска собственного почтового сервера.

  • Публичный статический IP-адрес
    IP-адрес почтового сервера должен быть общедоступным и постоянным во времени. Убедиться в этом можно у хостинг или Интернет-провайдера.

  • Доменное имя указывает на IP
    DNS-запись публичного доменного имени почтового сервера должна указывать на этот IP-адрес. Им можно управлять в настройках DNS провайдера доменного имени.

  • IP указывает на доменное имя
    Самое главное, обратная DNS-запись (именуемая PTR) должна указывать на доменное имя почтового сервера по IP-адресу. Можно попросить своего хостинг-провайдера или поставщика интернет-услуг настроить его. Его можно легко проверить по IP-адресу онлайн (например, тут), или с помощью команды nslookup в Windows и команды host в системах на основе UNIX.

Настройка MX записи в DNS

Запись почтового обмена (MX) указывает почтовый сервер, ответственный за прием сообщений электронной почты от имени домена.

Например, если наш домен - mycompany.com, почтовый сервер - mail.mycompany.com, то запись DNS для mycompany.com будет:

Type

Host

Value

Priority

TTL

MX

@

mail.mycompany.com

10

1 min

где:

  • Priority (приоритет) используется, когда в домене более одного почтового сервера.

  • TTL (время жизни) можно установить любое предпочтительное значение, а наименьшее значение используется для применения конфигурации DNS как можно скорее при отладке настроек.

Настройка DKIM записи в DNS

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

Понадобятся приватный и открытый ключи. Их можно создать с помощью онлайн-инструментов, например Power DMARC Toolbox - DKIM Record Generator, или с помощью команд OpenSSL (приведен пример для Windows):

  • Создать приватный ключ
    openssl.exe genrsa -out private.key 2048

  • Создать публичный ключ из приватного
    openssl.exe rsa -in private.key -pubout -outform der 2>nul | openssl base64 -A > public.key.txt

И запись DNS будет выглядеть так:

Type

Host

Value

TTL

TXT

selector._domainkey

v=DKIM1; k=rsa; p=public_key

1 min

где:

  • selector - самостоятельно выбранный идентификатор (например, mysrv), который будет использоваться в приложении почтового сервера (смотрите ниже).

  • public_key - открытый ключ, закодированный алгоритмом base64 (содержимое public.key.txt).

  • TTL (время жизни) имеет то же значение, что и в предыдущем разделе.

Настройка SPF записи в DNS

Инфраструктура политики отправителя (SPF) это стандарт проверки подлинности электронной почты, который проверяет IP-адрес отправителя по списку авторизованных IP-адресов владельца домена для проверки входящей электронной почты.

Тут запись DNS будет выглядеть так:

Type

Host

Value

TTL

TXT

@

v=spf1 a mx include:relayer_name -all

1 min

где:

  • relayer_name - имя необязательного внешнего почтового сервера-ретранслятора (смотрите ниже). Если не нужно - убирается вместе с "include:".

  • TTL (время жизни) имеет то же значение, что и в предыдущем разделе.

Можно использовать удобный онлайн-генератор записи SPF.

Дополнительные записи DNS

Некоторые поля не обязательны, но желательно иметь.

  • DMARC
    Запись доменной проверки подлинности сообщений, отчетов и соответствия (DMARC) позволяет собственному почтовому серверу декларировать политику того, как другие почтовые серверы должны реагировать на недостоверные сообщения от него.

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

  • TLS-RPT
    TLS-отчетность (TLS-RPT) дает ежедневные сводные отчеты с информацией о электронных письмах, которые не зашифровываются и не доставляются.

Все эти записи могут быть созданы с помощью Power DMARC Toolbox.

Выбор и запуск приложения почтового сервера

Конечно, хостинг должен позволять устанавливать программное обеспечение. Можно использовать любое подходящее приложение для почтового сервера. Например, есть бесплатный hMailServer для Windows, который предоставляет все необходимые функции с минимальным использованием ресурсов. Для систем на базе UNIX существует множество бесплатных почтовых серверов, таких как Exim Internet Mailer или iRedMail.

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

Инициализация

Когда программное обеспечение выбрано и установлено, самое время его настроить.

  • Домен и пользователи
    Нужно добавить домен и начальный набор пользователей почтового сервера.

  • Безопасность
    Чтобы обеспечить соответствующий уровень безопасности, мы должны добавить сертификат SSL для домена.

  • Подпись сообщений
    Далее, следует настроить DKIM. Нужно указать полученные выше приватный ключ и селектор. Кроме того, методы заголовка и тела должны быть установлены на расслабленный, алгоритм подписи должен быть установлен на SHA256, иначе на некоторых SMTP серверах не проходит проверка (например, google).

  • Защита от спама
    Наконец, нужно настроить антиспам-проверку специальными узлами черных списков, такими как spamhaus.org, чтобы защитить пользователей почтового сервера от нежелательных сообщений.

Протоколы электронной почты

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

SMTP

SMTP используется для приема входящей и исходящей почты с/на другие почтовые серверы. И это позволяет пользователям домена отправлять свои сообщения.

  • 25 порт
    Этот порт необходим для управления входящими подключениями от других почтовых серверов. Метод безопасности следует установить в STARTTLS.

  • 587 порт
    Он нужен для почтовых клиентов собственного почтового сервера. Метод безопасности следует установить в STARTTLS.

  • 465 порт
    Он не является официальным и может потребоваться для старых почтовых клиентов. И метод безопасности следует установить в SSL/TLS.

POP3, IMAP

POP3 и IMAP используются отдельными почтовыми клиентами, такими как Outlook на ПК или любой почтовый клиент на мобильных телефонах. Это позволяет пользователям домена управлять своими сообщениями.

Порт 993 следует использовать для защищенных соединений IMAP, а порт 995 - для POP3. Для обеспечения совместимости с большинством клиентов метод безопасности следует установить в SSL/TLS (не STARTTLS).

Также можно настроить порты 143 для IMAP и 110 для POP3, но они не шифруются и сейчас их уже мало кто использует.

Проверка

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

Теперь пора проверить отправку на внешний адрес.

Аккаунт Gmail.com

Если есть учетная запись Gmail.com (что наверняка), можно отправить тестовое письмо на свой адрес Gmail. Затем открываем свою электронную почту в браузере и нажимаем Показать подробности.

Если есть подписано: домен, подпись DKIM настроена правильно. Если есть отправлено по почте: домен, SPF в порядке.

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

Также, в Outlook можно видеть те же заголовки в свойствах сообщения.

Специальные онлайн-сервисы

Существует множество онлайн-сервисов, которые могут проверять отправку электронной почты. Ниже приведены некоторые из них.

  • AppMailDev
    Этот сервис позволяет тестировать конфигурацию почтового сервера, такую как DKIM и SPF, отправляя электронное письмо на указанный сгенерированный почтовый адрес. Нужно просто следовать инструкциям на экране и результаты теста будут отображены там же.

  • DKIMValidator
    Предоставляет те же функции, что и предыдущая служба. Результаты тестирования будут отправлены на адрес отправителя.

  • HAD Email Auth Tester
    Чтобы проверить отправку сообщения здесь, нужно отправить специальное сообщение на tester@email-test.had.dnsops.gov. Результаты тестирования будут отправлены на адрес отправителя.

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

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

Добавление почтового сервера в белые списки

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

Внесение в белый список в публичных источниках

Итак, сначала проверим IP (и, если необходимо, домен) онлайн на наличие в каких-либо черных списках. Его можно проверить в любом онлайн-чекере, который можно найти через поиск. Например, MXToolBox проверяет самые популярные черные списки. Также, multirbl.valli.org показывает много источников черного списка и доверие к каждому из них.

Затем нужно последовательно просмотреть каждый элемент в результатах и прочитать рекомендации о том, как внести IP-адрес в белый список в конкретном источнике черного списка. Но не все из них могут позволить это сделать бесплатно, например, немецкий UCEPROTECT-Network.

Кстати, на тут на habr обсуждалась автоматизация мониторинга IP в блэклистах.

Внесение в белый список определенных почтовых серверов

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

Обход черных списков

Если какой-то официальный черный список не разрешает добавление в исключения или когда-нибудь почта перестает отправляться на определенный домен - можно использовать внешние службы ретрансляции SMTP. Они позволяют использовать их в качестве шлюзов (или прокси) при отправке почты.

  • MailerSend
    Один из самых дешевых - позволяет бесплатно отправлять 20 тысяч писем в месяц и имеет низкую стоимость дополнительной отправки. Но есть особенность: поля CC и BCC пока не поддерживаются.

  • SendInBlue
    Это еще один хороший сервис, который позволяет бесплатно отправлять 9 тысяч писем в месяц с лимитом 200 в день. Но есть нюансы: встроенное отслеживание электронной почты нельзя отключить и высоковатая цена сверх бесплатного лимита.

В каждой службе нужно зарегистрироваться и получить подтверждение почтового домена. После подтверждения, каждый из них дает указания на то, что должно быть настроено для DNS (DKIM, SPF и DMARK) и почтового приложения (адрес сервера ретрансляции SMTP, порт и учетные данные).

Заключение

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

Подробнее..

Перевод Почему веб-производительность внутренних систем важна и нуждается в оптимизации?

02.03.2021 02:04:15 | Автор: admin
Как-то раз у меня был занятный разговор со службой поддержки Департамента международной торговли (DIT). Они хотели повысить производительность одного из своих веб-приложений. Подобные разговоры это то, что мне больше всего нравится на моей текущей позиции. Я общаюсь на темы, которые мне интересны, знакомлюсь с новыми людьми, рассказываю им про возможности, о которых они могут не знать, например, как улучшить UX приложения.

Если честно, я немного расстроился, когда мне сообщили, что этот сервис предназначен для внутреннего использования и закрыт для общего доступа. Это означало, что мои обычные goto tools для оценки веб-производительности были недоступны. А именно:


Это натолкнуло меня на мысль: а как все-таки тестировать внутренние сервисы и продукты? В этой статьей я постараюсь это выяснить.

Самое важное условие для быстрых внутренних систем


Как мы все знаем, мир значительно изменился из-за глобальной пандемии. Из-за повсеместных локдаунов все, у кого была такая возможность, начали работать из дома. Это значительно повлияло на производительность Интернета во всем мире и привело к высокому трафику и увеличению времени загрузки. Из-за этого все инструменты, которые необходимы сотрудникам для выполнении своей работы, должны быстро загружаться, а также быть интерактивными.

Раньше подобных проблем с производительностью не возникало, так как внутренние пользователи работали из офиса и использовали локальную сеть (LAN). Проблема усугубляется тем, что многие живут в небольших городах с медленным и нестабильными Интернетом. Или, наоборот, в крупных городах с высоким коэффициентом конкуренции (contention ratio). Поскольку мы говорим о внутренних системах, чаще всего сотрудникам нужно использовать VPN, чтобы войти в офисную сеть. Но это тоже не очень удобно: VPN чаще всего снижает скорость Интернета.

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

WebPageTest


Первое, что хотелось бы прояснить: когда тестируете внутренние системы, использовать открытую версию WebPageTest не получится. Но зато вы можете установить приватную. Благодаря этому, можно будет использовать ее во внутренней сети.



После запуска откроется доступ к огромному объему данных для всех внутренних систем. Не забудьте прочитать гайд, чтобы получить как можно больше информации из WebPageTest. Настройка собственной версии не так сложна, как кажется. Есть несколько отличных руководств, как самостоятельно ее настроить на AWS за пару минут:


Такой вариант даст возможность запускать WebPageTest автоматически. Сделать это можно несколькими способами:


Таким образом, вы сможете отслеживать, какое влияние на производительность (положительное или отрицательное) оказывают новые изменения в системе.

Lighthouse


Следующий goto инструмент, скорее всего, у вас уже есть, это Lighthouse от Google. Если вы установили копию Google Chrome на компьютер, то использовать Lighthouse для аудита внутренней системы очень просто:



Во вкладке DevTools найдите Lighthouse и нажмите Generate report.



Спустя минуту после запуска, аудит вернет результат, как показано на картинке выше. Настоятельно рекомендую настроить новый профиль Chrome специально для тестирования Lighthouse, поскольку расширения браузера могут негативно повлиять на производительность (зависит от того, что именно они делают на странице).

Но Lighthouse это не только панель аудита. Ниже несколько вариантов, как еще можно использовать этот инструмент:

Вы можете запустить Lighthouse, используя Command line interface (CLI)

Можно легко запустить Lighthouse на всех страницах сайта.

Сравнить производительность до и после с помощью Lighthouse CI Diff

Автоматически запускать Lighthouse через равные промежутки времени на нескольких сайтах через запуск тестов.

Добавить собственный аудит для мониторинга определенных частей сайта

Поделиться результатами через Github Gist и Lighthouse Report Viewer.

Sitespeed.io


Я ставлю Sitespeed.io на одно из первых мест в этом списке, потому что считаю, что многие его недооценивают. Это замечательный набор инструментов для повышения производительности сайта. Его можно быстро и легко настроить с помощью простой команды docker или npm. Также Sitespeed.io просто запустить на локальном компьютере для быстрого тестирования.



С помощью sitespeed.io можно непрерывно отслеживать столько страниц, сколько вам нужно, отправляя данные в Graphite / Grafana, чтобы получить подобные дашборды. По сути, Sitespeed.io представляет собой cледующий набор инструментов:

  • Coach автоматизированный инструмент, который помогает увеличить скорость загрузки страниц.
  • Browsertime главный инструмент Sitespeed. Он взаимодействует с тестовыми браузерами (например, Chrome, Firefox, iOS Safari), а также собирает показатели производительности, изображений, видео и многое другое.
  • PageXray используется для конвертации файлов формата HTTP-archive (HAR) в JSON для облегчения их чтения и использования. (Подробнее о файлах HAR читайте ниже)
  • Throttle инструмент командной строки для регулирования сетевого подключения при тестировании производительности.

Примечание: Throttle блокирует соединение с Интернетом на всем компьютере, поэтому не забудьте выключить его после завершения работы.

  • Compare онлайн-инструмент для быстрого и легкого сравнения файлов HAR (например, до и после).

DevTools в Chrome


Во всех современных браузерах уже есть встроенные инструменты для разработчика. Мы прошли долгий путь со времен Firebug в Firefox. Что немаловажно, DevTools становятся мощнее с каждой новой версией браузера. Это удобно и для разработчиков, и для юзеров, ведь на сайтах должно быть меньше багов, не так ли? Ха!



На изображении выше показана детальная информация, которую может предоставить аудит о производительности веб-страницы (вкладка Perfomance). Но Chrome DevTools, помимо вкладки измерения производительности, имеет много других функций:


А если вы ищете статьи по этой теме, не относящиеся к Google, обратите внимание на эти:


DevTools в Firefox


Существуют и другие браузеры, которые с помощью DevTools могут помочь в оценке проблем с производительностью. Я пользователь Firefox, поэтому регулярно применяю инструменты этого браузера. В Firefox также есть полный набор вкладок, которые можно использовать для поиска проблем на сайте:



Вы можете использовать эти инструменты для:


Библиотеки для расширения данных аналитики


Это может не сработать с внутренними инструментами, но если вы отслеживаете их использование с помощью аналитики (например, Google Analytics, Fathom, Matomo), то можно расширить собираемые данные, включив в них более полную информацию о веб-производительности.



Несколько библиотек, которые можно использовать:

  • Perfume.js можно настроить для сбора большого набора RUM-данных для передачи их в инструмент аналитики.
  • Analytics Perfume.js plugin обертка для Perfume.js, чтобы легко запушить данные о веб-производительности в разные инструменты для аналитики.
  • web-vitals точно захватывает информацию Core Web Vitals так же, как другие Web Vitals.

Perfume.js выделяется среди других инструментов объемом собираемых данных Real User Monitoring (RUM). Его можно полностью настроить для сбора такого количества, которое нужно вам. Вот пара руководств, как это сделать:


Аналитика JavaScript


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



К счастью, для этого есть много инструментов:

  • bundle-wizard CLI инструмент для создания визуализаций бандла JavaScript-а (см. изображение выше), чтобы можно было удалить все, что не нужно.
  • Bundle Phobia узнайте, сколько будет стоить добавление npm-пакета в ваш набор.
  • Webpack Bundle Analyzer визуализируйте внутреннюю структуру выходных файлов webpack с помощью этого инструмента интерактивной масштабируемой карты.
  • source-map-explorer используйте source maps для анализа раздутого кода JavaScript (этот инструмент также работает с Sass и LESS для анализа CSS).

Специальные фреймворки для анализа инструментов и статьи тоже имеются:

  • reactopt A CLI-инструмент React'а для оптимизации производительности определяет, нужен ли повторный рендеринг страницы.
  • TracerBench инструмент для тестирования контролируемой производительности веб-приложений. Обеспечивает понятный, действенный и удобный анализ разницы в производительности.
  • Приложение для измерения производительности в React DebugBear

CSS анализ


Помимо вкладки Coverage, упомянутой ранее в DevTools Chrome, есть также инструменты, которые вы можете запускать через интерфейс командной строки (CLI). Они будут анализировать CSS, учитывая его сложность, а также выявлять неиспользуемые селекторы на всем веб-сайте:

  • analyze-css анализатор сложности и производительности CSS-селекторов, запускаемый с использованием интерфейса командной строки.
  • uCSS пройдет весь сайт в поисках неиспользуемых селекторов CSS, которые затем можно удалить.

Измерение производительности сервера


Золотое правило производительности гласит, что: 80-90% времени пользователь проводит на фронтенде.

По-прежнему рекомендуется убедиться, что бэкенд / сервер оптимизированы. В конце концов, Time to First Byte matters.



Также важно удостовериться, что сервер сможет продолжать работать при большой нагрузке, если это когда-либо произойдет. Существует ряд инструментов, которые помогут вам сделать обе эти вещи:

  • httpstat небольшой скрипт Python для визуализации данных о времени подключения, возвращаемых из curl (см. изображение выше).
  • h2load инструмент для тестирования HTTP / 2 и HTTP / 1.1, запускаемый из интерфейса командной строки.
  • Hey маленькая программа для отправки нагрузки на сервер.
  • k6 создавайте реалистичные нагрузочные тесты, написав JavaScript. Поставляется с API и CLI.
  • Измерение производительности с помощью Server-таймингов настройка сервера для отправки заголовка, содержащего информацию сервер-таймингов. Предоставляет тайминги о производительности бэкенд-сервера на фронтенд для более удобного обзора в браузере.

Автоматизация с помощью Puppeteer


Puppeteer это библиотека Node, которая предоставляет высокоуровневый API для управления Chrome или Chromium по протоколу DevTools. Большинство вещей, которые вы делаете вручную в браузере, можно воспроизвести с помощью Puppeteer. Как это можно использовать для тестирования производительности в Интернете? Адди Османи написал в блоге об использовании Pupperteer для веб-тестирования производительности, а также поделился кодом на Github. Эти тесты можно легко запустить через интерфейс командной строки для тестирования как внутренних, так и внешних веб-сайтов:


Расширения для браузера


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

  • sloth расширение, замедляющее работу процессора и сети в браузере, позволяя легко имитировать производительность страницы на более медленных устройствах.
  • Perfmap при использовании этого расширения, браузер создает тепловую карту ресурсов, загруженных в браузер, и их индивидуального влияния на производительность в соответствии с Resource Timing API.
  • Web Vitals Chrome Extension расширение для Chrome, которое отображает основные показатели Web Vitals (LCP, CLS, FID) для любой посещенной страницы. Примечание: это скоро будет встроено в Chrome DevTools, сейчас он доступен в Canary.
  • perf-diagnostics.css это не совсем расширение браузера, скорее, набор CSS, который вы можете добавить на свою страницу для устранения распространенных проблем с производительностью. Простой и эффективный способ выделения изображений без атрибута ширины / высоты, среди ряда других.

Существуют также расширения, предназначенные конкретно для повышения производительности при использовании определенных фреймворков JavaScript:

  • React Developer Tools это расширение добавляет вкладку Profiler в DevTools, позволяя детально изучить производительность приложения React.
  • Angular Augury расширение для Chrome и Firefox, позволяющее отлаживать и профилировать приложения Angular.
  • Ember Inspector можно устранять баги и вникать в детали веб-приложения, созданного с помощью Ember.


Network Throttling


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

Вы можете спросить: Зачем мне блокировать мою сеть, если это встроено в DevTools Chrome?. Важно понимать, что не все методы регулирования сети работают одинаково. При регулировании с помощью Chrome DevTools применяется задержка на уровне браузера при получении каждого ответа. Lighthouse запускает тест на полной скорости, а затем моделирует скорость соединения, жертвуя точностью ради скорости сообщения. Следующие инструменты намного точнее. Они используют регулирование сети на уровне ОС, которое работает на гораздо более низком уровне.

Примечание: эти инструменты ниже регулируют соединение на всем компьютере, поэтому убедитесь, что вы закрыли ненужные приложения при тестировании, а также отключите троттлинг после завершения!


Я всегда использую throttle, потому что он довольно простой:

# Enable 3G Slowthrottle 3gslow# Use a custom connection profilethrottle --up 1600 --down 780 --rtt 250# Disable throttlethrottle --stop

Анализ файлов HAR


Я упоминал файлы формата HTTP Archive (HAR) ранее в этом статье. Эти файлы позволяют зафиксировать сетевое взаимодействие веб-браузеров с веб-сайтом. Самое замечательное в этих файлах то, что вы можете использовать их для любого сайта, на который можно попасть через браузер (внутренний или внешний). Найти их довольно просто в инструментах разработчика Firefox и Chrome:

Firefox


Chrome


Есть и другие инструменты, которые вы можете использовать для просмотра и анализа:

  • HAR analyzer браузерный инструмент анализа HAR от Google.
  • YSlow Command Line HAR analyser довольно старый сервис, но он может анализировать файлы HAR для улучшения производительности.
  • PageXray конвертируйте файл HAR в JSON, чтобы было легче читать и взаимодействовать (используется в Sitespeed.io).
  • Compare онлайн-инструмент, позволяющий быстро и легко сравнивать файлы HAR (например, результаты до и после).
  • HAR Viewer простой онлайн-просмотрщик HAR для визуализации показателей внутри.
  • Charles Proxy HTTP-прокси / HTTP-монитор, который может принимать файлы HAR в качестве входных данных для подробного анализа.
  • Fiddler инструмент для дебаггинга прокси-сервера, который может регистрировать, проверять и изменять трафик между компьютером и веб-сервером. Его также можно использовать для анализа файлов HAR.

Web APIs


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

  • performance.now() метод now() интерфейса производительности браузера возвращает timestamp с высокой точностью с момента вызова метода. Позволяет очень легко измерить время между 2 звонками. Добавление их до и после определенной части кода позволит вам измерить и оптимизировать его.
  • Navigation Timing этот API позволяет разработчикам собирать данные о времени, связанные с навигацией по документу.
  • Resource Timing этот API позволяет разработчикам собирать полную информацию о времени для ресурсов, загружаемых документом.
  • Assessing Loading Performance in Real Life with Navigation and Resource Timing Джереми Вагнер очень подробная статья о том, как два перечисленных выше API могут использоваться для оценки производительности загрузки веб-страницы.

Итоги


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

Категории

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

© 2006-2021, personeltest.ru