diff --git a/app/dashboard/admin/users/UsersClient.tsx b/app/dashboard/admin/users/UsersClient.tsx index e71693b..c60b004 100644 --- a/app/dashboard/admin/users/UsersClient.tsx +++ b/app/dashboard/admin/users/UsersClient.tsx @@ -17,7 +17,7 @@ import { Eye, EyeOff, } from 'lucide-react' -import { cn } from '@/lib/utils' +import { cn, formatDate } from '@/lib/utils' import Link from 'next/link' interface User { @@ -34,14 +34,6 @@ interface Props { currentUserId: string } -function formatDate(dateStr: string | null) { - if (!dateStr) return 'Jamais' - return new Date(dateStr).toLocaleDateString('fr-FR', { - day: '2-digit', - month: 'short', - year: 'numeric', - }) -} const roleConfig = { admin: { label: 'Admin', color: 'bg-purple-500/10 text-purple-400 border-purple-500/20' }, diff --git a/app/dashboard/quizzes/QuizzesClient.tsx b/app/dashboard/quizzes/QuizzesClient.tsx index f9ff804..ca08a5c 100644 --- a/app/dashboard/quizzes/QuizzesClient.tsx +++ b/app/dashboard/quizzes/QuizzesClient.tsx @@ -20,7 +20,7 @@ import { FileJson, RefreshCw, } from 'lucide-react' -import { cn } from '@/lib/utils' +import { cn, formatDate } from '@/lib/utils' interface Quiz { id: string @@ -50,13 +50,6 @@ interface Props { } } -function formatDate(dateStr: string): string { - return new Date(dateStr).toLocaleDateString('fr-FR', { - day: '2-digit', - month: 'short', - year: 'numeric', - }) -} export default function QuizzesClient({ initialCategories, stats: initialStats }: Props) { const router = useRouter() diff --git a/app/dashboard/reports/page.tsx b/app/dashboard/reports/page.tsx index 88f2948..17833bc 100644 --- a/app/dashboard/reports/page.tsx +++ b/app/dashboard/reports/page.tsx @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { createClient } from '@/lib/supabase/server' +import { formatDate } from '@/lib/utils' import { BarChart3 } from 'lucide-react' import Link from 'next/link' @@ -48,7 +49,7 @@ export default async function ReportsPage() { Code: {session.short_code} {session.school_name && ` · ${session.school_name}`} {session.class_name && ` · ${session.class_name}`} - {' · '}{new Date(session.created_at).toLocaleDateString('fr-FR')} + {' · '}{formatDate(session.created_at)}

' ?", + "explanation": "Le 'drain' prépare un nœud pour la maintenance en expulsant les Pods existants (vers d'autres nœuds via leurs Controllers) et en marquant le nœud comme non-planifiable (cordon).", "answers": [ - { "text": "Vrai", "correct": false }, - { "text": "Faux", "correct": true } + { "text": "Supprime tous les Pods du cluster", "correct": false }, + { "text": "Redémarre kubelet", "correct": false }, + { "text": "Déplace les Pods vers d’autres nœuds", "correct": true }, + { "text": "Vide les fichiers de logs", "correct": false } ] }, { - "question": "Quelles sont les trois fonctions principales de l'API Server ?", - "explanation": "L'API Server sert de hub central : il authentifie/valide les requêtes, stocke les données de manière persistante dans etcd et expose l'état actuel du cluster aux utilisateurs et composants.", + "question": "Lequel de ces outils est un runtime de conteneurs compatible avec Kubernetes ?", + "explanation": "Pour être compatible, un runtime doit implémenter l'interface CRI. containerd, CRI-O ou Podman (via cri-o) en font partie.", "answers": [ - { "text": "Valider les requêtes, persister dans etcd, exposer l'état du cluster", "correct": true }, - { "text": "Scheduler les Pods, créer les ReplicaSets, monitorer les Nodes", "correct": false }, - { "text": "Lancer les conteneurs, assigner les Pods, gérer le réseau", "correct": false }, - { "text": "Authentifier les utilisateurs, chiffrer les secrets, gérer les certificats", "correct": false } + { "text": "Cilium", "correct": false }, + { "text": "Podman", "correct": true }, + { "text": "Kubectl", "correct": false }, + { "text": "Kubelet", "correct": false } ] }, { - "question": "Quel composant du Control Plane détecte les Nodes en panne ?", - "explanation": "Le Node Controller (intégré au kube-controller-manager) est responsable de la surveillance des nœuds et de l'éviction des Pods si un nœud ne répond plus.", + "question": "Quel composant exécute les conteneurs à la demande du kubelet ?", + "explanation": "La Container Runtime Interface (CRI) est l'interface standard qui permet au kubelet d'interagir avec différents moteurs de conteneurs sans connaître leurs spécificités internes.", "answers": [ - { "text": "Node controller", "correct": true }, - { "text": "Job controller", "correct": false }, - { "text": "ReplicaSet controller", "correct": false }, - { "text": "Endpoints controller", "correct": false } + { "text": "etcd", "correct": false }, + { "text": "scheduler", "correct": false }, + { "text": "kube-proxy", "correct": false }, + { "text": "CRI", "correct": true } ] }, { - "question": "Le kube-controller-manager communique directement avec etcd pour mettre à jour l'état du cluster.", - "explanation": "Comme pour le Scheduler, le Controller Manager doit envoyer des requêtes à l'API Server, qui se chargera ensuite d'écrire dans etcd.", - "answers": [ - { "text": "Vrai", "correct": false }, - { "text": "Faux", "correct": true } - ] - }, - { - "question": "Quelles sont les deux étapes du processus de scheduling ?", - "explanation": "Le scheduler procède d'abord par 'Filtrage' (éliminer les nœuds incompatibles) puis par 'Scoring' (classer les nœuds restants pour choisir le meilleur).", - "answers": [ - { "text": "Création puis démarrage", "correct": false }, - { "text": "Filtrage puis scoring", "correct": true }, - { "text": "Validation puis persistence", "correct": false }, - { "text": "Assignation puis Exécution", "correct": false } - ] - }, - { - "question": "Si le Control Plane tombe, les Pods existants continuent de tourner sur les Worker Nodes.", - "explanation": "Le Control Plane gère l'orchestration. Si il disparaît, le cluster devient 'gelé' (pas de nouveaux Pods), mais le plan de données (les Workers) continue d'exécuter ce qui est déjà en place.", + "question": "Le mode iptables de kube-proxy peut devenir lent avec des milliers de Services.", + "explanation": "iptables utilise une recherche séquentielle (O(n)). Plus il y a de règles (services), plus le temps de traitement augmente. IPVS est alors recommandé.", "answers": [ { "text": "Vrai", "correct": true }, { "text": "Faux", "correct": false } ] }, { - "question": "Le kube-controller-manager agit uniquement lorsqu’un utilisateur interagit avec le cluster.", - "explanation": "Faux. C'est une boucle de contrôle infinie (control loop) qui compare l'état désiré à l'état réel en permanence, même sans action humaine.", + "question": "Quel outil permet de surveiller l’état du service kubelet sur un nœud Linux ?", + "explanation": "Kubelet tournant généralement comme un service système (Systemd) sur les nœuds, la commande standard est 'systemctl status kubelet'.", + "answers": [ + { "text": "systemctl status kubelet", "correct": true }, + { "text": "kubectl logs kubelet", "correct": false }, + { "text": "docker ps", "correct": false }, + { "text": "journalctl -u kubelet", "correct": true } + ] + }, + { + "question": "Kube-proxy fonctionne uniquement sur le control plane", + "explanation": "Kube-proxy doit tourner sur chaque nœud (Worker et Master) pour gérer les règles réseau permettant la communication vers les Services.", "answers": [ { "text": "Vrai", "correct": false }, { "text": "Faux", "correct": true } ] }, { - "question": "L'API Server est le seul composant du Control Plane qui peut lire et écrire dans etcd.", - "explanation": "C'est une architecture conçue pour la sécurité et la cohérence des données : l'API Server est le gardien d'etcd.", + "question": "Quel fichier contient les manifests locaux de Pods lus automatiquement par le kubelet ?", + "explanation": "Le chemin par défaut pour les Static Pods (Pods gérés par Kubelet sans passer par l'API Server) est souvent défini dans ce répertoire via le paramètre staticPodPath.", + "answers": [ + { "text": "/var/lib/kubelet/config/pod.yaml", "correct": true }, + { "text": "/etc/kubernetes/manifests", "correct": true }, + { "text": "/etc/pod.d/", "correct": false }, + { "text": "/var/run/kubernetes.json", "correct": false } + ] + }, + { + "question": "runc est le composant bas niveau qui crée réellement les conteneurs avec les namespaces et cgroups Linux.", + "explanation": "runc est l'implémentation de référence de l'OCI (Open Container Initiative) qui dialogue avec le noyau Linux pour isoler les processus.", "answers": [ { "text": "Vrai", "correct": true }, { "text": "Faux", "correct": false } ] }, { - "question": "Quel champ du Pod le Scheduler remplit-il lors de l'assignation à un Node ?", - "explanation": "Le processus de scheduling consiste techniquement à mettre à jour le champ 'nodeName' dans la définition du Pod.", - "answers": [ - { "text": "nodeName", "correct": true }, - { "text": "NamePod", "correct": false }, - { "text": "NomDuPod", "correct": false }, - { "text": "NameOfThePod", "correct": false } - ] - }, - { - "question": "Dans quel ordre les composants interviennent-ils lors de la création d'un Deployment ?", - "explanation": "L'API Server reçoit l'ordre, les Controllers créent les objets (RS, Pods), le Scheduler choisit le nœud, et enfin le Kubelet exécute.", - "answers": [ - { "text": "Scheduler → API Server → Controller Manager → Kubelet", "correct": false }, - { "text": "Controller Manager → Scheduler → Kubelet → API Server", "correct": false }, - { "text": "Kubelet → Scheduler → API Server → Controller Manager", "correct": false }, - { "text": "API Server → Deployment Controller → ReplicaSet Controller → Scheduler → Kubelet", "correct": true } - ] - }, - { - "question": "Un seul controller manager peut gérer plusieurs types de contrôleurs.", - "explanation": "Le 'kube-controller-manager' est un binaire unique qui regroupe de nombreux contrôleurs (Node, Deployment, Namespace, etc.) pour simplifier la gestion.", + "question": "Les Static Pods peuvent être créés même si l'API Server n'est pas disponible.", + "explanation": "Oui, car le Kubelet surveille un dossier local sur le disque. Il lance les Pods qu'il y trouve sans attendre d'ordre du Control Plane.", "answers": [ { "text": "Vrai", "correct": true }, { "text": "Faux", "correct": false } ] }, { - "question": "Le kube-apiserver interagit directement avec les kubelets sur les nœuds", - "explanation": "Bien que l'API Server puisse initier des connexions (pour les logs ou l'exécution de commandes), c'est généralement le Kubelet qui surveille l'API Server pour recevoir ses instructions.", + "question": "Le kubelet utilise le modèle pull pour obtenir l'état désiré depuis l'API Server.", + "explanation": "Le Kubelet 'watch' l'API Server. Il tire (pull) les informations concernant les Pods qui lui sont assignés.", "answers": [ - { "text": "Vrai", "correct": false }, - { "text": "Faux", "correct": true } + { "text": "Vrai", "correct": true }, + { "text": "Faux", "correct": false } + ] + }, + { + "question": "Quelle commande réactive la planification sur un Node après maintenance ?", + "explanation": "'uncordon' retire la marque 'node.kubernetes.io/unschedulable' et permet au scheduler d'y placer de nouveaux Pods.", + "answers": [ + { "text": "kubectl enable", "correct": false }, + { "text": "kubectl resume", "correct": false }, + { "text": "kubectl uncordon", "correct": true }, + { "text": "kubectl activate", "correct": false } + ] + }, + { + "question": "Quel protocole utilise le kubelet pour communiquer avec le runtime via CRI ?", + "explanation": "L'interface CRI est basée sur gRPC, ce qui permet des communications performantes et fortement typées entre Kubelet et le runtime.", + "answers": [ + { "text": "WebSocket", "correct": false }, + { "text": "TCP Socket", "correct": false }, + { "text": "gRPC", "correct": true }, + { "text": "REST API", "correct": false } + ] + }, + { + "question": "Quel mode de kube-proxy offre une performance constante O(1) grâce aux hash tables ?", + "explanation": "IPVS (IP Virtual Server) utilise des tables de hachage pour rediriger le trafic, ce qui le rend beaucoup plus performant que les listes séquentielles d'iptables sur de grands clusters.", + "answers": [ + { "text": "userspace", "correct": false }, + { "text": "iptables", "correct": false }, + { "text": "nftables", "correct": false }, + { "text": "ipvs", "correct": true } + ] + }, + { + "question": "Le kubelet communique avec le Control Plane via l’API server.", + "explanation": "L'API Server est le seul point de contact du Kubelet pour rapporter l'état des nœuds et recevoir les spécifications des Pods.", + "answers": [ + { "text": "Vrai", "correct": true }, + { "text": "Faux", "correct": false } ] } ]