Вопросы и ответы для собеседования DevOps
code | описание |
---|---|
1xx | информационные. запрос получен, продолжается обработка |
200 | ок |
3хх | перенаправление |
4хх | ошибки на стороне клиента |
400 | bad request - ошибка синтаксиса запроса |
401 | ошибка авторизации (неправильный пароль, просрочился токен) |
403 | доступ запрещен безусловно |
431 | header очень большой. export NODE_OPTIONS="--max-http-header-size=983040" |
5хх | ошибки на стороне сервера |
500 | внутренняя ошибка сервера |
502 | прокси получил недействительный ответ от настоящего бэкэнда |
504 | таймаут шлюза - прокси не дождался ответа настоящего бэкэнда |
Method | Description |
---|---|
GET | Transfer a current representation of the target resource |
HEAD | Only transfer the status line and header section |
POST | Perform resource-specific processing on the request payload |
PUT | Replace target resource with the request payload |
DELETE | Remove all current representations of the target resource |
CONNECT | Establish a tunnel to the server |
OPTIONS | Describe the communication options for the target resource |
TRACE | Perform a message loop-back test along the path to the target |
Это когда запрашиваемый ресурс содержит ссылку на объект на другом ресуре.
Например при обращении к сайту по https он содержит картинки ссылающиеся по
http.
При загрузке страницы елси у ресурсов разные схема / FQDN / port то загрузка будет заблокирована CORS политиками.
Необходима передача заголовка acess-control-allow-origin: * (или источник которому разрешен доступ)
CORS запросы могут быть простыми и сложными.
Признаки сложности запроса:
- методы отличные от GET, POST, или HEAD
- запрос включает заголовки отличные от Accept, Accept-Language или Content-Language
- запрос имеет значение заголовка Content-Type отличное от application/x-www-form-urlencoded, multipart/form-data, или text/plain.
Сложные запросы предваряются prflight запросами с методом options.
В ответ на который браузеру необходимо получиь заголовки:
- Access-Control-Allow-Methods, который указывает на то, какие методы поддерживаются URL-ом ответа в контексте CORS протокола.
- Access-Control-Allow-Headers, который указывает, на то, какие заголовки поддерживаются URL-ом ответа в контексте CORS протокола.
- Access-Control-Max-Age, который указывает число секунд (5 по умолчанию) и это значение соответствует периоду, на который предоставляемая заголовками Access-Control-Allow-Methods и Access-Control-Allow-Headers информация может быть кэширована.
Server Name Indication - расширение протокола TLS, аналог заголовка host при установлении https соединения. Т.е. сервер должен как то узнать какой сертификат ему отдать на запрос clientHello. Из этого заголовка он и будет понимать.
- не поддерживал заголовок HOST
- для каждого запроса открывалось отдельное соединение
- поддерживает постоянные соединения
- для нескольких запросов может быть использовано одно соединение
- поддержка метода options
- поддержка TLS
- передача в бинарном виде, экономит трафик
- нет проблем с кодировкой
- поддержка технологии server push
- мультиплексирование запросов на одном соединении TCP
На стадии черновика, но уже поддерживается несколькими браузерами. Основан на использовании QUIC - экспериментальном протоколе транспортного уровня от компании Google
- Round robin
- Round robin с весами для upstreams
- IP hash
- sticky session
- least connections
- peak exponentially weighted moving average хабр
Запись данных на диск производится отдельным постоянно работающим и независимым
процессом.
Изменение / создание одного файла может требовать нескольких фактических
операций записи.
Для ускорения, такие операции выполняются транзанкциями, при потере питания в
середине транзанкции целостность данных нарушается.
Для обеспечения большей согласованности используется журналирование, когда
операции записи перед непосредственно записью на диск сначала скидываются в
журнал (тоже на диск). При загрузке проверяется соответствие журнала и
состояния.
Журнал представляет из себя кольцевой буфер, который при наполнении
перезаписывается (место не кончится, бесконечно не растет).
Пример журналируемых файловых систем: ext3, ext4, xfs
Режимы журналирования:
- режим обратной связи writeback - журналируются только метаданные
- последовательный ordered - записываются изменения только мета-данных файловой системы, но записывает обновления данных файла на диск перед изменениями ассоциируемых мета-данных файловой системы.
- режим данных journal - запись всех изменений данных файловой системы и мета-данных. Наиболее медленный из всех трех режимов журналирования. Этот режим минимизирует шанс потери изменений файлов
Копирование при записи - ускоряет производительность. Суть в том, что фактическое копирование будет произведено только если будет меняться содержимое, а если нет - то будет передан указатель на то же фактическое расположение данных.
Преимущества:
- быстрее работа
- экономия места - дедубликация данных
- можно делать быстрые snapshots
Consistency - Availability - Patition tolerance
В ограниченный период времени можно обеспечивать только два из трех свойств
Примеры:
CA - реляционные базы MySQL, Postgres
CP - HBASE, mongodb, redis
AP - Cassandra, Kafka т.е. системы используемые для логов, событий, для данных
которые начинают читать не мгновенно.
PACELC - при условии наличия сетевого разделения **(P)**artitioning система может выбрать одно из двух: доступность **(A)**vailability или консистентность **(С)**onsistensy, иначе **(E)**lse, если сетевого разделения нет, система может выбрать одно из двух: время задержки **(L)**atency или консистентность **(С)**onsistensy.
- mq-deadline — реализация планировщика deadline с использованием blk-mq. Этот планировщик подходит для большинства случаев, но особенно для тех, в которых операции записи в основном асинхронны. Планировщик mq-deadline сортирует запросы ввода-вывода в очереди на чтение или запись, а затем планирует их выполнение в возрастающем порядке адресации логических блоков (LBA).
- kyber — планировщик, основанный на методах активного управления
очередями, используемых для сетевой маршрутизации.
Реализация основана на "токенах", которые служат механизмом ограничения запросов. Используется две очереди запросов — на запись и на чтение. kyber отдает приоритет запросам на чтение перед запросами на запись. Реализация алгоритма относительно проста и считается эффективной для NVME, SSD или других устройств с низкой задержкой. - bfq (Budget Fair Queuing) — основан на алгоритме от CFQ, но содержит улучшения. В конфигурации по умолчанию он больше нацелен на обеспечение минимальной задержки, а не на достижение максимальной пропускной способности. Этот планировщик обладает относительно высокими расходами на операцию, поэтому он не идеален для устройств с медленными процессорами или устройствами ввода-вывода с высокой пропускной способностью.
- none – планировщик ввода-вывода без операций с несколькими очередями. Не переупорядочивает запросы и имеет минимальные расходы. Идеально подходит для быстрых устройств произвольного ввода-вывода, таких как SSD или NVME.
noop, CFQ, Deadline
$ cat /sys/block/nvme0n1/queue/scheduler
[none] mq-deadline
Изменить однократно: через этот же файл.
Для постоянного изменения потребуется создавать правило в /etc/udev/rules.d
где указать какой планировщик применять к какому типу дисков.
Link-Local Address — адреса сети, предназначеные только для коммуникаций в
пределах одного сегмента местной сети. Они позволяют обращаться к хостам, не
используя общий префикс адреса. Маршрутизаторы не будут отправлять пакеты с
адресами link-local.
Адреса link-local часто используютя автоматического конфигурирования сетевого
адреса, в случаях, когда внешние источники информации об адресах сети
недоступны.
Пример использования link-local адресов — автоматическое конфигурирование
IP-адресов, используемое в IPv4 и IPv6.
Адреса IPv4 в диапазоне от 169.254.1.0 до 169.254.254.255 назначаются ОС хоста
автоматически в случае недоступности других источников информации,
например сервера DHCP.
Протоколы маршрутизации делятся на внешние протоколы (BGP) и внутренние
(OSPF и RIP).
Внешние протоколы маршрутизируют трафик среди автономных систем, грубо говоря,
подсети провайдеров объединяют внешние протоколы, объединенные внешним
маршрутизатором. А внутренние протоколы маршрутизации изучают сеть с помощью
других протоколов, таких как OSPF или RIP (чаще всего используют OSPF).
OSPF — это протокол внутреннего шлюза, который чаще всего используется в локальной сети. OSPF обычно считается более простым в развёртывании и управлении. Хранит информацию о соседних маршрутизаторах.
BGP был разработан для обмена информацией о маршрутизации между разрозненными сетями, известными как автономные системы AS. Хранит информацию об "интернете".
Отличие по времени сходимости - OSPF быстрее
По потреблению ресурсов - OSPF нужно больше для вычислений, требования к
ресурсам у BGP определяется размером таблицы
Информация в Кафка хранится в Топиках. Те, в свою очередь, разделны на 1 и
более партиций. Т.о. чтение топика может происходить из нескольких партиций
одновременно. Записи с одинаковыми ключами всегда попадают в одну и туже
партицию.
Партиции реплицируются, каждая реплика хранится на отдельном брокере. На запись
всегда работает только одна реплика партиции - она называется лидер. Остальные
реплики партиций называются фолловеры. Когда продюсер хочет произвести запись,
он обращается к брокерам и запрашивает метаданные, по которым определяет
лидера.
Консьюмеры объединяются в группы. Для группы кафка хранит значение оффсета -
того положения в логе с данными которое члены группы для данной партиции уже
считали.
Партиции распределяются между членами консьюмер группы. Одну и ту же партицию
будет читать только один член группы. Для добавления нового члена консьюмер
группы нужно будет создать новую партицию если их количество менее количества
членов группы.
По умолчанию кубернетес проверяет состояние процесса с pid 1 контейнера.
Readines probe это про траффик (добавление в объект endpoints)
Startup probe позволяет делать probe отложенно
Startup probes verify whether an application within a container has
started. It is only executed at startup, and if a container fails this
probe, the container is killed and follows the restartPolicy for the pod.
You can configure startup probes in the spec.containers.startupProbe
attribute for the pod configuration.
A primary motivation for startup probes is that some legacy applications
require additional startup time when first initialized, which can make setting
liveness probe parameters tricky.
When configuring a startupProbe, use the same protocol as the application and
ensure the failureThreshold * periodSeconds is enough to cover the worst case
startup time.
Readiness probes continuously verify whether a container is ready to serve
requests. If the probe returns a failed state, Kubernetes removes the IP
address for the pod from the endpoints of all services.
Readiness probes enable developers to instruct Kubernetes that a running
container should not receive traffic until additional tasks are completed, such
as loading files, warming caches, and establishing network connections. You can
configure a readiness probe in the spec.containers.readinessProbe attribute
for the pod configuration. These probes run periodically as defined by the
periodSeconds attribute.
Liveness probes help you evaluate whether an application that is running in
a container is in a healthy state. If not, Kubernetes kills the container and
attempts to redeploy it. These are useful when you want to ensure your
application is not deadlocked or silently unresponsive.
One can configure liveness probes in the spec.containers.livenessProbecode
attribute of the pod configuration.
Like readiness probes, liveness probes also run periodically.
их семь:
- PID - ID процесса в контейнере != ID процесса на хосте
- network когда запускаем контейнер с хостовой сетью:
$ docker run --net=host nginx
- не создаем новый network namespace - mount - изолируют ресурсы файловых систем /proc/$pid/mounts
для разных mount namespace можно смонтировать корневую фс "/" в разных местах в контейнерах, например, когда мы основываем образ на alpine - образ предоставляет минимальную корневую фс с минимально необходимыми системными файлами и это монтируется как корень. В результате в нэймспейсе контейнера можно безопасно сделать$ rm -rf /
- user - это про UID и GID. В разных user namespace GID/UID одного
процесса может быть разным. Уйти в новый user namespace можно с
$ unshare -U bash
Связь UID в разных user namespace происходит через файл маппинга /proc/$pid/uid_map - IPC
- cgroups
- UTS
- клиент запрашивает соединение с сервером, отправляет поддерживаемые способы шифрования и "случайное число клиента". Запрашивает сертификат и ключ сервера
- сервер подтверждает клиенту выбранный способ шифрования и сообщает "случайное число сервера". Сервер отправляет свой публичный ключ и сертификат
- клиент проверяет у CA что сертификат действительно принадлежит серверу
- СА подтверждает соответствие сертификата серверу
- клиент создает ключ сессии, с его участием генерирует случайную строку по алгоритму Дифи-Хелмана, шифрует ее открытым ключем сервера и отправляет серверу
- сервер расшифровывает случайную строку своим приватным ключем и восстанавливает по Дифи-Хелману ключ сессии
- все последующие сообщения шифруются и расшифровываются ключем сессии - синхронное шифрование
- Host
- User-Agent
- Accept
(strong , eventual consistency)
- at least one
- at least two
- all
- quorum
- read own writes
- strong consistency
- eventual consistency
После операции записи получить именно те же данные, т.е. запрос данных только с того же источника, куда производилась запись
время, которое система проводит в бездействии, когда в ней имеется хотя бы один процесс, ожидающий окончания операции дискового ввода-вывода
Internet Control Message Protocol это протокол третьего уровня, который
используется для диагностики проблем со связностью в сети.
ICMP помогает определить может ли достичь пакет адреса назначения в
установленные временные рамки
Для чего нужен ICMP - для диагностики проблем со связностью в сети
- read uncommited - низший уровень изоляции. Возможно чтение несогласованных, незакоммиченных данных. На запись блокируется до конца транзакции
- read committed большинство промышленных СУБД используют по умолчанию. На этом уровне обеспечивается защита от чернового, «грязного» чтения, тем не менее, в процессе работы одной транзакции другая может быть успешно закоммичена. В итоге первая транзакция будет работать с другим набором данных ситуация «неповторяющегося чтения»
- repeatable read уровень, при котором читающая транзакция «не видит» изменения данных, которые были ею ранее прочитаны. При этом никакая другая транзакция не может изменять данные, читаемые текущей транзакцией, пока та не окончена
- serializable самый высокий уровень изоляции; транзакции полностью изолируются друг от друга. Результат выполнения нескольких параллельных транзакций должен быть таким, как если бы они выполнялись последовательно. Только на этом уровне параллельные транзакции не подвержены эффекту «фантомного чтения»
- Basic Availability система обеспечивает базовую доступность, т. е. каждый запрос будет обязательно завершён, успешно или нет
- Soft-state система пребывает в гибком состоянии — очерёдность записей соблюдать необязательно, реплики могут какое-то время находиться в несогласованном состоянии, а система может самостоятельно изменяться для достижения согласованности
- Eventual Consistency все данные всё равно достигнут согласованности
B-tree - это алгоритм индексирования. Он основан на идее разделения данных
на несколько секций, которые называются узлами дерева. Каждый узел содержит
набор ключей и ссылок на дочерние узлы. Поиск значения в B-дереве
осуществляется путем последовательного перехода по узлам дерева, начиная с
корневого узла, и сравнения искомого ключа с ключами в текущем узле.
Этот алгоритм обеспечивает быстрое поиск, вставку и удаление данных, особенно в
случае большого объема данных
Хэширование представляет собой преобразование любого объема информации в уникальный набор символов, который присущ только этому массиву входящей информации. Этот набор символов и называется хэшем
- разрядность
- криптостойкость
- вычислительная сложность
Примеры. некриптостойкий - MD5, криптостойкий SHA256
Это строка в следующем формате header.payload.signature
Предположим, что мы хотим зарегистрироваться на сайте. В нашем случае есть три
участника — пользователь user, сервер приложения application server и
сервер аутентификации authentication server.
Сервер аутентификации будет обеспечивать пользователя токеном, с помощью
которого он позднее сможет взаимодействовать с приложением.
Хедер содержит информацию о том, как должна вычисляться JWT подпись:
{
"alg": "HS256",
"typ": "JWT"
}
Payload — это полезные данные (JWT-claims):
{
"userId": "b08f86af-35da-48f2-8fab-cef3904660bd"
}
Можно положить много заявок. Существует список стандартных заявок для JWT payload — вот некоторые из них:
- iss (issuer) — определяет приложение, из которого отправляется токен
- sub (subject) — определяет тему токена
- exp (expiration time) — время жизни токена
Эти поля могут быть полезными при создании JWT, но они не являются обязательными
Signature - header и payload кодируется base64, объединяется через точку и шифруется по HMAC-SHA256 c помощью секретного ключа
- Пользователь заходит на сервер аутентификации с помощью аутентификационного ключа (это может быть пара логин/пароль, либо ключ от другой учетки)
- Затем сервер аутентификации создает JWT и отправляет его пользователю
- Когда пользователь делает запрос к API приложения, он добавляет к нему полученный ранее JWT
- Приложение может проверить по переданному с запросом JWT является ли пользователь тем, за кого себя выдает. В этой схеме сервер приложения сконфигурирован так, что сможет проверить, является ли входящий JWT именно тем, что был создан сервером аутентификации
- Сервер приложения получает секретный ключ от сервера аутентификации во время
установки аутентификационных процессов. Поскольку приложение знает секретный
ключ, когда пользователь делает API-запрос с приложенным к нему токеном,
приложение может выполнить тот же алгоритм подписывания к JWT.
Приложение может потом проверить эту подпись, сравнивая ее со своей
собственной, вычисленной хешированием. Если подписи совпадают, значит JWT
валидный, т.е. пришел от проверенного источника. Если подписи не совпадают,
значит что-то пошло не так — возможно, это является признаком потенциальной
атаки.
Таким образом, проверяя JWT, приложение добавляет доверительный слой (a layer of trust) между собой и пользователем
Рефреш токен (RT) — эти токены выполняют только одну специфичную задачу — получение нового токена доступа. И на этот раз без сервера авторизации не обойтись. Они долгоживущие, но одноразовые.
Основной сценарий использования такой: как только старый JWT истекает, то с ним
мы уже не можем получить приватные данные, тогда отправляем RT и нам приходит
новая пара JWT+RT.
С новым JWT мы снова можем обращаться к приватным ресурсам. Конечно, рефреш
токен тоже может протухнуть, но случится это не скоро, поскольку живет он
намного дольше своего собрата.
Ресурс для изучения ссылка
ServiceMesh - парадигма организации сетевого взаимодействия микросервисов.
Когда монолит разбивается на микросервисы, возникает несколько проблем: как
организовать эффективную коммуникацию этих микросервисов. Парадигма сервис мэш
заключается в том, что для каждого микросервиса будет внедрен прокси, который
будет перехватывать и перенаправлять трафик. Попутно на этом же прокси может
быть организовано терминирование tls, сбор метрик, трейсов. Исользование
servicemesh позволяет организовать канареечное обновление микросервисов, когда
только часть клиентов будет направляться на новую версию приложения.
Самой популярной реализацией servicemash в kubernetes считается istio. Он
состоит из своего controlplane на istiod, своего ingress-gateway для кластера.
Активировать инъекцию проксей envoy как сайдкаров к подам микросервисов можно:
- выставить лэйбл sidecar.istio.io/inject="true" - для pod
- выставить лэйбл istio-injection=enabled - для для ns
- через инструмент командной строки istioctl
Requests Errors Duration
Utilisation Saturation Errors
Latency Traffic Errors Saturation
Специфично для oracle. не буду учить пока явно не потребуется с этим работать
level 0 - full backup - снэпшот
level 1 - increnmental
От чего берется разница при incremental backup - с времени последнего snapshot (полного бэкапа) до момента снятия инкрементального
Пулинг соединений
connection pool - разделение коннектов по типу write и read - при помощи
pgbouncer невозможно
Максимальное количество конкурентных подключений к БД postgres
superuser_reserved_connections - резервируются для админа
По дефолту 100 и 3, т.е. для полезной нагрузки - 97
В чем опасность выставления высоких значений max_connections?
Если все возможные конекшены заработают одновременно, это сильно нагрузит
систему, процессор будет метаться переключая процессы и в ожидании завершения
IO подсистемы. Такое может привести даже к зависанию.
Каждое подключение использует ОЗУ (ограничивается параметром work_mem для каждой операции), т.е. большее значение max_connections потребует снизитиь work_mem, а он будет влиять на скорость операций
postgres=# SHOW MAX_CONNECTIONS;
max_connections
-----------------
100
(1 row)
postgres=# SHOW WORK_MEM;
work_mem
----------
4MB
(1 row)
Информацию о подключениях можно получить:
SELECT * FROM PG_STAT_ACTIVITY;
Как управлять жизненным циклом индексов? - задать ILM через Kibana или api ILM:
PUT _ilm/policy/custom
{
"policy": {
"phases": {
"warm": {
"actions": {
"rollover": {
"max_size": "1GB",
"max_age": "1h"
}
}
},
"delete": {
"min_age": "1h",
"actions": {
"delete": {}
}
}
}
}
}
Фазы:
- Hot — индекс активно обновляется и запрашивается
- Warm — индекс больше не обновляется, но всё ещё запрашивается
- Cold — индекс больше не обновляется и редко запрашивается. Информация всё ещё должна быть доступна для поиска, но запросы могут выполняться медленнее
- Delete — индекс больше не нужен и может быть безопасно удален
Синхронная репликация - изменения записываются в WAL хотябы одного слейва, только после подтверждения слейвом мастеру фиксируются на мастере. Преимущество - надежность
Асинхронная репликация - изменения сначала применяются на мастере, затем WAL отправляется на реплики. Преимущество - скорость.
Q: liquibase в java как работает как понимает что нужно добавлять только новые
A: Происходит сверка с таблицей databaseChangelog от changeset считаются хэши и
хранятся в таблице. Если хеш в таблице есть, то changeset уже мигрировался
При первом запуске миграции Liquibase или Flyway создает таблицу в схеме базы данных для отслеживания примененных changeset и дальше работает с ней автоматически.
Если изменение уже применялось, повторного выполнения не будет.
конфигурация postgress. Max Connect параметр?
Отмасштабировать горизонтально и читающие запросы отправлять на реплики
- /var/log/
- dmesg - логи ядра,
- логи контейнеров на хосте
- количество inod
- iostat
- top
- lsblk
- fstab
- ss -p
$ lsof -i TCP
Подробный ответ: на Хабре
Перехватывает syscalls программы переданной как аргумент.
strace отслеживает не только syscalls но и передаваемые процессу сигналы.
По дефолту вывод программы и вывод от strace будут смешаны. Можно отфильтровать поток системных вызовов в файл через ключ о:
$ strace -o strace.log <комманда для перехвата>
Отслеживать конкретный вызов можно через флаг е:
$ strace -e trace=write echo "hello"
write(1, "hello\n", 6hello
) = 6
+++ exited with 0 +++
Или исключить некоторые вызовы через -o trace=\!<syscall_name>
Подцепиться к уже работающему процессу можно через флаг - p <PID>
Отслеживать вызовы не только родительского, но и дочерних процессов можно через
флаг - f
. В каждой строке вывода будет указываться PID процесса к которому
строка относится.
Через флаг -y
можно отслеживать обращения к конкретным файлам, а не
дескрипторы, например от вызовов write
Можно отслеживать вызовы только связанные с обращением к определенному файлу
через -P <путь к файлу>
- perf - утилита, легковесная альтернатива strace
- framegraphs
- tcpdump -i
- wireshark
- текстовый - tshark
Характеризует очередь процессов на выполнение. Считаются активные процессы в
состояниях R и D.
Треды от процессов go или java тоже будут влиять на очередь
сигнал | назначение | |
---|---|---|
1 | SIGHUP | |
2 | SIGINT | |
3 | SIGQUIT | |
4 | SIGILL | |
5 | SIGTRAP | |
6 | SIGABRT | |
7 | SIGBUS | |
8 | SIGFPE | |
9 | SIGKILL | |
10 | SIGUSR1 | |
11 | SIGSEGV | |
12 | SIGUSR2 | |
13 | SIGPIPE | |
14 | SIGALRM | |
15 | SIGTERM | |
16 | SIGSTKFLT | |
17 | SIGCHLD | |
18 | SIGCONT | |
19 | SIGSTOP | |
20 | SIGTSTP | |
21 | SIGTTIN | |
22 | SIGTTOU | |
23 | SIGURG | |
24 | SIGXCPU | |
25 | SIGXFSZ | |
26 | SIGVTALRM | |
27 | SIGPROF | |
28 | SIGWINCH | |
29 | SIGIO | |
30 | SIGPWR | |
31 | SIGSYS | |
34 | SIGRTMIN | |
35 | SIGRTMIN+1 | |
36 | SIGRTMIN+2 | |
37 | SIGRTMIN+3 | |
38 | SIGRTMIN+4 | |
39 | SIGRTMIN+5 | |
40 | SIGRTMIN+6 | |
41 | SIGRTMIN+7 | |
42 | SIGRTMIN+8 | |
43 | SIGRTMIN+9 | |
44 | SIGRTMIN+10 | |
45 | SIGRTMIN+11 | |
46 | SIGRTMIN+12 | |
47 | SIGRTMIN+13 | |
48 | SIGRTMIN+14 | |
49 | SIGRTMIN+15 | |
50 | SIGRTMAX-14 | |
51 | SIGRTMAX-13 | |
52 | SIGRTMAX-12 | |
53 | SIGRTMAX-11 | |
54 | SIGRTMAX-10 | |
55 | SIGRTMAX-9 | |
56 | SIGRTMAX-8 | |
57 | SIGRTMAX-7 | |
58 | SIGRTMAX-6 | |
59 | SIGRTMAX-5 | |
60 | SIGRTMAX-4 | |
61 | SIGRTMAX-3 | |
62 | SIGRTMAX-2 | |
63 | SIGRTMAX-1 | |
64 | SIGRTMAX |
kill -9 <PID>
-> ядру
kill -15 <PID>
-> процессу для gracefull shutdown. Есть таймаут
Particularly useful signals include HUP, INT, KILL, STOP, CONT, and 0
kill -1
kill -2
kill -19
kill -18
Первым пришел - первым обслужен - по таймеру не прерывется Планирование с приоритетом самого короткого задания Shortest Job First Кратчайшее оставшееся время Приоритетное планирование Планирование с циклическим перебором - процессы прерываются через одинаковый квант времени Справедливое планирование
№ п/п | команда | как будет интерпретировано |
---|---|---|
1 | command1 && command2 | Выполнить command2 только если command1 вернула 0 |
2 | command1 & command2 | Выполнение command1 отправить в фон (bg) и сразу выполнить command2 в (fg) |
3 | command1 ; command2 | Выполнить команды последовательно вне зависимости от результата первой |
4 | command1 || command2 | Выполнить command1, если она вернет не 0, выполнить command2 |
5 | command1 | command2 | Пайп. Передать stdout command1 в stadin command2 |
6 | command1 command2 | Выполнить command1 с аргументом 'command2' |
Как посмотреть какие есть controller-managers?
При классической установке argo-cd появляется несколько (3) контроллеров.
Для чего эти контроллеры нужны?
Для некастомных ресурсов в k8s имеются controller-managers которые отслеживают состояние этих ресурсов и управляют ими через api-server
Для кастом ресурсов необходимо предоставить свои кастом контроллеры.
У argo-cd это application group и application controller manager
Более удобная абстракция над replicaset позволяет реализовать стратегию deployment
- rolling update
- recreate
добавляет версионирование
--wait
- перед внесением записи о релизе как successfull будет ожидать
перехода подов в состояние ready но не более чем указано в параметре
--timeout
(default 5m0s)
--atomic
- откатит изменения если в upgrade случится ошибка
При использовании --atomic
флаг --wait
устанавливается автоматически
- через configmap / secret
- через env
- через init container / volume
Оборачивает вызов функции другой функцией.
Декоратор принимает функцию в качестве аргумента и возвращает функцию.
(doc string)? использовать functools.wraps() для декорирования wrapper функции самого декоратора
try
except - только в исключитьельной ситуации
finally - всегда
Как обрабатывать любую ошибку?
смотреть в сторону наследования, кто родитель классов групп ошибок и
перехватывать его
Перехватить ошибку 3й вложенной функции в 1ой (родительской)?
поднять свою ошибку в 3й функции при помощи raise и обработать в 1ой
try:
raise Exception("Some exception")
except Exception as e:
print("Exception " + str(e))
Это SSO сервис для управления доступом пользователей к веб приложениям
открытый дескриптор файла, например если известен процесс который имеет в него дескриптор, то можно пролистать:
$ ls -lA /proc/<pid>/fd
или по имени файла:
$ lsof <путь к файлу>
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
<команда> <PID> <пользователь> <дескриптор> REG 259,5 <размер> <inode> <путь к файлу>
например, это дескриптор FD=4, то можно обрезать файл до нуля байт:
$ truncate -s 0 /proc/<pid>/fd/4
inode - метаданные о файле:
- даты созания и модификации,
- права доступа
- в каком блоке размещаются данные
В некоторых файловых системах количество inode фиксировано и задается при
создании, в других может увеличиваться. Посмотреть количесво свободных inode
через df -i
inode хранятся в таблице в файловой системе
посмотреть информации можно через
sudo debugfs /dev/<раздел с файловой системой>
stat <2>
# листинг содержимого:
ls -l <2>
в выводимом результате будет информация по /, в т.ч. номер блока файла
корень имеет inode с номером 2
Посмотреть информацию по файловой системе можно командой
$ sudo tune2fs -l /dev/nvme0n1p5
tune2fs 1.45.5 (07-Jan-2020)
Filesystem volume name: <none>
Last mounted on: /
Filesystem UUID: <какой-то id>
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 15187968
Block count: 60751872
Reserved block count: 3037593
Free blocks: 24119087
Free inodes: 13383310
First block: 0
Block size: 4096
Fragment size: 4096
Group descriptor size: 64
Reserved GDT blocks: 1024
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 8192
Inode blocks per group: 512
Flex block group size: 16
Filesystem created: Tue Mar 15 11:04:34 2022
Last mount time: Wed Jul 12 08:08:18 2023
Last write time: Wed Jul 12 08:08:18 2023
Mount count: 718
Maximum mount count: -1
Last checked: Sat Jun 25 00:07:37 2022
Check interval: 0 (<none>)
Lifetime writes: 2934 GB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 32
Desired extra isize: 32
Journal inode: 8
First orphan inode: 2495490
Default directory hash: half_md4
Directory Hash Seed: <hash>
Journal backup: inode blocks
Checksum type: crc32c
Checksum: 0xb08ae7d8
какое то количество inodes и blocks могут быть зарезервированы для рута
память используемая процессом - колонка res available memory = free + buff/cache
buff/cache - буферная память используемая устройствами ввода-вывода. cache - кэш, файлы которые могут быть прочитаны опять.
Cкинуть буферы и почистить кэш:
~# sync; echo 1 > /proc/sys/vm/drop_caches
- Объединить интерфейсы с помощью утилиты ifenslave. Будет создан bond0 который будет агрегировать другие интерфейсы
- параметры из /proc/sys/: /proc/sys/net/ip_local_port_range и /proc/sys/fs/file-max
Расширение гранулярности доступа к файлам и папкам - списки контроля доступа
Для работы с этим потребуется смонтировать файловую систему с поддержкой
acl mount
установка и просмотр правил через команды setfacl; getfacl
признак наличия acl на каталоге - символ + после стандартных прав доступа в
выводе ls -l
Нет. слишком опасно.
Механизм для разграничения доступных процессу ресурсов
Память, процессорное время, дисковое пространство
по пути /sys/fs/cgroup/<подсистема>/tasks
Через какое количество сегментов отправляется подтверждение о получении
Они зашиты в ОС. IP адреса общеизвестны
Их 13 штук + много реплик отвечающих по anycast
Как запускаются объекты при отправке манифеста с деплойментом:
Может быть настроен в спецификации на уровне pod и на уровне container
spec:
containers:
– name: <имя_контейнера>
image: alpine
securityContext:
...
Можно переопределять user, mount volums
Ключи поля securityContext | Значение ключа | эффект |
---|---|---|
spec.containers.<контейнер>.securityContext.runAsUser | <ID пользователя> | Контейнер будет запущен от пользователя с указанным |
spec.containers.<контейнер>.securityContext.runAsNonRoot | true | От рута контейнер НЕ будет запущен |
spec.containers.<контейнер>.securityContext.privileged | true | Будет запущен в привилегированном режиме, например для работы с iptables или с устройствами /dev/* |
spec.containers.<контейнер>.securityContext.capabilities | add.[<список CAP>] | Меняет привилегии более гранулярно чем Nonroot или privileged |
spec.containers.<контейнер>.securityContext.capabilities | drop.[<список CAP>] | capabilities linux-docker |
spec.containers.<контейнер>.securityContext.readOnlyRootFilesystem | true | Запрещает контейнеру запись в файловую систему контейнера, можно писать только в смонтированные volumeMounts.readOnly: false |
spec.securityContext.fsGroup | <group_id> | GUID пользователя контейнеров пода будет <group_id>. Возможна совместная работа с файлами в томах |
Все такие контексты перед применением манифеста api-server проходят проверку на соответствие PodSecurityPolicy
Через группы в инвентори
-
Отключить сбор фактов
gather_facts: False
-
По умолчанию таски для групп выполняются параллельно на 5-и узлах, затем на следующих 5-и. Можно настроить в ansible.cfg:
[defaults] inventory = ./hosts forks = <количество>
-
вместо копирования скриптов отправлять их в stdin интерпретатору python
[ssh_connection] pipelining = true
-
тюнинг ssh в ansible.cfg
ControlMaster – позволяет «утрамбовать» несколько одновременных SSH-сеансов с удаленным узлом в одно сетевое подключение. Это экономит время, поскольку сетевое подключение к узлу производится только при первом SSH-сеансе, а последующие просто работают через это подключение.
ControlPersist – время, в течение которого неактивный SSH-сеанс остается открытым в фоновом режиме. Например, ControlPersist=60s означает, что неактивное соединение живет 60 секунд: host_key_checking - проверка и верификация SSH ключей[defaults] host_key_checking = False [ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=60s
-
Не дожидаться выполнения task до конца и запускать следующую
- hosts: servers strategy: free tasks: ...
В официальной документации указано 22 способа определять переменные. И указаны их приоритеты
- hosts
- group_vars
- host_vars
- facts
- task vars
- command line variables
через параметры jvm:
параметр | назначение |
---|---|
-Xms512m | начальный размер кучи |
-Xmx1024m | максимальный размер кучи |
-Xss1m | размер стека потоков |
-Xmn256m | размер кучи для молодого поколения. Должно быть ниже, чем -Xmx |
-verbosegc | выводить логи сборщика мусора |
-cp | class path - указать путь к библиотеке |
-jar | указать путь к архиву с байт кодом, который запустить |
-D<property_name>=<property_value> - передать приложению параметр <property_name> со значением <property_value>
Получить доступ к <property_name> внутри приложения можно
String propertyName = System.getProperty("<property_name>", "default_value");
При запуске приложения передать параметр:
$ java \
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 \
-jar target/jarfile.jar
suspend=n - не ждать пока подключится клиент и приступить к выполнению приложения сразу или suspend=y - не начинать выполнение приложения пока не подключится клиент
kv2 поддерживает версионность
vault kv delete - при удалении секрета метаданные остаются
vault kv destroy - удаление ключа делает vault kv undelete невозможным
нужен сервис аккаунт для волта для валидации токена в кубе
волту нужна будет сервисная учетка с правами на auth delegate стучаться на api k8s для валидации токена.
approle - метод аутентификации в волте
proxy_set_headers -> переопределить хэдеры на таргет
add_header -> переопределить в респонс
как подсчитать какую долю процессовгого времени потребляет контейнер в кубе через rate
set -eo pipefail
посмотреть открытые порты:
lsof -i
netcat -tunapl
ss -tunapl
посмотреть открытые сокеты: lsof -i -U
посмотреть трафик:
tcpdump
iftop
это генератор трафика, предназначена для проверки скорости и пропускной
способности сети. Состоит из клиентской и серверной части.
Для игр с этим потребуется 2 компьютера.
Один запускаем как сервер с ключем -s
, другой как клиент с ключем -c
и
передаем адрес сервера
для изменения направления можно применять ключ -R
Это такие файлы которым выделяется места больше чем фактически можно.
Определяется по тому что его использование диска меньше чем его размер
Через du -sh
один размер, а через ls -lh
- другой
искать через find, с параметром форматированного вывода "%S\t%p\n"
$ sudo find /var/log -type f -printf "%S\t%p\t%s\n"
1 /var/log/tallylog
1.00095 /var/log/audit/audit.log.1
0.0419982 /var/log/lastlog
..
..
Здесь первая колонка равна отношению BLOCK-SIZE*st_blocks / st_size,
которое для sparse файлов будет менее 1
lsblk,
fdisk -l
- R - running или runnable
- D - непрерываемый сон. запросил данные и ждет их получения. прервать процесс не получится
- I - бездействующий. не учитывается в load average
- S - спит - ожидает ресурсы которые в данный момент недоступны. после получения ресурсов перейдет в R
- T/t - остановленный сигналом или отладчиком
- Z - после завершения работы зомби освобождает свои ресурсы, но сохраняется запись в таблице pid. Для удаления записи посылается сигнал родителю процесса. Если родитель не обрабатывает этот сигнал, не освобождает PID по каким то причинам, то процесс остается зомби
Если есть идентификатор родительского зомби-процесса, можно использовать следующую команду для отправки сигнала SIGCHLD родительскому процессу:
$ kill -s SIGCHLD <Parent PID>
Подброс новых конфигураций
Хелм хуки это специальные темплйты манифестов в папке с темплейтами чарта,
которые имеют аннотацию, определяющую в какой момент хук должен быть исполнен.
Типичные примеры использования:
- накатка миграций перед обновлением приложения
- подгрузка секретов для доступа к репо с образами перед раскаткой сервиса
- зачистка внешних ресурсов после удаления сервиса
- проверка предварительных условий перед раскаткой сервиса
Удаление подов хуков автоматически не происходит при удалении релизов. Такие поды удалить нужно вручную.
pipelines для модификаций : перевести в верхний регистр, обернуть в кавычки строковые значения, использовать default
---
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
app: frontend
spec:
type: {{ .Values.service.type | default "NodePort" }}
selector:
app: frontend
ports:
- name: http
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
{{ if eq .Values.service.type "NodePort" }}nodePort: {{ .Values.service.nodePort }}{{ end }}
...
(iptables)
Методом срезов с отрицательным шагом:
# взять срез с шагом -1
>>> a="abc"
>>> a[::-1]
'cba'
Или воспользоваться функцией reversed(<строка>):
>>> a='string'
>>> print(reversed(a))
<reversed object at 0x7f341f467f70>
>>> b=''.join(reversed(a))
>>> print(b)
gnirts
What happens when one of your Kubernetes nodes fails?
Post node failure, in about 1 minute, kubectl get nodes will report NotReady state.
In about 5 minutes, the states of all the pods running on the NotReady node will change to either Unknown or NodeLost. This is based on pod eviction timeout settings, the default duration is 5 minutes.
Irrespective of deployments (StatefuleSet or Deployment), Kubernetes will automatically evict the pod on the failed node and then try to recreate a new one with old volumes.
If the node is back online within 5 – 6 minutes of the failure, Kubernetes will restart pods, unmount, and re-mount volumes.
Incase evicted pod gets stuck in Terminating state and the attached volumes cannot be released/reused, the newly created pod(s) will get stuck in ContainerCreating state. There are 2 options now:
- Either to forcefully delete the stuck pods manually
- Kubernetes will take about another 6 minutes to delete the VolumeAttachment objects associated with the Pod and then finally detach the volume from the lost Node and allow it to be used by the new pod(s).
In summary, if the failed node is recovered later, Kubernetes will restart those terminating pods, detach the volumes, wait for the old VolumeAttachment cleanup, and reuse (re-attach & re-mount) the volumes. Typically these steps would take about 1 ~ 7 minutes.
W(1) User Commands W(1)
NAME
w - Show who is logged on and what they are doing.
SYNOPSIS
w [options] user [...]
DESCRIPTION
w displays information about the users currently on the machine, and their processes. The header shows, in this order, the current time, how long the system has been
running, how many users are currently logged on, and the system load averages for the past 1, 5, and 15 minutes.
The following entries are displayed for each user: login name, the tty name, the remote host, login time, idle time, JCPU, PCPU, and the command line of their current
process.
The JCPU time is the time used by all processes attached to the tty. It does not include past background jobs, but does include currently running background jobs.
The PCPU time is the time used by the current process, named in the "what" field.
запущен процесс?
cat /proc/<PID>/cmdline
-
Внести запись в /etc/passwd с данными пользователя:
username : password : UID : GID : Comments : User Home Directory : User Login Shell 1 2 3 4 5 6 7 1- Username
2- Password (x) --> encrypted password is stored at /etc/shadow file.
3- User ID: ID (0-Zero) is reserved for root, UID (1-99) reserved for system users and UID (100-999) reserved for system accounts/groups
4- Group ID (GID): is stored at /etc/group file.
5- Comment
6- Home directory (/home/$USER): It indicates the user's home directory.
7- shell (/bin/bash): It indicates the user's shell. -
Внести запись в /etc/group о группе пользователя:
groupname : x : group_id : -
Задать пароль пользователю
$ sudo passwd <user_name>
Посылает сигнал SIGHUP
$ sudo nginx -s <argument>
Send a signal to the master process.
The argument signal can be one of: stop, quit, reopen, reload
argument | signal |
---|---|
stop | SIGTERM |
quit | SIGQUIT |
reopen | SIGUSR1 |
reload | SIGHUP |
set -e
- в скриптах, завершит выполнение скрипта как только случится ошибка, без этого флага ошибка останется незамеченной и скрипт продолжит выполнениеset -x
- печатать команды в терминал, полезно для отладочных целейset -u
- если произойдет обращение к переменной, которая не была объявлена в скрипте, то скрипт упадет. В противном случае, отсутствующая переменная будет интерпретирована как ""set -o pipefail
- по умолчанию из пайпа возвращается код последней команды, с этим флагом если посередине исполнения образуется ненулевой код, то он и будет возвращен
при помощи команды trap
#!/bin/bash
trap 'echo "# $BASH_COMMAND";read' DEBUG
echo line1
echo line2
echo line3
перед выолнением каждой строки скрипта будет выводиться значение $BASH_COMMAND (которая будет сейчас выполняться) и будет запрошен ввод для продолжения
meta: flush handlers - незамедлительное исполнение вызванных ранее при помощи notify обработчиков
tasks:
- name: "Some task"
command: ...
- name: "Flush handlers"
meta: flush_handlers
- name: "Some other task"
command: ...
- set_facts:
my_var = "my_value"
сначала нужно сделать ее register на одной машине (пусть это будет единственная машина в группе хостов first_group) и, далее в плейбуке, можно будет обращаться к этой переменной так:
- name: print value_to_reuse
debug:
var: hostvars[groups['first_group'].0].value_to_reuse.stdout_lines
UDP и TCP
по UDP можно передавать не более 512 байт.
DNS передает данные зоны с помощью TCP
И при синхронизации DNS серверов
NAT трансляция IP адресов
Port forwarding (PAT) то же самое, только на уровне портов
pvc, а deployment такое не умеет
Что произойдет если worker node становится недоступной?
node controller не сможет связаться с нодой, ждет 40с и переводит состояние ноды в Unknown
статус подов stateful set станет Terminating или Unknown. Удалены и перевоссозданы не будут.
Если нода опять заведется, а этот под был запущен на другой ноде, то может оказаться что их будут работать 2шт, с общим pvc - т.е. нарушение принципа exactly once / избежание split brain
Без удаления pod stateful set новый не будет создан
При открытии файла вызов к ОС возвращает файловый дескриптор - номер индекса в специальной структуре данных, ассоциированной с процессом. Эта структура включает в себя, том числе, копию дискового inode.
$ echo 'test' > /tmp/test && vi /tmp/test
$ ps aux | grep ' vi /tmp/test'
anduser 72299 0.0 0.0 23724 10496 pts/2 S+ 06:09 0:00 vi /tmp/test
anduser 72311 0.0 0.0 9224 2560 pts/1 S+ 06:11 0:00 grep --color=auto vi /tmp/test
$ ls -l /proc/72299/fd
total 0
lrwx------ 1 anduser anduser 64 авг 14 06:10 0 -> /dev/pts/2
lrwx------ 1 anduser anduser 64 авг 14 06:10 1 -> /dev/pts/2
lrwx------ 1 anduser anduser 64 авг 14 06:10 2 -> /dev/pts/2
lrwx------ 1 anduser anduser 64 авг 14 06:10 4 -> /tmp/.test.swp
Файловый дескриптор для открытого в редакторе файла (по пути /tmp/test) - 4
inode - описатель файла. Запись на диске с метаинформацией о файле.
$ ls -l /tmp/test
-rw-rw-r-- 1 anduser anduser 5 авг 14 06:06 /tmp/test
Если удалить файл, то счетчик hardlink в его inode записи будет уменьшен на 1. Если он стал 0 - запись удаляется из таблицы inode. inode может быть переиспользован.
Но если перед удалением файла он был открыт каким либо процессом, то открытый fd в файл не даст ядру отметить в структурах в памяти что этот файл удален и блоки освобождены.
Такое положение сохранится до перезагрузки системы, т.к. это хранится в ОЗУ.
Если нужно освободить место, то нужно будет сделать truncate по этому fd или перенаправить в него /dev/null.
Constraints это ограничения накладываемые на таблицы и поля, используются чтобы контролировать типы данных и принимаемые значения.
Могут быть на уровне таблицы или поля.
название | описание |
---|---|
NOT NULL | Поле не сможет принят значение NULL |
UNIQUE | Все значения в колонке уникальные |
PRIMARY KEY | Комбинация NOT NULL и UNIQUE. Унакальный id любой строки |
FOREIGN KEY | Связывает поля из разных таблиц |
CHECK | Накладывает условие на значения колонки |
DEFAULT | Устанавливает значение по умолчанию если не указано |
вид | описание |
---|---|
INNER JOIN | выводятся только совпадающие строки |
LEFT JOIN | все поля из левой таблицы + совпадающие поля из правой. Не совпашие поля тоже добаляются NULL значением |
RIGHT JOIN | все поля из правой таблицы + совпадающие поля из левой. Не совпашие поля тоже добаляются NULL значением |
FULL JOIN | все поля из обеих таблиц |
CROSS JOIN | все возможные объединения |
вид | особенности |
---|---|
Логическая | pg_dump, pg_dumpall, pg_resore |
- клиент к базе. требуются права на копируемые таблицы. | |
- дамп базы можно загрузить в более новые версии или на серверы с другой архитектурой | |
- восстановление большой базы будет занимать много времени по сравнению с физической репликацией | |
- перед восстановлением саму базу, пользователей надо создать руками | |
- выгрузка в текстовом формате или в арив. Доступна параллельная выгрузка в архивном формате | |
Физическая | - Копируется каталог с данными после отстановки БД |
- Или создать checkpoint, сделать снепшот и восстанавливать из снепшота. | |
База будет считать что в момент снятия снепшота она была аварийно выключена. | |
Будет накатываться журнал WAL | |
Файлы данных, табличные пространства, журналы должны находиться на обном разделе, т.к. снимок должен | |
быть одновременным | |
- rsync + rsync --checksum | |
- pg_basebackup | |
Потоковая | - архивирование wal и восстановление из базового архива + из wal |
- нужен wal_level не ниже replica и archive_mode=on и задать archive_command | |
- архивирование WAL не учитывает изменения конфигурационных файлов. Их нужно архивировать отдельно |
Традиционно использовался telnet, но в контейнере нет такого исполняемого файла.
Интерпретатор оболочки bash воспринимает некоторые пути при перенаправлении потоков ввода-вывода по особенному.
Если файлы существуют в ОС, - они будут использованы. Если нет, - оболочка будет их эмулировать с таким поведением:
'специальный' путь | действие оболочки |
---|---|
/dev/fd/fd | Если fd целое число, файловый дескриптор fd дублируется |
/dev/stdin | Файловый дескриптор 0 дублируется |
/dev/stdout | Файловый дескриптор 1 дублируется |
/dev/stderr | Файловый дескриптор 2 дублируется |
/dev/tcp/host/port | Если host - имя или адрес и port - целое число или имя сервиса -> создания TCP сокета |
/dev/udp/host/port | Если host - имя или адрес и port - целое число или имя сервиса -> создания UDP сокета |
NOTE: в оболочке sh такое не работает