Au début, je ne voulais pas vraiment faire d’article sur Omni, je me disais que je n’aurais rien à dire dessus et que “it just works”… Je ne me doutais pas que je tomberai autant amoureux de cette solution. 

Déjà, récapitulons mon contexte : J’anime (avec Joel Seguillon) une émission chaque lundi soir (21h) sur Twitch. Durant ces lives, on fait des POCs et de la veille sur des projets Infra/DevOps. Très souvent, on gravite autour de l’écosystème Kubernetes, mais pas que.

Au début, c’était une grosse galère d’avoir un cluster Kubernetes prêt à l’emploi avant chaque émission, je ne voulais pas utiliser mes clusters persos, le risque de leak les crédentials étant trop haut. Je me suis donc mis à utiliser Pulumi pour déployer des clusters sur Openstack en 20min à l’aide de kubespray, ce qui nécessitait une petite préparation en amont :

  • Lancer le pulumi up 20min avant le live ;
  • Récupérer le kubeconfig, l’envoyer à Joel ;
  • Lancer un port-forward en SSH (car on n’exposait pas l’API-Server directement).

Ce n’était pas l’idéal, mais ça marchait plutôt bien.

La deuxième version de ce setup était de basculer sur Talos (que j’affectionne particulièrement). Il “suffisait” de créer un code qui allait déployer une image Talos sur Openstack, ainsi on se chargeait uniquement d’envoyer la configuration Talos aux noeuds (Merci à Mickael avec son dépot qui nous a bien aidé).

Avantages : 

  • Talos <3 (oui, rien que le fait d’être sur Talos est un avantage, c’est mon article je dis ce que je veux).
  • Plus rapide (environ 10min).
  • Plus flexible (la configuration Talos est plus facile à gérer que celle de Kubespray).

Inconvénients :

  • Envoyer une image sur Openstack est toujours un peu compliqué*.

*La complexité venant du fait qu’il faut upload l’image, et laisser openstack la traiter (et c’est souvent à cette étape que ça foire). Devoir relancer plusieurs fois le job avant que ça fonctionne était donc courant.

Ainsi, cette deuxième version était bien meilleure, mais on a toujours besoin de cette micro-logistique pour avoir chacun un accès au cluster (envoyer le kubeconfig, le port-forward sur la machine admin, etc.). Ça peut paraître anodin, mais quand tu fais ça chaque semaine (en terminant parfois le setup en live), c’est lourd (en quand nous avons un guest, ça l’est encore plus).

Et là, Sidero rend open-source Omni, et ça va tout changer !

Plus, la licence permet son usage dans un cadre hors production.

Omni, c’est quoi ?

Omni est l’application qui permet aux papas et mamans de Talos de manger (puisqu’il s’agit du seul projet payant dans l’écosystème Talos). Elle permet de gérer des machines Talos sur n’importe quelle plateforme (AWS, Azure, GCP, Openstack, Baremetal, etc.). Concrètement, il va exposer un VPN Wireguard sur lequel les Talos vont s’authentifier. Au sein de ce réseau, Omni peut piloter les clients comme on le ferait avec talosctl.

alt text

Ainsi, pour créer un cluster Kubernetes, je peux juste : 

  • Créer une ISO (image raw, script PXE…) sur Omni ;
  • Créer une machine avec cette même image ;
  • La piloter depuis Omni.

Je ne sais pas si les étapes ci-dessus arriveront à faire transparaître la facilité d’utilisation que ça apporte : Je n’ai pas besoin de savoir où sont mes machines, ni exposer les API Talos pour les contrôler.

Et si je veux faire du talosctl standard, je peux le faire à travers Omni qui va faire office de proxy. Il va rediriger ma requête à travers son réseau VPN en prenant soin de m’authentifier sur l’interface web d’Omni.

Plus besoin de se farcir les talosconfig. Maintenant, ils ne contiennent que l’URL d’Omni et votre mail, merci l’OIDC (à chaque commande talosctl, mon navigateur va s’ouvrir pour m’authentifier sur Omni).

context: omni-turingpi
contexts:
    omni-turingpi:
        endpoints:
            - https://omni.home.une-tasse-de.cafe
        auth:
            siderov1:
                identity: [email protected]
        cluster: turingpi

