Railshot
AI deployment & operations platform
將本機建置的網頁應用程式,部署到備妥的雲端與地端環境並維運。
把在本機建置的網頁應用程式部署到備妥的雲端或地端環境,並持續維運的 AI 部署與維運平台。
維運叢集與客戶應用程式叢集分開,公開路徑也與部署控制分離。
在維運 K3s 中,儀表板、產品 API 與 build controller 部署在 platform 角色節點,runner Job 部署在 build 角色節點,由 Argo CD 負責部署。客戶應用程式在每個已註冊目標各自獨立的單節點 K3s + Cilium 叢集中,於指定的 namespace 執行。
建置 → 發布映像檔
產品 API 請求 GitHub Actions 執行,build 節點上的 runner 領取並檢查該 job。只有通過相同檢查的 bundle,才由 GitHub-hosted release job 發布到 GHCR。
產品 API · cd.js → bridge.py
railshot-system執行 · 套用: workflow_dispatchloop job · self-hosted runnerrailshot-deploy.yml產品 API 以 tenant、app、source commit 與 target 請求 GitHub Actions 執行。API 從不直接呼叫 runner Job。
build controller · CronJob
railshot-system執行 · 套用: 補充 runner Jobrunner Job · hostNetwork · Docker socketrailshot-buildbuild controller CronJob(每分鐘,在 platform 節點上)在 railshot-build namespace 中建立 runner Job。其 Role 只允許對 Job 執行 get、list 與 create,以及對唯一一個 runner 註冊 Secret 執行 get、update 與 patch;無法建立 namespace 或其他 Secret。
runner Job · hostNetwork · Docker socket
railshot-build執行 · 套用: 領取 jobloop job · self-hosted runnerrailshot-deploy.ymlbuild 角色節點上的 runner(精確 hostname、NoSchedule toleration)依 self-hosted 標籤領取 loop job 並執行。客戶原始碼在既有的受限 Docker 建置與檢查容器中執行。
runner Job · hostNetwork · Docker socket
railshot-build資料: 檢查過的 bundlerelease job · GitHub-hostedrailshot-deploy.ymlloop job 留下通過相同檢查的 bundle,release job 只接收該 bundle。
release job · GitHub-hosted
railshot-deploy.yml資料: 依摘要值發布GHCRGitHub-hosted release job(ubuntu-24.04)將檢查過的 bundle 映像檔發布到 GHCR,不重新建置。映像檔發布從不在客戶應用程式叢集內進行。
Config Git → Argo → 客戶 namespace
Config Git 承載期望的資源,GHCR 承載映像檔位元組。Argo CD 只套用到已註冊的客戶 namespace。
產品 API · cd.js → bridge.py
railshot-system資料: workload commit · pushconfig Git 儲存庫cd.js 執行 bridge.py,僅在發布記錄與已註冊目標一致時 commit 並 push workload.json,再讀回遠端修訂版本。Git 承載期望的資源;GHCR 承載映像檔位元組。
config Git 儲存庫資料: revisionArgo CD · Application
argocdApplication 只讀取其受限的 config 儲存庫、路徑與修訂版本。
產品 API · cd.js → bridge.py
railshot-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 無法依名稱限制,因此產品的輸入驗證也負責把名稱維持在範圍內。
Argo CD · Application
argocd執行 · 套用: 套用到 namespace<app namespace>Argo CD 以已註冊 cluster Secret 的認證資訊,套用到客戶叢集中的指定 namespace。AppProject 只允許 namespace 範圍的 kind,不允許叢集範圍的資源。
Deployment · Pod · 摘要值映像檔
<app namespace>資料: 依摘要值 pullGHCR已發布的摘要值映像檔透過同一 namespace 中依名稱參照的 pull Secret 拉取。Secret 的值從不進入產出物或 config Git。
公開請求路徑
應用程式請求依序經過供應商 L7 入口 → 節點 NodePort → Service → 應用程式 Pod。Cilium 的策略強制執行是另外的控制,不是承載請求的一跳。進入維運儀表板的路徑是另一條。
應用程式使用者資料: HTTPS 443供應商 L7 入口
應用程式使用者透過已註冊的 hostname 連到供應商的 L7 入口。每個供應商各自實作入口。
供應商 L7 入口資料: NodePortNodePort Service · Local
<app namespace>入口轉送到節點的私有位址與 NodePort。NodePort 是註冊目標時分配的值。
NodePort Service · Local
<app namespace>資料: 送往 PodDeployment · Pod · 摘要值映像檔<app namespace>Service 將請求送往同一節點上的應用程式 Pod(Deployment)。由於 externalTrafficPolicy 為 Local,來源位址不經改變即到達 NetworkPolicy 的已註冊 CIDR 檢查。
Cilium · Helm · VXLAN
kube-system執行 · 套用: 強制執行策略NetworkPolicy · 僅列出的 CIDR<app namespace>Cilium 強制執行 NetworkPolicy:入站只允許從已註冊 CIDR 到應用程式連接埠;預設無出站,僅核准的資料庫位址例外。雲端防火牆與主機規則仍然必要。
Railshot 使用者資料: 儀表板 · APIdashboard · nginx
railshot-system使用者經由維運入口進入 nginx 儀表板,nginx 位於產品 API 前端。只有提供核准的 node port 時,dashboard Service 才是 NodePort;API 維持 ClusterIP。
驗證 · 觀測
部署判定只依據 Argo 狀態與公開 URL 檢查。Pod 診斷、目前日誌與維運指標是另外的訊號,從不改變判定。
產品 API · cd.js → bridge.py
railshot-system觀測: 修訂版本 · health · 映像檔Argo CD · Applicationargocd判定為 deployed 需要 Application 的 sync 修訂版本、Synced 與 Healthy、operation Succeeded,且 Argo Application 狀態中記錄的映像檔參照等於審查過的 Deployment 的摘要值映像檔。這不是直接檢查 Pod imageID 的關卡,僅憑 Argo 的綠色狀態也無法確立此一致。
產品 API · cd.js → bridge.py
railshot-system觀測: 公開 HTTPS 檢查供應商 L7 入口以不跟隨重新導向的方式檢查已註冊的公開 URL。必須同時有 Argo 判定與此檢查,才記錄為 succeeded。
產品 API · cd.js → bridge.py
railshot-system觀測: Pod 診斷 · 非判定Deployment · Pod · 摘要值映像檔<app namespace>Argo 判定與公開檢查之後,以已註冊的認證資訊另外讀取 Deployment、ReplicaSet 與 Pod,並將 imageID 與就緒狀態以 ready、progressing 或 unavailable 診斷附加。診斷失敗或不一致,從不改變 deployed 或 succeeded 判定。
產品 API · cd.js → bridge.py
railshot-system觀測: 日誌 tail · 每個 Pod 100 行Deployment · Pod · 摘要值映像檔<app namespace>僅針對目前已部署的 operation,使用受信任的 config 與已註冊的認證資訊。對每個目前的 Pod(最多三個),執行中的映像檔摘要值必須等於預期的摘要值;接著在位元組上限內,每個 Pod 讀取最多 100 行已遮蔽敏感值的日誌。較舊的嘗試回應 superseded;未設定時回應 not_configured。這不是日誌彙整。
觀測 VM觀測: scrape · NodePortrailshot-observability
觀測 VM 上的 Prometheus 透過兩個受防火牆限制的 NodePort scrape node-exporter 與 kube-state-metrics。缺失或過時的值是未知,而非零。
觀測 VM觀測: Blackbox probe供應商 L7 入口
probe_success=1 表示在該探針位置收到 2xx。它既不證明每位使用者都能存取,也不證明部署的版本,且從不將已發布提升為已部署。
維運人員安裝 · 註冊
叢集安裝、註冊 bootstrap 與目標輸入、Secret,以及認證資訊更新設定,都是維運人員的輸入,從不屬於 tenant 應用程式 payload。
維運人員 bootstrap執行 · 套用: platform 渲染 · Secretrailshot-system
維運人員以 render-platform.py 產生 platform 宣告,並提供私有的維運設定與 Secret。遠端 MCP 只在提供其映像檔時納入,個人 gateway(WireGuard)只在使用 --personal 時納入。
維運人員 bootstrap執行 · 套用: 註冊 bootstrapAppProject · cluster Secret
argocd維運人員在 argocd 中安裝註冊 bootstrap Role 與空的 registrations Role,並準備目標輸入。接著,產品 API 執行的註冊 helper(environment.py、applications.py)以限定範圍的認證資訊寫入 railshot-<target> Secret(clusterResources false,列出允許的 namespace),並將已驗證的確切名稱附加到 registrations Role。逐應用程式的註冊將 app-<id> namespace 繫結到同名的 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 小時
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 共用。