RAILSHOT.
Terug naar de zaal

Railshot

AI deployment & operations platform

Een lokaal gebouwde webapp uitrollen naar voorbereide cloud- en on-premises-omgevingen en daarna laten draaien.

Een AI-platform voor uitrol en beheer dat een lokaal gebouwde webapp naar voorbereide cloud- of on-premises-omgevingen brengt en blijft laten draaien.

2026.09.28 tot 2026.10.04 · Afgerond

Teamproject · mijn aandeel: CI-planning en -implementatie, CSP-clusters en Ansible-interface, beheer, codereview en integratie in het team

SoftBank Hackathon 2026 powered by KOREC & ProgateDeelnemer voorronde · selectie voor de finale bekend op 2026.10.26 (stand 2026.10.07)

  • WebGeïmplementeerd · hackathon
  • MCP-serverGeïmplementeerd · remote · lokaal

Operationele en klantappclusters zijn gescheiden, en het publieke pad blijft los van de uitrolbesturing.

In de operationele K3s staan het dashboard, de product-API en de buildcontroller op nodes met de platformrol en runner-Jobs op een node met de buildrol, terwijl Argo CD de uitrol verzorgt. Klantapps draaien in een aangewezen namespace van een apart single-node-cluster met K3s + Cilium per geregistreerd doel.

Clusterkaart · getekend op basis van de declaraties en code in publieke commit 645e28a
Clusterkaart van Railshot: operations en klantenHet operationele K3s-cluster en een geregistreerd klantappcluster. In het operationele cluster plaatst de namespace railshot-system het dashboard, de product-API, de remote MCP (alleen als het image wordt aangeleverd) en de buildcontroller op nodes met de platformrol; runner-Jobs in de namespace railshot-build nemen GitHub Actions-jobs aan op de getainte node met de buildrol. Een door GitHub gehoste release-job publiceert de geteste bundle naar GHCR. De product-API commit de workload naar config-Git en synct een Application in de namespace argocd, en Argo CD past een Deployment, NodePort-Service en NetworkPolicy toe op de namespace die in het klantcluster is geregistreerd. Appverzoeken komen via een L7-ingang van de provider binnen bij de NodePort en Service van de node en dan bij de app-Pod. Het uitroloordeel steunt alleen op de Argo-status en de controle van de publieke URL; Pod-diagnostiek, logs en metrics worden als aparte signalen gelezen. Installatie- en registratie-input van de operator blijft gescheiden van de payload van de tenant-app.Railshot-gebruikerdashboard · MCPOperator-bootstrapinstalleren · registreren · SecretGHCRdigest-imagesconfig-Git-repositoryworkload.json · revisionL7-ingang van de providerALB · GCP LB · AmphoraAppgebruikerpublieke HTTPSObserver-VMbuiten klant-K3s · Composerailshot-systemdashboard · nginxremote MCP · alleen met imagebuild controller · CronJobproduct-API · cd.js → bridge.pyargocdArgo CD · ApplicationAppProject · cluster Secretvernieuwings-CronJob · elke 2 urailshot-buildrunner Job · hostNetwork · Docker socketrailshot-deploy.ymlloop job · self-hosted runnerrelease job · GitHub-hosted<app namespace>Deployment · Pod · digest-imageNodePort Service · LocalNetworkPolicy · opgegeven CIDR’srailshot-argocd SA · tokenkube-systemCilium · Helm · VXLANrailshot-observabilitynode-exporterkube-state-metricsOperationeel cluster · K3sAWS · rolnodesnodes met platformrolnodeSelectornode met buildrolNoSchedule taintGitHubActions · GHCRKlantappcluster · voorbeeldéén per geregistreerd doelEén K3s-node · serverCilium · kube-proxy behouden1workflow_dispatch2runner-Job aanvullen3job aannemen4geteste bundle5 publiceren per digest · release job · GitHub-hosted → GHCR51workload commit · push2revision3 Application sync · product-API · cd.js → bridge.py → Argo CD · Application34toepassen op namespace5pull per digest1HTTPS 4432NodePort3 naar de Pod · NodePort Service · Local → Deployment · Pod · digest-image34 policy afdwingen · Cilium · Helm · VXLAN → NetworkPolicy · opgegeven CIDR’s45 dashboard · API · Railshot-gebruiker → dashboard · nginx51 revisie · health · images · product-API · cd.js → bridge.py → Argo CD · Application12publieke HTTPS-controle3Pod-diagnostiek · niet het oordeel4log-tail · 100 regels per Pod5scrape · NodePorts6Blackbox probe1platform renderen · Secret2registratie-bootstrap3K3s · Cilium installeren4TokenRequest · 6 u

Build → image publiceren

