RAILSHOT.
Înapoi în sală

Railshot

AI deployment & operations platform

Implementarea unei aplicații web construite local în medii cloud și on-premises pregătite, apoi operarea ei.

O platformă AI de implementare și operare care duce o aplicație web construită local în medii cloud sau on-premises pregătite și o ține în funcțiune.

28 septembrie 2026 – 4 octombrie 2026 · Încheiat

Proiect de echipă · partea mea: planificarea și implementarea CI, clusterele CSP și interfața Ansible, operare, revizuirea codului și integrare în echipă

SoftBank Hackathon 2026 powered by KOREC & ProgateParticipant în preliminarii · selecția pentru finală va fi anunțată pe 26 octombrie 2026 (la 7 octombrie 2026)

  • Interfață webImplementat · hackathon
  • Server MCPImplementat · la distanță · local

Clusterele de operare și cele pentru aplicațiile clienților sunt separate, iar calea publică este ținută separat de controlul implementării.

În K3s-ul de operare, dashboardul, API-ul produsului și build controller-ul sunt plasate pe noduri cu rol platform, iar Job-urile runner pe un nod cu rol build, în timp ce Argo CD se ocupă de implementare. Aplicațiile clienților rulează într-un namespace desemnat al unui cluster separat K3s + Cilium cu un singur nod, câte unul pentru fiecare țintă înregistrată.

Harta clusterelor · desenată după declarațiile și codul din commitul public 645e28a
Harta clusterelor de operare și ale clienților RailshotClusterul K3s de operare și un cluster înregistrat pentru aplicațiile clienților. În clusterul de operare, namespace-ul railshot-system plasează dashboardul, API-ul produsului, MCP-ul la distanță (doar când imaginea lui este furnizată) și build controller-ul pe noduri cu rol platform; Job-urile runner din namespace-ul railshot-build preiau joburile GitHub Actions pe nodul cu rol build, marcat cu taint. Un job de release găzduit de GitHub publică pachetul testat în GHCR. API-ul produsului face commit pentru sarcina de lucru în config Git și sincronizează o Application în namespace-ul argocd, iar Argo CD aplică un Deployment, un NodePort Service și o NetworkPolicy în namespace-ul înregistrat din clusterul clientului. Cererile către aplicație intră printr-un punct de intrare L7 al furnizorului către NodePort-ul și Service-ul nodului, apoi către Pod-ul aplicației. Verdictul implementării se bazează doar pe starea Argo și pe verificarea URL-ului public; diagnosticul Pod, jurnalele și metricile sunt citite ca semnale separate. Intrările operatorului pentru instalare și înregistrare sunt ținute separat de payloadul aplicației tenantului.Utilizator Railshotdashboard · MCPBootstrap-ul operatoruluiinstalare · înregistrare · SecretGHCRimagini prin digestdepozitul config Gitworkload.json · revisionPunctul de intrare L7 al furnizoruluiALB · GCP LB · AmphoraUtilizatorul aplicațieiHTTPS publicVM de observareîn afara K3s al clientului · Composerailshot-systemdashboard · nginxMCP la distanță · doar cu imaginebuild controller · CronJobAPI-ul produsului · cd.js → bridge.pyargocdArgo CD · ApplicationAppProject · cluster SecretCronJob de reînnoire · la fiecare 2 hrailshot-buildrunner Job · hostNetwork · Docker socketrailshot-deploy.ymlloop job · self-hosted runnerrelease job · GitHub-hosted<app namespace>Deployment · Pod · imagine prin digestNodePort Service · LocalNetworkPolicy · doar CIDR-urile listateSA railshot-argocd · tokenkube-systemCilium · Helm · VXLANrailshot-observabilitynode-exporterkube-state-metricsCluster de operare · K3sAWS · noduri pe rolurinoduri cu rol platformnodeSelectornod cu rol buildNoSchedule taintGitHubActions · GHCRCluster pentru aplicațiile clientului · exemplucâte unul pentru fiecare țintă înregistratăUn nod K3s · serverCilium · kube-proxy păstrat1workflow_dispatch2completarea Job-urilor runner3preluarea jobului4pachet testat5 publicare prin digest · release job · GitHub-hosted → GHCR51workload commit · push2revision3 Application sync · API-ul produsului · cd.js → bridge.py → Argo CD · Application34aplicare în namespace5pull prin digest1HTTPS 4432NodePort3 către Pod · NodePort Service · Local → Deployment · Pod · imagine prin digest34 aplicarea politicii · Cilium · Helm · VXLAN → NetworkPolicy · doar CIDR-urile listate45 dashboard · API · Utilizator Railshot → dashboard · nginx51 revizie · health · imagini · API-ul produsului · cd.js → bridge.py → Argo CD · Application12verificare HTTPS publică3Diagnostic Pod · nu verdictul4coada jurnalului · 100 de rânduri per Pod5scrape · NodePort-uri6Blackbox probe1randarea platformei · Secret2bootstrap de înregistrare3instalare K3s · Cilium4TokenRequest · 6 h

