Перейти до вмісту

Документація

Агенти

Агент є єдиною частиною Provibr, що працює на вашому власному обладнанні. Він зберігає облікові дані до систем, які ви підключаєте, виконує роботу, про яку просить панель, і повідомляє, що бачить. Платформа ніколи не підключається до вас сама.

Що таке агент

Один агент обслуговує одну мережу: те місце, звідки доступні ваші гіпервізори й панелі. Усе, що Provibr робить з вашою інфраструктурою, проходить через нього.

  • Зʼєднання вихідне. Агент сам відкриває його до платформи й тримає відкритим; ніщо не мусить бути доступним з інтернету, і жодного порту прокидати не треба.
  • Облікові дані живуть на вашому боці. Вони один раз передаються агенту й запечатуються в зашифрованому сейфі на цьому хості; платформа зберігає лише назви полів, які ви заповнили.
  • Він повідомляє про те, що спостерігає. Машини опитуються з коротким інтервалом, а раз на кілька хвилин виконується повне звіряння, і саме так панель помічає машину, яку зупинили поза Provibr.
  • Він чіпає лише те, що ви йому передали. Ресурс, якого немає в записах Provibr, ігнорується: його порахують і одразу забудуть. Агент ніколи не бере машину під керування самотужки.

Який хост йому потрібен

Нічого екзотичного, і нічого не треба встановлювати наперед. Агент — це один статично злінкований виконуваний файл: він несе власну бібліотеку C, тож немає ані середовища виконання, ані інтерпретатора, ані пакунка дистрибутива, який мусив би підійти. Невеликої віртуальної машини цілком достатньо. Розміри, які ми виміряли, наведено далі на цій сторінці.

Що має забезпечити хост агента
ВимогаЩо потрібноЧому
Процесор64-бітний x86 (x86_64, він же amd64)Ми випускаємо одну збірку для Linux, і саме під цю архітектуру її зібрано. Скрипт встановлення перевіряє uname -m ще до того, як щось завантажити, і на будь-якій іншій архітектурі зупиняється, а не встановлює те, що не зможе працювати. Збірки під ARM поки немає.
Операційна системаБудь-який дистрибутив LinuxНіщо не залежить від ваших системних бібліотек, тож ані дистрибутив, ані його версія, ані його менеджер пакунків не мають значення. У наступному розділі перелічено ті, на яких цю збірку справді запускали.
Менеджер службsystemd або ваш власнийСкрипт встановлення пише юніт systemd і вмикає його. На хості без systemd він так само все встановлює й реєструє, а тоді друкує команду, якою запустити агента під тим, що ви використовуєте замість systemd. Половинчасте встановлення було б гіршим за чесне.
Права під час встановленняroot, один разВстановлення створює службовий обліковий запис provibr-agent, два каталоги та юніт. Далі агент працює від імені цього непривілейованого облікового запису, і таким його тримає скрипт оновлення, у який агенту писати не дозволено.
Вихідні зʼєднанняTCP 50051 і 50052 до gw.provibr.netПорт 50051 використовується один раз, під час реєстрації. Порт 50052 несе сесію й лишається відкритим. Обидва працюють через TLS. Якщо ваш фаєрвол фільтрує вихідний трафік, дозволити йому треба лише ці два правила.
Вхідні зʼєднанняЖоднихАгент сам відкриває зʼєднання, тож ніщо не мусить бути доступним з інтернету і жодного порту прокидати до нього не треба. Єдиним винятком є встановлення машин мережею, та й тоді агент слухає лише в локальному сегменті.
Доступ у вашу власну мережуДо систем, які ви підключаєтеЗ вашим гіпервізором, панеллю керування чи ігровою панеллю агент розмовляє через їхній власний API, саме з цього хоста. Чого агент не дістає, тим Provibr не керує.
Памʼять512 МБ цілком достатньоМи виміряли 18 МБ на тисячі машин, розкиданих по пʼятьох системах, — це найважчий випадок у таблиці нижче. Пік припадає на інше: розшифрування файлу ліцензії під час реєстрації ненадовго забирає близько 70 МБ, бо цей крок навмисно дорогий для перебору.
Диск1 ГБ цілком достатньоВиконуваний файл важить 17 МБ, а все, що агент тримає поруч із ним, у наших вимірюваннях лишалося меншим за 40 кБ. Винятком є встановлення машин мережею: воно кешує завантажувальні файли, типово до 20 ГБ.
ГодинникПриблизно правильнийСертифікати й файли ліцензій мають строки дії, і обидві сторони їх перевіряють, тож хост, годинник якого розходиться на дні, зареєструватися не зможе. Підійде будь-який клієнт NTP.
Агент працює від власного непривілейованого облікового запису в посиленому юніті systemd. Він отримує рівно дві додаткові можливості, і лише для того, щоб обслуговувати встановлення мережею; заберіть їх, і працюватиме все, крім цього.

