Railshot
AI deployment & operations platform
Triển khai một ứng dụng web xây dựng cục bộ lên các môi trường đám mây và on-premises đã chuẩn bị, rồi vận hành nó.
Một nền tảng AI triển khai và vận hành, đưa ứng dụng web xây dựng cục bộ lên các môi trường đám mây hoặc on-premises đã chuẩn bị và tiếp tục vận hành nó.
Cụm vận hành và cụm ứng dụng của khách hàng được tách riêng, và đường công khai tách khỏi điều khiển triển khai.
Trong K3s vận hành, bảng điều khiển, API sản phẩm và build controller được đặt trên các node vai trò platform và runner Job trên một node vai trò build, còn Argo CD đảm nhận triển khai. Ứng dụng của khách hàng chạy trong một namespace được chỉ định của một cụm K3s + Cilium một node riêng cho mỗi đích đã đăng ký.
Build → phát hành image
API sản phẩm yêu cầu một lượt chạy GitHub Actions, và runner trên node build nhận và kiểm tra job. Chỉ bundle đã qua cùng các kiểm tra mới được một job release do GitHub lưu trữ phát hành lên GHCR.
API sản phẩm · cd.js → bridge.py
railshot-systemchạy · áp dụng: workflow_dispatchloop job · self-hosted runnerrailshot-deploy.ymlAPI sản phẩm yêu cầu một lượt chạy GitHub Actions với tenant, app, source commit và target. API không bao giờ gọi trực tiếp một runner Job.
build controller · CronJob
railshot-systemchạy · áp dụng: bổ sung runner Jobrunner Job · hostNetwork · Docker socketrailshot-buildCronJob của build controller (mỗi phút, trên một node platform) tạo runner Job trong namespace railshot-build. Role của nó chỉ cho phép get, list và create Job cùng get, update và patch trên một Secret đăng ký runner duy nhất; nó không thể tạo namespace hay các Secret khác.
runner Job · hostNetwork · Docker socket
railshot-buildchạy · áp dụng: nhận jobloop job · self-hosted runnerrailshot-deploy.ymlRunner trên node vai trò build (hostname chính xác, NoSchedule toleration) nhận job loop theo nhãn self-hosted và chạy nó. Nguồn của khách hàng chạy trong các container build và kiểm tra Docker hạn chế sẵn có.
runner Job · hostNetwork · Docker socket
railshot-builddữ liệu: bundle đã kiểm thửrelease job · GitHub-hostedrailshot-deploy.ymlJob loop để lại bundle đã qua cùng các kiểm tra, và job release chỉ nhận bundle đó.
release job · GitHub-hosted
railshot-deploy.ymldữ liệu: phát hành theo digestGHCRMột job release do GitHub lưu trữ (ubuntu-24.04) phát hành image của bundle đã kiểm thử lên GHCR mà không build lại. Việc phát hành image không bao giờ diễn ra bên trong cụm ứng dụng khách hàng.
Config Git → Argo → namespace khách hàng
Config Git mang các tài nguyên mong muốn và GHCR mang các byte của image. Argo CD chỉ áp dụng vào namespace khách hàng đã đăng ký.
API sản phẩm · cd.js → bridge.py
railshot-systemdữ liệu: workload commit · pushKho config Gitcd.js chạy bridge.py, script này chỉ commit và push workload.json khi bản ghi phát hành và đích đã đăng ký khớp nhau, rồi đọc lại revision ở remote. Git mang các tài nguyên mong muốn; GHCR mang các byte của image.
Kho config Gitdữ liệu: revisionArgo CD · Application
argocdApplication chỉ đọc kho config, đường dẫn và revision bị giới hạn của nó.
API sản phẩm · cd.js → bridge.py
railshot-systemchạy · áp dụng: Application syncArgo CD · ApplicationargocdApplication được đặt tên được thiết lập bằng server-side apply, và một lần sync cho đúng một revision được yêu cầu mà không prune. ServiceAccount railshot-product của API sản phẩm nắm cả quyền bootstrap đăng ký do người vận hành cài (create cho Secret, AppProject và Application trong argocd; get, update và escalate trên các Role được đặt tên) và quyền get và patch được nối thêm theo đúng tên cho từng đích đã xác minh. create của Kubernetes không thể giới hạn theo tên, nên việc xác thực đầu vào của sản phẩm cũng giữ các tên trong phạm vi.
Argo CD · Application
argocdchạy · áp dụng: áp dụng vào namespace<app namespace>Argo CD áp dụng vào namespace được chỉ định trong cụm khách hàng bằng thông tin xác thực của cluster Secret đã đăng ký. AppProject chỉ cho phép các kind có namespace và không có tài nguyên phạm vi cụm.
Deployment · Pod · image theo digest
<app namespace>dữ liệu: kéo theo digestGHCRImage theo digest đã phát hành được kéo bằng một pull Secret được tham chiếu theo tên trong cùng namespace. Giá trị Secret không bao giờ đi vào artifact hay config Git.
Đường yêu cầu công khai
Yêu cầu đến ứng dụng đi theo điểm vào L7 của nhà cung cấp → NodePort của node → Service → Pod ứng dụng. Việc thực thi chính sách của Cilium là một cơ chế kiểm soát riêng, không phải một chặng mang yêu cầu. Đường vào bảng điều khiển vận hành là một đường riêng.
Người dùng ứng dụngdữ liệu: HTTPS 443Điểm vào L7 của nhà cung cấp
Người dùng ứng dụng đến điểm vào L7 của nhà cung cấp qua hostname đã đăng ký. Mỗi nhà cung cấp hiện thực điểm vào riêng.
Điểm vào L7 của nhà cung cấpdữ liệu: NodePortNodePort Service · Local
<app namespace>Điểm vào chuyển tiếp đến địa chỉ riêng và NodePort của node. NodePort là giá trị được cấp khi đăng ký đích.
NodePort Service · Local
<app namespace>dữ liệu: đến PodDeployment · Pod · image theo digest<app namespace>Service gửi yêu cầu đến Pod ứng dụng (Deployment) trên cùng node. Với externalTrafficPolicy Local, địa chỉ nguồn đến phần kiểm tra CIDR đã đăng ký của NetworkPolicy mà không thay đổi.
Cilium · Helm · VXLAN
kube-systemchạy · áp dụng: thực thi chính sáchNetworkPolicy · các CIDR được liệt kê<app namespace>Cilium thực thi NetworkPolicy: lưu lượng vào chỉ từ các CIDR đã đăng ký đến cổng ứng dụng; mặc định không có lưu lượng ra, trừ một địa chỉ cơ sở dữ liệu được phê duyệt. Tường lửa đám mây và quy tắc máy chủ vẫn quan trọng.
Người dùng Railshotdữ liệu: bảng điều khiển · APIdashboard · nginx
railshot-systemNgười dùng đi qua điểm vào vận hành đến bảng điều khiển nginx, và nginx đứng trước API sản phẩm. Service của bảng điều khiển chỉ là NodePort khi có một node port được phê duyệt; API vẫn là ClusterIP.
Xác minh · quan sát
Phán định triển khai chỉ dựa trên trạng thái Argo và kiểm tra URL công khai. Chẩn đoán Pod, log hiện tại và chỉ số vận hành là các tín hiệu riêng không bao giờ thay đổi nó.
API sản phẩm · cd.js → bridge.py
railshot-systemquan sát: revision · health · imageArgo CD · ApplicationargocdTrạng thái deployed đòi hỏi sync revision của Application, Synced và Healthy, operation Succeeded, và các tham chiếu image ghi trong trạng thái Argo Application phải bằng các image theo digest của Deployment đã rà soát. Đây không phải cổng kiểm tra trực tiếp imageID của Pod, và chỉ trạng thái xanh của Argo không xác lập được sự khớp này.
API sản phẩm · cd.js → bridge.py
railshot-systemquan sát: kiểm tra HTTPS công khaiĐiểm vào L7 của nhà cung cấpURL công khai đã đăng ký được kiểm tra mà không theo redirect. Succeeded chỉ được ghi khi có cả phán định của Argo và lần kiểm tra này.
API sản phẩm · cd.js → bridge.py
railshot-systemquan sát: chẩn đoán Pod · không phải phán địnhDeployment · Pod · image theo digest<app namespace>Sau phán định của Argo và kiểm tra công khai, Deployment, ReplicaSet và Pod được đọc riêng bằng thông tin xác thực đã đăng ký, và imageID cùng trạng thái sẵn sàng được nối thêm như chẩn đoán ready, progressing hoặc unavailable. Chẩn đoán thất bại hoặc khác biệt không bao giờ thay đổi phán định deployed hay succeeded.
API sản phẩm · cd.js → bridge.py
railshot-systemquan sát: tail log · 100 dòng mỗi PodDeployment · Pod · image theo digest<app namespace>Chỉ cho operation đang được triển khai, với config tin cậy và thông tin xác thực đã đăng ký. Với mỗi Pod hiện tại (tối đa ba), digest của image đang chạy phải bằng digest mong đợi; sau đó tối đa 100 dòng đã che dữ liệu mỗi Pod được đọc trong một giới hạn byte. Lần thử cũ hơn trả lời superseded; không có cấu hình thì not_configured. Đây không phải tổng hợp log.
VM quan sátquan sát: scrape · NodePortrailshot-observability
Prometheus trên VM quan sát scrape node-exporter và kube-state-metrics qua hai NodePort bị tường lửa giới hạn. Giá trị thiếu hoặc cũ là không xác định, không phải không.
VM quan sátquan sát: Blackbox probeĐiểm vào L7 của nhà cung cấp
probe_success=1 nghĩa là nhận 2xx tại vị trí probe đó. Nó không chứng minh khả năng truy cập của mọi người dùng cũng như phiên bản đã triển khai, và không bao giờ nâng published thành deployed.
Cài đặt · đăng ký của người vận hành
Việc cài đặt cụm, bootstrap đăng ký và đầu vào của đích, Secret và thiết lập gia hạn thông tin xác thực là đầu vào của người vận hành, không bao giờ là một phần của payload ứng dụng của tenant.
Bootstrap của người vận hànhchạy · áp dụng: dựng platform · Secretrailshot-system
Người vận hành dựng khai báo platform bằng render-platform.py và cung cấp config vận hành và Secret riêng tư. MCP remote chỉ được đưa vào khi có image, gateway cá nhân (WireGuard) chỉ khi dùng --personal.
Bootstrap của người vận hànhchạy · áp dụng: bootstrap đăng kýAppProject · cluster Secret
argocdNgười vận hành cài Role bootstrap đăng ký và một Role registrations rỗng trong argocd và chuẩn bị đầu vào của đích. Sau đó các helper đăng ký mà API sản phẩm chạy (environment.py, applications.py) ghi Secret railshot-<target> với thông tin xác thực có phạm vi (clusterResources false, liệt kê các namespace được phép) và nối các tên chính xác đã xác minh vào Role registrations. Đăng ký theo từng ứng dụng gắn namespace app-<id> với AppProject cùng tên.
Bootstrap của người vận hànhchạy · áp dụng: cài K3s · CiliumCilium · Helm · VXLAN
kube-systeminstall-k3s.sh cài một K3s server một node (tắt flannel, network policy, traefik và servicelb; giữ kube-proxy), và Cilium được cài như một Helm release (kubeProxyReplacement false, VXLAN, tắt Hubble).
CronJob gia hạn · mỗi 2 h
argocdchạy · áp dụng: TokenRequest · 6 hrailshot-argocd SA · token<app namespace>CronJob railshot-credentials yêu cầu một token sáu giờ mới cho SA của khách hàng mỗi hai giờ. Role phía khách hàng chỉ cho phép create token cho SA của chính nó. Sáu giờ là TTL của một token, không phải thời điểm quyền truy cập của người vận hành kết thúc.
Mọi kết nối có cùng độ đậm. Chọn một luồng để chỉ làm nổi bật đường đi của nó, kèm các bước được đánh số.
- Nét liền · hướng đi của yêu cầu, bundle, image và khai báo
- Nét đứt · yêu cầu chạy, áp dụng, cài đặt, thông tin xác thực
- Nét gạch chấm dài · đọc trạng thái, log, probe, chỉ số; tách khỏi phán định
- Nét đen đậm · luồng được chọn; số chỉ thứ tự
- Hộp · một namespace, tên ở phần đầu (không phải node)
- Chip bên trong · một thành phần trong namespace đó
- Hộp nét đứt · bên ngoài các cụm
- railshot-system · sản phẩm
- argocd · thẩm quyền triển khai
- railshot-build · thẩm quyền Docker của host
- GitHub · cụm khách hàng
Quyết định bố trí ngày October 2 trong docs/architecture (hai node vai trò) và sơ đồ README công khai là lịch sử; bản đồ này theo khai báo và mã tại 645e28a. Mũi tên thể hiện nguyên nhân và hướng đi, không phải bằng chứng rằng mọi đường của nhà cung cấp hiện đang hoạt động.
- Namespace và node
- Namespace là một phạm vi đặt tên: không phải phần cứng, cũng không tự nó là một ranh giới bảo mật. Vai trò platform và build là cách bố trí lập lịch bằng nodeSelector và taint; bản đồ này không cố định số node của cụm vận hành. Vị trí node của Argo CD cũng là một phần kiểm tra riêng.
- Thẩm quyền của node build
- Runner Job chạy với hostNetwork, Docker socket của host, NET_ADMIN và root. Namespace, taint hay RBAC không loại bỏ thẩm quyền Docker của host, nên đây không phải cô lập quản trị viên VM cũng không phải sandbox cho mã tùy ý.
- Namespace của khách hàng
- Mỗi đích đã đăng ký dùng một namespace và AppProject không mặc định (ví dụ tenant-demo, hoặc app-<id> cho từng ứng dụng). Chỉ Deployment của một dịch vụ (tắt automount token ServiceAccount), NodePort Service và NetworkPolicy, cùng một PVC hoặc migration Job tùy chọn, được tạo; Secret chỉ được tham chiếu theo tên (pull Secret và một DATABASE_URL được phê duyệt), không bao giờ được tạo.
- Điểm vào AWS
- Route 53 Alias → ALB dùng chung HTTPS 443 → địa chỉ riêng và NodePort của node khách hàng. Nhiều ứng dụng dùng lại một node, mỗi ứng dụng có namespace, Application và NodePort riêng.
- Điểm vào GCP
- Global EXTERNAL_MANAGED HTTPS LB → zonal GCE_VM_IP_PORT NEG → NodePort riêng của VM hiện có. Chứng chỉ đến từ Certificate Manager với DNS authorization. Module không sở hữu VM hay VPC, và một VM vẫn là điểm lỗi đơn.
- Điểm vào OpenStack
- Amphora TLS listener 443 với chính sách L7 theo Host và path → HTTP NodePort. Địa chỉ mặc định là một VIP riêng; Octavia, K3s, cơ sở dữ liệu và DNS nằm ngoài module. Khả năng truy cập công khai và mức sẵn sàng của Amphora tại chỗ cần nghiệm thu riêng, và chưa có lần áp dụng tại chỗ nào được xác minh với module này.
- Giữa các nhà cung cấp
- Ba điểm vào là các phần hiện thực riêng, không có failover hay sao chép tự động giữa các nhà cung cấp. Cụm ứng dụng khách hàng là một ví dụ về đích đã đăng ký, không phải tuyên bố rằng cùng một lần triển khai chạy trên mọi đám mây cùng lúc.
- Tùy chọn của người vận hành
- Gateway cá nhân (WireGuard) chỉ tham gia platform khi người vận hành bật --personal; nó không phải đường bắt buộc cho đám mây của khách hàng. Trong chế độ direct được hỗ trợ, VM quan sát có thể dùng chung VM điều khiển vận hành.