Build → publicarea imaginii

API-ul produsului cere o rulare GitHub Actions, iar runnerul de pe nodul build preia și verifică jobul. Doar un pachet care a trecut aceleași verificări este publicat în GHCR de un job de release găzduit de GitHub.

  1. API-ul produsului · cd.js → bridge.pyrailshot-systemrulare · aplicare: workflow_dispatchloop job · self-hosted runnerrailshot-deploy.yml

    API-ul produsului cere o rulare GitHub Actions cu tenant, app, source commit și țintă. API-ul nu apelează niciodată direct un Job runner.

  2. build controller · CronJobrailshot-systemrulare · aplicare: completarea Job-urilor runnerrunner Job · hostNetwork · Docker socketrailshot-build

    CronJob-ul build controller (la fiecare minut, pe un nod platform) creează Job-uri runner în namespace-ul railshot-build. Role-ul său permite doar get, list și create pentru Job-uri, plus get, update și patch pe singurul Secret de înregistrare a runnerului; nu poate crea namespace-uri sau alte Secret-uri.

  3. runner Job · hostNetwork · Docker socketrailshot-buildrulare · aplicare: preluarea jobuluiloop job · self-hosted runnerrailshot-deploy.yml

    Runnerul de pe nodul cu rol build (hostname exact, toleration NoSchedule) preia jobul loop după etichetele self-hosted și îl rulează. Sursa clientului rulează în containerele restricționate existente de build și verificare Docker.

  4. runner Job · hostNetwork · Docker socketrailshot-builddate: pachet testatrelease job · GitHub-hostedrailshot-deploy.yml

    Jobul loop lasă pachetul care a trecut aceleași verificări, iar jobul de release preia doar acel pachet.

  5. release job · GitHub-hostedrailshot-deploy.ymldate: publicare prin digestGHCR

    Un job de release găzduit de GitHub (ubuntu-24.04) publică imaginea pachetului testat în GHCR fără a o reconstrui. Publicarea imaginilor nu are loc niciodată în clusterul aplicațiilor clientului.

Config Git → Argo → namespace-ul clientului