Який саме Linux

Немає ані пакунка, який треба встановити, ані дистрибутива, під який треба підлаштуватися, тож далі йде не перелік підтримуваних систем. Це перелік систем, на яких цю збірку справді запускали. Будь-що інше з 64-бітним ядром Linux для x86 має поводитися так само, а якщо ні, ми хотіли б про це почути.

Дистрибутиви Linux, на яких запускали агента
СистемаВерсіяПримітки
Debian13 (Trixie)
Debian12 (Bookworm)Дистрибутив, на якому пройшла повна перевірка: встановлено, зареєстровано, підключено й опитує.
Ubuntu24.04 LTSСаме з Ubuntu 24.04 ядро почало обмежувати ті самі простори імен, які потрібні автоматизаціям. Агент постачається з профілем AppArmor для цього; усе інше працює без жодних змін.
Ubuntu22.04 LTS
AlmaLinux9
AlmaLinux8Значно старіша бібліотека C, ніж та, на якій зроблено цю збірку. Це не має значення, бо агент несе власну.
Fedora42
openSUSE Leap15
Amazon Linux2023
Alpine Linux3.21musl і взагалі жодного glibc: найгостріша перевірка, яка тільки буває для статично злінкованого виконуваного файлу.
У цього переліку є дві чесні межі. Він показує, що виконуваний файл запускається й виконує свою криптографічну роботу на кожному з цих користувацьких оточень; повну сесію, із сертифікатами й опитуванням, виміряно на одному з них. І всі перевірки відбувалися на машинах зі спільним ядром, тож доводить він незалежність від дистрибутива, а не від версії ядра.

Яка машина потрібна

Сам агент невеликий і таким лишається. Росте те, за чим він стежить: кожні двадцять секунд він зчитує повний перелік машин з кожної підключеної системи, порівнює його з попереднім колом і передає далі лише те, що змінилося. Кожні пʼять хвилин він натомість передає всю картину, страхувальну сітку на все те, що інакше коштувало б втрачене повідомлення; у цьому ж колі він запитує ваші вузли, скільки в них місткості.

Виміряно на одному агенті; кожен рядок — це вікно у пʼять хвилин
СитуаціяПамʼятьПроцесор
Підключено, ще нічого не приєднано8 МБ0,02% одного ядра
Одна система, 10 машин12 МБ0,03%
Одна система, 250 машин14 МБ0,06%
Одна система, 1000 машин15 МБ0,14%
Пʼять систем, по 200 машин18 МБ0,19%
Кроки між рядками кажуть більше, ніж самі рядки. Приєднати першу систему коштує приблизно 4 МБ, а кожну наступну — приблизно 0,75 МБ, і саме цим відрізняються два останні рядки. Машини дешевшають, що більше їх стає: перехід від 10 до 1000 додав 3 МБ загалом, тобто десь по 3 кБ на кожну, а крок від 250 до 1000 був іще дешевшим. Виміряно в серпні 2026 року на змодельованих системах саме таких розмірів, щоб числа говорили про агента, а не про чийсь кластер.

Трафік є другим числом, яке варто мати. Та тисяча машин коштує приблизно 250 кБ кожні двадцять секунд у бік ваших власних систем, приблизно гігабайт на добу у вашій власній мережі, тоді як десять машин коштують 2,5 кБ за коло. Із цього показника для тисячі машин приблизно 17 кБ за коло йде далі до нас, близько 70 МБ на добу, бо передається лише те, що змінилося.