alt text

Coté Infra, c’est incroyable mais quid du coté utilisateur ? Beh c’est toujours aussi incroyable ! Il va également être l’intermédiaire de l’API-Server de Kubernetes et va encore jouer le rôle du proxy.

A l’instar d’au dessus, voici un kubeconfig pour accéder à un cluster Kubernetes :

apiVersion: v1
kind: Config
clusters:
  - cluster:
      server: https://omni.home.une-tasse-de.cafe:8100/
    name: omni-turingpi
contexts:
  - context:
      cluster: omni-turingpi
      namespace: default
      user: [email protected]
    name: omni-turingpi
current-context: omni-turingpi
users:
- name: [email protected]
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
        - oidc-login
        - get-token
        - --oidc-issuer-url=https://omni.home.une-tasse-de.cafe/oidc
        - --oidc-client-id=native
        - --oidc-extra-scope=cluster:turingpi
      command: kubectl
      env: null
      provideClusterInfo: false

side-note: Le fait qu’Omni joue le role de proxy permet de pouvoir révoquer l’accès à un cluster à un utilisateur instantanément (si on passait par l’OIDC branché sur le cluster, l’utilisateur aurait toujours accès au cluster jusqu’à expiration de sa session).

Mais ça, c’est la “base” d’Omni, on peut aller un peu plus loin et créer des templates de cluster.

Templates

Le terme “template” est un peu trompeur (mais ça s’appelle comme ça dans la doc, donc je le garde). En fait, il s’agit de “blueprints” qui vont vous permettre de créer des clusters Kubernetes à partir d’une configuration envoyée à Omni.

Dans l’idée, je demande un cluster de n noeuds prennant en paramètre des machines précises ou des machinesClass.

Petite parenthèse sur les MachinesClass : dès qu’on ajoute une machine Talos à Omni, elle va automatiquement obtenir des labels qui peuvent venir :

  • Des specifications de la machine (CPU, RAM, etc.) ;
  • Du cloud-provider (AWS, GCP, etc.) ;
  • Manuellement (en ajoutant des labels à la main).

alt text

Une machineClass est un groupe de machines en fonction des labels présents sur celle-ci. Je peux utiliser ces groupes dans la création de mes clusters et ainsi, je n’ai même pas à sélectionner les machines, Omni le fait pour moi.

alt text

C’est également une méthode pour pouvoir booter des machines qui rejoindront le cluster dès le démarrage !.

On peut alors faire une template comme ceci :

kind: Cluster
name: turing
kubernetes:
  version: v1.32.2
talos:
  version: v1.9.4
features:
  enableWorkloadProxy: false
  diskEncryption: false
  useEmbeddedDiscoveryService: true
patches:
  - name: spegel
    file: patches/spegel.yaml
  - name: enable-workload
    file: patches/workload-on-cp.yml
  - name: no-cni # we will install cilium in extraManifests
    file: patches/cni.yml
  - name: disable-kubeproxy
    file: patches/disable-kubeproxy.yml
  - name: manifests
    file: patches/extraManifests.yml
---
kind: ControlPlane
labels:
  type: control-plane
machineClass:
  name: turingpi
  size: 3
---
kind: Workers
name: workers
labels:
  type: worker
machineClass:
  name: turingpi
  size: 1

Pour l’appliquer, il me suffit de passer par la CLI (eh oui, Omni a une CLI) :

omnictl cluster template sync -f template.yaml

Grâce aux templates, je peux modifier la configuration des Talos ou injecter des manifests Kubernetes (comme Cilium, ArgoCD…). L’alternative aurait été de coller ces manifests dans l’interface web d’Omni (mais c’est franchement pas pratique).

Workload Proxy

Une autre fonctionnalité (que j’utilise peu mais qui est très intéressante) est le “workload proxy”. Il s’agit d’un proxy qui va permettre d’exposer des services Kubernetes sur l’interface web d’Omni, ce qui est idéal pour exposer une application qui ne serait accessible que par des personnes identifiées par Omni.

En bref, si je veux rendre une application disponible à mes collègues, je n’ai pas à me prendre la tête à : 

  • Créer un LoadBalancer (dépendant de l’infrastructure) ;
  • Créer un Ingress + Gérer le certificat SSL.

