RAILSHOT.
返回展廳

Railshot

AI deployment & operations platform

將本機建置的網頁應用程式,部署到備妥的雲端與地端環境並維運。

把在本機建置的網頁應用程式部署到備妥的雲端或地端環境,並持續維運的 AI 部署與維運平台。

2026.09.28 — 2026.10.04 · 已結束

團隊專案 · 負責:CI 規劃與實作、CSP 叢集與 Ansible 介面、維運、團隊程式碼審查與整合

SoftBank Hackathon 2026 powered by KOREC & Progate參加預賽 · 決賽入選名單預定 2026年10月26日公布(截至 2026年10月7日)

  • 網頁已實作 · 黑客松
  • MCP 伺服器已實作 · 遠端 · 本機

維運叢集與客戶應用程式叢集分開,公開路徑也與部署控制分離。

在維運 K3s 中,儀表板、產品 API 與 build controller 部署在 platform 角色節點,runner Job 部署在 build 角色節點,由 Argo CD 負責部署。客戶應用程式在每個已註冊目標各自獨立的單節點 K3s + Cilium 叢集中,於指定的 namespace 執行。

叢集架構圖 · 依公開提交 645e28a 的宣告與程式碼繪製
Railshot 維運與客戶叢集架構圖維運 K3s 叢集與一個已註冊的客戶應用程式叢集。在維運叢集中,railshot-system namespace 將儀表板、產品 API、遠端 MCP(僅在提供其映像檔時)與 build controller 部署在 platform 角色節點;railshot-build namespace 中的 runner Job 在設有 taint 的 build 角色節點上領取 GitHub Actions job。GitHub-hosted release job 將檢查過的 bundle 發布到 GHCR。產品 API 將 workload 提交到 config Git,並 sync argocd namespace 中的 Application,Argo CD 再將 Deployment、NodePort Service 與 NetworkPolicy 套用到客戶叢集中已註冊的 namespace。應用程式請求從供應商的 L7 入口進入節點的 NodePort 與 Service,再到應用程式 Pod。部署判定只依據 Argo 狀態與公開 URL 檢查;Pod 診斷、日誌與指標作為另外讀取的訊號。維運人員的安裝與註冊輸入,與 tenant 應用程式 payload 分開。Railshot 使用者儀表板 · MCP維運人員 bootstrap安裝 · 註冊 · SecretGHCR摘要值映像檔config Git 儲存庫workload.json · revision供應商 L7 入口ALB · GCP LB · Amphora應用程式使用者公開 HTTPS觀測 VM客戶 K3s 之外 · Composerailshot-systemdashboard · nginx遠端 MCP · 僅在提供映像檔時build controller · CronJob產品 API · cd.js → bridge.pyargocdArgo CD · ApplicationAppProject · cluster Secret認證更新 CronJob · 每 2 小時railshot-buildrunner Job · hostNetwork · Docker socketrailshot-deploy.ymlloop job · self-hosted runnerrelease job · GitHub-hosted<app namespace>Deployment · Pod · 摘要值映像檔NodePort Service · LocalNetworkPolicy · 僅列出的 CIDRrailshot-argocd SA · 權杖kube-systemCilium · Helm · VXLANrailshot-observabilitynode-exporterkube-state-metrics維運叢集 · K3sAWS · 各角色節點platform 角色節點nodeSelectorbuild 角色節點NoSchedule taintGitHubActions · GHCR客戶應用程式叢集 · 範例每個已註冊目標各一單一 K3s 節點 · serverCilium · 保留 kube-proxy1workflow_dispatch2補充 runner Job3領取 job4檢查過的 bundle5 依摘要值發布 · release job · GitHub-hosted → GHCR51workload commit · push2revision3 Application sync · 產品 API · cd.js → bridge.py → Argo CD · Application34套用到 namespace5依摘要值 pull1HTTPS 4432NodePort3 送往 Pod · NodePort Service · Local → Deployment · Pod · 摘要值映像檔34 強制執行策略 · Cilium · Helm · VXLAN → NetworkPolicy · 僅列出的 CIDR45 儀表板 · API · Railshot 使用者 → dashboard · nginx51 修訂版本 · health · 映像檔 · 產品 API · cd.js → bridge.py → Argo CD · Application12公開 HTTPS 檢查3Pod 診斷 · 非判定4日誌 tail · 每個 Pod 100 行5scrape · NodePort6Blackbox probe1platform 渲染 · Secret2註冊 bootstrap3安裝 K3s · Cilium4TokenRequest · 6 小時