Чи має значення вид системи? Майже ні. Чи розмовляє агент з гіпервізором, панеллю керування хостингом чи ігровою панеллю, робота та сама: один виклик на систему за коло, одне порівняння, одне повідомлення. Дві відмінності реальні, але невеликі: у гіпервізора ще запитують адреси всередині його гостей, не частіше ніж раз на пʼять хвилин на кожну запущену машину, а панель, яка нічого не вимірює, не надсилає жодних показників споживання. А от машина по той бік відрізняється величезно, і її розмір визначає те, що на ній працює, а не агент.

Тож розміри нижче — це не виміряні нами мінімуми; агент вміщується в значно менше. Це те, що замовили б ми, бо операційна система, її журнали й ваші власні інструменти хочуть більше місця, ніж агент.

Що ми дали б хосту агента
З чим має впоратисяvCPUПамʼятьДиск
До кількох сотень машин11 ГБ10 ГБ
До кількох тисяч машин22 ГБ10 ГБ
Ще й встановлення машин мережею22 ГБ40 ГБ

Чого просять додаткові можливості

Усе вище — це те, що агенту потрібно, щоб спостерігати за вашими системами й керувати ними. Про чотири його можливості варто сказати ще дещо понад це, і кожна з них відмовляє чесно: не виконайте вимогу, і агент робитиме решту, а вам скаже, якої саме можливості він не пропонує.

Встановлення машин мережею
Тут агент має стояти в тому самому сегменті мережі, що й машина, яку встановлюють, бо він відповідає на її завантажувальний запит напряму. Його юніт уже несе дві можливості, потрібні для завантажувальних портів; надані вони вузько і використовуються лише поки триває встановлення. Що воно справді додає — це диск: завантажувальні файли кешуються на хості, типово до 20 ГБ, і першими викидаються найстаріші.
Виконання автоматизацій
Автоматизації — це ваш власний TypeScript, тож вони виконуються в пісочниці, зібраній із просторів імен ядра, а середовище виконання для цього не є частиною агента: одна закріплена версія Bun має лежати в каталозі агента, що належить root, де обліковий запис, від імені якого працює агент, не може її підмінити. Ubuntu 24.04 і новіші обмежують саме той простір імен, який тут потрібен; агент постачається з профілем AppArmor, який повертає цей один дозвіл для цього одного виконуваного файлу. Якщо бракує будь-чого з двох, агент каже про це під час запуску, не пропонує цю можливість і працює далі. Кожен запуск отримує щонайменше 4 ГБ адресного простору — це простір віртуальний, а не памʼять, яка мусить існувати. А скільки автоматизація, яка виконується, насправді коштує на вашому хості, ми не вимірювали.
Перезавантаження хоста з панелі
Перезавантаження — це питання не привілеїв, а дозволу: агент питає logind, logind питає polkit, а скрипт встановлення лишає по собі правило, яке дозволяє рівно дві дії рівно для цього облікового запису. Хостам, які встановили ще до появи цього правила, скрипт треба виконати ще раз, бо оновлення агента з панелі замінює виконуваний файл і нічого в /etc. До того часу панель відмовляє й каже, чому.
Консоль і діагностика
Встановлювати нічого не треба. Ping і traceroute користуються сокетом ICMP, який не потребує привілеїв, поки хост дозволяє його для групи службового облікового запису, а він дозволяв на кожному хості, який ми міряли; де ні, там агент міряє через TCP і каже вам, який метод використав. Консоль передається тим зʼєднанням, яке вже відкрите.

Встановлення однією командою

На вкладці налаштувань агента панель складає одну команду з посиланням для встановлення всередині. Виконайте її від імені root на хості. Посилання працює один раз: воно перестає працювати, щойно агента зареєстровано, і щонайпізніше через 72 години. Нове можна створити будь-коли.

shell
curl -fsSL https://app.provibr.com/api/install/<token> | sh
Ставтеся до посилання як до облікових даних. Будь-хто, у кого воно є, може зареєструвати цього одного агента, так само як це дозволив би ключ автентифікації. У панелі воно ніде не зберігається, тож замість шукати старе створіть нове.
Команди та вивід термінала всюди англійською і в панелі, і на цих сторінках. Один текст, одна правда: те, що ви читаєте тут, ваш хост виведе дослівно так само.

