Railshot
AI deployment & operations platform
Розгорнути локально створений вебзастосунок у підготовлених хмарних і локальних середовищах, а потім підтримувати його роботу.
Платформа AI для розгортання й експлуатації, що переносить локально створений вебзастосунок у підготовлені хмарні чи локальні середовища й підтримує його роботу.
Кластери експлуатації й клієнтських застосунків розділено, а публічний шлях тримається окремо від керування розгортанням.
В операційному K3s дашборд, API продукту й build controller розміщено на вузлах із роллю platform, а runner Jobs — на вузлі з роллю build, тоді як розгортанням займається Argo CD. Клієнтські застосунки працюють у визначеному просторі імен окремого одновузлового кластера K3s + Cilium для кожної зареєстрованої цілі.
Збірка → публікація образу
API продукту запитує запуск GitHub Actions, а runner на вузлі build бере й перевіряє job. Лише bundle, що пройшов ті самі перевірки, публікує в GHCR release job на GitHub-hosted.
API продукту · cd.js → bridge.py
railshot-systemзапуск · застосування: workflow_dispatchloop job · self-hosted runnerrailshot-deploy.ymlAPI продукту запитує запуск GitHub Actions із tenant, app, комітом джерела й ціллю. API ніколи не викликає runner Job напряму.
build controller · CronJob
railshot-systemзапуск · застосування: поповнення runner Jobrunner Job · hostNetwork · Docker socketrailshot-buildCronJob build controller (щохвилини, на вузлі platform) створює runner Jobs у просторі імен railshot-build. Його Role дозволяє лише get, list і create для Job, а також get, update і patch для одного Secret реєстрації runner; він не може створювати простори імен чи інші Secrets.
runner Job · hostNetwork · Docker socket
railshot-buildзапуск · застосування: узяти jobloop job · self-hosted runnerrailshot-deploy.ymlRunner на вузлі з роллю build (точний hostname, toleration NoSchedule) бере loop job за мітками self-hosted і виконує його. Клієнтське джерело виконується в наявних обмежених контейнерах збірки й перевірки Docker.
runner Job · hostNetwork · Docker socket
railshot-buildдані: перевірений bundlerelease job · GitHub-hostedrailshot-deploy.ymlLoop job залишає bundle, що пройшов ті самі перевірки, а release job бере лише цей bundle.
release job · GitHub-hosted
railshot-deploy.ymlдані: публікація за дайджестомGHCRRelease job на GitHub-hosted (ubuntu-24.04) публікує образ перевіреного bundle в GHCR без перезбирання. Публікація образів ніколи не відбувається всередині клієнтського кластера застосунків.
Config Git → Argo → простір імен клієнта
Config Git несе бажані ресурси, а GHCR — байти образу. Argo CD застосовує зміни лише до зареєстрованого простору імен клієнта.
API продукту · cd.js → bridge.py
railshot-systemдані: workload commit · pushРепозиторій config Gitcd.js запускає bridge.py, який комітить і пушить workload.json лише тоді, коли запис публікації й зареєстрована ціль узгоджуються, а потім зчитує віддалену ревізію. Git несе бажані ресурси; GHCR несе байти образу.
Репозиторій config Gitдані: revisionArgo CD · Application
argocdApplication читає лише свій обмежений конфігураційний репозиторій, шлях і ревізію.
API продукту · cd.js → bridge.py
railshot-systemзапуск · застосування: Application syncArgo CD · ApplicationargocdІменований Application задається через server-side apply, і запитується синхронізація однієї точної ревізії без prune. ServiceAccount railshot-product в API продукту має і встановлений оператором bootstrap реєстрації (create для Secrets, AppProjects і Applications в argocd; get, update й escalate для іменованих Roles), і права get та patch, що додаються за точною назвою для кожної перевіреної цілі. Create у Kubernetes не можна обмежити назвою, тож назви в межах обсягу утримує також валідація входів продукту.
Argo CD · Application
argocdзапуск · застосування: застосування до простору імен<app namespace>Argo CD застосовує зміни до визначеного простору імен у клієнтському кластері з обліковими даними зареєстрованого cluster Secret. AppProject дозволяє лише kinds у межах простору імен і жодних ресурсів рівня кластера.
Deployment · Pod · образ за дайджестом
<app namespace>дані: pull за дайджестомGHCRОпублікований образ за дайджестом завантажується з pull Secret, на який посилаються за назвою в тому самому просторі імен. Значення Secret ніколи не потрапляють в артефакт чи config Git.
Публічний шлях запиту
Запити до застосунку йдуть L7-точка входу провайдера → NodePort вузла → Service → Pod застосунку. Застосування політики Cilium — окремий контроль, а не ланка, що несе запит. Вхід до операційного дашборда — окремий шлях.
Користувач застосункудані: HTTPS 443L7-точка входу провайдера
Користувачі застосунку доходять до L7-точки входу провайдера за зареєстрованим hostname. Кожен провайдер реалізує власну точку входу.
L7-точка входу провайдерадані: NodePortNodePort Service · Local
<app namespace>Точка входу пересилає на приватну адресу й NodePort вузла. NodePort — той, що виділений під час реєстрації цілі.
NodePort Service · Local
<app namespace>дані: до PodDeployment · Pod · образ за дайджестом<app namespace>Service надсилає запит до Pod застосунку (Deployment) на тому самому вузлі. З externalTrafficPolicy Local адреса джерела доходить до перевірки зареєстрованих CIDR у NetworkPolicy без змін.
Cilium · Helm · VXLAN
kube-systemзапуск · застосування: застосування політикиNetworkPolicy · лише зареєстровані CIDR<app namespace>Cilium застосовує NetworkPolicy: вхідний трафік лише із зареєстрованих CIDR до порту застосунку; типово без вихідного трафіку, крім схваленої адреси бази даних. Хмарні брандмауери й правила хоста й далі мають значення.
Користувач Railshotдані: дашборд · APIdashboard · nginx
railshot-systemКористувачі заходять через операційну точку входу до дашборда nginx, а nginx стоїть перед API продукту. Service дашборда є NodePort лише тоді, коли задано схвалений порт вузла; API лишається ClusterIP.
Перевірка · спостереження
Вердикт про розгортання спирається лише на стан Argo й перевірку публічної URL-адреси. Діагностика Pod, поточні журнали й операційні метрики — окремі сигнали, які ніколи його не змінюють.
API продукту · cd.js → bridge.py
railshot-systemспостереження: ревізія · health · образиArgo CD · ApplicationargocdДля deployed потрібні ревізія синхронізації Application, Synced і Healthy, operation Succeeded, а також посилання на образи, записані в статусі Argo Application, що дорівнюють образам за дайджестом у переглянутому Deployment. Це не прямий поріг за imageID Pod, і самий лише зелений статус Argo не встановлює збігу.
API продукту · cd.js → bridge.py
railshot-systemспостереження: публічна перевірка HTTPSL7-точка входу провайдераЗареєстрована публічна URL-адреса перевіряється без переспрямувань. Succeeded записується лише за наявності і вердикту Argo, і цієї перевірки.
API продукту · cd.js → bridge.py
railshot-systemспостереження: діагностика Pod · не вердиктDeployment · Pod · образ за дайджестом<app namespace>Після вердикту Argo й публічної перевірки Deployment, ReplicaSets і Pods окремо читаються із зареєстрованими обліковими даними, а imageID і готовність додаються як діагностика ready, progressing або unavailable. Невдала чи відмінна діагностика ніколи не змінює вердикту deployed чи succeeded.
API продукту · cd.js → bridge.py
railshot-systemспостереження: хвіст журналу · 100 рядків на PodDeployment · Pod · образ за дайджестом<app namespace>Лише для поточної розгорнутої операції, з довіреною конфігурацією й зареєстрованими обліковими даними. Для кожного поточного Pod (щонайбільше трьох) дайджест запущеного образу має дорівнювати очікуваному; тоді в межах ліміту байтів читається до 100 очищених рядків на Pod. Старіша спроба відповідає superseded; без конфігурації — not_configured. Це не агрегування журналів.
VM спостереженняспостереження: збирання · NodePortsrailshot-observability
Prometheus на VM спостереження збирає метрики node-exporter і kube-state-metrics через два NodePort, обмежені брандмауером. Відсутні чи застарілі значення — невідомі, а не нуль.
VM спостереженняспостереження: Blackbox probeL7-точка входу провайдера
probe_success=1 означає 2xx у тій точці проби. Це не доводить ні доступу кожного користувача, ні розгорнутої версії й ніколи не підвищує published до deployed.
Встановлення · реєстрація оператором
Встановлення кластера, bootstrap реєстрації й вхідні дані цілі, Secrets і налаштування оновлення облікових даних — це вхідні дані оператора, а не частина payload застосунку орендаря.
Bootstrap операторазапуск · застосування: рендер platform · Secretrailshot-system
Оператор рендерить оголошення платформи за допомогою render-platform.py і надає приватну операційну конфігурацію та Secrets. Віддалений MCP включається лише тоді, коли надано його образ, а персональний gateway (WireGuard) — лише з --personal.
Bootstrap операторазапуск · застосування: bootstrap реєстраціїAppProject · cluster Secret
argocdОператор встановлює в argocd Role bootstrap реєстрації й порожню Role реєстрацій та готує вхідні дані цілі. Потім помічники реєстрації, які запускає API продукту (environment.py, applications.py), записують Secret railshot-<target> з обмеженими обліковими даними (clusterResources false, дозволені простори імен перелічено) і додають перевірені точні назви до Role реєстрацій. Реєстрація для кожного застосунку прив’язує простір імен app-<id> до AppProject з такою самою назвою.
Bootstrap операторазапуск · застосування: встановлення K3s · CiliumCilium · Helm · VXLAN
kube-systeminstall-k3s.sh встановлює одновузловий сервер K3s (flannel, network policy, traefik і servicelb вимкнено; kube-proxy збережено), а Cilium встановлюється як реліз Helm (kubeProxyReplacement false, VXLAN, Hubble вимкнено).
CronJob оновлення · кожні 2 h
argocdзапуск · застосування: TokenRequest · 6 hrailshot-argocd SA · токен<app namespace>CronJob railshot-credentials кожні дві години запитує новий шестигодинний токен для клієнтського SA. Role на боці клієнта дозволяє лише create токена для власного SA. Шість годин — це TTL одного токена, а не момент, коли закінчується доступ оператора.
Усі зв’язки однакової товщини. Оберіть потік, щоб підсвітити лише його шлях із пронумерованими кроками.
- Суцільна · напрямок, яким рухаються запити, bundles, образи й оголошення
- Штрихова · запити на запуск, застосування, встановлення, облікові дані
- Довга штрихпунктирна · читання стану, журналів, проб, метрик; окремо від вердикту
- Товста чорна лінія · обраний потік; номери показують порядок
- Рамка · простір імен, його назва в заголовку (не вузол)
- Внутрішня плашка · компонент у цьому просторі імен
- Штрихова рамка · поза кластерами
- railshot-system · продукт
- argocd · повноваження на розгортання
- railshot-build · повноваження Docker хоста
- GitHub · клієнтський кластер
Рішення про розміщення від October 2 у docs/architecture (два вузли за ролями) і схема в публічному README — історія; ця карта відповідає оголошенням і коду на 645e28a. Стрілки показують причину й напрямок, а не доказ, що кожен шлях провайдера зараз активний.
- Простори імен і вузли
- Простір імен — це область назв: ні апаратне забезпечення, ні сам по собі межа безпеки. Ролі platform і build — це розміщення під час планування через nodeSelector і taint; кількість вузлів операційного кластера ця карта не фіксує. Розміщення Argo CD на вузлах — також окрема перевірка.
- Повноваження вузла build
- Runner Jobs працюють із hostNetwork, сокетом Docker хоста, NET_ADMIN і root. Простір імен, taint чи RBAC не прибирають повноважень Docker хоста, тож це ні ізоляція від адміністратора VM, ні пісочниця для довільного коду.
- Простір імен клієнта
- Кожна зареєстрована ціль використовує нетиповий простір імен і AppProject (наприклад, tenant-demo або app-<id> для кожного застосунку). Створюються лише Deployment одного сервісу (автомонтування токена ServiceAccount вимкнено), NodePort Service і NetworkPolicy, а також необов’язкові PVC чи Job міграції; на Secrets лише посилаються за назвою (pull Secret і схвалений DATABASE_URL), але ніколи їх не створюють.
- Вхід AWS
- Route 53 Alias → спільний ALB HTTPS 443 → приватна адреса й NodePort клієнтського вузла. Багато застосунків повторно використовують один вузол, кожен зі своїм простором імен, Application і NodePort.
- Вхід GCP
- Глобальний EXTERNAL_MANAGED HTTPS LB → зональний GCE_VM_IP_PORT NEG → приватний NodePort наявної VM. Сертифікати видає Certificate Manager з DNS-авторизацією. Модуль не володіє ні VM, ні VPC, і одна VM лишається єдиною точкою відмови.
- Вхід OpenStack
- TLS-слухач Amphora 443 з L7-політиками Host і шляху → HTTP NodePort. Типова адреса — приватний VIP; Octavia, K3s, база даних і DNS — поза модулем. Публічна доступність і готовність Amphora на місці потребують окремого приймання, і жодного застосування на місці з цим модулем ще не перевірено.
- Між провайдерами
- Три точки входу — окремі реалізації, без автоматичного failover чи реплікації між провайдерами. Клієнтський кластер застосунків — приклад зареєстрованої цілі, а не твердження, що те саме розгортання працює в усіх хмарах одночасно.
- Опції оператора
- Персональний gateway (WireGuard) приєднується до платформи лише тоді, коли оператор вмикає --personal; це не обов’язковий шлях для клієнтських хмар. У підтримуваному прямому режимі VM спостереження може ділити операційну керівну VM.