RAILSHOT.
Powrót do sali

Railshot

AI deployment & operations platform

Wdrożenie lokalnie zbudowanej aplikacji webowej w przygotowanych środowiskach chmurowych i lokalnych, a potem jej utrzymanie.

Platforma AI do wdrażania i utrzymania, która przenosi lokalnie zbudowaną aplikację webową do przygotowanych środowisk chmurowych lub lokalnych (on-premises) i dalej ją utrzymuje.

2026.09.28 — 2026.10.04 · Zakończony

Projekt zespołowy · mój udział: planowanie i implementacja CI, klastry CSP i interfejs Ansible, utrzymanie, przegląd kodu zespołu i integracja

SoftBank Hackathon 2026 powered by KOREC & ProgateUczestnik eliminacji · wybór finalistów zostanie ogłoszony 2026.10.26 (stan na 2026.10.07)

  • Wersja webowaZaimplementowane · hackathon
  • Serwer MCPZaimplementowane · zdalnie · lokalnie

Klaster operacyjny i klastry aplikacji klientów są oddzielone, a ścieżka publiczna jest odseparowana od sterowania wdrożeniem.

W operacyjnym K3s panel, API produktu i build controller są umieszczone na węzłach w roli platform, a Joby runnerów na węźle w roli build, natomiast wdrożeniem zajmuje się Argo CD. Aplikacje klientów działają w wyznaczonej przestrzeni nazw osobnego, jednowęzłowego klastra K3s + Cilium dla każdego zarejestrowanego celu.

Mapa klastrów · narysowana na podstawie deklaracji i kodu w publicznym commicie 645e28a
Mapa klastrów operacyjnego i klientów RailshotOperacyjny klaster K3s i zarejestrowany klaster aplikacji klienta. W klastrze operacyjnym przestrzeń nazw railshot-system umieszcza panel, API produktu, zdalny MCP (tylko gdy dostarczono jego obraz) i build controller na węzłach w roli platform; Joby runnerów w przestrzeni nazw railshot-build przyjmują zadania GitHub Actions na węźle w roli build oznaczonym taintem. Zadanie wydania hostowane przez GitHub publikuje przetestowany bundle w GHCR. API produktu commituje workload do config Git i synchronizuje Application w przestrzeni nazw argocd, a Argo CD stosuje Deployment, Service NodePort i NetworkPolicy w przestrzeni nazw zarejestrowanej w klastrze klienta. Żądania do aplikacji wchodzą przez wejście L7 dostawcy do NodePort i Service węzła, a następnie do poda aplikacji. Werdykt wdrożenia opiera się wyłącznie na stanie Argo i kontroli publicznego URL; diagnostyka podów, logi i metryki są odczytywane jako osobne sygnały. Dane instalacyjne i rejestracyjne operatora są oddzielone od ładunku aplikacji tenanta.Użytkownik Railshotpanel · MCPBootstrap operatorainstalacja · rejestracja · SecretGHCRobrazy według digestRepozytorium config Gitworkload.json · revisionWejście L7 dostawcyALB · GCP LB · AmphoraUżytkownik aplikacjipubliczny HTTPSVM obserwacyjnapoza K3s klienta · Composerailshot-systemdashboard · nginxzdalny MCP · tylko z obrazembuild controller · CronJobAPI produktu · cd.js → bridge.pyargocdArgo CD · ApplicationAppProject · cluster SecretCronJob odnowienia · co 2 hrailshot-buildrunner Job · hostNetwork · Docker socketrailshot-deploy.ymlloop job · self-hosted runnerrelease job · GitHub-hosted<app namespace>Deployment · Pod · obraz według digestNodePort Service · LocalNetworkPolicy · wymienione CIDRSA railshot-argocd · tokenkube-systemCilium · Helm · VXLANrailshot-observabilitynode-exporterkube-state-metricsKlaster operacyjny · K3sAWS · węzły według rólwęzły w roli platformnodeSelectorwęzeł w roli buildNoSchedule taintGitHubActions · GHCRKlaster aplikacji klienta · przykładjeden na zarejestrowany celJeden węzeł K3s · serverCilium · kube-proxy zachowany1workflow_dispatch2uzupełnianie Jobów runnera3pobranie zadania4przetestowany bundle5 publikacja według digest · release job · GitHub-hosted → GHCR51workload commit · push2revision3 Application sync · API produktu · cd.js → bridge.py → Argo CD · Application34zastosowanie w przestrzeni nazw5pobranie według digest1HTTPS 4432NodePort3 do poda · NodePort Service · Local → Deployment · Pod · obraz według digest34 egzekwowanie polityki · Cilium · Helm · VXLAN → NetworkPolicy · wymienione CIDR45 panel · API · Użytkownik Railshot → dashboard · nginx51 rewizja · health · obrazy · API produktu · cd.js → bridge.py → Argo CD · Application12publiczna kontrola HTTPS3diagnostyka poda · nie werdykt4tail logów · 100 wierszy na pod5scrape · NodePorty6Blackbox probe1renderowanie platform · Secret2bootstrap rejestracji3instalacja K3s · Cilium4TokenRequest · 6 h