De product-API vraagt een GitHub Actions-run aan, en de runner op de buildnode neemt de job aan en controleert hem. Alleen een bundle die dezelfde controles doorstond, wordt door een door GitHub gehoste release-job naar GHCR gepubliceerd.

  1. product-API · cd.js → bridge.pyrailshot-systemuitvoeren · toepassen: workflow_dispatchloop job · self-hosted runnerrailshot-deploy.yml

    De product-API vraagt een GitHub Actions-run aan met tenant, app, source commit en target. De API roept nooit rechtstreeks een runner-Job aan.

  2. build controller · CronJobrailshot-systemuitvoeren · toepassen: runner-Job aanvullenrunner Job · hostNetwork · Docker socketrailshot-build

    De CronJob van de buildcontroller (elke minuut, op een platformnode) maakt runner-Jobs aan in de namespace railshot-build. Zijn Role staat alleen get, list en create op Jobs toe plus get, update en patch op het ene runner-registratie-Secret; namespaces of andere Secrets kan hij niet aanmaken.

  3. runner Job · hostNetwork · Docker socketrailshot-builduitvoeren · toepassen: job aannemenloop job · self-hosted runnerrailshot-deploy.yml

    De runner op de node met de buildrol (exacte hostnaam, NoSchedule-toleration) neemt de loop-job aan via zijn self-hosted labels en voert hem uit. Klantbroncode draait in de bestaande beperkte Docker-build- en controlecontainers.

  4. runner Job · hostNetwork · Docker socketrailshot-buildgegevens: geteste bundlerelease job · GitHub-hostedrailshot-deploy.yml

    De loop-job laat de bundle achter die dezelfde controles doorstond, en de release-job neemt alleen die bundle aan.

  5. release job · GitHub-hostedrailshot-deploy.ymlgegevens: publiceren per digestGHCR

    Een door GitHub gehoste release-job (ubuntu-24.04) publiceert het image van de geteste bundle zonder rebuild naar GHCR. Images worden nooit binnen het klantappcluster gepubliceerd.

Config-Git → Argo → klantnamespace

Config-Git draagt de gewenste resources en GHCR de imagebytes. Argo CD past alleen toe op de geregistreerde klantnamespace.

  1. product-API · cd.js → bridge.pyrailshot-systemgegevens: workload commit · pushconfig-Git-repository

    cd.js draait bridge.py, dat workload.json alleen commit en pusht als de publicatievastlegging en het geregistreerde doel overeenkomen, en daarna de remote revisie terugleest. Git draagt de gewenste resources; GHCR draagt de imagebytes.

  2. config-Git-repositorygegevens: revisionArgo CD · Applicationargocd

    De Application leest alleen haar beperkte configrepository, pad en revisie.

  3. product-API · cd.js → bridge.pyrailshot-systemuitvoeren · toepassen: Application syncArgo CD · Applicationargocd

    De benoemde Application wordt via server-side apply ingesteld, en er wordt een sync van precies één revisie aangevraagd zonder prune. Het ServiceAccount railshot-product van de product-API heeft zowel de door de operator geïnstalleerde registratie-bootstrap (create voor Secrets, AppProjects en Applications in argocd; get, update en escalate op benoemde Roles) als get- en patch-rechten die per gevalideerd doel op exacte naam worden toegevoegd. Kubernetes-create kan niet op naam worden beperkt, dus houdt ook de inputvalidatie van het product de namen binnen bereik.

  4. Argo CD · Applicationargocduitvoeren · toepassen: toepassen op namespace<app namespace>

    Argo CD past toe op de aangewezen namespace in het klantcluster met de credential van het geregistreerde cluster-Secret. Het AppProject staat alleen namespaced kinds toe en geen clusterbrede resources.

  5. Deployment · Pod · digest-image<app namespace>gegevens: pull per digestGHCR

    Het gepubliceerde digest-image wordt opgehaald met een pull-Secret waarnaar in dezelfde namespace op naam wordt verwezen. Secret-waarden komen nooit in het artefact of in config-Git terecht.

Publiek verzoekpad