Що робить команда, по порядку:

  • Перевіряє, що виконується від імені root на 64-бітному x86-хості, і бере curl або wget, залежно від того, що є.
  • Завантажує виконуваний файл і його контрольну суму та звіряє їх. Якщо на хості взагалі немає чим обчислити контрольну суму, вона зупиняється, а не пропускає перевірку.
  • Створює службовий обліковий запис і два каталоги, встановлює виконуваний файл і кладе на місце скрипт оновлення та його відкритий ключ; обидва належать root, тож обліковий запис, від імені якого працює агент, не може їх підмінити.
  • Запитує код активації в терміналі, отримує файл ліцензії, передаючи цей код у заголовку запиту, і встановлює його.
  • Реєструє агента від імені службового облікового запису, далі встановлює юніт systemd і запускає службу.

Перевірте результат на хості:

shell
systemctl status provibr-agent
journalctl -u provibr-agent -f
Виконати команду ще раз безпечно, з новим посиланням: старе перестало працювати, коли агента зареєстрували. Якщо хост уже зареєстровано, оновляться лише виконуваний файл і юніт; ідентичність, сертифікат і сейф з обліковими даними лишаються недоторканими. На хості без systemd усе так само встановлюється й реєструється, а команда друкує, як запустити агента власноруч.

Встановлення вручну

Усе, що робить команда в один рядок, — це також кілька окремих команд, і панель друкує їх для вас із уже підставленими поточними значеннями. Виглядає це приблизно так.

  1. Підготуйте хост: службовий обліковий запис, каталоги й виконуваний файл.

    shell
    # System user without a shell and without a home directory
    id -u provibr-agent >/dev/null 2>&1 || \
      sudo useradd --system --no-create-home --shell /usr/sbin/nologin provibr-agent
    
    # Directories for configuration (license, key) and state (identity, vault)
    sudo install -d -o provibr-agent -g provibr-agent -m 0750 /etc/provibr-agent
    sudo install -d -o provibr-agent -g provibr-agent -m 0700 /var/lib/provibr-agent
    
    # The binary from the download
    sudo install -o root -g root -m 0755 ./provibr-agent-linux-x86_64 /usr/local/bin/provibr-agent
    /usr/local/bin/provibr-agent version
  2. Покладіть на місце файл ліцензії. Ви завантажуєте його зі сторінки агента; він зашифрований кодом активації, і завантажити його можна один раз на кожен токен.

    shell
    sudo install -o root -g provibr-agent -m 0640 \
      ./provibr-<agent>.plic /etc/provibr-agent/license.plic
  3. Зареєструйте агента від імені службового облікового запису, вказавши код активації.

    shell
    sudo -u provibr-agent /usr/local/bin/provibr-agent enroll \
      --license /etc/provibr-agent/license.plic --code XXXXX-XXXXX
  4. Встановіть юніт і запустіть службу.

    shell
    sudo install -o root -g root -m 0644 provibr-agent.service /etc/systemd/system/provibr-agent.service
    sudo systemctl daemon-reload
    sudo systemctl enable --now provibr-agent
Разом із виконуваним файлом пропонуються його контрольна сума та підпис. Перевірка підпису і є тим кроком, якого просте завантаження вам не дає; це та сама перевірка, яку крок оновлення виконує для кожного нового випуску.

Docker і Kubernetes

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

Реєстрація відбувається під час першого запуску. Передайте контейнеру посилання на встановлення з панелі й код активації; він отримує свій файл ліцензії, реєструється й зберігає свою ідентичність на томі. Під час кожного наступного запуску використовується ця ідентичність, а ці два значення більше не читаються.

Посилання на встановлення й код лежать у середовищі контейнера, а отже в docker inspect, історії оболонки або secret Kubernetes. Це той самий ризик, що й з однорядковою командою, і він триває, доки агента не зареєстровано: відтоді посилання більше не працює. Усе одно приберіть його із secret; агент його більше не читає.
Усе, що зберігає агент, лежить на томі в /var/lib/provibr-agent: його сертифікат, зашифроване сховище з вашими обліковими даними та ключ до цього сховища. Без тому кожен новий контейнер є новим, незареєстрованим агентом. З томом цей том і є всім секретом: поводьтеся з його копією як з копією агента.

Docker

Панель показує цю команду з уже підставленими посиланням і кодом вашого агента. Іменований том переймає власника з образу, тож агент може писати в нього без chown.