Build → publikacja obrazu

API produktu zleca przebieg GitHub Actions, a runner na węźle build pobiera i sprawdza zadanie. Tylko bundle, który przeszedł te same kontrole, jest publikowany w GHCR przez zadanie wydania hostowane przez GitHub.

  1. API produktu · cd.js → bridge.pyrailshot-systemuruchomienie · zastosowanie: workflow_dispatchloop job · self-hosted runnerrailshot-deploy.yml

    API produktu zleca przebieg GitHub Actions z tenantem, aplikacją, commitem źródłowym i celem. API nigdy nie wywołuje Joba runnera bezpośrednio.

  2. build controller · CronJobrailshot-systemuruchomienie · zastosowanie: uzupełnianie Jobów runnerarunner Job · hostNetwork · Docker socketrailshot-build

    CronJob build controllera (co minutę, na węźle platform) tworzy Joby runnerów w przestrzeni nazw railshot-build. Jego Role pozwala tylko na get, list i create dla Jobów oraz get, update i patch dla jednego Secretu rejestracji runnera; nie może tworzyć przestrzeni nazw ani innych Secretów.

  3. runner Job · hostNetwork · Docker socketrailshot-builduruchomienie · zastosowanie: pobranie zadanialoop job · self-hosted runnerrailshot-deploy.yml

    Runner na węźle w roli build (dokładna nazwa hosta, toleracja NoSchedule) pobiera zadanie loop według etykiet self-hosted i je wykonuje. Kod źródłowy klienta działa w istniejących, ograniczonych kontenerach budowania i kontroli Docker.

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

    Zadanie loop pozostawia bundle, który przeszedł te same kontrole, a zadanie wydania przyjmuje tylko ten bundle.

  5. release job · GitHub-hostedrailshot-deploy.ymldane: publikacja według digestGHCR

    Zadanie wydania hostowane przez GitHub (ubuntu-24.04) publikuje obraz z przetestowanego bundla w GHCR bez przebudowy. Publikacja obrazów nigdy nie odbywa się wewnątrz klastra aplikacji klienta.

Config Git → Argo → przestrzeń nazw klienta