De plus, si l’application ne gère pas l’authentification, je dois la gérer moi-même (basic-auth ? OAuth2 Proxy ? Agent authentik ?).

Ou encore l’exposer à travers un VPN comme Tailscale ou Cloudflare tunnel.

Avec Omni et le workload proxy, il suffit de créer un service Kubernetes avec une annotation spécifique et Omni va s’occuper de tout (pour peu qu’on ait activé la feature dans la configuration de notre cluster).

Afin d’activer le workload proxy, il faut ajouter la feature enableWorkloadProxy à la configuration de notre cluster, ou cocher la case dans l’interface web d’Omni.

alt text

features:
  enableWorkloadProxy: true

Voici une application Nginx qui va être exposée sur l’interface web d’Omni :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: workload-proxy-example-nginx
  namespace: default
spec:
  selector:
    matchLabels:
      app: workload-proxy-example-nginx
  template:
    metadata:
      labels:
        app: workload-proxy-example-nginx
    spec:
      containers:
        - name: workload-proxy-example-nginx
          image: nginx:stable-alpine-slim
---
apiVersion: v1
kind: Service
metadata:
  name: workload-proxy-example-nginx
  namespace: default
  annotations:
    omni-kube-service-exposer.sidero.dev/port: "50080"
    omni-kube-service-exposer.sidero.dev/label: Sample Nginx
    omni-kube-service-exposer.sidero.dev/icon: H4sICB0B1mQAA25naW54LXN2Z3JlcG8tY29tLnN2ZwBdU8ly2zAMvfcrWPZKwiTANWM5015yyiHdDr1kNLZsa0axvKix8/cFJbvNdCRCEvEAPDxQ8/vLSydem+Op7XeVtGCkaHbLftXuNpX8Pax1kveL+UetxY9919erZiWG/k58+/kgvjb7Xonz+Qyn182RP2DZvyjx0OyaYz30x38o8dhemqP43vfdSWi9+DDnCHFuV8O2ksmY/UWKbdNutsPfz9e2OX/pL5U0wghCvqVgqrtTJbfDsL+bzUrhM0F/3MzQGDPjlHIxH9qhaxbrtmueh7d987zbtLvLfDZtz/f1sBWrSj5aD9klhVswwdfWgLNJXR+GL6sgRwSP6QmRd53yELzCCMmRShCjqyFmLOsWwCiIKS01GJOUA0qZHQUby5ZXlsAGjkv8wmuK00A+gDfxoD1DSREQOm0teBdVgOA4wqdY1i0i+AiG4lOGbFEhg7icZWJIgCMz+It1DA/hYDQXScxVjyyohpCprBt7SswylJze49htVNxQjk6xDuSXTAs12OQgUGLWMRenLj4pTsNb11SSde/uPhmbA2U5e6c3qxBiEdhTOhhO77CIwxvJ55p7NVlN1owX+xkOJhUb3M1OTuShAZpQIoK72mtcSF5bwExLoxECjsqzssgIzdMLB2IdiPViApHbsTwhH1KNkIgFHO2tTOB54pjfXu3k4QLechmK9lCGzfm9s0XbQtmWfqa4NB0Oo1lzVtUsx6wjKxtYBcKSMkJOyGzJBbYxBM0aBypZfdBRJyDCz0zNRjXZKw0D/J75KFApFvPVTt73kv/6b0Lr9bqMp/wziz8W9M/pAwQAAA==
spec:
  selector:
    app: workload-proxy-example-nginx
  ports:
    - name: http
      port: 80
      targetPort: 80

alt text alt text

Comment ça marche ?

C’est encore une fois grâce au mode de communication d’Omni : son réseau interne Wireguard. Dès qu’on active le proxy, Omni va déployer un DaemonSet sur le cluster Kubernetes en mode HostNetwork (ce qui lui permet d’exposer sur la machine hôte avec ses interfaces réseaux) mais uniquement à travers le réseau Wireguard (security first).

Omni va donc créer un manifest Kubernetes qui va être appliqué par Talos, on peut le trouver ici. C’est d’ailleurs à cet endroit qu’on voit qu’il utilise la plage du réseau wireguard d’Omni --bind-cidrs="fdae:41e4:649b:9303::/64".