建置 → 發布映像檔

產品 API 請求 GitHub Actions 執行,build 節點上的 runner 領取並檢查該 job。只有通過相同檢查的 bundle,才由 GitHub-hosted release job 發布到 GHCR。

  1. 產品 API · cd.js → bridge.pyrailshot-system執行 · 套用: workflow_dispatchloop job · self-hosted runnerrailshot-deploy.yml

    產品 API 以 tenant、app、source commit 與 target 請求 GitHub Actions 執行。API 從不直接呼叫 runner Job。

  2. build controller · CronJobrailshot-system執行 · 套用: 補充 runner Jobrunner Job · hostNetwork · Docker socketrailshot-build

    build controller CronJob(每分鐘,在 platform 節點上)在 railshot-build namespace 中建立 runner Job。其 Role 只允許對 Job 執行 get、list 與 create,以及對唯一一個 runner 註冊 Secret 執行 get、update 與 patch;無法建立 namespace 或其他 Secret。

  3. runner Job · hostNetwork · Docker socketrailshot-build執行 · 套用: 領取 jobloop job · self-hosted runnerrailshot-deploy.yml

    build 角色節點上的 runner(精確 hostname、NoSchedule toleration)依 self-hosted 標籤領取 loop job 並執行。客戶原始碼在既有的受限 Docker 建置與檢查容器中執行。

  4. runner Job · hostNetwork · Docker socketrailshot-build資料: 檢查過的 bundlerelease job · GitHub-hostedrailshot-deploy.yml

    loop job 留下通過相同檢查的 bundle,release job 只接收該 bundle。

  5. release job · GitHub-hostedrailshot-deploy.yml資料: 依摘要值發布GHCR

    GitHub-hosted release job(ubuntu-24.04)將檢查過的 bundle 映像檔發布到 GHCR,不重新建置。映像檔發布從不在客戶應用程式叢集內進行。

Config Git → Argo → 客戶 namespace

Config Git 承載期望的資源,GHCR 承載映像檔位元組。Argo CD 只套用到已註冊的客戶 namespace。

  1. 產品 API · cd.js → bridge.pyrailshot-system資料: workload commit · pushconfig Git 儲存庫

    cd.js 執行 bridge.py,僅在發布記錄與已註冊目標一致時 commit 並 push workload.json,再讀回遠端修訂版本。Git 承載期望的資源;GHCR 承載映像檔位元組。

  2. config Git 儲存庫資料: revisionArgo CD · Applicationargocd

    Application 只讀取其受限的 config 儲存庫、路徑與修訂版本。

  3. 產品 API · cd.js → bridge.pyrailshot-system執行 · 套用: Application syncArgo CD · Applicationargocd

    指定的 Application 以 server-side apply 設定,並請求不帶 prune、針對單一確切修訂版本的 sync。產品 API 的 railshot-product ServiceAccount 同時持有維運人員安裝的註冊 bootstrap(在 argocd 中對 Secret、AppProject 與 Application 的 create;對具名 Role 的 get、update 與 escalate),以及針對每個已驗證目標依確切名稱追加的 get 與 patch 授權。Kubernetes 的 create 無法依名稱限制,因此產品的輸入驗證也負責把名稱維持在範圍內。

  4. Argo CD · Applicationargocd執行 · 套用: 套用到 namespace<app namespace>

    Argo CD 以已註冊 cluster Secret 的認證資訊,套用到客戶叢集中的指定 namespace。AppProject 只允許 namespace 範圍的 kind,不允許叢集範圍的資源。

  5. Deployment · Pod · 摘要值映像檔<app namespace>資料: 依摘要值 pullGHCR

    已發布的摘要值映像檔透過同一 namespace 中依名稱參照的 pull Secret 拉取。Secret 的值從不進入產出物或 config Git。

公開請求路徑