shell
docker run -d --name provibr-agent --restart unless-stopped \
  --hostname provibr-agent \
  --read-only --cap-drop ALL --security-opt no-new-privileges \
  -v provibr-agent-data:/var/lib/provibr-agent \
  -e PROVIBR_INSTALL_URL='https://app.provibr.com/api/install/<token>' \
  -e PROVIBR_ACTIVATION_CODE='XXXXX-XXXXX' \
  ghcr.io/provibr/provibr-agent:latest

Або те саме як файл Docker Compose:

docker-compose.yml
# Provibr agent — Docker Compose.
#
# The agent connects outbound to the platform; it needs no published ports.
# On the first start it enrolls itself with the installation link and the
# activation code below, and stores its identity on the volume. After that the
# two values are no longer read; the link expires 72 hours after it was made.
#
# Update: change the image tag, then `docker compose up -d`. The volume keeps
# identity and credentials.
services:
  provibr-agent:
    image: ghcr.io/provibr/provibr-agent:latest
    container_name: provibr-agent
    hostname: provibr-agent
    restart: unless-stopped
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    environment:
      PROVIBR_INSTALL_URL: "https://app.provibr.com/api/install/<token>"
      PROVIBR_ACTIVATION_CODE: "XXXXX-XXXXX"
    volumes:
      - provibr-agent-data:/var/lib/provibr-agent

volumes:
  provibr-agent-data:
Надаєте перевагу bind mount замість іменованого тому? Спершу створіть каталог і передайте його користувачеві агента: mkdir -p /srv/provibr-agent && chown 65532:65532 /srv/provibr-agent. Bind mount спочатку належить root, а агент, який працює не від root, не зможе в нього писати.

Kubernetes

Прості маніфести, без Helm: namespace, secret із посиланням і кодом, volume claim і deployment. Панель заповнює secret для вашого агента.

provibr-agent.yaml
# Provibr agent — Kubernetes (plain manifests, no Helm).
#
# kubectl apply -f provibr-agent.yaml
#
# The agent connects outbound to the platform; there is no Service and no port.
# On the first start it enrolls itself with the installation link and the
# activation code from the Secret, and stores its identity on the volume. After
# that the Secret is no longer read; the link expires 72 hours after it was made.
#
# Exactly one replica, and Recreate: one agent is one identity (one
# certificate). Two pods would be two agents fighting over it.
apiVersion: v1
kind: Namespace
metadata:
  name: provibr-agent
---
apiVersion: v1
kind: Secret
metadata:
  name: provibr-agent-enrollment
  namespace: provibr-agent
type: Opaque
stringData:
  PROVIBR_INSTALL_URL: "https://app.provibr.com/api/install/<token>"
  PROVIBR_ACTIVATION_CODE: "XXXXX-XXXXX"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: provibr-agent-data
  namespace: provibr-agent
spec:
  # One pod, and only one, may mount this volume. On clusters older than
  # Kubernetes 1.29 (or storage without it), use ReadWriteOnce instead; the
  # agent also refuses to start a second time on the same data directory.
  accessModes:
    - ReadWriteOncePod
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: provibr-agent
  namespace: provibr-agent
  labels:
    app.kubernetes.io/name: provibr-agent
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app.kubernetes.io/name: provibr-agent
  template:
    metadata:
      labels:
        app.kubernetes.io/name: provibr-agent
    spec:
      hostname: provibr-agent
      automountServiceAccountToken: false
      enableServiceLinks: false
      securityContext:
        runAsNonRoot: true
        runAsUser: 65532
        runAsGroup: 65532
        fsGroup: 65532
        # Only when the volume root does not match yet; otherwise the kubelet
        # widens the modes on the private keys at every mount.
        fsGroupChangePolicy: OnRootMismatch
        seccompProfile:
          type: RuntimeDefault
        # The ping check uses an unprivileged ICMP socket. Some container
        # runtimes keep those closed, and then the check reports a source
        # error. This safe sysctl opens them for the agent's group only.
        sysctls:
          - name: net.ipv4.ping_group_range
            value: "65532 65532"
      containers:
        - name: agent
          image: ghcr.io/provibr/provibr-agent:latest
          args: ["run"]
          envFrom:
            # optional: the agent reads it on its first start only, so you can
            # delete the Secret once it is enrolled.
            - secretRef:
                name: provibr-agent-enrollment
                optional: true
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: ["ALL"]
          resources:
            requests:
              cpu: 50m
              memory: 32Mi
            limits:
              memory: 256Mi
          volumeMounts:
            - name: data
              mountPath: /var/lib/provibr-agent
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: provibr-agent-data
Залиште replicas рівним 1, а стратегію Recreate. Один агент означає одну ідентичність: два pod на одному томі ділять один сертифікат і витісняють один одного з платформи, а два pod із власними томами обидва реєструються, після чого дійсний лише останній. Поступове оновлення на мить зробило б саме це.
Перевірка ping використовує ICMP-сокет без привілеїв, а не capability NET_RAW. Деякі середовища виконання контейнерів тримають ці сокети закритими; виміряно із закритими сокетами: діагностичний ping перейшов на TCP, а перевірка моніторингу повідомила про помилку джерела. Маніфест відкриває їх для групи агента безпечним sysctl net.ipv4.ping_group_range. Додавання NET_RAW не допомагає: агент працює не від root, тож не отримує дієвих capabilities.

