Demo sur k3s
Un Kubernetes local dans Docker, sur lequel le serveur se deploie d’une facon ou d’une autre : un pod, trois pods qui partagent leur etat, ou les memes objets sans le chart. Docker est le seul prerequis.
demo/k3s/demo.sh cluster-up # k3s dans Docker ; relance : reprend et repare
demo/k3s/demo.sh deploy cluster # le chart, 3 replicas
demo/k3s/demo.sh check cluster # joue le scenario et le verifie
demo/k3s/demo.sh deploy single --preset example --with-s3
demo/k3s/demo.sh deploy cluster --with-oidc # avec Keycloak, fournisseur OIDC
demo/k3s/demo.sh list # modes, deployes ou non, ports
demo/k3s/demo.sh remove single # son namespace seulement
demo/k3s/demo.sh cluster-down # chaque conteneur, volume, reseau cfg-demo-*
deploy affiche les adresses et les comptes, avec des mots de passe tires a
chaque deploiement et haches par hash-password de l’image ; ils restent
dans demo/k3s/.work/<mode>/env.sh. Les etapes : Scenario multi-instance.
Apres une execution interrompue ou un docker restart cfg-demo-k3s,
cluster-up attend de nouveau le serveur d’API, recree le conteneur
d’outils et relance les port-forwards des consoles des modes deployes.
Modes
Un mode est la topologie : demo/k3s/modes/<mode>/. Chacun vit dans son
namespace cfg-demo-<mode>, sa release s’appelle gate, et les modes
coexistent sur leurs propres ports de l’hote.
| Mode | Quoi | SFTP | Explorateur | Console | Console S3 | Keycloak |
|---|---|---|---|---|---|---|
cluster | le chart, 3 replicas, ban.backend: configmap, Secret partage, canal du cluster, porte de controle, cluster.unreadyWhen: auto | 32122 | 32180 | 32181 | 32190 | 32191 |
single | le chart, 1 replica, bans dans un fichier d’un volume | 32222 | 32280 | 32281 | 32290 | 32291 |
ansible | le playbook, les objets de cluster | 32322 | 32380 | 32381 | 32390 | 32391 |
L’explorateur est http://127.0.0.1:<port>/files/, la console
http://127.0.0.1:<port>/ (un kubectl port-forward vers gate-control), la
console S3 http://127.0.0.1:<port>/rustfs/console/, celle de Keycloak
http://127.0.0.1:<port>/admin/.
CFG_DEMO_PORT_BASE (32000) deplace chaque port, CFG_DEMO_BIND
(127.0.0.1) l’adresse ; cluster-up les lit.
| Fichier du mode | Role |
|---|---|
mode.env | DESCRIPTION, SLOT (ports : base + 100 x slot), KIND (helm ou ansible), TOPOLOGY (cluster ou single), REPLICAS |
values.yaml | les valeurs du chart (KIND=helm) |
check.sh | son scenario, lance par demo.sh check <mode> |
Un autre mode est un autre repertoire : un slot libre (1 a 4), ses valeurs.
Presets
Un preset est le contenu, le meme dans chaque mode :
demo/k3s/presets/<nom>/, ou tout repertoire (--preset REP, ou
PRESET=REP). Chaque fichier est facultatif ; sans lui, presets/default/
sert.
| Fichier | Effet |
|---|---|
config.toml | la configuration, a la place de presets/default/config.toml |
accounts.env | ADMIN_PASSWORD, USER_PASSWORD : les mots de passe d’admin et de demo, au lieu de mots tires |
users.toml | des [[users]] ajoutes a la configuration, haches d’avance |
values.yaml | des valeurs du chart par-dessus celles du mode (modes helm) |
data/files/... | des fichiers du backend local (sa root), apres ceux de presets/default/data/ |
data/archive/... | des objets du bucket, sous le prefixe du backend (avec S3) |
bans.json | [{"ip", "protocol", "minutes"}] : des bans en vigueur des le depart |
grants.json | [{"username", "role", "hours", "reason"}] : des acces temporaires donnes au deploiement |
preset.env | WITH_S3=1, WITH_OIDC=1 : comme --with-s3, --with-oidc |
Le mode ajoute ce qui est a lui, dans chaque configuration : backend
(ConfigMap) ou persist_file (fichier) sous chaque [sftp.ban],
[api.ban], [admin.ban], [cluster], et la methode JWT (jwt sous
[auth.methods], eteinte, et [auth.jwt] avec --with-oidc) ; le chart
passe au serveur le Secret partage, les revocations, les acces et les
pairs. Le config.toml d’un preset laisse de cote [cluster],
[auth.jwt], auth.methods.jwt et, sous les tables de bans, de session et
d’acces, backend, persist_file, key_file, secret_name et les noms
de ConfigMap. Avant tout deploiement, la configuration passe par
config check de l’image, avec les variables du mode, et les valeurs par
helm template.
| Marque | Valeur |
|---|---|
{{ADMIN_PASSWORD_HASH}}, {{USER_PASSWORD_HASH}} | les hashes des deux mots de passe |
{{HOST_KEY}}, {{FILES_ROOT}} | /keys/host_ed25519 (Secret gate-host-keys), /data (le volume partage par les pods) |
{{S3_ENDPOINT}}, {{S3_BUCKET}}, {{S3_PREFIX}} | http://s3:9000, archive, gate/ |
{{S3_ACCESS_KEY_FILE}}, {{S3_SECRET_KEY_FILE}} | les cles du Secret demo-s3, montees en fichiers |
lignes entre #{{S3_BEGIN}} et #{{S3_END}} | gardees avec S3 seulement |
presets/example/ sert de chaque fichier : mots de passe fixes, un compte
partner, l’environnement DEMO en vert, un fichier et un objet, un ban,
un acces, S3.
Le stockage S3
Sans S3, le backend local seul : assez pour deposer et relever des
fichiers, et le plus leger. --with-s3 ajoute RustFS (rustfs/rustfs:1.0.3,
tire par k3s au premier usage) et le backend archive (/archive) : ses
cles, tirees au deploiement, sont affichees avec les comptes, et sa console
web montre les objets a leur arrivee. Mesure ici : un pod du serveur tient
5 Mio environ, RustFS 60 Mio environ.
Le fournisseur OIDC
--with-oidc ajoute Keycloak (quay.io/keycloak/keycloak:26.8.1, tire par
k3s, en start-dev : sa base vit et meurt avec le pod) et le realm demo,
importe au demarrage de demo/k3s/oidc-realm.json. Le serveur demarre
apres lui : son demarrage charge les cles.
| Dans le realm | Quoi |
|---|---|
| roles de realm | users et console-admins, les noms des roles de la configuration : un preset les garde |
alice | console-admins et users : la console et les fichiers |
bob | users : les fichiers seuls |
carol | users, desactivee par le scenario |
client craft-file-gate | public, grant mot de passe ; un mapper d’audience met craft-file-gate dans aud, realm_access.roles ne porte que les deux roles |
| cle de signature | ES256 : un jeton de 700 caracteres environ, sous la limite de 1023 que sftp d’OpenSSH met a un mot de passe |
Les mots de passe des trois, et celui d’admin, l’administrateur de
Keycloak, sont tires au deploiement et affiches avec les autres. Le mode
ajoute a la configuration (sans --with-oidc, jwt = { enabled = false }) :
[auth.methods]
jwt = { enabled = true }
[auth.jwt]
jwks_url = "http://keycloak:8080/realms/demo/protocol/openid-connect/certs"
issuer = "http://127.0.0.1:32191/realms/demo" # le port Keycloak du mode
audience = "craft-file-gate"
username_path = "/preferred_username"
authorities_path = "/realm_access/roles"
KC_HOSTNAME fixe l’adresse que Keycloak ecrit dans iss : un jeton pris
sur l’hote, dans le conteneur d’outils ou dans un pod nomme le meme
emetteur. Son hote est CFG_DEMO_PUBLIC_HOST, sinon CFG_DEMO_BIND
(127.0.0.1 quand il vaut 0.0.0.0). Le realm ne laisse ni s’inscrire ni changer de nom :
preferred_username peut servir de nom. Les cles viennent en http dans
le cluster, et config check comme le demarrage le disent en WARN :
acceptable pour une demo, pas en production. Apres un redemarrage de k3s,
cluster-up redemarre Keycloak (le realm reimporte, une cle neuve, les
memes mots de passe), puis le serveur. Mesure ici : Keycloak pret en 20 s
environ, 600 Mio environ (limite 1 Gio).
Ce qui est monte
| Piece | Dans la demo |
|---|---|
| k3s | le conteneur cfg-demo-k3s (rancher/k3s:v1.34.1-k3s1), sans Traefik, ServiceLB ni metrics-server |
| image | craftogether/craft-file-gate:v<appVersion> (l’appVersion du chart, la derniere version publiee) ; LOCAL_IMAGE=craft-file-gate:dev importe une image locale |
| volumes | demo-files (le backend local, partage par les pods : un seul noeud), demo-state (fichiers de bans de single), ecrits par le pod demo-seed |
| outils | le conteneur cfg-demo-tools (sftp, curl, jq) dans le reseau du noeud : il joint chaque pod |
Des delais courts, pour la demo, dans presets/default/config.toml :
[server.backend_probe]
interval_secs = 5 # une panne de stockage est vue en 7 s environ
timeout_secs = 2
failures_before_down = 1
[admin.session]
reread_interval_secs = 1 # de meme [admin.grants]
Le mode cluster ajoute unready_after_secs = 10 et
ready_after_secs = 5 sous [cluster].