Un second chemin de déploiement aux côtés de Docker Compose — pour un cluster qui existe déjà et nécessite une release Helm, ou qui a spécifiquement besoin de faire évoluer les services sans état horizontalement (par exemple derrière un HPA) plutôt que de tout exécuter sur un seul hôte.
Utilisez Docker Compose pour un déploiement autohébergé sur un seul hôte — c'est plus simple à exploiter, et cela reste l'implémentation de référence pour la façon dont chaque service est interconnecté.
Utilisez ce chart une fois que le cluster d'un client existe déjà, ou que les besoins de mise à l'échelle dépassent ce qu'un seul hôte Compose peut offrir.
Chaque composant est templatisé directement — aucune dépendance vers un chart externe :
| Composant | Ce que c'est |
|---|---|
postgres | Postgres 17 en clair, StatefulSet à instance unique |
keycloak | Authentification — Direct Access Grant, sans interface de connexion hébergée |
rustfs | Stockage d'objets pour le contenu des payloads, et le bucket verrouillé WORM sur lequel repose le plan d'intégrité en ajout seul — optionnel, voir Utiliser votre propre stockage compatible S3 |
ledger-api | Le service d'ingestion |
ledger-alerting | Exécuteur autonome de revérification de chaîne/miroir/ancrage/outbox — même image que ledger-api, commande différente, volontairement un singleton |
dashboard | L'interface web |
Déjà supposés présents dans le cluster du client — ce n'est pas le rôle de ce chart de les fournir :
kubectl configuré pour le cluster cible, et Helm 3.8+ en localingress.className: nginx dans values.yaml) ; modifiez-le à cet endroit et dans votre fichier de secrets si le client utilise autre choseClusterIssuer déjà créé — son nom va dans ingress.annotations["cert-manager.io/cluster-issuer"]StorageClass par défaut (ou des valeurs storageClassName explicites) — Postgres et le stockage d'objets fourni réclament des volumes persistantsmetrics-server, si vous conservez la mise à l'échelle automatique activée — les valeurs par défaut activent les HPA pour ledger-api/dashboard, et sans lui ces HPA affichent <unknown> pour le CPU et ne mettent jamais à l'échelleLe chart s'attend à ce que ledgerApi.image.repository / dashboard.image.repository existent déjà dans un registre que le cluster peut utiliser pour le pull — il ne les construit ni ne les publie.
docker build -t <registry>/<client>/ledger-api:<tag> -f api/Dockerfile api
docker push <registry>/<client>/ledger-api:<tag>
docker build -t <registry>/<client>/ledger-dashboard:<tag> -f dashboard/Dockerfile dashboard
docker push <registry>/<client>/ledger-dashboard:<tag>
cd k8s/ledger
cp values-example-secrets.yaml values-secrets.<client>.yaml
Renseignez values-secrets.<client>.yaml — il est exclu de git, un fichier par client, jamais committé :
ingress.dashboardHost, ingress.apiHost, ingress.authHost.ledgerApi.image.repository/tag, ledgerAlerting.image.repository/tag (même image que ledgerApi), dashboard.image.repository/tag.kubectl get svc -n <ingress-namespace> <ingress-controller-service>
Créez des enregistrements A/CNAME pour les trois noms d'hôte de l'étape 2 pointant vers cette adresse. Cela peut se faire avant l'installation — les défis HTTP-01 de cert-manager ne réussiront simplement pas (et les certificats TLS ne seront pas émis) tant que les enregistrements ne résolvent pas, donc faites-le dès que possible.
helm install <release> . -n <namespace> --create-namespace \
-f values.yaml -f values-secrets.<client>.yaml
kubectl -n <namespace> get pods -w
Postgres et Keycloak prennent le plus de temps au premier démarrage. Si quelque chose reste bloqué en CrashLoopBackOff ou Pending, kubectl -n <namespace> logs <pod> et kubectl -n <namespace> describe pod <pod> sont les deux premières commandes à utiliser — un PVC Pending signifie presque toujours l'absence de StorageClass par défaut.
Le chart démarre avec un Postgres vide — les migrations de schéma constituent une étape séparée, comme pour le chemin Compose :
kubectl -n <namespace> port-forward svc/postgres 5432:5432 &
for f in api/drizzle/0*.sql; do
psql -h localhost -U postgres -d postgres -v ON_ERROR_STOP=1 -f "$f"
done
cd api && DATABASE_URL=postgresql://postgres:<PGPASSWORD>@localhost:5432/postgres npm run db:functions
PGPASSWORD est secrets.postgresPassword depuis votre fichier values-secrets. Appliquez les fichiers api/drizzle/*.sql dans l'ordre numérique — 0000_baseline.sql crée le schéma complet à partir de zéro, sans étape de bootstrap séparée. npm run db:functions applique ensuite chaque fonction/vue/trigger qui n'est pas un objet drizzle-kit.
curl -s https://<apiHost>/healthz
et ouvrez https://<dashboardHost> dans un navigateur.
Aucun utilisateur administrateur n'est initialisé par défaut. Créez-en un avec le même script que celui utilisé par le chemin Compose :
kubectl -n <namespace> exec deploy/ledger-api -- node dist/seed_admin.js \
you@example.com --org-name="Your Org Name"
Omettez --org-name et passez plutôt --org=<id> si l'organisation existe déjà. Affiche un mot de passe généré, une seule fois — connectez-vous sur https://<dashboardHost> avec celui-ci, puis invitez tout le monde via le tableau de bord.
L'application du registre (nouvelle image ledger-api/dashboard) : répétez l'étape 1, incrémentez ledgerApi.image.tag/dashboard.image.tag dans le fichier values du client, puis :
helm upgrade <release> . -n <namespace> -f values.yaml -f values-secrets.<client>.yaml
Changements de schéma : appliquez tout nouveau fichier api/drizzle/*.sql de la même manière qu'à l'étape 6, avant de mettre à niveau ledger-api/ledger-alerting vers une version qui les attend.
Par défaut, ce chart exécute un StatefulSet de stockage d'objets fourni. Si un client possède déjà son propre bucket compatible S3 (AWS S3, Cloudflare R2, Backblaze B2, son propre MinIO/RustFS, etc.) et ne souhaite pas du StatefulSet fourni ni de son PVC, définissez dans le fichier values du client :
rustfs:
enabled: false
storage:
endpoint: "s3.us-east-1.amazonaws.com"
port: 443
useSsl: true
region: "us-east-1"
secrets:
s3RootUser: "<clé d'accès restreinte au bucket du client>"
s3RootPassword: "<clé secrète>"
ledgerApi.storage.bucket continue de nommer le bucket à utiliser — soit vous le pré-créez, soit vous accordez aux identifiants fournis la permission CreateBucket ; l'API du registre le crée de manière différée lors du premier envoi s'il est manquant.
StatefulSet à instance unique — ce chart met à l'échelle la couche sans état de l'API, pas la base de données. Pour une véritable haute disponibilité, pointez plutôt vers une instance Postgres managée externe (postgres.enabled: false, puis faites pointer les URL de base de données de ledger-api/ledger-alerting/keycloak vers celle-ci via des surcouches de values) ou un opérateur Postgres (CloudNativePG, StackGres).postgres — ajoutez un pooler (par exemple PgBouncer) en tant que Deployment séparé devant celui-ci si le pooling devient nécessaire sous charge.docker build/push manuels aujourd'hui, comme à l'étape 1 — pas encore d'automatisation CI pour cela.Hébergement avec Docker
Exécutez la pile complète du Registre Sannvit — Postgres, Keycloak, l'API du registre, le stockage d'objets et le tableau de bord — avec Docker Compose.
SDKs
Bibliothèques clientes que les agents appellent pour sceller leur activité dans le registre — Python, TypeScript, Go, Java et C#.