Для Kubernetes кращий шлях дає файл ліцензії: покладіть у secret файл ліцензії й код замість посилання на встановлення, змонтуйте файл у pod і вкажіть його шлях у PROVIBR_LICENSE_FILE. Токен у файлі працює рівно один раз, тож у secret немає нічого, чим можна вдруге зареєструвати агента.

Оновлення контейнера

Типово контейнер не оновлюється сам: образ і є випуском. Панель показує, який образ поточний; завантажте його й створіть контейнер заново або встановіть новий тег у deployment. Том зберігає ідентичність і облікові дані. Автоматичні оновлення пропускають таких агентів; параметр нижче це змінює.

shell
docker pull ghcr.io/provibr/provibr-agent:latest
docker stop provibr-agent && docker rm provibr-agent
# then run the same docker run command again with the new image
shell
kubectl -n provibr-agent set image deployment/provibr-agent agent=ghcr.io/provibr/provibr-agent:latest

Параметр: оновлення з тому

Встановіть PROVIBR_SELF_UPDATE=volume або позначте параметр у панелі. Тоді контейнер бере участь у кнопці оновлення та нічних оновленнях: нова версія завантажується, її підпис перевіряється ключем платформи, вбудованим в образ, і вона зберігається на томі. Контейнер зупиняється з кодом виходу 0, Docker або kubelet запускає його знову, і бінарний файл в образі запускає нову версію з тому, ще раз перевіривши її підпис.

shell
docker run -d --name provibr-agent --restart unless-stopped \
  --hostname provibr-agent \
  --read-only --cap-drop ALL --security-opt no-new-privileges \
  -v provibr-agent-data:/var/lib/provibr-agent \
  -e PROVIBR_INSTALL_URL='https://app.provibr.com/api/install/<token>' \
  -e PROVIBR_ACTIVATION_CODE='XXXXX-XXXXX' \
  -e PROVIBR_SELF_UPDATE=volume \
  ghcr.io/provibr/provibr-agent:latest

Нова версія має 60 секунд, щоб зʼєднатися з платформою. Якщо не вдається, її позначають на томі як збійну й більше ніколи не запускають, а контейнер повертається з попередньою версією. Коли ви розгортаєте новіший образ, перевагу має образ: те, що зберігалося на томі для старого образу, більше не використовується.

Що ви віддаєте натомість: тег образу більше не показує, яка версія працює (панель показує), сканери образів перевіряють бінарний файл в образі, а не той, що на томі, а інструмент GitOps бачить под, який запускає не те, що каже його маніфест. Для кластерів, якими керує інструмент GitOps, ми цього не радимо.

Параметр: образ tools для автоматизацій

Стандартний образ не має середовища виконання автоматизацій. Образ tools із суфіксом тегу -tools містить того самого підписаного агента на Debian, до якого додано закріплене середовище виконання автоматизацій, тож автоматизації можуть працювати в контейнері. Приклади Docker дають йому невеликий /tmp і обмеження pids (--pids-limit); у Kubernetes /tmp — це emptyDir у памʼяті, а обмеження pids задають на kubelet (podPidsLimit), а не в маніфесті. Коренева файлова система лишається лише для читання.