Config Git przenosi pożądane zasoby, a GHCR bajty obrazu. Argo CD stosuje zmiany tylko w zarejestrowanej przestrzeni nazw klienta.

  1. API produktu · cd.js → bridge.pyrailshot-systemdane: workload commit · pushRepozytorium config Git

    cd.js uruchamia bridge.py, który commituje i wypycha workload.json tylko wtedy, gdy zapis publikacji i zarejestrowany cel są zgodne, a następnie odczytuje zdalną rewizję. Git przenosi pożądane zasoby; GHCR przenosi bajty obrazu.

  2. Repozytorium config Gitdane: revisionArgo CD · Applicationargocd

    Application odczytuje tylko swoje ograniczone repozytorium konfiguracji, ścieżkę i rewizję.

  3. API produktu · cd.js → bridge.pyrailshot-systemuruchomienie · zastosowanie: Application syncArgo CD · Applicationargocd

    Wskazana Application jest ustawiana przez server-side apply, a synchronizacja jednej dokładnej rewizji jest zlecana bez prune. ServiceAccount railshot-product API produktu ma zarówno zainstalowany przez operatora bootstrap rejestracji (create dla Secretów, AppProjectów i Applications w argocd; get, update i escalate dla wskazanych Roles), jak i uprawnienia get i patch dopisywane dokładną nazwą dla każdego zweryfikowanego celu. Kubernetesowego create nie da się ograniczyć nazwą, więc nazw w zakresie pilnuje też walidacja wejścia w produkcie.

  4. Argo CD · Applicationargocduruchomienie · zastosowanie: zastosowanie w przestrzeni nazw<app namespace>

    Argo CD stosuje zmiany w wyznaczonej przestrzeni nazw w klastrze klienta z poświadczeniem z zarejestrowanego Secretu klastra. AppProject dopuszcza tylko rodzaje w zakresie przestrzeni nazw i żadnych zasobów o zakresie klastra.

  5. Deployment · Pod · obraz według digest<app namespace>dane: pobranie według digestGHCR

    Opublikowany obraz według digest jest pobierany z użyciem pull Secretu wskazanego nazwą w tej samej przestrzeni nazw. Wartości Secretów nigdy nie trafiają do artefaktu ani do config Git.

Publiczna ścieżka żądań

Żądania aplikacji idą: wejście L7 dostawcy → NodePort węzła → Service → pod aplikacji. Egzekwowanie polityki przez Cilium to osobna kontrola, a nie etap przenoszący żądanie. Wejście do panelu operacyjnego to osobna ścieżka.

  1. Użytkownik aplikacjidane: HTTPS 443Wejście L7 dostawcy

    Użytkownicy aplikacji docierają do wejścia L7 dostawcy pod zarejestrowaną nazwą hosta. Każdy dostawca implementuje własne wejście.

  2. Wejście L7 dostawcydane: NodePortNodePort Service · Local<app namespace>

    Wejście przekazuje ruch na prywatny adres węzła i NodePort. NodePort to ten przydzielony przy rejestracji celu.

  3. NodePort Service · Local<app namespace>dane: do podaDeployment · Pod · obraz według digest<app namespace>

    Service wysyła żądanie do poda aplikacji (Deployment) na tym samym węźle. Przy externalTrafficPolicy Local adres źródłowy dociera bez zmian do kontroli zarejestrowanych CIDR w NetworkPolicy.

  4. Cilium · Helm · VXLANkube-systemuruchomienie · zastosowanie: egzekwowanie politykiNetworkPolicy · wymienione CIDR<app namespace>

    Cilium egzekwuje NetworkPolicy: ruch przychodzący tylko z zarejestrowanych CIDR na port aplikacji; domyślnie brak ruchu wychodzącego, z wyjątkiem zatwierdzonego adresu bazy danych. Zapory chmurowe i reguły hosta nadal mają znaczenie.

  5. Użytkownik Railshotdane: panel · APIdashboard · nginxrailshot-system

    Użytkownicy przechodzą przez wejście operacyjne do panelu nginx, a nginx stoi przed API produktu. Service panelu jest typu NodePort tylko wtedy, gdy podano zatwierdzony port węzła; API pozostaje ClusterIP.

Weryfikacja · obserwacja

