Перейти к основному содержимому

Управление большим парком qf

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

Что хранится в каждом контуре​

ОбъектИнтерфейс управленияНазначение
qf_policy и selectorTerraformПравила и область их действия
qf_object_groupTerraformПереиспользуемые наборы адресов, портов и хостов
Bootstrap-токенКонсоль или REST APIНачальные лейблы и параметры enrollment
Host groupКонсоль или REST APIОбщие лейблы и явный список участников

Лейблы из label_template копируются на хост при enrollment. Последующее изменение токена не меняет уже подключённые хосты.

Членство в host group всегда явное. Хост добавляется через консоль, REST API или поле target_group_id bulk-токена. Совпадение лейблов само по себе не добавляет хост в группу.

Для selector используются эффективные лейблы:

лейблы групп по приоритету + собственные лейблы хоста

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

Рекомендуемая схема: selector по лейблам​

В этой схеме Terraform описывает правила и selector, а bulk-токен выдаёт новым хостам те же лейблы.

Terraform: policy selector role=web, env=prod
│
▼
bulk-токен: label_template role=web, env=prod
│
▼
новый хост получает лейблы и автоматически попадает под политику

1. Описать политику в Terraform​

resource "qf_object_group" "mgmt_net" {
name = "mgmt-net"
type = "ipset"
spec = jsonencode({ cidrs = ["10.0.0.0/16"] })
}

resource "qf_policy" "web" {
name = "web-ingress"
priority = 100
selector = jsonencode({
matchLabels = { role = "web", env = "prod" }
})

rule {
name = "allow-https"
priority = 10
direction = "ingress"
action = "allow"
match = jsonencode({ protocol = "tcp", dst_ports = ["443"] })
}
}

Пары внутри matchLabels соединены по AND. Политика из примера действует только на хосты, у которых одновременно есть role=web и env=prod.

2. Выпустить bulk-токен для когорты​

Токен создаётся в разделе Tokens или через POST /tokens:

{
"type": "bulk",
"label_template": { "role": "web", "env": "prod" },
"max_uses": 500,
"ttl_seconds": 2592000
}

Один токен обслуживает несколько хостов в пределах TTL и max_uses. Значение max_uses меньше единицы заменяется сервером на 1.

3. Подключить хосты​

Автоматизация распространяет agent.conf с адресом Control Plane, токеном и одним из поддерживаемых способов проверки CA. При первом подключении агент получает сертификат, а Control Plane сохраняет лейблы токена и вычисляет подходящие политики.

Настройка доверия и enrollment описаны в руководстве по подключению хоста.

Host groups для общих изменяемых лейблов​

Host group полезна, когда одинаковый набор лейблов нужно менять для нескольких хостов в одном месте. Например, группа может выдавать своим участникам maintenance=true.

Порядок работы:

  1. Создать группу и задать её лейблы.
  2. Добавить существующие хосты через консоль или POST /host-groups/{id}/members.
  3. Для новых хостов при необходимости указать target_group_id в bulk-токене.
  4. Строить политики по эффективным лейблам.

Пример токена с автоматическим вступлением в группу:

{
"type": "bulk",
"target_group_id": "<group-uuid>",
"max_uses": 500,
"ttl_seconds": 2592000
}

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

Как работает назначение группы​

В консоли добавление строки в таблице Группы записывает в selector текущие matchLabels группы и служебное поле _groupId. При сопоставлении Control Plane проверяет лейблы; _groupId не ограничивает результат явными участниками группы.

Следствия:

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

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

Подробнее — в руководстве по selector.

Как выбрать между токеном и группой​

ЗадачаПодходящий механизм
Выдать начальные role и env при enrollmentlabel_template токена
Автоматически подключать новые хосты к политикеSelector по лейблам токена
Менять общий лейбл у нескольких хостовЛейбл host group
Явно вести состав административной группыЧленство в host group
Добавлять новые хосты в группу без ручного шагаtarget_group_id bulk-токена
Сделать исключение для одного хоста_hostId через таблицу Хосты политики

Обычно постоянные признаки, например role и env, задаются токеном. Временные признаки, например maintenance или canary, удобнее выдавать через группы.

Изменение лейблов подключённых хостов​

label_template не синхронизирует лейблы после enrollment. Для одного хоста используется PATCH /hosts/{id}. Поле labels заменяет всю карту, поэтому перед изменением нужно получить текущее значение, объединить его с новым и отправить полный результат.

Отдельного bulk-endpoint для лейблов нет. Массовое изменение выполняется циклом запросов или через лейбл host group. Во время цикла другие изменения тех же лейблов следует приостановить: параллельный full-replace может потерять одну из правок.

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

AND и OR в selector​

Все пары matchLabels одного блока соединяются по AND:

{ "matchLabels": { "role": "web", "env": "prod" } }

Несколько блоков anyOf соединяются по OR:

{
"anyOf": [
{ "matchLabels": { "role": "web" } },
{ "matchLabels": { "role": "api" } }
]
}

В Terraform anyOf задаётся внутри jsonencode. Консоль формирует его при добавлении нескольких назначений.

Пустой selector {} выбирает весь парк и требует confirm_match_all = true в Terraform. Selector {"anyOf":[]} не выбирает ни одного хоста.

Группы объектов​

Группа объектов хранит переиспользуемое ограничение правила:

ТипСодержимоеРезультат при компиляции
ipsetCIDR и IP-адресаСписок сетей и адресов
portsetПорты и диапазоныСписок диапазонов портов
hostsetSelector хостовАдреса интерфейсов подходящих хостов

ipset и portset не могут быть пустыми. Если hostset временно не находит хосты или их dataplane-адреса, Control Plane не превращает пустой результат в ANY и не выпускает зависимое поколение правил. Агент продолжает использовать last-good generation до появления подходящих адресов.

Изменение группы объектов пересчитывает все политики, которые на неё ссылаются. Группу с активными ссылками нельзя архивировать: API возвращает 409. Неиспользуемые группы не удаляются автоматически; их жизненным циклом управляет оператор.

Проверка перед массовым изменением​

Для изменения существующей политики или группы Зона влияния показывает результат черновика до применения. При создании нового объекта такого предпросмотра нет, поэтому область задаётся узким selector, а блокирующее правило сначала создаётся с действием log.

Перед применением проверить:

  • область действия в Зоне влияния;
  • результат AND/OR и возможные совпадения общих лейблов;
  • разрешения для SSH и других административных каналов перед широким deny;
  • состояние desired и confirmed generation после применения;
  • last-good generation на хостах, которые были офлайн.

Стабильные политики и группы объектов остаются в Git и проходят обычное ревью. Токены имеют ограниченные TTL и max_uses, а временные изменения состава парка выполняются через группы и лейблы.