應用程式請求依序經過供應商 L7 入口 → 節點 NodePort → Service → 應用程式 Pod。Cilium 的策略強制執行是另外的控制,不是承載請求的一跳。進入維運儀表板的路徑是另一條。

  1. 應用程式使用者資料: HTTPS 443供應商 L7 入口

    應用程式使用者透過已註冊的 hostname 連到供應商的 L7 入口。每個供應商各自實作入口。

  2. 供應商 L7 入口資料: NodePortNodePort Service · Local<app namespace>

    入口轉送到節點的私有位址與 NodePort。NodePort 是註冊目標時分配的值。

  3. NodePort Service · Local<app namespace>資料: 送往 PodDeployment · Pod · 摘要值映像檔<app namespace>

    Service 將請求送往同一節點上的應用程式 Pod(Deployment)。由於 externalTrafficPolicy 為 Local,來源位址不經改變即到達 NetworkPolicy 的已註冊 CIDR 檢查。

  4. Cilium · Helm · VXLANkube-system執行 · 套用: 強制執行策略NetworkPolicy · 僅列出的 CIDR<app namespace>

    Cilium 強制執行 NetworkPolicy:入站只允許從已註冊 CIDR 到應用程式連接埠;預設無出站,僅核准的資料庫位址例外。雲端防火牆與主機規則仍然必要。

  5. Railshot 使用者資料: 儀表板 · APIdashboard · nginxrailshot-system

    使用者經由維運入口進入 nginx 儀表板,nginx 位於產品 API 前端。只有提供核准的 node port 時,dashboard Service 才是 NodePort;API 維持 ClusterIP。

驗證 · 觀測

部署判定只依據 Argo 狀態與公開 URL 檢查。Pod 診斷、目前日誌與維運指標是另外的訊號,從不改變判定。

  1. 產品 API · cd.js → bridge.pyrailshot-system觀測: 修訂版本 · health · 映像檔Argo CD · Applicationargocd

    判定為 deployed 需要 Application 的 sync 修訂版本、Synced 與 Healthy、operation Succeeded,且 Argo Application 狀態中記錄的映像檔參照等於審查過的 Deployment 的摘要值映像檔。這不是直接檢查 Pod imageID 的關卡,僅憑 Argo 的綠色狀態也無法確立此一致。

  2. 產品 API · cd.js → bridge.pyrailshot-system觀測: 公開 HTTPS 檢查供應商 L7 入口

    以不跟隨重新導向的方式檢查已註冊的公開 URL。必須同時有 Argo 判定與此檢查,才記錄為 succeeded。

  3. 產品 API · cd.js → bridge.pyrailshot-system觀測: Pod 診斷 · 非判定Deployment · Pod · 摘要值映像檔<app namespace>

    Argo 判定與公開檢查之後,以已註冊的認證資訊另外讀取 Deployment、ReplicaSet 與 Pod,並將 imageID 與就緒狀態以 ready、progressing 或 unavailable 診斷附加。診斷失敗或不一致,從不改變 deployed 或 succeeded 判定。

  4. 產品 API · cd.js → bridge.pyrailshot-system觀測: 日誌 tail · 每個 Pod 100 行Deployment · Pod · 摘要值映像檔<app namespace>

    僅針對目前已部署的 operation,使用受信任的 config 與已註冊的認證資訊。對每個目前的 Pod(最多三個),執行中的映像檔摘要值必須等於預期的摘要值;接著在位元組上限內,每個 Pod 讀取最多 100 行已遮蔽敏感值的日誌。較舊的嘗試回應 superseded;未設定時回應 not_configured。這不是日誌彙整。

  5. 觀測 VM觀測: scrape · NodePortrailshot-observability

    觀測 VM 上的 Prometheus 透過兩個受防火牆限制的 NodePort scrape node-exporter 與 kube-state-metrics。缺失或過時的值是未知,而非零。

  6. 觀測 VM觀測: Blackbox probe供應商 L7 入口

    probe_success=1 表示在該探針位置收到 2xx。它既不證明每位使用者都能存取,也不證明部署的版本,且從不將已發布提升為已部署。

維運人員安裝 · 註冊