shell
docker run -d --name provibr-agent --restart unless-stopped \
  --hostname provibr-agent \
  --read-only --cap-drop ALL --security-opt no-new-privileges \
  --tmpfs /tmp:rw,noexec,nosuid,size=16m --pids-limit 256 \
  -v provibr-agent-data:/var/lib/provibr-agent \
  -e PROVIBR_INSTALL_URL='https://app.provibr.com/api/install/<token>' \
  -e PROVIBR_ACTIVATION_CODE='XXXXX-XXXXX' \
  ghcr.io/provibr/provibr-agent:latest-tools
На Linux-хості автоматизація працює в пісочниці з власними просторами імен: без мережі, без файлів хоста, з власним деревом процесів. Контейнер не може створити такі простори імен, тож в образі tools агент обмежує середовище виконання двома іншими способами. Фільтр seccomp, що працює на будь-якому ядрі, блокує кожен мережевий сокет (TCP і UDP), сигнали іншим процесам, запуск нових процесів і читання памʼяті іншого процесу. Landlock (Linux 5.13 або новіший) обмежує файли: скрипт може читати лише середовище виконання й системні бібліотеки і нічого не може записувати. Агент перевіряє обидва під час запуску; якщо ядро або профіль seccomp середовища контейнерів їх не дозволяє, автоматизації в контейнері вимкнені. Те, що лишається, слабше, ніж на хості: скрипт і далі бачить, які процеси працюють у контейнері. Вибір образу tools означає цей вибір.

Що не працює в контейнері

Деякі функції потребують самого хоста, а обмежений контейнер його не має:

  • Мережеві встановлення (PXE): їм потрібні мережа хоста й порти нижче 1024.
  • Перезавантаження хоста з панелі: контейнер не має доступу до системи ініціалізації хоста.
  • Автоматизації у стандартному образі: у ньому немає середовища виконання автоматизацій, а пісочниці, яку вони отримують на хості, потрібні простори імен користувачів, яких обмежений контейнер не надає. Образ tools натомість виконує їх у самому контейнері.
  • Метрики хоста: процесор, памʼять і час роботи описують машину, на якій працює контейнер, а не власні обмеження контейнера.

Код активації та файл ліцензії

Коли ви створюєте агента, панель один раз показує код активації. Ніде він не записується, навіть у вигляді хешу. Саме цим кодом шифрується файл ліцензії, тож файл на вашому хості зашифровано тим, чого на цьому хості немає.

Загубили код або сам файл? Створіть новий токен на сторінці агента. Це робить попередній недійсним, разом із файлом ліцензії, який уже був у дорозі. Натомість ви отримуєте новий код і нове завантаження.

Сам файл ліцензії не містить жодних таємниць про вашу інфраструктуру. Він каже агенту, до якої платформи той належить, якому центру сертифікації довіряти і з яким одноразовим токеном реєструватися.

Керування агентами в панелі

Список агентів показує все одразу: статус, версію, чи підключений агент просто зараз, коли його востаннє бачили в мережі й коли спливає його сертифікат.

  • Назву й опис ви змінюєте самі, і це лише позначки. Назва, яка вже потрапила у виданий файл ліцензії, залишається такою, як була, — це суто косметично і не привід реєструвати агента заново.
  • Підключений агент чи ні — це зчитується з живого сигналу з коротким строком дії, а не з того, коли востаннє оновили рядок у базі. Якщо сказати напевно не можна, панель так і пише, а не стверджує, що ваш агент лежить.
  • Версія й операційна система — це те, що агент повідомив під час останнього підключення. Агент, який жодного разу не підключався, показує риску, а не здогадку.
  • Оберіть у списку кілька агентів, щоб оновити їх за один раз. Кнопка рахує лише тих агентів, яких справді можна оновити просто зараз, тож ще до натискання ви бачите, що з дванадцяти обраних оновляться троє.
  • Хід виконання зчитується з команди, яка виконується, а не з того, що запамʼятав ваш браузер, тож після перезавантаження сторінки він відновлюється.

Три стани