Config Git transportă resursele dorite, iar GHCR octeții imaginii. Argo CD aplică doar în namespace-ul înregistrat al clientului.

  1. API-ul produsului · cd.js → bridge.pyrailshot-systemdate: workload commit · pushdepozitul config Git

    cd.js rulează bridge.py, care face commit și push pentru workload.json doar când înregistrarea de publicare și ținta înregistrată corespund, apoi recitește revizia de pe remote. Git transportă resursele dorite; GHCR transportă octeții imaginii.

  2. depozitul config Gitdate: revisionArgo CD · Applicationargocd

    Application citește doar depozitul de configurație, calea și revizia restricționate.

  3. API-ul produsului · cd.js → bridge.pyrailshot-systemrulare · aplicare: Application syncArgo CD · Applicationargocd

    Application numită este setată prin server-side apply, iar sincronizarea unei singure revizii exacte este cerută fără prune. ServiceAccount-ul railshot-product al API-ului produsului deține atât bootstrap-ul de înregistrare instalat de operator (create pentru Secret-uri, AppProject-uri și Application-uri în argocd; get, update și escalate pe Role-uri numite), cât și permisiunile get și patch adăugate cu numele exact pentru fiecare țintă validată. create din Kubernetes nu poate fi limitat după nume, așa că validarea intrărilor din produs menține și ea numele în domeniu.

  4. Argo CD · Applicationargocdrulare · aplicare: aplicare în namespace<app namespace>

    Argo CD aplică în namespace-ul desemnat din clusterul clientului cu credențiala Secret-ului de cluster înregistrat. AppProject permite doar tipuri cu namespace și nicio resursă la nivel de cluster.

  5. Deployment · Pod · imagine prin digest<app namespace>date: pull prin digestGHCR

    Imaginea publicată prin digest este descărcată cu un Secret de pull referit după nume în același namespace. Valorile Secret nu intră niciodată în artefact sau în config Git.

Calea publică a cererilor

Cererile către aplicație merg pe ruta punct de intrare L7 al furnizorului → NodePort-ul nodului → Service → Pod-ul aplicației. Aplicarea politicilor de către Cilium este un control separat, nu un pas care transportă cererea. Accesul la dashboardul de operare urmează o cale separată.

  1. Utilizatorul aplicațieidate: HTTPS 443Punctul de intrare L7 al furnizorului

    Utilizatorii aplicației ajung la punctul de intrare L7 al furnizorului prin hostname-ul înregistrat. Fiecare furnizor își implementează propriul punct de intrare.

  2. Punctul de intrare L7 al furnizoruluidate: NodePortNodePort Service · Local<app namespace>

    Punctul de intrare redirecționează către adresa privată și NodePort-ul nodului. NodePort-ul este cel alocat la înregistrarea țintei.

  3. NodePort Service · Local<app namespace>date: către PodDeployment · Pod · imagine prin digest<app namespace>

    Service trimite cererea către Pod-ul aplicației (Deployment) de pe același nod. Cu externalTrafficPolicy Local, adresa sursă ajunge neschimbată la verificarea CIDR-urilor înregistrate din NetworkPolicy.

  4. Cilium · Helm · VXLANkube-systemrulare · aplicare: aplicarea politiciiNetworkPolicy · doar CIDR-urile listate<app namespace>

    Cilium aplică NetworkPolicy: trafic de intrare doar din CIDR-urile înregistrate către portul aplicației; implicit niciun trafic de ieșire, cu excepția unei adrese de bază de date aprobate. Firewallurile din cloud și regulile gazdei contează în continuare.

  5. Utilizator Railshotdate: dashboard · APIdashboard · nginxrailshot-system

    Utilizatorii vin prin punctul de intrare de operare către dashboardul nginx, iar nginx stă în fața API-ului produsului. Service-ul dashboardului este NodePort doar când este dat un port de nod aprobat; API-ul rămâne ClusterIP.

Verificare · observare

