Kubernetes
Déployer PNeX sur Kubernetes avec cert-manager, CloudNativePG et le chart Helm
Le chart vit dans pnex-deploy
(helm/pnex). Il déploie le serveur PNeX et le worker de jobs, Rauthy,
OpenObserve, Valkey, RustFS et un cluster PostgreSQL.
Cette page déroule une vraie installation de 0.1.0-beta.2, enregistrée sur
une VM Ubuntu neuve avec IP publique. La démo utilise k3s, qui monte un
cluster mono-nœud en une commande, avec un ingress controller (Traefik) et une
StorageClass par défaut inclus. N'importe quel Kubernetes conforme convient :
managé (EKS, GKE, AKS, Scaleway Kapsule…), RKE2, microk8s, kubeadm… Seule la
classe d'ingress change.
Prérequis
- Kubernetes 1.27 ou plus récent, une StorageClass par défaut.
- Un ingress controller (Traefik dans la démo, ingress-nginx par défaut dans le chart).
helmetkubectlpointant sur le cluster.- Un nom public pour PNeX, avec les ports 80 et 443 accessibles depuis internet
pour Let's Encrypt. Les devices ont besoin d'un certificat reconnu
publiquement. La démo utilise sslip.io :
pnex-78-232-42-13.sslip.iorésout vers78.232.42.13, aucun DNS à gérer.
curl -sfL https://get.k3s.io | sh -
kubectl get nodes
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4 | bash
echo "export KUBECONFIG=/etc/rancher/k3s/k3s.yaml" >> ~/.bashrck3s installe kubectl et fournit Traefik (classe d'ingress traefik) et la
StorageClass local-path. helm lit le kubeconfig de k3s via KUBECONFIG.
1. cert-manager (certificats TLS)
cert-manager obtient et renouvelle le certificat Let's Encrypt :
helm install cert-manager oci://quay.io/jetstack/charts/cert-manager --version v1.21.2 \
-n cert-manager --create-namespace --set crds.enabled=true --waitPuis un ClusterIssuer Let's Encrypt, qui valide le domaine via l'ingress
controller (HTTP-01). Mettez dans ingressClassName la classe de votre
controller (traefik sur k3s, nginx avec ingress-nginx), et remplacez
[email protected] par votre propre email :
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected] # ← votre email (compte Let's Encrypt)
privateKeySecretRef:
name: letsencrypt-account
solvers:
- http01:
ingress:
ingressClassName: traefikkubectl apply -f cluster-issuer.yaml
kubectl get clusterissuer # READY True2. Opérateur CloudNativePG (PostgreSQL)
Le chart déclare sa base comme un Cluster CloudNativePG :
l'opérateur doit être installé avant.
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm install cnpg cnpg/cloudnative-pg --version 0.29.1 \
-n cnpg-system --create-namespace --wait
kubectl -n cnpg-system get pods3. PNeX (chart Helm)
Récupérez le chart d'une release publiée. Le chart d'un tag de release déploie
les images de cette release (son appVersion) ; sur main, il suit latest.
git clone --depth 1 --branch v0.1.0-beta.5 https://github.com/Pnex/pnex-deploygit peut signaler que le tag « is not a commit » et que vous êtes en
« detached HEAD » : c'est sans conséquence pour un tag de release annoté.
Les values : le nom public, le compte admin et l'ingress. ingress.tls pointe
vers le certificat demandé à cert-manager :
publicHost: pnex-78-232-42-13.sslip.io
admin:
email: [email protected] # ← votre email (connexion admin PNeX)
ingress:
className: traefik # nginx avec ingress-nginx
tls:
- secretName: pnex-tlsapiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: pnex-tls
namespace: pnex
spec:
secretName: pnex-tls
dnsNames: [pnex-78-232-42-13.sslip.io]
issuerRef:
kind: ClusterIssuer
name: letsencryptkubectl create namespace pnex && kubectl apply -f certificate.yaml
helm upgrade --install pnex ./pnex-deploy/helm/pnex -n pnex -f pnex-values.yaml
kubectl -n pnex wait --for=condition=Available deployment --all --timeout=15m
kubectl -n pnex get podsLe premier démarrage prend quelques minutes (téléchargement des images, puis
PostgreSQL). pnex-api redémarre quelques fois le temps que la base soit
prête : c'est normal.
4. Vérifier et récupérer le mot de passe admin
kubectl -n pnex get certificate,ingress # certificat READY True
curl -sI https://pnex-78-232-42-13.sslip.io/ | head -1Le mot de passe admin est généré dans le cluster à la première installation.
Lisez-le dans le Secret pnex-secrets (<release>-secrets) :
kubectl -n pnex get secret pnex-secrets -o jsonpath='{.data.admin-password}' | base64 -d; echoConnectez-vous sur https://<publicHost>/ avec admin.email et ce mot de
passe. Il n'initialise le compte qu'au premier démarrage de Rauthy : changez-le
ensuite depuis la page du compte (la valeur du Secret n'est alors plus valable).
Secrets
Tout secret laissé vide est généré dans le cluster à la première installation
et conservé aux mises à jour. Pour les gérer vous-même, gardez-les dans un
fichier de values chiffré (sops) ou pointez secrets.existingSecret vers votre
propre Secret.
Sauvegardez l'entrée secrets-keys du Secret généré avec les sauvegardes de la
base : c'est le trousseau du coffre de secrets des organisations. Sans lui,
les secrets restaurés ne peuvent pas être déchiffrés.
kubectl -n pnex get secret pnex-secrets -o jsonpath='{.data.secrets-keys}' | base64 -d; echoSécurité par défaut
- Conteneurs non-root, sans élévation de privilèges ni capabilities, profil seccomp RuntimeDefault, sans token de service account.
- Valkey exige un mot de passe ; Valkey, OpenObserve et RustFS n'acceptent que les pods PNeX (NetworkPolicy, nécessite un CNI qui l'applique).
- Les routes non authentifiées sont limitées en débit. Derrière un CDN, ajoutez
ses plages IP à
api.rateLimit.trustedProxiespour que la limite s'applique par client. - La connexion se fait uniquement en authorization code avec PKCE.
- Rauthy fait confiance aux adresses client transmises depuis les plages
privées (les pods de l'ingress controller, quel que soit le CNI). Sur un
cluster partagé, restreignez
rauthy.trustedProxiesau CIDR de vos pods.
Montée en charge
Passez api.replicas au-dessus de 1 : les pods se partagent le trafic HTTP et
WebSocket et forment un cluster d'exécution des flows — les flows de chaque
organisation tournent sur exactement un pod, et migrent quand un pod tombe ou
est drainé. Les mises à jour progressives drainent d'abord l'ancien pod. Gardez
replicas × (api.dbMaxConnections + 2) sous le max_connections de PostgreSQL.
Mettre à jour
git -C pnex-deploy fetch --depth 1 origin tag v0.1.0-beta.6 # la release suivante
git -C pnex-deploy checkout v0.1.0-beta.6
helm upgrade pnex ./pnex-deploy/helm/pnex -n pnex -f pnex-values.yamlimage.tag remplace l'appVersion du chart (ex. main-<sha>).