Werdykt wdrożenia opiera się wyłącznie na stanie Argo i kontroli publicznego URL. Diagnostyka podów, bieżące logi i metryki operacyjne to osobne sygnały, które nigdy go nie zmieniają.

  1. API produktu · cd.js → bridge.pyrailshot-systemobserwacja: rewizja · health · obrazyArgo CD · Applicationargocd

    Stan deployed wymaga rewizji synchronizacji Application, Synced i Healthy, operacji Succeeded oraz zgodności odwołań do obrazów zapisanych w stanie Application w Argo z obrazami według digest z przejrzanego Deploymentu. To nie jest bramka bezpośrednio na imageID poda, a sam zielony stan Argo nie potwierdza tej zgodności.

  2. API produktu · cd.js → bridge.pyrailshot-systemobserwacja: publiczna kontrola HTTPSWejście L7 dostawcy

    Zarejestrowany publiczny URL jest sprawdzany bez przekierowań. Succeeded jest zapisywane tylko przy werdykcie Argo i tej kontroli łącznie.

  3. API produktu · cd.js → bridge.pyrailshot-systemobserwacja: diagnostyka poda · nie werdyktDeployment · Pod · obraz według digest<app namespace>

    Po werdykcie Argo i kontroli publicznej Deployment, ReplicaSety i pody są odczytywane osobno z zarejestrowanym poświadczeniem, a imageID i gotowość są dołączane jako diagnostyka ready, progressing lub unavailable. Nieudana lub odmienna diagnostyka nigdy nie zmienia werdyktu deployed ani succeeded.

  4. API produktu · cd.js → bridge.pyrailshot-systemobserwacja: tail logów · 100 wierszy na podDeployment · Pod · obraz według digest<app namespace>

    Tylko dla obecnie wdrożonej operacji, z zaufaną konfiguracją i zarejestrowanym poświadczeniem. Dla każdego bieżącego poda (najwyżej trzech) digest uruchomionego obrazu musi być równy oczekiwanemu; wtedy odczytywane jest do 100 zamaskowanych wierszy na pod w limicie bajtów. Starsza próba odpowiada superseded; bez konfiguracji not_configured. To nie jest agregacja logów.

  5. VM obserwacyjnaobserwacja: scrape · NodePortyrailshot-observability

    Prometheus na VM obserwacyjnej zbiera dane z node-exporter i kube-state-metrics przez dwa NodePorty ograniczone zaporą. Brakujące lub nieaktualne wartości są nieznane, a nie zerowe.

  6. VM obserwacyjnaobserwacja: Blackbox probeWejście L7 dostawcy

    probe_success=1 oznacza odpowiedź 2xx w miejscu tej sondy. Nie dowodzi dostępu każdego użytkownika ani wdrożonej wersji i nigdy nie podnosi published do deployed.

Instalacja · rejestracja przez operatora

Instalacja klastra, bootstrap rejestracji i dane celów, Secrety oraz konfiguracja odnawiania poświadczeń to dane wejściowe operatora, nigdy część ładunku aplikacji tenanta.

  1. Bootstrap operatorauruchomienie · zastosowanie: renderowanie platform · Secretrailshot-system

    Operator renderuje deklarację platformy za pomocą render-platform.py i dostarcza prywatną konfigurację operacyjną i Secrety. Zdalny MCP jest dołączany tylko wtedy, gdy dostarczono jego obraz, a osobista bramka (WireGuard) tylko z --personal.

  2. Bootstrap operatorauruchomienie · zastosowanie: bootstrap rejestracjiAppProject · cluster Secretargocd

    Operator instaluje w argocd Role bootstrapu rejestracji i pustą Role registrations oraz przygotowuje dane celu. Następnie helpery rejestracji uruchamiane przez API produktu (environment.py, applications.py) zapisują Secret railshot-<target> z poświadczeniem o ograniczonym zakresie (clusterResources false, wymienione dozwolone przestrzenie nazw) i dopisują zweryfikowane dokładne nazwy do Role registrations. Rejestracja dla aplikacji wiąże przestrzeń nazw app-<id> z AppProject o tej samej nazwie.

  3. Bootstrap operatorauruchomienie · zastosowanie: instalacja K3s · CiliumCilium · Helm · VXLANkube-system

    install-k3s.sh instaluje jednowęzłowy serwer K3s (flannel, network policy, traefik i servicelb wyłączone; kube-proxy zachowany), a Cilium jest instalowany jako wydanie Helm (kubeProxyReplacement false, VXLAN, Hubble wyłączony).

  4. CronJob odnowienia · co 2 hargocduruchomienie · zastosowanie: TokenRequest · 6 hSA railshot-argocd · token<app namespace>

    CronJob railshot-credentials co dwie godziny żąda nowego sześciogodzinnego tokenu dla SA klienta. Role po stronie klienta pozwala tylko na token create dla własnego SA. Sześć godzin to TTL jednego tokenu, a nie moment, w którym kończy się dostęp operatora.

