Railshot
AI deployment & operations platform
Men-deploy aplikasi web yang dibangun secara lokal ke lingkungan cloud dan on-premise yang telah disiapkan, lalu menjalankannya.
Platform AI untuk deployment dan operasi yang membawa aplikasi web yang dibangun secara lokal ke lingkungan cloud atau on-premise yang telah disiapkan dan terus menjalankannya.
Klaster operasi dan klaster aplikasi pelanggan terpisah, dan jalur publik dipisahkan dari kendali deployment.
Di K3s operasi, dasbor, API produk, dan build controller ditempatkan di node berperan platform dan runner Job di node berperan build, sementara Argo CD menangani deployment. Aplikasi pelanggan berjalan di namespace yang ditentukan pada klaster K3s + Cilium satu node yang terpisah untuk setiap target terdaftar.
Build → publikasi image
API produk meminta eksekusi GitHub Actions, dan runner di node build mengambil serta memeriksa job tersebut. Hanya bundle yang lolos pemeriksaan yang sama yang dipublikasikan ke GHCR oleh job rilis yang di-hosting GitHub.
API produk · cd.js → bridge.py
railshot-systemeksekusi · terapkan: workflow_dispatchloop job · self-hosted runnerrailshot-deploy.ymlAPI produk meminta eksekusi GitHub Actions dengan tenant, app, source commit, dan target. API tidak pernah memanggil runner Job secara langsung.
build controller · CronJob
railshot-systemeksekusi · terapkan: isi ulang runner Jobrunner Job · hostNetwork · Docker socketrailshot-buildCronJob build controller (setiap menit, di node platform) membuat runner Job di namespace railshot-build. Role-nya hanya mengizinkan get, list, dan create Job serta get, update, dan patch pada satu Secret pendaftaran runner; ia tidak dapat membuat namespace atau Secret lain.
runner Job · hostNetwork · Docker socket
railshot-buildeksekusi · terapkan: ambil jobloop job · self-hosted runnerrailshot-deploy.ymlRunner di node berperan build (hostname persis, toleration NoSchedule) mengambil job loop berdasarkan label self-hosted dan menjalankannya. Sumber pelanggan berjalan di kontainer build dan pemeriksaan Docker terbatas yang sudah ada.
runner Job · hostNetwork · Docker socket
railshot-builddata: bundle terujirelease job · GitHub-hostedrailshot-deploy.ymlJob loop meninggalkan bundle yang lolos pemeriksaan yang sama, dan job rilis hanya mengambil bundle itu.
release job · GitHub-hosted
railshot-deploy.ymldata: publikasi per digestGHCRJob rilis yang di-hosting GitHub (ubuntu-24.04) memublikasikan image dari bundle teruji ke GHCR tanpa build ulang. Publikasi image tidak pernah terjadi di dalam klaster aplikasi pelanggan.
Config Git → Argo → namespace pelanggan
Config Git membawa sumber daya yang diinginkan dan GHCR membawa byte image. Argo CD hanya menerapkan ke namespace pelanggan yang terdaftar.
API produk · cd.js → bridge.py
railshot-systemdata: workload commit · pushRepositori config Gitcd.js menjalankan bridge.py, yang meng-commit dan push workload.json hanya bila catatan publikasi dan target terdaftar cocok, lalu membaca kembali revisi remote. Git membawa sumber daya yang diinginkan; GHCR membawa byte image.
Repositori config Gitdata: revisionArgo CD · Application
argocdApplication hanya membaca repositori config, path, dan revisi terbatas miliknya.
API produk · cd.js → bridge.py
railshot-systemeksekusi · terapkan: Application syncArgo CD · ApplicationargocdApplication bernama disetel dengan server-side apply, dan sync untuk satu revisi yang persis diminta tanpa prune. ServiceAccount railshot-product milik API produk memegang izin bootstrap pendaftaran yang dipasang operator (create untuk Secret, AppProject, dan Application di argocd; get, update, dan escalate pada Role bernama) sekaligus izin get dan patch yang ditambahkan dengan nama persis untuk setiap target terverifikasi. create di Kubernetes tidak dapat dibatasi dengan nama, sehingga validasi input produk juga menjaga nama tetap dalam cakupan.
Argo CD · Application
argocdeksekusi · terapkan: terapkan ke namespace<app namespace>Argo CD menerapkan ke namespace yang ditentukan di klaster pelanggan dengan kredensial cluster Secret yang terdaftar. AppProject hanya mengizinkan kind bernamespace dan tidak mengizinkan sumber daya lingkup klaster.
Deployment · Pod · image per digest
<app namespace>data: tarik per digestGHCRImage digest yang dipublikasikan ditarik dengan pull Secret yang dirujuk lewat nama di namespace yang sama. Nilai Secret tidak pernah masuk ke artefak atau config Git.
Jalur permintaan publik
Permintaan aplikasi berjalan entri L7 penyedia → NodePort node → Service → Pod aplikasi. Penegakan kebijakan Cilium adalah kendali terpisah, bukan lompatan yang membawa permintaan. Jalan masuk ke dasbor operasi adalah jalur terpisah.
Pengguna aplikasidata: HTTPS 443Entri L7 penyedia
Pengguna aplikasi mencapai entri L7 penyedia lewat hostname terdaftar. Setiap penyedia mengimplementasikan entrinya sendiri.
Entri L7 penyediadata: NodePortNodePort Service · Local
<app namespace>Entri meneruskan ke alamat privat dan NodePort node. NodePort adalah yang dialokasikan saat pendaftaran target.
NodePort Service · Local
<app namespace>data: ke PodDeployment · Pod · image per digest<app namespace>Service mengirim permintaan ke Pod aplikasi (Deployment) di node yang sama. Dengan externalTrafficPolicy Local, alamat sumber mencapai pemeriksaan CIDR terdaftar NetworkPolicy tanpa berubah.
Cilium · Helm · VXLAN
kube-systemeksekusi · terapkan: tegakkan kebijakanNetworkPolicy · CIDR terdaftar<app namespace>Cilium menegakkan NetworkPolicy: ingress hanya dari CIDR terdaftar ke port aplikasi; tanpa egress secara bawaan, kecuali alamat basis data yang disetujui. Firewall cloud dan aturan host tetap penting.
Pengguna Railshotdata: dasbor · APIdashboard · nginx
railshot-systemPengguna datang lewat entri operasi ke dasbor nginx, dan nginx berada di depan API produk. Service dasbor menjadi NodePort hanya bila node port yang disetujui diberikan; API tetap ClusterIP.
Verifikasi · observasi
Putusan deployment hanya bertumpu pada status Argo dan pemeriksaan URL publik. Diagnostik Pod, log saat ini, dan metrik operasi adalah sinyal terpisah yang tidak pernah mengubahnya.
API produk · cd.js → bridge.py
railshot-systemamati: revisi · health · imageArgo CD · ApplicationargocdStatus deployed memerlukan revisi sync Application, Synced dan Healthy, operation Succeeded, dan referensi image yang tercatat di status Argo Application sama dengan image digest Deployment yang telah ditinjau. Ini bukan gerbang imageID Pod secara langsung, dan status hijau Argo saja tidak menetapkan kecocokan itu.
API produk · cd.js → bridge.py
railshot-systemamati: pemeriksaan HTTPS publikEntri L7 penyediaURL publik terdaftar diperiksa tanpa redirect. Succeeded hanya dicatat bila ada putusan Argo sekaligus pemeriksaan ini.
API produk · cd.js → bridge.py
railshot-systemamati: diagnostik Pod · bukan putusanDeployment · Pod · image per digest<app namespace>Setelah putusan Argo dan pemeriksaan publik, Deployment, ReplicaSet, dan Pod dibaca terpisah dengan kredensial terdaftar, dan imageID serta kesiapan ditambahkan sebagai diagnostik ready, progressing, atau unavailable. Diagnostik yang gagal atau berbeda tidak pernah mengubah putusan deployed atau succeeded.
API produk · cd.js → bridge.py
railshot-systemamati: tail log · 100 baris per PodDeployment · Pod · image per digest<app namespace>Hanya untuk operation yang sedang ter-deploy, dengan config tepercaya dan kredensial terdaftar. Untuk setiap Pod saat ini (paling banyak tiga), digest image yang berjalan harus sama dengan digest yang diharapkan; lalu hingga 100 baris tersamarkan per Pod dibaca dalam batas byte. Percobaan yang lebih lama menjawab superseded; tanpa konfigurasi, not_configured. Ini bukan agregasi log.
VM pengamatamati: scrape · NodePortrailshot-observability
Prometheus di VM pengamat melakukan scrape node-exporter dan kube-state-metrics melalui dua NodePort yang dibatasi firewall. Nilai yang hilang atau basi berarti tidak diketahui, bukan nol.
VM pengamatamati: Blackbox probeEntri L7 penyedia
probe_success=1 berarti 2xx di lokasi probe itu. Ini tidak membuktikan akses setiap pengguna maupun versi yang ter-deploy, dan tidak pernah menaikkan published menjadi deployed.
Instalasi · pendaftaran operator
Instalasi klaster, bootstrap pendaftaran dan input target, Secret, serta penyiapan pembaruan kredensial adalah input operator, tidak pernah bagian dari payload aplikasi tenant.
Bootstrap operatoreksekusi · terapkan: merender platform · Secretrailshot-system
Operator merender deklarasi platform dengan render-platform.py dan menyediakan config operasi dan Secret privat. MCP jarak jauh hanya disertakan bila image-nya disediakan, gateway pribadi (WireGuard) hanya dengan --personal.
Bootstrap operatoreksekusi · terapkan: bootstrap pendaftaranAppProject · cluster Secret
argocdOperator memasang Role bootstrap pendaftaran dan Role registrations kosong di argocd serta menyiapkan input target. Helper pendaftaran yang dijalankan API produk (environment.py, applications.py) kemudian menulis Secret railshot-<target> dengan kredensial bercakupan (clusterResources false, namespace yang diizinkan dicantumkan) dan menambahkan nama persis yang telah divalidasi ke Role registrations. Pendaftaran per aplikasi mengikat namespace app-<id> ke AppProject dengan nama yang sama.
Bootstrap operatoreksekusi · terapkan: instal K3s · CiliumCilium · Helm · VXLAN
kube-systeminstall-k3s.sh memasang server K3s satu node (flannel, network policy, traefik, dan servicelb nonaktif; kube-proxy dipertahankan), dan Cilium dipasang sebagai Helm release (kubeProxyReplacement false, VXLAN, Hubble nonaktif).
CronJob pembaruan · setiap 2 h
argocdeksekusi · terapkan: TokenRequest · 6 hSA railshot-argocd · token<app namespace>CronJob railshot-credentials meminta token enam jam baru untuk SA pelanggan setiap dua jam. Role di sisi pelanggan hanya mengizinkan create token untuk SA-nya sendiri. Enam jam adalah TTL satu token, bukan saat akses operator berakhir.
Setiap koneksi dengan bobot yang sama. Pilih alur untuk menyorot hanya jalurnya, dengan langkah bernomor.
- Garis utuh · arah aliran permintaan, bundle, image, dan deklarasi
- Garis putus · permintaan eksekusi, terapkan, instal, kredensial
- Garis titik-strip panjang · membaca status, log, probe, metrik; terpisah dari putusan
- Garis hitam tebal · alur yang dipilih; angka menunjukkan urutan
- Kotak · namespace, namanya di bagian kepala (bukan node)
- Chip dalam · komponen di namespace itu
- Kotak putus-putus · di luar klaster
- railshot-system · produk
- argocd · otoritas deployment
- railshot-build · otoritas Docker host
- GitHub · klaster pelanggan
Keputusan penempatan October 2 di docs/architecture (dua node peran) dan diagram README publik adalah riwayat; peta ini mengikuti deklarasi dan kode pada 645e28a. Panah menunjukkan sebab dan arah, bukan bukti bahwa setiap jalur penyedia aktif sekarang.
- Namespace dan node
- Namespace adalah lingkup penamaan: bukan perangkat keras, dan dengan sendirinya bukan batas keamanan. Peran platform dan build adalah penempatan penjadwalan lewat nodeSelector dan taint; peta ini tidak menetapkan jumlah node klaster operasi. Penempatan node Argo CD juga merupakan pemeriksaan tersendiri.
- Otoritas node build
- Runner Job berjalan dengan hostNetwork, socket Docker host, NET_ADMIN, dan root. Namespace, taint, atau RBAC tidak menghapus otoritas Docker host, sehingga ini bukan isolasi administrator VM maupun sandbox untuk kode sembarang.
- Namespace pelanggan
- Setiap target terdaftar memakai namespace dan AppProject non-bawaan (misalnya tenant-demo, atau app-<id> per aplikasi). Hanya Deployment satu layanan (automount token ServiceAccount nonaktif), NodePort Service, dan NetworkPolicy, ditambah PVC atau migration Job opsional, yang dibuat; Secret hanya dirujuk lewat nama (pull Secret dan DATABASE_URL yang disetujui), tidak pernah dibuat.
- Entri AWS
- Route 53 Alias → ALB bersama HTTPS 443 → alamat privat dan NodePort node pelanggan. Banyak aplikasi memakai ulang satu node, masing-masing dengan namespace, Application, dan NodePort sendiri.
- Entri GCP
- Global EXTERNAL_MANAGED HTTPS LB → zonal GCE_VM_IP_PORT NEG → NodePort privat VM yang ada. Sertifikat berasal dari Certificate Manager dengan DNS authorization. Modul tidak memiliki VM maupun VPC, dan satu VM tetap menjadi titik kegagalan tunggal.
- Entri OpenStack
- Amphora TLS listener 443 dengan kebijakan L7 Host dan path → HTTP NodePort. Alamat bawaannya VIP privat; Octavia, K3s, basis data, dan DNS berada di luar modul. Keterjangkauan publik dan kesiapan Amphora di lokasi memerlukan penerimaan tersendiri, dan belum ada penerapan di lokasi yang diverifikasi dengan modul ini.
- Antarpenyedia
- Ketiga entri adalah implementasi terpisah, tanpa failover atau replikasi otomatis antarpenyedia. Klaster aplikasi pelanggan adalah contoh target terdaftar, bukan klaim bahwa deployment yang sama berjalan di setiap cloud sekaligus.
- Opsi operator
- Gateway pribadi (WireGuard) bergabung ke platform hanya bila operator mengaktifkan --personal; ini bukan jalur wajib untuk cloud pelanggan. Dalam mode direct yang didukung, VM pengamat dapat berbagi dengan VM kontrol operasi.