Appverzoeken lopen L7-ingang van de provider → NodePort van de node → Service → app-Pod. De policyhandhaving van Cilium is een aparte controle, geen hop die het verzoek draagt. De weg naar het operationele dashboard is een apart pad.

  1. Appgebruikergegevens: HTTPS 443L7-ingang van de provider

    Appgebruikers bereiken de L7-ingang van de provider via de geregistreerde hostnaam. Elke provider implementeert zijn eigen ingang.

  2. L7-ingang van de providergegevens: NodePortNodePort Service · Local<app namespace>

    De ingang stuurt door naar het privéadres en de NodePort van de node. De NodePort is die welke bij de registratie van het doel is toegewezen.

  3. NodePort Service · Local<app namespace>gegevens: naar de PodDeployment · Pod · digest-image<app namespace>

    De Service stuurt het verzoek naar de app-Pod (Deployment) op dezelfde node. Met externalTrafficPolicy Local bereikt het bronadres de controle op geregistreerde CIDR’s van de NetworkPolicy ongewijzigd.

  4. Cilium · Helm · VXLANkube-systemuitvoeren · toepassen: policy afdwingenNetworkPolicy · opgegeven CIDR’s<app namespace>

    Cilium dwingt de NetworkPolicy af: ingress alleen vanaf de geregistreerde CIDR’s naar de app-poort; standaard geen egress, behalve naar een goedgekeurd databaseadres. Cloudfirewalls en hostregels blijven nodig.

  5. Railshot-gebruikergegevens: dashboard · APIdashboard · nginxrailshot-system

    Gebruikers komen via de operationele ingang bij het nginx-dashboard, en nginx staat vóór de product-API. De dashboard-Service is alleen een NodePort als er een goedgekeurde nodepoort is opgegeven; de API blijft ClusterIP.

Verifiëren · observeren

Het uitroloordeel steunt alleen op de Argo-status en de controle van de publieke URL. Pod-diagnostiek, actuele logs en operationele metrics zijn aparte signalen die het nooit veranderen.

  1. product-API · cd.js → bridge.pyrailshot-systemobserveren: revisie · health · imagesArgo CD · Applicationargocd

    Deployed vereist de syncrevisie van de Application, Synced en Healthy, de operation Succeeded, en image-referenties in de status van de Argo-Application die gelijk zijn aan de digest-images van de beoordeelde Deployment. Het is geen directe gate op de imageID van de Pod, en een groene Argo-status alleen bewijst de overeenkomst niet.

  2. product-API · cd.js → bridge.pyrailshot-systemobserveren: publieke HTTPS-controleL7-ingang van de provider

    De geregistreerde publieke URL wordt gecontroleerd zonder redirects. Succeeded wordt alleen vastgelegd met zowel het Argo-oordeel als deze controle.

  3. product-API · cd.js → bridge.pyrailshot-systemobserveren: Pod-diagnostiek · niet het oordeelDeployment · Pod · digest-image<app namespace>

    Na het Argo-oordeel en de publieke controle worden de Deployment, ReplicaSets en Pods apart gelezen met de geregistreerde credential, en imageID en gereedheid worden toegevoegd als diagnose ready, progressing of unavailable. Een mislukte of afwijkende diagnose verandert nooit het oordeel deployed of succeeded.

  4. product-API · cd.js → bridge.pyrailshot-systemobserveren: log-tail · 100 regels per PodDeployment · Pod · digest-image<app namespace>

    Alleen voor de momenteel uitgerolde operation, met de vertrouwde config en de geregistreerde credential. Voor elke huidige Pod (hoogstens drie) moet de digest van het draaiende image gelijk zijn aan de verwachte digest; daarna worden per Pod tot 100 geredigeerde regels gelezen binnen een bytelimiet. Een oudere poging antwoordt superseded; zonder configuratie not_configured. Dit is geen logaggregatie.

  5. Observer-VMobserveren: scrape · NodePortsrailshot-observability

    Prometheus op de observer-VM scrapet node-exporter en kube-state-metrics via twee door de firewall beperkte NodePorts. Ontbrekende of verouderde waarden zijn onbekend, niet nul.

  6. Observer-VMobserveren: Blackbox probeL7-ingang van de provider

    probe_success=1 betekent een 2xx op die probelocatie. Het bewijst niet de toegang van elke gebruiker of de uitgerolde versie, en het promoveert published nooit tot deployed.

Operator: installatie · registratie