Każde połączenie z tą samą wagą. Wybór przepływu wyróżnia tylko jego ścieżkę z ponumerowanymi krokami.

  • Linia ciągła · kierunek przepływu żądań, bundli, obrazów i deklaracji
  • Linia przerywana · żądania uruchomienia, zastosowanie, instalacja, poświadczenia
  • Długa kreska z kropką · odczyt stanu, logów, sond, metryk; oddzielnie od werdyktu
  • Gruba czarna linia · wybrany przepływ; liczby podają kolejność
  • Ramka · przestrzeń nazw, nazwa w nagłówku (nie węzeł)
  • Wewnętrzny element · komponent w tej przestrzeni nazw
  • Przerywana ramka · poza klastrami
  • railshot-system · produkt
  • argocd · uprawnienia wdrożeniowe
  • railshot-build · uprawnienia Docker hosta
  • GitHub · klaster klienta

Decyzja o rozmieszczeniu z October 2 w docs/architecture (dwa węzły ról) i diagram w publicznym README to historia; ta mapa odpowiada deklaracjom i kodowi w 645e28a. Strzałki pokazują przyczynę i kierunek, a nie dowód, że każda ścieżka dostawcy działa teraz.

Przestrzenie nazw i węzły
Przestrzeń nazw to zakres nazewnictwa: ani sprzęt, ani sama w sobie granica bezpieczeństwa. Role platform i build to rozmieszczenie w planowaniu przez nodeSelector i taint; ta mapa nie ustala liczby węzłów klastra operacyjnego. Rozmieszczenie Argo CD na węzłach to również osobna kontrola.
Uprawnienia węzła build
Joby runnerów działają z hostNetwork, gniazdem Docker hosta, NET_ADMIN i jako root. Przestrzeń nazw, taint ani RBAC nie usuwają uprawnień Docker hosta, więc nie jest to ani izolacja od administratora VM, ani piaskownica dla dowolnego kodu.
Przestrzeń nazw klienta
Każdy zarejestrowany cel używa niedomyślnej przestrzeni nazw i AppProject (na przykład tenant-demo lub app-<id> dla każdej aplikacji). Tworzone są tylko Deployment jednej usługi (automount tokenu ServiceAccount wyłączony), Service NodePort i NetworkPolicy oraz opcjonalnie PVC lub Job migracji; Secrety są tylko wskazywane nazwą (pull Secret i zatwierdzony DATABASE_URL), nigdy tworzone.
Wejście AWS
Route 53 Alias → współdzielony ALB HTTPS 443 → prywatny adres węzła klienta i NodePort. Wiele aplikacji korzysta z jednego węzła, każda z własną przestrzenią nazw, Application i NodePort.
Wejście GCP
Globalny EXTERNAL_MANAGED HTTPS LB → strefowy GCE_VM_IP_PORT NEG → prywatny NodePort istniejącej VM. Certyfikaty pochodzą z Certificate Manager z autoryzacją DNS. Moduł nie jest właścicielem ani VM, ani VPC, a jedna VM pozostaje pojedynczym punktem awarii.
Wejście OpenStack
Listener TLS Amphora 443 z politykami L7 dla Host i ścieżki → HTTP NodePort. Domyślny adres to prywatny VIP; Octavia, K3s, baza danych i DNS są poza modułem. Publiczna osiągalność i gotowość Amphory na miejscu wymagają osobnego odbioru, a żadnego wdrożenia na miejscu nie zweryfikowano jeszcze tym modułem.
Między dostawcami
Trzy wejścia to osobne implementacje, bez automatycznego failoveru ani replikacji między dostawcami. Klaster aplikacji klienta to przykład zarejestrowanego celu, a nie twierdzenie, że to samo wdrożenie działa jednocześnie w każdej chmurze.
Opcje operatora
Osobista bramka (WireGuard) dołącza do platformy tylko wtedy, gdy operator włączy --personal; nie jest wymaganą ścieżką dla chmur klientów. W obsługiwanym trybie direct VM obserwacyjna może współdzielić operacyjną VM sterującą.