chore: update
This commit is contained in:
@@ -0,0 +1,89 @@
|
|||||||
|
# Isolation réseau du namespace monitoring (beszel-agent) — deny-by-default +
|
||||||
|
# allowlist :
|
||||||
|
# - Egress : HTTPS sortant vers le Hub (HUB_URL, hôte externe arbitraire —
|
||||||
|
# voir beszel-agent-secret.yml) pour l'auto-enregistrement au démarrage.
|
||||||
|
# - Ingress : le Hub se connecte à l'agent en SSH sur le port LISTEN
|
||||||
|
# (45876) pour récupérer les métriques — IP du Hub non fixe/connue
|
||||||
|
# d'avance, ouvert largement mais authentifié par TOKEN/KEY (voir
|
||||||
|
# beszel-agent-secret.yml), pas par l'origine réseau.
|
||||||
|
#
|
||||||
|
# ⚠️ LIMITE IMPORTANTE : le DaemonSet tourne en hostNetwork: true (voir
|
||||||
|
# daemonset-beszel.yml) — avec Calico (CNI de ce cluster, voir
|
||||||
|
# deploy/cni/calico-install.yml), un NetworkPolicy standard ne s'applique en
|
||||||
|
# général PAS aux pods hostNetwork (il faudrait un HostEndpoint/
|
||||||
|
# GlobalNetworkPolicy Calico, une ressource différente, pour un enforcement
|
||||||
|
# réel au niveau du nœud). Ce manifeste reste appliqué pour la correction
|
||||||
|
# d'intention et si hostNetwork est retiré un jour, mais ne pas compter
|
||||||
|
# dessus comme protection effective du port 45876 en l'état — un pare-feu
|
||||||
|
# hôte (iptables/nftables/ufw) ou une GlobalNetworkPolicy Calico est
|
||||||
|
# nécessaire pour une vraie restriction.
|
||||||
|
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: default-deny-all
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-ingress-hub-ssh
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from: []
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 45876
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-dns
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
- protocol: TCP
|
||||||
|
port: 53
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-hub-https
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
except:
|
||||||
|
- 10.0.0.0/8
|
||||||
|
- 172.16.0.0/12
|
||||||
|
- 192.168.0.0/16
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 443
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
# Isolation réseau du namespace cert-manager — même logique que
|
||||||
|
# deploy/chart-gestion/network-policy (deny-by-default + allowlist), adaptée
|
||||||
|
# aux flux réels de cert-manager :
|
||||||
|
# - Ingress : l'API server appelle le webhook d'admission de cert-manager
|
||||||
|
# (validation des CRD Certificate/Issuer/ClusterIssuer) sur le port 10250.
|
||||||
|
# - Egress : API server (lecture/écriture des CRD + Secrets), DNS, et
|
||||||
|
# Internet en HTTPS (Let's Encrypt ACME + API Cloudflare pour le
|
||||||
|
# challenge DNS-01 — IPs non fixes, pas de CIDR précis possible).
|
||||||
|
#
|
||||||
|
# ⚠️ AVANT D'APPLIQUER : remplacer CHANGE_ME_apiserver_ip par l'IP réelle de
|
||||||
|
# l'API server de votre cluster (trouvable via :
|
||||||
|
# kubectl get endpoints kubernetes -n default -o wide
|
||||||
|
# ). Une mauvaise valeur bloque l'accès de cert-manager à l'API Kubernetes —
|
||||||
|
# le renouvellement automatique des certificats s'arrête silencieusement
|
||||||
|
# (pas d'impact immédiat, le cert en cours reste valide jusqu'à expiration).
|
||||||
|
# Testez avec `kubectl apply --dry-run=server` puis surveillez
|
||||||
|
# `kubectl get certificate -A` après application.
|
||||||
|
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: default-deny-all
|
||||||
|
namespace: cert-manager
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-intra-namespace
|
||||||
|
namespace: cert-manager
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector: {}
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector: {}
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-ingress-apiserver-webhook
|
||||||
|
namespace: cert-manager
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: CHANGE_ME_apiserver_ip/32
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 10250
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-dns
|
||||||
|
namespace: cert-manager
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
- protocol: TCP
|
||||||
|
port: 53
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-apiserver
|
||||||
|
namespace: cert-manager
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: CHANGE_ME_apiserver_ip/32
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 6443
|
||||||
|
|
||||||
|
---
|
||||||
|
# Let's Encrypt (ACME) + API Cloudflare (challenge DNS-01) : IPs publiques
|
||||||
|
# non fixes, seul HTTPS sortant est nécessaire.
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-internet-https
|
||||||
|
namespace: cert-manager
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
except:
|
||||||
|
- 10.0.0.0/8
|
||||||
|
- 172.16.0.0/12
|
||||||
|
- 192.168.0.0/16
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 443
|
||||||
@@ -2,7 +2,7 @@ replicaCount: 2
|
|||||||
|
|
||||||
image:
|
image:
|
||||||
repository: backend-mln
|
repository: backend-mln
|
||||||
tag: helm
|
tag: latest
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
service:
|
service:
|
||||||
@@ -27,10 +27,6 @@ persistence:
|
|||||||
uploads:
|
uploads:
|
||||||
enabled: true
|
enabled: true
|
||||||
size: 5Gi
|
size: 5Gi
|
||||||
# Répliqué sur 2 nœuds (Longhorn) : survit à la perte d'un nœud. Voir
|
|
||||||
# deploy/longhorn/storageclass.yml pour le prérequis d'installation.
|
|
||||||
# N'a d'effet que pour storage_driver=local (les uploads S3 ne passent
|
|
||||||
# jamais par ce PVC, voir ProvisionConfig.StorageDriver).
|
|
||||||
storageClass: "longhorn-replicated"
|
storageClass: "longhorn-replicated"
|
||||||
accessMode: ReadWriteOnce
|
accessMode: ReadWriteOnce
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ apiUrl: ""
|
|||||||
|
|
||||||
image:
|
image:
|
||||||
repository: frontend-mln
|
repository: frontend-mln
|
||||||
tag: helm
|
tag: latest
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
service:
|
service:
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# 1. Deny-by-default : sans règle explicite plus bas, AUCUN trafic entrant
|
||||||
|
# ni sortant n'est autorisé pour les pods de ce namespace. C'est ce qui
|
||||||
|
# empêche par défaut toute communication vers un autre namespace de démo
|
||||||
|
# et vers l'API Kubernetes.
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: default-deny-all
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# 4. DNS uniquement vers kube-system, port 53. C'est la SEULE ouverture vers
|
||||||
|
# kube-system : aucun accès à autre chose dans ce namespace, et l'API
|
||||||
|
# server (kubernetes.default.svc, namespace "default") n'est jamais
|
||||||
|
# autorisé nulle part dans ce chart -> bloqué par le deny-by-default.
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-dns
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: {{ .Values.kubeSystemNamespace }}
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
- protocol: TCP
|
||||||
|
port: 53
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# 3. Ingress externe autorisé : uniquement depuis le Traefik partagé
|
||||||
|
# (aucune autre démo, aucun autre client, ne peut ouvrir de connexion
|
||||||
|
# directe vers les pods de cette démo).
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-ingress-from-traefik
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: {{ .Values.traefikNamespace }}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# 5. Internet public sortant (webhooks Telegram/NowPayments, GPS TomTom...),
|
||||||
|
# en excluant les plages privées : ça couvre par construction l'IP de
|
||||||
|
# l'API server et celles des autres namespaces, sans avoir besoin de la
|
||||||
|
# connaître explicitement.
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-internet
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
except:
|
||||||
|
{{ toYaml .Values.blockedEgressCIDRs | nindent 14 }}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# 2. Trafic intra-démo : frontend <-> backend <-> postgresql/redis, dans
|
||||||
|
# CE namespace uniquement (le podSelector du namespaceSelector par défaut
|
||||||
|
# de Kubernetes limite déjà à ce namespace : pas de namespaceSelector ici
|
||||||
|
# équivaut à "même namespace").
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-intra-namespace
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector: {}
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector: {}
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
# -------------------------------------------------------------------
|
|
||||||
# 1. Deny-by-default : sans règle explicite plus bas, AUCUN trafic entrant
|
|
||||||
# ni sortant n'est autorisé pour les pods de ce namespace. C'est ce qui
|
|
||||||
# empêche par défaut toute communication vers un autre namespace de démo
|
|
||||||
# et vers l'API Kubernetes.
|
|
||||||
# -------------------------------------------------------------------
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: NetworkPolicy
|
|
||||||
metadata:
|
|
||||||
name: default-deny-all
|
|
||||||
spec:
|
|
||||||
podSelector: {}
|
|
||||||
policyTypes:
|
|
||||||
- Ingress
|
|
||||||
- Egress
|
|
||||||
|
|
||||||
---
|
|
||||||
# -------------------------------------------------------------------
|
|
||||||
# 2. Trafic intra-démo : frontend <-> backend <-> postgresql/redis, dans
|
|
||||||
# CE namespace uniquement (le podSelector du namespaceSelector par défaut
|
|
||||||
# de Kubernetes limite déjà à ce namespace : pas de namespaceSelector ici
|
|
||||||
# équivaut à "même namespace").
|
|
||||||
# -------------------------------------------------------------------
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: NetworkPolicy
|
|
||||||
metadata:
|
|
||||||
name: allow-intra-namespace
|
|
||||||
spec:
|
|
||||||
podSelector: {}
|
|
||||||
policyTypes:
|
|
||||||
- Ingress
|
|
||||||
- Egress
|
|
||||||
ingress:
|
|
||||||
- from:
|
|
||||||
- podSelector: {}
|
|
||||||
egress:
|
|
||||||
- to:
|
|
||||||
- podSelector: {}
|
|
||||||
|
|
||||||
---
|
|
||||||
# -------------------------------------------------------------------
|
|
||||||
# 3. Ingress externe autorisé : uniquement depuis le Traefik partagé
|
|
||||||
# (aucune autre démo, aucun autre client, ne peut ouvrir de connexion
|
|
||||||
# directe vers les pods de cette démo).
|
|
||||||
# -------------------------------------------------------------------
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: NetworkPolicy
|
|
||||||
metadata:
|
|
||||||
name: allow-ingress-from-traefik
|
|
||||||
spec:
|
|
||||||
podSelector: {}
|
|
||||||
policyTypes:
|
|
||||||
- Ingress
|
|
||||||
ingress:
|
|
||||||
- from:
|
|
||||||
- namespaceSelector:
|
|
||||||
matchLabels:
|
|
||||||
kubernetes.io/metadata.name: {{ .Values.traefikNamespace }}
|
|
||||||
|
|
||||||
---
|
|
||||||
# -------------------------------------------------------------------
|
|
||||||
# 4. DNS uniquement vers kube-system, port 53. C'est la SEULE ouverture vers
|
|
||||||
# kube-system : aucun accès à autre chose dans ce namespace, et l'API
|
|
||||||
# server (kubernetes.default.svc, namespace "default") n'est jamais
|
|
||||||
# autorisé nulle part dans ce chart -> bloqué par le deny-by-default.
|
|
||||||
# -------------------------------------------------------------------
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: NetworkPolicy
|
|
||||||
metadata:
|
|
||||||
name: allow-egress-dns
|
|
||||||
spec:
|
|
||||||
podSelector: {}
|
|
||||||
policyTypes:
|
|
||||||
- Egress
|
|
||||||
egress:
|
|
||||||
- to:
|
|
||||||
- namespaceSelector:
|
|
||||||
matchLabels:
|
|
||||||
kubernetes.io/metadata.name: {{ .Values.kubeSystemNamespace }}
|
|
||||||
ports:
|
|
||||||
- protocol: UDP
|
|
||||||
port: 53
|
|
||||||
- protocol: TCP
|
|
||||||
port: 53
|
|
||||||
|
|
||||||
---
|
|
||||||
# -------------------------------------------------------------------
|
|
||||||
# 5. Internet public sortant (webhooks Telegram/NowPayments, GPS TomTom...),
|
|
||||||
# en excluant les plages privées : ça couvre par construction l'IP de
|
|
||||||
# l'API server et celles des autres namespaces, sans avoir besoin de la
|
|
||||||
# connaître explicitement.
|
|
||||||
# -------------------------------------------------------------------
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: NetworkPolicy
|
|
||||||
metadata:
|
|
||||||
name: allow-egress-internet
|
|
||||||
spec:
|
|
||||||
podSelector: {}
|
|
||||||
policyTypes:
|
|
||||||
- Egress
|
|
||||||
egress:
|
|
||||||
- to:
|
|
||||||
- ipBlock:
|
|
||||||
cidr: 0.0.0.0/0
|
|
||||||
except:
|
|
||||||
{{- toYaml .Values.blockedEgressCIDRs | nindent 14 }}
|
|
||||||
@@ -13,7 +13,6 @@ kubeSystemNamespace: kube-system
|
|||||||
# Namespace du Traefik partagé (voir deploy/chart-gestion/traefik) : seule
|
# Namespace du Traefik partagé (voir deploy/chart-gestion/traefik) : seule
|
||||||
# origine externe autorisée à ouvrir une connexion ingress vers cette démo.
|
# origine externe autorisée à ouvrir une connexion ingress vers cette démo.
|
||||||
traefikNamespace: traefik
|
traefikNamespace: traefik
|
||||||
|
|
||||||
# Plages privées exclues de l'egress "internet" autorisé (RFC1918) : empêche
|
# Plages privées exclues de l'egress "internet" autorisé (RFC1918) : empêche
|
||||||
# tout mouvement latéral vers d'autres pods/namespaces/nœuds/l'API server par
|
# tout mouvement latéral vers d'autres pods/namespaces/nœuds/l'API server par
|
||||||
# IP directe, tout en laissant sortir vers l'internet public (Telegram,
|
# IP directe, tout en laissant sortir vers l'internet public (Telegram,
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: gestion-resource-quota
|
||||||
|
description: Plafond agrégé de ressources par namespace de démo (ResourceQuota + LimitRange) — empêche un client de saturer le cluster au détriment des autres démos, même via l'autoscaling (HPA) du backend/frontend.
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: "1.0.0"
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ResourceQuota
|
||||||
|
metadata:
|
||||||
|
name: demo-quota
|
||||||
|
spec:
|
||||||
|
hard:
|
||||||
|
requests.cpu: {{ .Values.quota.requestsCpu | quote }}
|
||||||
|
requests.memory: {{ .Values.quota.requestsMemory | quote }}
|
||||||
|
limits.cpu: {{ .Values.quota.limitsCpu | quote }}
|
||||||
|
limits.memory: {{ .Values.quota.limitsMemory | quote }}
|
||||||
|
pods: {{ .Values.quota.maxPods | quote }}
|
||||||
|
persistentvolumeclaims: {{ .Values.quota.maxPVCs | quote }}
|
||||||
|
|
||||||
|
---
|
||||||
|
# Défauts requests/limits pour tout container qui ne les préciserait pas —
|
||||||
|
# nécessaire pour que le ResourceQuota ci-dessus n'empêche pas la création
|
||||||
|
# de pods qui omettraient ces champs.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: LimitRange
|
||||||
|
metadata:
|
||||||
|
name: demo-limits
|
||||||
|
spec:
|
||||||
|
limits:
|
||||||
|
- type: Container
|
||||||
|
defaultRequest:
|
||||||
|
cpu: {{ .Values.limitRange.defaultRequestCpu | quote }}
|
||||||
|
memory: {{ .Values.limitRange.defaultRequestMemory | quote }}
|
||||||
|
default:
|
||||||
|
cpu: {{ .Values.limitRange.defaultLimitCpu | quote }}
|
||||||
|
memory: {{ .Values.limitRange.defaultLimitMemory | quote }}
|
||||||
|
min:
|
||||||
|
cpu: {{ .Values.limitRange.minCpu | quote }}
|
||||||
|
memory: {{ .Values.limitRange.minMemory | quote }}
|
||||||
|
max:
|
||||||
|
cpu: {{ .Values.limitRange.maxCpu | quote }}
|
||||||
|
memory: {{ .Values.limitRange.maxMemory | quote }}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Plafonds calculés à partir du pire cas d'une démo au complet, HPA au max
|
||||||
|
# (voir deploy/chart-gestion/{postgresql,redis,backend,frontend,lbtelegram}
|
||||||
|
# /values.yaml — postgres 1 replica, redis 1 replica, backend jusqu'à 5
|
||||||
|
# replicas, frontend jusqu'à 4, lbtelegram 1 replica si activé) :
|
||||||
|
# requests cpu : 250m + 100m + 5×100m + 4×50m + 100m = 1150m -> arrondi 2
|
||||||
|
# requests mem : 256 + 128 + 5×128 + 4×64 + 128 = 1408Mi -> arrondi 2Gi
|
||||||
|
# limits cpu : 1000m + 500m + 5×500m + 4×200m + 500m = 5300m -> arrondi 6
|
||||||
|
# limits mem : 1024 + 512 + 5×256 + 4×128 + 256 = 3584Mi -> arrondi 5Gi
|
||||||
|
# Marge volontaire au-dessus du calcul pour laisser de la place à des pods
|
||||||
|
# ponctuels (exec admin, job de migration) sans bloquer le provisioning.
|
||||||
|
quota:
|
||||||
|
requestsCpu: "2"
|
||||||
|
requestsMemory: "2Gi"
|
||||||
|
limitsCpu: "6"
|
||||||
|
limitsMemory: "5Gi"
|
||||||
|
# Cap dur sur le nombre de pods/PVC du namespace — empêche un pod-spam ou
|
||||||
|
# une boucle de CrashLoop mal configurée d'épuiser les IP/ressources du
|
||||||
|
# nœud. 3 PVC utilisés aujourd'hui (postgres, redis, uploads) + marge.
|
||||||
|
maxPods: "20"
|
||||||
|
maxPVCs: "5"
|
||||||
|
|
||||||
|
# Défauts appliqués à tout container qui ne préciserait pas ses propres
|
||||||
|
# requests/limits — sans ça, le ResourceQuota ci-dessus rendrait la création
|
||||||
|
# de pod obligatoirement explicite (K8s rejette un pod sans requests/limits
|
||||||
|
# dans un namespace où un ResourceQuota les couvre).
|
||||||
|
limitRange:
|
||||||
|
defaultRequestCpu: "100m"
|
||||||
|
defaultRequestMemory: "128Mi"
|
||||||
|
defaultLimitCpu: "500m"
|
||||||
|
defaultLimitMemory: "256Mi"
|
||||||
|
minCpu: "10m"
|
||||||
|
minMemory: "16Mi"
|
||||||
|
maxCpu: "2"
|
||||||
|
maxMemory: "1Gi"
|
||||||
@@ -28,6 +28,14 @@ spec:
|
|||||||
- effect: NoSchedule
|
- effect: NoSchedule
|
||||||
key: node-role.kubernetes.io/control-plane
|
key: node-role.kubernetes.io/control-plane
|
||||||
operator: Exists
|
operator: Exists
|
||||||
|
# Niveau pod : s'applique à tous les containers (ici un seul).
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 101
|
||||||
|
runAsGroup: 101
|
||||||
|
fsGroup: 101
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
containers:
|
containers:
|
||||||
- name: beszel-agent
|
- name: beszel-agent
|
||||||
image: henrygd/beszel-agent:latest
|
image: henrygd/beszel-agent:latest
|
||||||
@@ -45,6 +53,10 @@ spec:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: data
|
- name: data
|
||||||
mountPath: /var/lib/beszel-agent
|
mountPath: /var/lib/beszel-agent
|
||||||
|
# Filet de sécurité pour readOnlyRootFilesystem : couvre d'éventuelles
|
||||||
|
# écritures temporaires (non documentées) sans réouvrir tout le rootfs.
|
||||||
|
- name: tmp
|
||||||
|
mountPath: /tmp
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 10m
|
cpu: 10m
|
||||||
@@ -52,11 +64,25 @@ spec:
|
|||||||
limits:
|
limits:
|
||||||
cpu: 50m
|
cpu: 50m
|
||||||
memory: 32Mi
|
memory: 32Mi
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop: [ALL]
|
||||||
|
# Inféré (pas de doc officielle confirmant l'absence d'écriture
|
||||||
|
# ailleurs) : le seul chemin persistant documenté par le projet
|
||||||
|
# est /var/lib/beszel-agent (déjà monté ci-dessous), ce qui
|
||||||
|
# suggère que c'est le seul état écrit sur disque (ex. clé hôte
|
||||||
|
# SSH). À VÉRIFIER après rollout (kubectl logs -n monitoring
|
||||||
|
# -l app=beszel-agent) — si le pod crash-loop ou que le Hub ne
|
||||||
|
# voit plus l'agent, repasser cette valeur à false.
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
volumes:
|
volumes:
|
||||||
- name: data
|
- name: data
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /var/lib/beszel-agent
|
path: /var/lib/beszel-agent
|
||||||
type: DirectoryOrCreate
|
type: DirectoryOrCreate
|
||||||
|
- name: tmp
|
||||||
|
emptyDir: {}
|
||||||
# - name: docker-sock
|
# - name: docker-sock
|
||||||
# hostPath:
|
# hostPath:
|
||||||
# path: /var/run/docker.sock
|
# path: /var/run/docker.sock
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# Isolation réseau du namespace velero — deny-by-default + allowlist, adaptée
|
||||||
|
# aux flux réels de Velero :
|
||||||
|
# - Ingress : AUCUN. Personne n'a besoin d'ouvrir une connexion vers les
|
||||||
|
# pods Velero (le CLI "velero backup/restore" parle à l'API server, pas
|
||||||
|
# directement aux pods) ; le node-agent (File System Backup) lit les
|
||||||
|
# données des volumes via hostPath sur le nœud, pas par le réseau.
|
||||||
|
# - Egress : API server (CRD Backup/Restore/Schedule + lecture des Secrets
|
||||||
|
# à sauvegarder), DNS, et le endpoint S3/RustFS/MinIO configuré dans
|
||||||
|
# values.yaml.
|
||||||
|
#
|
||||||
|
# ⚠️ AVANT D'APPLIQUER : remplacer CHANGE_ME_apiserver_ip et
|
||||||
|
# CHANGE_ME_s3_endpoint_ip par les IP réelles (API server : voir
|
||||||
|
# deploy/cert-manager/networkpolicy.yml ; endpoint S3 : IP de votre instance
|
||||||
|
# RustFS/MinIO, celle configurée dans s3Url de values.yaml). Une mauvaise
|
||||||
|
# valeur ne casse rien d'immédiat (les démos continuent de tourner) mais fait
|
||||||
|
# silencieusement échouer TOUTES les sauvegardes — vérifiez après application
|
||||||
|
# avec `velero backup create test-netpol --wait` puis `velero backup describe
|
||||||
|
# test-netpol` (statut Completed attendu).
|
||||||
|
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: default-deny-all
|
||||||
|
namespace: velero
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-dns
|
||||||
|
namespace: velero
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
- protocol: TCP
|
||||||
|
port: 53
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-apiserver
|
||||||
|
namespace: velero
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: CHANGE_ME_apiserver_ip/32
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 6443
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: allow-egress-s3-storage
|
||||||
|
namespace: velero
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: CHANGE_ME_s3_endpoint_ip/32
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 443
|
||||||
+21
-13
@@ -27,6 +27,19 @@
|
|||||||
# -f deploy/velero/values.yaml
|
# -f deploy/velero/values.yaml
|
||||||
# kubectl apply -f deploy/velero/schedule.yml
|
# kubectl apply -f deploy/velero/schedule.yml
|
||||||
#
|
#
|
||||||
|
# 5. Sécurité du bucket — à vérifier CÔTÉ RustFS/MinIO (rien de tout ça ne
|
||||||
|
# se configure depuis ce repo) : chaque sauvegarde contient les Secrets
|
||||||
|
# K8s en clair (mots de passe postgres/redis, JWT, tokens Telegram...)
|
||||||
|
# de toutes les démos.
|
||||||
|
# - Chiffrement at-rest activé sur le bucket/disque côté RustFS/MinIO
|
||||||
|
# (indépendant du header SSE ci-dessous, qui ne fait que le demander
|
||||||
|
# au serveur).
|
||||||
|
# - Clé d'accès dédiée à ce bucket UNIQUEMENT (voir étape 1) — jamais la
|
||||||
|
# clé d'admin du cluster de stockage.
|
||||||
|
# - Versioning ou object-lock (WORM) activé si le fournisseur le
|
||||||
|
# supporte : sans ça, une clé compromise peut aussi supprimer/écraser
|
||||||
|
# l'historique des sauvegardes, pas seulement les données live.
|
||||||
|
#
|
||||||
# Pourquoi File System Backup (kopia) plutôt que des snapshots CSI Longhorn :
|
# Pourquoi File System Backup (kopia) plutôt que des snapshots CSI Longhorn :
|
||||||
# ça fonctionne indépendamment du provisioner de stockage (pas de
|
# ça fonctionne indépendamment du provisioner de stockage (pas de
|
||||||
# VolumeSnapshotClass/CRD supplémentaire à maintenir), et couvre aussi bien
|
# VolumeSnapshotClass/CRD supplémentaire à maintenir), et couvre aussi bien
|
||||||
@@ -61,23 +74,18 @@ configuration:
|
|||||||
name: cloud-credentials
|
name: cloud-credentials
|
||||||
key: cloud
|
key: cloud
|
||||||
config:
|
config:
|
||||||
# Région du bucket (AWS) ou région arbitraire acceptée par votre
|
region: "us-east-1"
|
||||||
# fournisseur S3-compatible (souvent "us-east-1" par défaut).
|
s3Url: "CHANGE_ME_https://votre-endpoint-rustfs-ou-minio"
|
||||||
region: "CHANGE_ME_region"
|
|
||||||
# URL du endpoint S3-compatible — uniquement si ce n'est PAS AWS S3
|
|
||||||
# (ex: "https://s3.fr-par.scw.cloud", "https://s3.eu-de.io.cloud.ovh.net").
|
|
||||||
# Laisser vide pour AWS S3.
|
|
||||||
s3Url: ""
|
|
||||||
# La plupart des fournisseurs S3-compatibles (hors AWS) exigent le
|
|
||||||
# style "path" plutôt que "virtual-hosted" pour adresser un bucket.
|
|
||||||
s3ForcePathStyle: "true"
|
s3ForcePathStyle: "true"
|
||||||
|
insecureSkipTLSVerify: "false"
|
||||||
|
# Chiffrement côté serveur du contenu des sauvegardes (SSE-S3,
|
||||||
|
# AES256 géré par le bucket) — RustFS et MinIO le supportent tous
|
||||||
|
# les deux. Ne dispense pas de vérifier le chiffrement at-rest réel
|
||||||
|
# du stockage sous-jacent (voir étape 5 ci-dessus).
|
||||||
|
serverSideEncryption: "AES256"
|
||||||
|
|
||||||
# Pas de VolumeSnapshotLocation : sauvegarde des volumes via File System
|
|
||||||
# Backup (node-agent + kopia) plutôt que des snapshots CSI natifs.
|
|
||||||
volumeSnapshotLocation: []
|
volumeSnapshotLocation: []
|
||||||
|
|
||||||
snapshotsEnabled: false
|
snapshotsEnabled: false
|
||||||
|
|
||||||
# Node-agent (DaemonSet) : nécessaire pour sauvegarder le contenu réel des
|
|
||||||
# PVC (postgres, redis, uploads) via File System Backup.
|
|
||||||
deployNodeAgent: true
|
deployNodeAgent: true
|
||||||
|
|||||||
Reference in New Issue
Block a user