Verdictul implementării se bazează doar pe starea Argo și pe verificarea URL-ului public. Diagnosticul Pod, jurnalele curente și metricile de operare sunt semnale separate, care nu îl schimbă niciodată.

  1. API-ul produsului · cd.js → bridge.pyrailshot-systemobservare: revizie · health · imaginiArgo CD · Applicationargocd

    Starea deployed cere revizia de sincronizare a Application, Synced și Healthy, operation Succeeded și ca referințele de imagine înregistrate în starea Argo Application să fie egale cu imaginile prin digest ale Deployment-ului revizuit. Nu este o poartă directă pe imageID-ul Pod-ului, iar o stare Argo verde nu stabilește singură potrivirea.

  2. API-ul produsului · cd.js → bridge.pyrailshot-systemobservare: verificare HTTPS publicăPunctul de intrare L7 al furnizorului

    URL-ul public înregistrat este verificat fără redirecționări. Succeeded este înregistrat doar cu verdictul Argo și cu această verificare.

  3. API-ul produsului · cd.js → bridge.pyrailshot-systemobservare: Diagnostic Pod · nu verdictulDeployment · Pod · imagine prin digest<app namespace>

    După verdictul Argo și verificarea publică, Deployment-ul, ReplicaSet-urile și Pod-urile sunt citite separat cu credențiala înregistrată, iar imageID și starea de pregătire sunt adăugate ca diagnostic ready, progressing sau unavailable. Un diagnostic eșuat sau diferit nu schimbă niciodată verdictul deployed sau succeeded.

  4. API-ul produsului · cd.js → bridge.pyrailshot-systemobservare: coada jurnalului · 100 de rânduri per PodDeployment · Pod · imagine prin digest<app namespace>

    Doar pentru operația implementată în prezent, cu configurația de încredere și credențiala înregistrată. Pentru fiecare Pod curent (cel mult trei), digest-ul imaginii care rulează trebuie să fie egal cu digest-ul așteptat; apoi sunt citite cel mult 100 de rânduri mascate per Pod, într-o limită de octeți. O încercare mai veche primește răspunsul superseded; fără configurație, not_configured. Nu este agregare de jurnale.

  5. VM de observareobservare: scrape · NodePort-urirailshot-observability

    Prometheus de pe VM-ul de observare colectează node-exporter și kube-state-metrics prin două NodePort-uri restricționate de firewall. Valorile lipsă sau învechite sunt necunoscute, nu zero.

  6. VM de observareobservare: Blackbox probePunctul de intrare L7 al furnizorului

    probe_success=1 înseamnă un 2xx în acel punct de sondare. Nu dovedește nici accesul fiecărui utilizator, nici versiunea implementată și nu promovează niciodată published la deployed.

Instalare · înregistrare de către operator

Instalarea clusterului, bootstrap-ul de înregistrare și intrările țintei, Secret-urile și configurarea reînnoirii credențialelor sunt intrări ale operatorului, niciodată parte din payloadul aplicației tenantului.

  1. Bootstrap-ul operatoruluirulare · aplicare: randarea platformei · Secretrailshot-system

    Operatorul randează declarația platformei cu render-platform.py și furnizează configurația de operare privată și Secret-urile. MCP-ul la distanță este inclus doar când imaginea lui este furnizată, iar gateway-ul personal (WireGuard) doar cu --personal.

  2. Bootstrap-ul operatoruluirulare · aplicare: bootstrap de înregistrareAppProject · cluster Secretargocd

    Operatorul instalează în argocd Role-ul de bootstrap pentru înregistrare și un Role registrations gol și pregătește intrările țintei. Apoi helperii de înregistrare rulați de API-ul produsului (environment.py, applications.py) scriu Secret-ul railshot-<target> cu o credențială limitată (clusterResources false, namespace-uri permise listate) și adaugă numele exacte validate în Role-ul registrations. Înregistrarea per aplicație leagă un namespace app-<id> de un AppProject cu același nume.

  3. Bootstrap-ul operatoruluirulare · aplicare: instalare K3s · CiliumCilium · Helm · VXLANkube-system

    install-k3s.sh instalează un server K3s cu un singur nod (flannel, network policy, traefik și servicelb dezactivate; kube-proxy păstrat), iar Cilium este instalat ca release Helm (kubeProxyReplacement false, VXLAN, Hubble dezactivat).

  4. CronJob de reînnoire · la fiecare 2 hargocdrulare · aplicare: TokenRequest · 6 hSA railshot-argocd · token<app namespace>

    CronJob-ul railshot-credentials cere la fiecare două ore un token nou de șase ore pentru SA-ul clientului. Role-ul din partea clientului permite doar token create pentru propriul SA. Șase ore este TTL-ul unui token, nu momentul în care se încheie accesul operatorului.