Очікує реєстрації
Створений у панелі, але ще не зареєстрований. На нього чекають токен і код активації, а сертифіката ще немає.
Зареєстровано
Має власний сертифікат і може підключатися. Це єдиний стан, у якому агенту можна давати роботу, і єдиний, у якому його не можна видалити.
Відкликано
Ви його відкликали. Сесію закрито, чинні токени недійсні, і повернутися він не може.

Відкликання агента

Відкликання — це той важіль, до якого ви тягнетеся, коли хост скомпрометовано, виведено з експлуатації або він просто більше не ваш. Воно спрацьовує без жодного дотику до самого хоста.

  • Активну сесію буде закрито протягом хвилини. Агенту повідомляють причину, а не просто розривають зʼєднання.
  • Далі агент стирає власну ідентичність, свій сертифікат і сейф з обліковими даними. Облікових даних до вашого гіпервізора на цьому хості більше немає.
  • Чинні токени реєстрації стають недійсними, тож уже завантажений файл ліцензії не дасть повернутися.
Скасувати це неможливо. Агента, якого ви відкликали помилково, доведеться створити заново, встановити заново й заново видати йому облікові дані.

Видалення агента

Видалення прибирає агента з панелі. Це окремий крок, не те саме, що відкликання, і він навмисно прискіпливий до того, коли його дозволено.

  • Зареєстрованого агента видалити не можна. Спершу відкличте його, інакше ви прибрали б запис про те, що досі підключене.
  • Агента, до якого привʼязані інтеграції або сервери, теж видалити не можна, і у відмові названо обидві кількості. Ці записи тримаються на агенті, тож одне натискання забрало б із собою ваш парк.
  • Якщо агент жодного разу не виконував команди й жодного разу не мав сервера, запис справді зникає. Інакше він ховається звідусіль, але історія його команд зберігається: журнал аудиту, який можна стерти, видаливши того, про кого він ведеться, — це не журнал аудиту.

Прибирання агента з хоста

Відкликання стирає секрети агента, але файли лишаються. Щоб прибрати за собою на хості, панель пропонує другу однорядкову команду й ті самі чотири кроки вручну.

Цей скрипт нічого не відкликає. Спершу відкличте агента в панелі, а вже потім прибирайте хост, саме в такому порядку. У зворотному порядку на хості залишиться чинна ідентичність.
  1. Зупиніть службу, вимкніть її автозапуск і приберіть юніт.

    shell
    # Stop the service and forget the unit
    sudo systemctl disable --now provibr-agent
    sudo rm -f /etc/systemd/system/provibr-agent.service
    sudo systemctl daemon-reload
    sudo systemctl reset-failed provibr-agent 2>/dev/null || true
  2. Приберіть виконуваний файл, скрипт оновлення та ключ оновлення.

    shell
    # Binary, update script and the trust anchor of the update step
    sudo rm -f /usr/local/bin/provibr-agent
    sudo rm -f /usr/local/lib/provibr-agent/apply-update.sh /usr/local/lib/provibr-agent/license-signing.pub
    
    # The polkit rule that allowed host.reboot (and its 0.105 fallback)
    sudo rm -f /etc/polkit-1/rules.d/49-provibr-agent-reboot.rules /etc/polkit-1/localauthority/50-local.d/49-provibr-agent-reboot.pkla
    
    # Only if nothing else lives in there
    sudo rmdir /usr/local/lib/provibr-agent 2>/dev/null || true
  3. Приберіть дані. Це найважливіший крок: тут лежать ліцензія, ключ сейфа й зашифровані облікові дані.

    shell
    # License and vault key
    sudo rm -rf /etc/provibr-agent
    
    # Identity, encrypted credential vault, outbox and staged updates
    sudo rm -rf /var/lib/provibr-agent
  4. Приберіть службовий обліковий запис.

    shell
    sudo userdel provibr-agent
    sudo groupdel provibr-agent 2>/dev/null || true

Після цього обидві команди мають не вивести взагалі нічого:

shell
ls -d /etc/provibr-agent /var/lib/provibr-agent /usr/local/lib/provibr-agent /usr/local/bin/provibr-agent /etc/systemd/system/provibr-agent.service /etc/polkit-1/rules.d/49-provibr-agent-reboot.rules /etc/polkit-1/localauthority/50-local.d/49-provibr-agent-reboot.pkla 2>/dev/null
id provibr-agent 2>/dev/null
# Both commands should print nothing at all