Limitations d’Omni

Dans ce que nous avons vu, Omni est un outil tentaculaire très pratique, mais vous avez peut-être remarqué une grosse limitation. En effet, le déploiement de nos machines reste toujours manuel (ou via un outil d’automatisation comme Terraform).

L’alternative à la partie déploiement d’Omni serait de passer par la ClusterAPI (qui ne concurrence QUE la partie création de cluster, les autres fonctionnalités comme l’OIDC, le workload proxy, etc. étant propres à Omni).

La ClusterAPI est un projet permettant de déployer des clusters Kubernetes sur la majorité des platformes cloud (avec des providers, comme pour Terraform) à partir d’un cluster Kubernetes de management qui va créer les machines, créer le cluster, et stocker la configuration dans des secrets. Si ça vous intéresse, j’ai un article qui en parle ici avec Talos et Proxmox.

Pour en revenir à Omni, celui-ci n’est pas capable de piloter une infrastructure cloud… pour l’instant ! 

Infrastructure Providers

Sur la documentation d’Omni, on retrouve cette page qui détaille le projet d’Omni de pouvoir créer des providers pilotant, à la volée, des machines sur des infrastructures cloud ou on-premise.

En principe, Omni va avoir à disposition une machineClass correspondant à l’infrastructure cible et, dès qu’une machine y est demandée (e.g. en créant un cluster), un programme interfacé avec Omni va créer cette machine automatiquement.

Pour l’instant, il n’en existe que deux : 

  • Baremetal (pilotant du IPMI ou du Redfish).
  • Kubevirt (pour créer des VMs sur un cluster Kubernetes).

C’est avec ce second que j’ai pu m’amuser. Je vous présente ça tout de suite !

Créer un provider Kubevirt

On va détailler ensemble comment ajouter ce provider Kubevirt pour créer des clusters automatiquement !

Je vais volontairement rester très vague à propos de Kubevirt (je ne maîtrise pas vraiment cette solution, donc je risque de dire des bêtises). Je vais donc me concentrer sur Omni et la création de machines virtuelles.

Déjà, de quoi avons-nous besoin ?

  • D’un cluster Kubernetes capable d’héberger des VMs ;
  • D’Omni (évidemment).

Ce premier cluster Kubernetes sera, BIEN entendu, lui-même présent dans Omni (ça n’est pas obligatoire, mais j’aime bien Omni :P).

Installer Kubevirt

Je dispose déjà d’un cluster prêt-à-l’emploi, il s’agit d’une machine Baremetal hostée chez Hetzner (ne retenez pas cette information : elle est inutile). J’installe alors kubevirt de la manière la plus simple proposée par la documentation :

export VERSION=$(curl -s https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt)
echo $VERSION
kubectl create -f "https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml"
kubectl create -f "https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml"

Puis, je vais avoir besoin de CDI (Containerized Data Importer) qui va me permettre de créer des VMs à partir de sources externes. Toujours comme un bon petit élève, je vais suivre la documentation :