Fiecare conexiune cu aceeași grosime. Alegeți un flux pentru a evidenția doar traseul lui, cu pași numerotați.

  • Continuă · direcția în care circulă cererile, pachetele, imaginile și declarațiile
  • Întreruptă · cereri de rulare, aplicare, instalare, credențiale
  • Linie-punct lungă · citirea stării, jurnalelor, sondelor, metricilor; separată de verdict
  • Linie neagră groasă · fluxul selectat; numerele dau ordinea
  • Casetă · un namespace, cu numele în antet (nu un nod)
  • Etichetă interioară · o componentă din acel namespace
  • Casetă întreruptă · în afara clusterelor
  • railshot-system · produs
  • argocd · dreptul de implementare
  • railshot-build · drept asupra Docker-ului gazdei
  • GitHub · clusterul clientului

Decizia de plasare din 2 octombrie din docs/architecture (două noduri cu roluri) și diagrama din README-ul public sunt istoric; această hartă urmează declarațiile și codul de la 645e28a. Săgețile arată cauza și direcția, nu o dovadă că fiecare cale de furnizor este activă acum.

Namespace-uri și noduri
Un namespace este un domeniu de nume: nici hardware, nici, prin el însuși, o graniță de securitate. Rolurile platform și build sunt plasări de planificare prin nodeSelector și taint; această hartă nu fixează numărul de noduri al clusterului de operare. Plasarea pe noduri a Argo CD este, de asemenea, o verificare separată.
Drepturile nodului build
Job-urile runner rulează cu hostNetwork, socketul Docker al gazdei, NET_ADMIN și root. Un namespace, un taint sau RBAC nu elimină dreptul asupra Docker-ului gazdei, așa că nu este nici izolare de administratorul VM, nici un sandbox pentru cod arbitrar.
Namespace-ul clientului
Fiecare țintă înregistrată folosește un namespace și un AppProject care nu sunt implicite (de exemplu tenant-demo sau app-<id> pentru fiecare aplicație). Sunt create doar Deployment-ul unui singur serviciu (cu montarea automată a tokenului ServiceAccount dezactivată), un NodePort Service și o NetworkPolicy, plus opțional un PVC sau un Job de migrare; Secret-urile sunt doar referite după nume (Secret-ul de pull și un DATABASE_URL aprobat), niciodată create.
Punctul de intrare AWS
Route 53 Alias → ALB partajat HTTPS 443 → adresa privată și NodePort-ul nodului clientului. Multe aplicații refolosesc un singur nod, fiecare cu propriul namespace, propria Application și propriul NodePort.
Punctul de intrare GCP
LB HTTPS global EXTERNAL_MANAGED → NEG zonal GCE_VM_IP_PORT → NodePort-ul privat al VM-ului existent. Certificatele vin din Certificate Manager cu autorizare DNS. Modulul nu deține nici VM-ul, nici VPC-ul, iar un singur VM rămâne un punct unic de eșec.
Punctul de intrare OpenStack
Listener TLS Amphora 443 cu politici L7 pe Host și cale → HTTP NodePort. Adresa implicită este un VIP privat; Octavia, K3s, baza de date și DNS sunt în afara modulului. Accesibilitatea publică și pregătirea Amphora la fața locului necesită o recepție separată, iar nicio aplicare la fața locului nu a fost încă verificată cu acest modul.
Între furnizori
Cele trei puncte de intrare sunt implementări separate, fără failover sau replicare automată între furnizori. Clusterul aplicațiilor clientului este un exemplu de țintă înregistrată, nu o afirmație că aceeași implementare rulează simultan în fiecare cloud.
Opțiuni ale operatorului
Gateway-ul personal (WireGuard) se alătură platformei doar când operatorul activează --personal; nu este o cale obligatorie pentru cloud-urile clienților. În modul direct acceptat, VM-ul de observare poate împărți VM-ul de control al operării.