叢集安裝、註冊 bootstrap 與目標輸入、Secret,以及認證資訊更新設定,都是維運人員的輸入,從不屬於 tenant 應用程式 payload。

  1. 維運人員 bootstrap執行 · 套用: platform 渲染 · Secretrailshot-system

    維運人員以 render-platform.py 產生 platform 宣告,並提供私有的維運設定與 Secret。遠端 MCP 只在提供其映像檔時納入,個人 gateway(WireGuard)只在使用 --personal 時納入。

  2. 維運人員 bootstrap執行 · 套用: 註冊 bootstrapAppProject · cluster Secretargocd

    維運人員在 argocd 中安裝註冊 bootstrap Role 與空的 registrations Role,並準備目標輸入。接著,產品 API 執行的註冊 helper(environment.py、applications.py)以限定範圍的認證資訊寫入 railshot-<target> Secret(clusterResources false,列出允許的 namespace),並將已驗證的確切名稱附加到 registrations Role。逐應用程式的註冊將 app-<id> namespace 繫結到同名的 AppProject。

  3. 維運人員 bootstrap執行 · 套用: 安裝 K3s · CiliumCilium · Helm · VXLANkube-system

    install-k3s.sh 安裝單節點 K3s server(關閉 flannel、network policy、traefik 與 servicelb;保留 kube-proxy),Cilium 則以 Helm release 安裝(kubeProxyReplacement false、VXLAN、關閉 Hubble)。

  4. 認證更新 CronJob · 每 2 小時argocd執行 · 套用: TokenRequest · 6 小時railshot-argocd SA · 權杖<app namespace>

    railshot-credentials CronJob 每兩小時為客戶 SA 請求新的六小時權杖。客戶端的 Role 只允許對自己的 SA 執行 token create。六小時是單一權杖的 TTL,不是維運存取結束的時間。

所有連線以相同粗細顯示。選擇一個流程,即只突顯其路徑,並標出步驟編號。

  • 實線 · 請求、bundle、映像檔與宣告的流向
  • 虛線 · 執行請求、套用、安裝、認證資訊
  • 長點劃線 · 讀取狀態、日誌、探針、指標;與判定分開
  • 粗黑線 · 所選流程;數字表示順序
  • 方框 · namespace,標題列為其名稱(不是節點)
  • 內層小框 · 該 namespace 中的元件
  • 虛線框 · 叢集之外
  • railshot-system · 產品
  • argocd · 部署權限
  • railshot-build · 主機 Docker 權限
  • GitHub · 客戶叢集

docs/architecture 中 10月2日的配置決定(兩個角色節點)與公開 README 圖屬於歷史記錄;此架構圖依循 645e28a 的宣告與程式碼。箭頭表示因果與方向,並不證明每條供應商路徑目前都在運作。

namespace 與節點
namespace 是命名範圍:既不是硬體,本身也不是安全邊界。platform 與 build 角色是以 nodeSelector 與 taint 進行的排程配置;此架構圖不固定維運叢集的節點數量。Argo CD 的節點配置也是另外的檢查項目。
build 節點權限
runner Job 以 hostNetwork、主機 Docker 通訊端、NET_ADMIN 與 root 執行。namespace、taint 或 RBAC 都無法移除主機 Docker 權限,因此這既不是 VM 管理員隔離,也不是任意程式碼的沙箱。
客戶 namespace
每個已註冊目標使用非預設的 namespace 與 AppProject(例如 tenant-demo,或每個應用程式的 app-<id>)。只建立一個服務的 Deployment(關閉 ServiceAccount 權杖自動掛載)、NodePort Service 與 NetworkPolicy,外加選用的 PVC 或 migration Job;Secret 只依名稱參照(pull Secret 與核准的 DATABASE_URL),從不建立。
AWS 入口
Route 53 Alias → 共用 ALB HTTPS 443 → 客戶節點私有位址與 NodePort。多個應用程式重複使用同一節點,各自有自己的 namespace、Application 與 NodePort。
GCP 入口
全域 EXTERNAL_MANAGED HTTPS LB → zonal GCE_VM_IP_PORT NEG → 既有 VM 的私有 NodePort。憑證由 Certificate Manager 以 DNS authorization 核發。模組既不擁有 VM 也不擁有 VPC,單一 VM 仍是單一故障點。
OpenStack 入口
帶有 Host 與 path L7 策略的 Amphora TLS listener 443 → HTTP NodePort。預設位址是私有 VIP;Octavia、K3s、資料庫與 DNS 在模組之外。公開可達性與現場 Amphora 就緒需另行驗收,此模組尚未驗證任何現場套用。
跨供應商
三個入口是各自獨立的實作,供應商之間沒有自動 failover 或複寫。客戶應用程式叢集是已註冊目標的範例,並不表示同一部署同時在每個雲端上執行。
維運人員選項
個人 gateway(WireGuard)只在維運人員啟用 --personal 時加入平台;它不是客戶雲端的必要路徑。在支援的 direct 模式下,觀測 VM 可與維運控制 VM 共用。