export TAG=$(curl -s -w %{redirect_url} https://github.com/kubevirt/containerized-data-importer/releases/latest)
export VERSION=$(echo ${TAG##*/})
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-operator.yaml
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-cr.yaml

Kubevirt et CDI, ça semble OK ! Mais on les stocke où ces VMs ?

LocalPathProvisioner

Maintenant, on a besoin de configurer un CSI pour stocker les disques des machines virtuelles !

Je vais faire (très) simple et configurer le LocalPathProvisioner de Rancher mais, dans l’idéal, il faudrait utiliser un stockage partagé pour permettre de migrer les VMs entre les noeuds (ce qui n’est pas le cas avec le LocalPathProvisioner qui utilise le disque hôte).

Toutefois, le stockage LocalPathProvisioner nécessite un petit patch dans la configuration de notre noeud Talos (toujours celui qui va héberger les VMs) :

machine:
  kubelet:
    extraMounts:
      - destination: /var/local-path-provisioner
        type: bind
        source: /var/local-path-provisioner
        options:
          - bind
          - rshared
          - rw

Ainsi, on peut installer le LocalPathProvisioner comme indiqué dans la documentation de Talos.

# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- github.com/rancher/local-path-provisioner/deploy?ref=v0.0.26
patches:
- patch: |-
    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: local-path-config
      namespace: local-path-storage
    data:
      config.json: |-
        {
                "nodePathMap":[
                {
                        "node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",
                        "paths":["/var/local-path-provisioner"]
                }
                ]
        }        
- patch: |-
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: local-path
      annotations:
        storageclass.kubernetes.io/is-default-class: "true"        
- patch: |-
    apiVersion: v1
    kind: Namespace
    metadata:
      name: local-path-storage
      labels:
        pod-security.kubernetes.io/enforce: privileged      

Kubevirt, check. CDI, check. LocalPathProvisioner, check.

Créer le serviceAccount Omni

On s’approche de l’objectif : le provider Kubevirt. Maintenant, nous avons besoin d’un serviceAccount Omni pour se rendre disponible, et on peut le faire via la WebUI ou en CLI :

omnictl serviceaccount create --role=InfraProvider --use-user-role=false infra-provider:hetzner

Note : Le hetzner à la fin est le nom du cluster tel qu’il sera référencé dans Omni, si on veut plusieurs clusters, il faut créer plusieurs serviceAccount.

OMNI_ENDPOINT=https://omni.home.une-tasse-de.cafe:443
OMNI_SERVICE_ACCOUNT_KEY=wowcestvraimentunsupertoken

On peut le garder dans un coin, on en aura besoin plus tard.

Dernière étape, un kubeconfig pour que le provider puisse créer des VMs sur le cluster Kubernetes.

Créer un KubeConfig

Petit disclaimer, cette partie là ne se base sur aucune documentation, il est donc possible que j’oublie des permissions ou des étapes.

En voyant que le provider avait besoin d’un kubeconfig, j’ai forcément utilisé mon kubeconfig administrateur dans un premier temps. Mais, clairement, ce n’est pas très propre !

Je vais donc essayer de vous montrer l’exemple en créant un serviceAccount avec les permissions minimales pour créer des VMs.

Je vais commencer par créer le serviceAccount et le secret qui va contenir son token d’authentification :

name=kubevirt-omni
kubectl create ns $name
kubectl create sa $name

kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
  name: $name
  annotations:
    kubernetes.io/service-account.name: $name
EOF

Maintenant, on peut créer le kubeconfig en utilisant le secret qu’on vient de créer :

server=https://135.181.219.54:6443
ca=$(kubectl get secret/$name -o jsonpath='{.data.ca\.crt}')
token=$(kubectl get secret/$name -o jsonpath='{.data.token}' | base64 --decode)
namespace=$(kubectl get secret/$name -o jsonpath='{.data.namespace}' | base64 --decode)

echo "
apiVersion: v1
kind: Config
clusters:
- name: default-cluster
  cluster:
    certificate-authority-data: ${ca}
    server: ${server}
contexts:
- name: default-context
  context:
    cluster: default-cluster
    namespace: default
    user: default-user
current-context: default-context
users:
- name: default-user
  user:
    token: ${token}
" > sa.kubeconfig

Sauf que dans l’état actuel, on ne peut pas aller bien loin puisqu’il n’a aucun droit dans le cluster. On va donc lui donner les permissions dont il a besoin, la création de VMs et de Datavolumes (pour la création de disques avec Talos).

kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: $name
rules:
  - apiGroups:
      - cdi.kubevirt.io
    resources:
      - datavolumes
    verbs:
      - get
      - list
      - watch
      - create
      - update
      - delete
  - apiGroups:
      - kubevirt.io
    resources:
      - virtualmachines
    verbs:
      - get
      - list
      - watch
      - create
      - update
      - delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: $name
subjects:
  - kind: ServiceAccount
    name: $name
    namespace: $namespace
roleRef:
  kind: ClusterRole
  name: $name
  apiGroup: rbac.authorization.k8s.io
EOF

Ça y est, on y est enfin ! On va pouvoir lancer le provider pour la première fois :

docker run --platform=linux/amd64 --name omni-kubevirt -it -v ./sa.kubeconfig:/kubeconfig ghcr.io/siderolabs/omni-infra-provider-kubevirt --kubeconfig-file /kubeconfig --omni-api-endpoint $OMNI_ENDPOINT --omni-service-account-key $OMNI_SERVICE_ACCOUNT_KEY --id hetzner -n $namespace

… et pour finir, on ajoute la MachineClass dans Omni.

alt text alt text

On se le crée ce cluster ?

alt text

Roulement de tambour…

Il se passe beaucoup de choses en quelques secondes ! Comme par exemple un pod “cdi-importer” qui va télécharger l’image de Talos sur un PVC. Ce pod utilise Factory (le site de Talos pour créer des images customisées), on est en terrain connu.

alt text

Mais surtout, on a des VMs !!!

$ kubectl get vm          
NAME                                      AGE    STATUS    READY
talos-in-kubevirt-control-planes-mbk7g8   4m3s   Running   True
talos-in-kubevirt-workers-fhzmxd          4m2s   Running   True

Chose amusante, si on regarde le manifest d’une des VMs, on remarque qu’elle est configurée avec du CloudInit qui va contenir l’URL de l’API d’Omni et un token d’authentification.

alt text

Bon après… Omni n’est pas très content :/

alt text

$ talosctl -n talos-in-kubevirt-control-planes-mbk7g8 dmesg
fdae:41e4:649b:9303:260b:ed52:8620:177b: user: warning: [2025-04-07T17:27:07.689754559Z]: [talos] diagnostic still active {"component": "controller-runtime", "controller": "runtime.DiagnosticsLoggerController", "id": "address-overlap", "message": "host and Kubernetes pod/service CIDR addresses overlap", "details": ["host routed addresses: [\"10.244.0.55/24\"]", "Kubernetes pod CIDRs: [\"10.244.0.0/16\"]", "Kubernetes service CIDRs: [\"10.96.0.0/12\"]"], "url": "https://talos.dev/diagnostic/address-overlap"}

On a un petit conflit d’adresse IP entre le réseau du cluster hôte et les VMs qui essayent d’utiliser les mêmes plages d’adresses pour son cluster. Logiquement, ça marche pas !

On va donc créer un petit patch Talos pour changer la plage du cluster de VM : 

# netcidr.yaml
cluster:
  network:
    dnsDomain: cluster.local
    podSubnets:
      - 198.18.0.0/15
    serviceSubnets:
      - 172.30.0.0/16

On pourrait l’appliquer depuis l’interface web d’Omni, mais c’est l’occasion parfaite de se faire une template de cluster !

Créer une template de cluster

kind: Cluster
name: talos-with-kubevirt
labels:
  template: true
kubernetes:
  version: v1.32.2
talos:
  version: v1.9.5
patches:
  - name: cidr-overlap
    file: netcidr.yaml
---
kind: ControlPlane
labels:
  type: control-plane
machineClass:
  name: hetzner
  size: 1
---
kind: Workers
labels:
  type: workers
machineClass:
  name: hetzner
  size: 1

On l’applique :

$ omnictl cluster template sync -f template.yaml
* creating Clusters.omni.sidero.dev(talos-with-kubevirt)
* creating ConfigPatches.omni.sidero.dev(200-talos-with-kubevirt-cidr-overlap)
* creating MachineSets.omni.sidero.dev(talos-with-kubevirt-workers)
* creating MachineSets.omni.sidero.dev(talos-with-kubevirt-control-planes)```

Et on a un cluster Kubernetes qui est prêt à l’emploi ! Je peux alors récupérer le kubeconfig et l’utiliser comme un cluster (Omni) classique.

$ omnictl kubeconfig --cluster talos-with-kubevirt

Conclusion

Aujourd’hui, j’utilise mon selfhost Omni presque tous les jours sur mes clusters personnels (OVH, TuringPI, VM Proxmox, etc.). Le fait de pouvoir créer des clusters Kubernetes rapidos sans m’occuper de la créations des machines est vraiment un game-changer (que ça soit pour les lives ou pour mes projets).

Bref, si Omni vous intéresse, foncez voir ce que fait Sidero, il y a vraiment de quoi faire ! J’ai vraiment hâte de voir les prochains providers (Proxmox ou Openstack ?) et comment Omni va évoluer dans le temps.

En plus, Omni en SAS ne coute que 10$/mois pour la version Hobby. Foncez !