документация

Эта статья на Хабре https://habr.com/ru/post/675728/

Описание проблемы

Дано

  • кластер k8s
  • много приложений, которые пишут свои логи в stdout/stderr, а контейнерный движок (в данном случае docker) складывает их в файлы
  • fluent-bit, запущенный на каждой ноде k8s. Он собирает логи, фильтрует их и отправляет в Loki
  • loki - хранилище логов от Grafana Labs

В чём заключается проблема

При просмотре логов через Grafana (источник - Loki) видно, что логи приходят с сильной задержкой или часть логов вообще отсутствует. При просмотре через kubectl logs все логи на месте

Решение проблемы

Settings

  • Client ID

    Уникальный идентификатор клиента

  • Name

    Отображаемое имя (например, в окне согласия (Consent))

  • Description

    Описание

  • Enabled

    Вкл/Выкл

  • Always Display in Console

    Всегда показываться клиента в списках приложений пользователя в Account Management Console

Keycloak Scopes OIDC

default - включен в scopes по-умолчанию

optional - включается в scopes при запроса

consent - отображать в окне согласия при запросе разрешения на аутентификацию у пользователя

scope - добавлять в список scope токена

OIDC

  • profile

    default, consent, scope

    mappers:

    • profile, name, gender, locale, etc…

Realm Settings

General

  • Name

    Название/ID реалма

  • Display name

    Отображаемое имя

  • HTML Display name

    Отображаемое имя с возможность использования html-тегов (например, добавление лого). Если задано, то имеет приоритет над Display name

  • Frontend URL

    Позволяет для реалма задать отдельное доменное имя. Например, можно сделать такой матчинг auth.example.com -> sso.example.com/auth/realms/myrealm. Обработкой занимается встроенный веб-сервер. То же самое можно реализовать через reverse-proxy, типа nginx, с установкой Host хидера при проксировании и “обрезанием” путей

  • Enabled

    Вкл/Выкл

  • User-Managed Access

    Включить управление своими ресурсами в Account Management Console (auth/realms/myrealm/account/resource)

  • Endpoints

    Ссылки OIDC/SAML, где можно получить все доступные точки входа для проктоколов

Оригинальный syslogd

Cвязка journald + rsyslogd

Форматы syslog сообщений

RFC 3164 (устаревший)

RFC 3164 - The BSD Syslog Protocol

Описание формата сообщения

The first part is called the PRI, the second part is the HEADER, and the third part is the MSG. The total length of the packet MUST be 1024 bytes or less

Варианты запуска сборок

  1. Shell executor

    • Небезопасно, т.к. можно выполнять какие угодно docker команды на хосте, в т.ч. пробрасывать хостовые папки и запускать privileged контейнеры
  2. docker-in-docker

    • Изолированные друг от друга контейнеры, т.к. здесь child контейнеры от контейнера dind, а не от хостового docker.sock
    • Необходим запуск с privileged (небезопасно)
  3. Проброс docker.sock

    • Все контейнеры - siblings (видят друг друга), т.к. запускается через хостовый docker
    • Небезопасно, т.к. можно выполнять какие угодно docker команды на хосте, в т.ч. пробрасывать хостовые папки и запускать privileged контейнеры
  4. buildah/buildkit/img

    • Позволяют внутри докер контейнера запускать сборку образа без докер-демона
    • Требуется unprivileged_userns_clone (user namespaces), у которого свои security-риски
    • Синтаксис запуска отличается -> переучивать команду
  5. kaniko

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

Потенциальные векторы атаки

  1. Источник

    • В сборке используется публичный образ, в котором в entrypoint выполняется команда проверки docker.sock и запуск контейнера через него
    • При сборке в зависимостях (напрмер, node) скачивается зловред, который запускается в процессе сборки. Далее проверка docker.sock и запуск контейнера через него
  2. Цель

    • Закрепиться в системе. Через докер возможно установить свои бинарники и сервисы в систему
    • Дальнейший скан сети и поиск уязвимостей для распространения и закрепления

Перезапустить kubelet

Контейнеры продолжают работать, но в момент синхронизации состояния подов с api-server поды могут переходить в состояние 0/1 Running, когда трафик на них перестаёт направляться

Остановить kubelet

Нода переходит в состояние NotReady, никаких событий на подах не происходит - они продолжают пребывать в состоянии 1/1 Running, но трафик на них перестаёт идти (из endpoint’ов сервисов удаляются IP адрес подов, которые находятся на “мёртвой” ноде).

Спустя указанный pod-eviction-timeout (5m по-умолчанию) для kube-controller-manager поды переходят в статус Terminating и начинают запускаться на живых воркерках. Поды будут продолжать находиться в статусе Terminating либо до старта kubelet, либо до удаления ноды из кластера. При этом не выгоняются поды DaemonSet и поды, поднятые kubelet’ом(kube-proxy, nginx-proxy, kube-flannel, nodelocaldns и т.п.)

Атуально для Akka HTTP начиная с версии 10.2.0

Github Issue: Add coordinated shutdown support

По-умолчанию, Akka при завершении (в т.ч. получении SIGTERM) запускает процесс Coordinated Shutdown, в рамках которого происходят последовательно несколько фаз:

  • before-service-unbind
  • service-unbind
  • service-requests-done
  • service-stop
  • before-cluster-shutdown
  • cluster-sharding-shutdown-region
  • cluster-leave
  • cluster-exiting
  • cluster-exiting-done
  • cluster-shutdown
  • before-actor-system-terminate
  • actor-system-terminate

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

В рамках Akka HTTP нас в первую очередь интересуют следующие фазы

  • service-unbind #перестаёт слушаться tcp порт и перестают приниматься новые соединения. Установленные соединения не разрываются
  • service-requests-done #ожидается окончание запросов, которые в данный момент обрабатываются кодом и клиент ожидает на них ответ
  • service-stop #закрываются все установленные соединения

По-умолчанию (default-phase-timeout = 5s), после unbind есть 5 секунд на завершение текущих запросов

При использовании Kubernetes, стоит принимать во внимание также его таймаут terminationGracePeriodSeconds, в течение которого будет ожидаться реакция на SIGTERM, после чего будет послан SIGKILL. По-умолчанию, он равен 30s

Немного о RBAC

В kubernetes есть сущность, которая называется RoleBinding. Она определяет, каким субъектам какая роль будет назначена. RoleBinding действует в рамках namespace, в котором она создана. Для разрешения действий во всех namespace без ограничений необходимо создавать ClusterRoleBinding, который является cluster-wide объектом.

Пример RoleBinding

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: edit
  namespace: project-a-devel
subjects:
- kind: Group
  name: sre
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: edit
  apiGroup: rbac.authorization.k8s.io

Эта роль:

  • Действует в рамках namespace project-a-devel - (metadata:)
  • Применяется к пользователям в группе sre (/O=sre) - (subjects:)
  • Разрешает действия, описанные в созданной по-умолчанию кластерной роли (ClusterRole) edit - (roleRef:)

Пайплайны для Merge Requests существуют отдельно (имеют лейбл detached) и запускается независимо от основного pipeline. Из-за этого если сделать push в репу в ветку, из которой в гитлабе есть открытый МР, то запускаются 2 одинаковых пайплайна

  Есть варианта, чтобы это избежать:

  1. Дублировать все джобы через extends, чтобы разделить на запускаемые на МРах и на обычные
  2. Не запускать CI на некоторых ветках, пока из них нет открытого МРа