Railshot
AI deployment & operations platform
Внедряване на локално създадено уеб приложение в подготвени облачни и локални среди и последваща експлоатация.
AI платформа за внедряване и експлоатация, която отвежда локално създадено уеб приложение в подготвени облачни или локални (on-premises) среди и го поддържа в работа.
Оперативният клъстер и клъстерите за клиентски приложения са отделни, а публичният път е отделен от управлението на внедряването.
В оперативния K3s таблото, продуктовият API и build controller са разположени на възли с роля platform, а runner Job са на възел с роля build, докато Argo CD отговаря за внедряването. Клиентските приложения работят в определен namespace на отделен еднонодов клъстер K3s + Cilium за всяка регистрирана цел.
Изграждане → публикуване на образа
Продуктовият API иска изпълнение в GitHub Actions, а runner на build възела поема и проверява задачата. Само пакет, преминал същите проверки, се публикува в GHCR от release job, хостван в GitHub.
продуктов API · cd.js → bridge.py
railshot-systemизпълнение · прилагане: workflow_dispatchloop job · self-hosted runnerrailshot-deploy.ymlПродуктовият API иска изпълнение в GitHub Actions с tenant, app, source commit и цел. API никога не извиква runner Job директно.
build controller · CronJob
railshot-systemизпълнение · прилагане: попълване на runner Jobrunner Job · hostNetwork · Docker socketrailshot-buildCronJob на build controller (всяка минута, на platform възел) създава runner Job в namespace railshot-build. Неговата Role позволява само get, list и create за Job, както и get, update и patch върху единствения Secret за регистрация на runner; тя не може да създава namespace или други Secret.
runner Job · hostNetwork · Docker socket
railshot-buildизпълнение · прилагане: поемане на задачатаloop job · self-hosted runnerrailshot-deploy.ymlRunner на възела с роля build (точен hostname, NoSchedule toleration) поема loop job по етикетите self-hosted и го изпълнява. Изходният код на клиента се изпълнява в съществуващите ограничени Docker контейнери за изграждане и проверка.
runner Job · hostNetwork · Docker socket
railshot-buildданни: тестван пакетrelease job · GitHub-hostedrailshot-deploy.ymlLoop job оставя пакета, преминал същите проверки, а release job поема само този пакет.
release job · GitHub-hosted
railshot-deploy.ymlданни: публикуване по digestGHCRRelease job, хостван в GitHub (ubuntu-24.04), публикува образа на тествания пакет в GHCR, без да го изгражда отново. Публикуване на образи никога не се извършва в клъстера за клиентски приложения.
Config Git → Argo → namespace на клиента
Config Git носи желаните ресурси, а GHCR байтовете на образа. Argo CD прилага само в регистрирания namespace на клиента.
продуктов API · cd.js → bridge.py
railshot-systemданни: workload commit · pushхранилище config Gitcd.js изпълнява bridge.py, който прави къмит и push на 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 за Secret, AppProject и Application в argocd; get, update и escalate за посочени Role), така и правата get и patch, добавени с точно име за всяка валидирана цел. Create в Kubernetes не може да се ограничи по име, затова валидирането на входа в продукта също държи имената в обхвата.
Argo CD · Application
argocdизпълнение · прилагане: прилагане в namespace<app namespace>Argo CD прилага в определения namespace на клиентския клъстер с идентификационните данни на регистрирания Secret на клъстера. AppProject позволява само видове в рамките на namespace и никакви ресурси на ниво клъстер.
Deployment · Pod · образ по digest
<app namespace>данни: изтегляне по digestGHCRПубликуваният образ по digest се изтегля с pull Secret, посочен по име в същия namespace. Стойностите на 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 · образ по digest<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, с образите по digest на прегледания Deployment. Това не е пряка порта по imageID на Pod, а зеленото състояние в Argo само по себе си не установява съвпадението.
продуктов API · cd.js → bridge.py
railshot-systemнаблюдение: публична HTTPS проверкаL7 входна точка на доставчикаРегистрираният публичен URL се проверява без пренасочвания. Succeeded се записва само при вердикта от Argo и тази проверка.
продуктов API · cd.js → bridge.py
railshot-systemнаблюдение: Диагностика на Pod · не вердиктDeployment · Pod · образ по digest<app namespace>След вердикта от Argo и публичната проверка Deployment, ReplicaSet и Pod се четат отделно с регистрираните идентификационни данни, а imageID и готовността се добавят като диагностика ready, progressing или unavailable. Неуспешна или различаваща се диагностика никога не променя вердикта deployed или succeeded.
продуктов API · cd.js → bridge.py
railshot-systemнаблюдение: край на лога · 100 реда на PodDeployment · Pod · образ по digest<app namespace>Само за текущо внедрената операция, с доверената конфигурация и регистрираните идентификационни данни. За всеки текущ Pod (най-много три) digest на работещия образ трябва да съвпада с очаквания digest; след това се четат до 100 реда със заличени данни на Pod в рамките на лимит в байтове. За по-стар опит отговорът е superseded; без конфигурация – not_configured. Това не е агрегиране на логове.
VM за наблюдениенаблюдение: scrape · NodePortrailshot-observability
Prometheus на VM за наблюдение събира node-exporter и kube-state-metrics през два NodePort, ограничени със защитна стена. Липсващите или остарелите стойности са неизвестни, а не нула.
VM за наблюдениенаблюдение: Blackbox probeL7 входна точка на доставчика
probe_success=1 означава 2xx в тази точка на пробата. Това не доказва нито достъпа на всеки потребител, нито внедрената версия и никога не повишава published до deployed.
Инсталиране · регистрация от оператора
Инсталирането на клъстера, bootstrap за регистрацията и входните данни за целта, Secret и настройката за подновяване на идентификационните данни са входове на оператора и никога не са част от payload на приложението на клиента.
Bootstrap от оператораизпълнение · прилагане: рендиране на платформата · Secretrailshot-system
Операторът рендира декларацията на платформата с render-platform.py и подава непубличната оперативна конфигурация и Secret. Отдалеченият MCP се включва само когато е подаден образът му, а личният gateway (WireGuard) само с --personal.
Bootstrap от оператораизпълнение · прилагане: bootstrap за регистрацияAppProject · cluster Secret
argocdОператорът инсталира в argocd Role за bootstrap на регистрацията и празна Role registrations и подготвя входните данни за целта. След това помощните програми за регистрация, изпълнявани от продуктовия API (environment.py, applications.py), записват Secret railshot-<target> с ограничени идентификационни данни (clusterResources false, изброени разрешени namespace) и добавят валидираните точни имена в Role registrations. Регистрацията на всяко приложение обвързва namespace app-<id> с AppProject със същото име.
Bootstrap от оператораизпълнение · прилагане: инсталиране на K3s · CiliumCilium · Helm · VXLAN
kube-systeminstall-k3s.sh инсталира еднонодов K3s server (flannel, network policy, traefik и servicelb изключени; kube-proxy запазен), а Cilium се инсталира като Helm release (kubeProxyReplacement false, VXLAN, Hubble изключен).
CronJob за подновяване · на всеки 2 h
argocdизпълнение · прилагане: TokenRequest · 6 hSA railshot-argocd · токен<app namespace>CronJob railshot-credentials иска на всеки два часа нов шестчасов токен за клиентския SA. Role от страна на клиента позволява само token create за собствения му SA. Шест часа е TTL на един токен, а не моментът, в който приключва достъпът на оператора.
Всички връзки с еднаква дебелина. Изберете поток, за да се откроят само неговият път и номерираните стъпки.
- Плътна · посоката, в която текат заявките, пакетите, образите и декларациите
- Прекъсната · заявки за изпълнение, прилагане, инсталиране, идентификационни данни
- Дълга щрих-пунктирна · четене на състояние, логове, проби, метрики; отделно от вердикта
- Дебела черна линия · избраният поток; числата показват реда
- Кутия · namespace, с името в заглавието (не е възел)
- Вътрешен етикет · компонент в този namespace
- Прекъсната кутия · извън клъстерите
- railshot-system · продукт
- argocd · правомощие за внедряване
- railshot-build · правомощие върху Docker на хоста
- GitHub · клиентски клъстер
Решението за разположение от 2 октомври в docs/architecture (два възела по роли) и диаграмата в публичния README са история; тази карта следва декларациите и кода при 645e28a. Стрелките показват причина и посока, а не доказателство, че всеки път на доставчик работи в момента.
- Namespace и възли
- Namespace е обхват на имена: нито хардуер, нито сам по себе си граница на сигурността. Ролите platform и build са разположение при планирането чрез nodeSelector и taint; тази карта не фиксира броя на възлите в оперативния клъстер. Разположението на Argo CD по възли също е отделна проверка.
- Правомощия на build възела
- Runner Job работят с hostNetwork, Docker сокета на хоста, NET_ADMIN и root. Namespace, taint или RBAC не премахват правомощието върху Docker на хоста, затова това не е нито изолация от администратора на VM, нито sandbox за произволен код.
- Namespace на клиента
- Всяка регистрирана цел използва namespace и AppProject, различни от тези по подразбиране (например tenant-demo или app-<id> за всяко приложение). Създават се само Deployment на една услуга (с изключено автоматично монтиране на токена на ServiceAccount), NodePort Service и NetworkPolicy, както и по избор PVC или Job за миграция; Secret само се посочват по име (pull Secret и одобрен DATABASE_URL) и никога не се създават.
- Входна точка в AWS
- Route 53 Alias → споделен ALB HTTPS 443 → частният адрес и NodePort на клиентския възел. Много приложения използват един възел, всяко със собствени namespace, Application и NodePort.
- Входна точка в GCP
- Глобален EXTERNAL_MANAGED HTTPS LB → зонален GCE_VM_IP_PORT NEG → частният NodePort на съществуващата VM. Сертификатите идват от Certificate Manager с DNS авторизация. Модулът не притежава нито VM, нито VPC, а една VM остава единична точка на отказ.
- Входна точка в OpenStack
- Amphora TLS listener 443 с L7 политики по Host и път → HTTP NodePort. Адресът по подразбиране е частен VIP; Octavia, K3s, базата данни и DNS са извън модула. Публичната достъпност и готовността на Amphora на място изискват отделно приемане, а прилагане на място с този модул още не е потвърдено.
- Между доставчиците
- Трите входни точки са отделни реализации, без автоматичен failover или репликация между доставчиците. Клъстерът за клиентско приложение е пример за регистрирана цел, а не твърдение, че едно и също внедряване работи едновременно във всеки облак.
- Опции на оператора
- Личният gateway (WireGuard) се присъединява към платформата само когато операторът включи --personal; той не е задължителен път за клиентските облаци. В поддържания режим direct VM за наблюдение може да споделя оперативната контролна VM.