Clusterinstallatie, de registratie-bootstrap en doelinput, Secrets en de inrichting van de credentialvernieuwing zijn operatorinput, nooit onderdeel van de payload van de tenant-app.

  1. Operator-bootstrapuitvoeren · toepassen: platform renderen · Secretrailshot-system

    De operator rendert de platformdeclaratie met render-platform.py en levert de private operationele config en Secrets aan. De remote MCP wordt alleen opgenomen als het image wordt aangeleverd, de persoonlijke gateway (WireGuard) alleen met --personal.

  2. Operator-bootstrapuitvoeren · toepassen: registratie-bootstrapAppProject · cluster Secretargocd

    De operator installeert in argocd de registratie-bootstrap-Role en een lege registratie-Role en bereidt de doelinput voor. De registratiehelpers die de product-API draait (environment.py, applications.py) schrijven daarna het Secret railshot-<target> met een afgebakende credential (clusterResources false, toegestane namespaces opgesomd) en voegen de gevalideerde exacte namen toe aan de registratie-Role. Registratie per app koppelt een namespace app-<id> aan een AppProject met dezelfde naam.

  3. Operator-bootstrapuitvoeren · toepassen: K3s · Cilium installerenCilium · Helm · VXLANkube-system

    install-k3s.sh installeert een single-node K3s-server (flannel, network policy, traefik en servicelb uit; kube-proxy behouden), en Cilium wordt geïnstalleerd als Helm-release (kubeProxyReplacement false, VXLAN, Hubble uit).

  4. vernieuwings-CronJob · elke 2 uargocduitvoeren · toepassen: TokenRequest · 6 urailshot-argocd SA · token<app namespace>

    De CronJob railshot-credentials vraagt elke twee uur een nieuw token van zes uur aan voor het klant-SA. De Role aan klantzijde staat alleen token create voor het eigen SA toe. Zes uur is de TTL van één token, niet het moment waarop operatortoegang eindigt.

Alle verbindingen even zwaar. Kies een stroom om alleen het pad daarvan te markeren, met genummerde stappen.

  • Doorgetrokken · richting waarin verzoeken, bundles, images en declaraties stromen
  • Gestreept · runverzoeken, toepassen, installatie, credentials
  • Lange streep-punt · status, logs, probes en metrics lezen; los van het oordeel
  • Dikke zwarte lijn · de gekozen stroom; nummers geven de volgorde
  • Vak · een namespace, naam in de kop (geen node)
  • Binnenchip · een component in die namespace
  • Gestreept vak · buiten de clusters
  • railshot-system · product
  • argocd · uitrolbevoegdheid
  • railshot-build · host-Docker-bevoegdheid
  • GitHub · klantcluster

De plaatsingsbeslissing van October 2 in docs/architecture (twee rolnodes) en het diagram in de openbare README zijn geschiedenis; deze kaart volgt de declaraties en code van 645e28a. Pijlen tonen oorzaak en richting, geen bewijs dat elk providerpad nu actief is.

Namespaces en nodes
Een namespace is een naambereik: geen hardware en op zichzelf ook geen beveiligingsgrens. De rollen platform en build zijn schedulingplaatsing via nodeSelector en taint; deze kaart legt het aantal nodes van het operationele cluster niet vast. Ook de nodeplaatsing van Argo CD is een aparte controle.
Bevoegdheid van de buildnode
Runner-Jobs draaien met hostNetwork, de Docker-socket van de host, NET_ADMIN en root. Een namespace, taint of RBAC neemt de host-Docker-bevoegdheid niet weg, dus dit is geen isolatie van de VM-beheerder en geen sandbox voor willekeurige code.
Klantnamespace
Elk geregistreerd doel gebruikt een niet-standaard namespace en AppProject (bijvoorbeeld tenant-demo, of app-<id> per app). Alleen de Deployment van één dienst (automount van het ServiceAccount-token uit), een NodePort-Service en een NetworkPolicy, plus optioneel een PVC of migratie-Job, worden aangemaakt; naar Secrets wordt alleen op naam verwezen (het pull-Secret en een goedgekeurde DATABASE_URL), ze worden nooit aangemaakt.
AWS-ingang
Route 53 Alias → gedeelde ALB HTTPS 443 → privéadres en NodePort van de klantnode. Veel apps hergebruiken één node, elk met een eigen namespace, Application en NodePort.
GCP-ingang
Globale EXTERNAL_MANAGED HTTPS-LB → zonale GCE_VM_IP_PORT NEG → privé-NodePort van de bestaande VM. Certificaten komen uit Certificate Manager met DNS-autorisatie. De module bezit de VM noch de VPC, en één VM blijft een single point of failure.
OpenStack-ingang
Amphora-TLS-listener 443 met L7-policies voor host en pad → HTTP-NodePort. Het standaardadres is een private VIP; Octavia, K3s, de database en DNS vallen buiten de module. Publieke bereikbaarheid en de gereedheid van Amphora ter plaatse vereisen een aparte acceptatie, en met deze module is nog geen apply ter plaatse geverifieerd.
Tussen providers
De drie ingangen zijn aparte implementaties, zonder automatische failover of replicatie tussen providers. Het klantappcluster is een voorbeeld van een geregistreerd doel, geen bewering dat dezelfde uitrol tegelijk op elke cloud draait.
Opties van de operator
De persoonlijke gateway (WireGuard) wordt alleen deel van het platform als de operator --personal inschakelt; het is geen verplicht pad voor klantclouds. In de ondersteunde directe modus mag de observer-VM de operationele control-VM delen.