Je construis ma propre console
Après l’échec KubeSphere, j’ai décidé de construire ma propre console. Pas une usine à gaz, juste ce dont j’avais besoin.
Le stack
- Backend : Go avec client-go (le client Kubernetes officiel)
- Frontend : React + TypeScript + Vite + Tailwind
Pourquoi Go ? Parce que client-go est en Go, et je voulais apprendre.
Pourquoi React ? Parce que je connais, et c’est efficace.
L’architecture
┌─────────────────────┐ ┌─────────────────────┐
│ Frontend │ │ Backend │
│ React + TS │◀─────▶│ Go + client-go │
│ Port 80 │ API │ Port 8080 │
└─────────────────────┘ └──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Kubernetes API │
└─────────────────────┘
Simple. Le frontend fait des appels API au backend, qui parle à Kubernetes.
Le backend Go
Le truc cool avec Go et client-go, c’est que t’as accès à toute l’API Kubernetes nativement.
import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
func main() {
// Config in-cluster (quand on tourne dans K8s)
config, _ := rest.InClusterConfig()
// Client Kubernetes
clientset, _ := kubernetes.NewForConfig(config)
// Lister les pods
pods, _ := clientset.CoreV1().Pods("").List(ctx, metav1.ListOptions{})
}
Pour KubeVirt, j’utilise le dynamic client parce que les VirtualMachines c’est des CRDs :
import "k8s.io/client-go/dynamic"
var vmGVR = schema.GroupVersionResource{
Group: "kubevirt.io",
Version: "v1",
Resource: "virtualmachines",
}
vms, _ := dynamicClient.Resource(vmGVR).
Namespace("").
List(ctx, metav1.ListOptions{})
Le frontend React
Classique : des pages, des composants, des hooks pour fetch les données.
// hooks/usePods.ts
export function usePods(namespace: string) {
return useQuery({
queryKey: ['pods', namespace],
queryFn: () => fetch(`/api/v1/pods?ns=${namespace}`).then(r => r.json()),
refetchInterval: 5000,
})
}
J’utilise React Query pour le cache et le refresh automatique.
Les features
Ce que ma console fait :
- Dashboard : Vue d’ensemble du cluster (nodes, pods, mémoire)
- Pods : Liste, logs, delete, exec
- VMs : Liste, start/stop, accès console
- Deployments : Scale, restart
- Chat IA : Mais ça c’est venu après
Le déploiement
Deux containers dans le même namespace :
# Backend
apiVersion: apps/v1
kind: Deployment
metadata:
name: console-api
spec:
template:
spec:
serviceAccountName: console-api # Important pour les permissions
containers:
- name: api
image: mon-registry/console-api:latest
ports:
- containerPort: 8080
# Frontend
apiVersion: apps/v1
kind: Deployment
metadata:
name: console-ui
spec:
template:
spec:
containers:
- name: ui
image: mon-registry/console-ui:latest
ports:
- containerPort: 80
Le backend a besoin d’un ServiceAccount avec les bonnes permissions (ClusterRole) pour accéder à l’API Kubernetes.
Le RBAC
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: console-api
rules:
- apiGroups: ["", "apps", "kubevirt.io"]
resources: ["*"]
verbs: ["*"]
Oui, c’est permissif. C’est un homelab, pas une banque.
Ce que j’ai appris
-
Go c’est cool. Typage statique, compilation rapide, binaires standalone.
-
client-go est bien documenté. Les exemples dans le repo GitHub sont utiles.
-
Le dynamic client c’est la solution pour les CRDs.
-
Vite c’est rapide. Build en quelques secondes.
-
Faire simple marche. Ma console fait 10% de KubeSphere mais c’est 100% de ce que j’utilise.
L’évolution
Au début c’était juste un dashboard. Puis j’ai ajouté la gestion des VMs. Puis le déploiement d’apps.
Et puis j’ai eu une idée : et si je pouvais juste parler au cluster ?
Prochain article : Et si je parlais à mon cluster ? - L’idée de l’agent IA.