Parmi les nombreux challenges du développement de l’informatique moderne, la simplification du déploiement, que ce soit des applications en elles-mêmes ou des infrastructures sous-jacentes, constitue un des principaux points d’intérêt.
Depuis maintenant une quinzaine d’années on entend parler du concept de DevOps, utilisé parfois à tort et à travers, mais qui représente globalement un ensemble de principes et de pratiques répondant à la question « Comment faire pour déployer au plus vite son application » ; car comme tout le monde le sait pouvoir déployer facilement son application permet d’éviter de perdre du temps, de l’argent et les cheveux des responsables de mise en prod.
Tout un écosystème s’est développé autour de ce besoin, notamment des solutions de CI/CD ou de GitOps qu’on ne présente plus, mais plus récemment une nouvelle approche est apparue : l’Open Application Model (OAM).
1- L’OAM (Open Application Model)

L’approche de l’Open Application Model est la suivante : l’important dans une application c’est … l’application ! Cela veut dire qu’un développeur ne devrait pas avoir à se soucier de la complexité de l’infrastructure sous-jacente lorsqu’il veut déployer son application.
C’est pour ça que Microsoft et Alibaba lancent en 2019 la spécification OAM portée par l’Open Web Foundation. Depuis 2021, la spécification est portée par la CNCF à travers une de ses implémentations : KubeVela.
L’OAM regroupe un ensemble de spécifications permettant de définir le déploiement de son application avec une abstraction haut niveau agnostique à l’infrastructure. Actuellement, le modèle fournit les définitions suivantes :
- Les Component, qui sont des unités fonctionnelles faisant partie d’une application, par exemple un backend ou un microservice de manière générale. Ces unités définissent un ensemble de « properties » servant à leur configuration, par exemple l’image du conteneur de l’entité, des variables d’environnement, le port utilisé etc.
- Les Workload, qui représentent la ressource sous-jacente qui va porter notre Component, par exemple dans le cadre de Kubernetes un Deployment, un Job, ou une CRD custom.
- Les Traits sont des fonctionnalités opérationnelles qui peuvent être attachées à un Component sans avoir à les inclure dans la définition de ce dernier. Dans le cadre de Kubernetes un Trait peu par exemple rajouter un Ingress pour exposer notre Component, des Network Policies pour contrôler les flux ou encore un HorizontalPodAutoscaler pour configurer l’autoscaling de l’application.
- Les Application Scopes sont similaires aux Traits mais s’appliquent à des groupes de Components plutôt qu’individuellement. On peut par exemple définir des Scopes réseaux permettant de grouper des Components dans un même réseau, ou des Scopes utilitaires comme un scope logging, permettant d’exporter les logs de tous les Components du Scope.
- Les Applications, qui sont l’entité finale, dans laquelle on indique les Components à déployer, ainsi que les éventuels Traits et Scopes à appliquer.
Ces spécifications permettent une claire séparation des responsabilités :
-L’équipe opérationnelle est chargée de créer les Components (en implémentant notamment le Workload sous-jacent), les Traits, ainsi que les Application Scopes.
-Les développeurs quant à eux créent l’Application en elle-même, en consommant les Components, Traits et Application Scopes fournis par l’équipe opérationnelle.
Cela permet aux développeurs d’être plus autonomes dans le déploiement de leurs applications, sans avoir à comprendre les complexités infrastructurelles comme des configurations réseau, des changements de versions d’API Kube, la configuration de l’autoscaling etc.
Quant à l’équipe opérationnelle, elle peut imposer le respect des bonnes pratiques et règles de l’entreprise en les incluant dans les définitions des Components, Traits et Scopes. De plus, en définissant des Components génériques et flexibles, on peut imaginer que les Components puissent être utilisés par différentes équipes pour différentes applications, ce qui permet de gagner du temps ainsi que d’uniformiser le parc applicatif.
En théorie, le modèle OAM peut être implémenté dans n’importe quel environnement, mais il est maintenant majoritairement porté par KubeVela une implémentation dans l’écosystème Kubernetes.
2. KubeVela

J’imagine que je vous ai déjà convaincu que l’OAM était fantastique, mais comment ça fonctionne en pratique ? Comme expliqué précédemment, KubeVela est l’implémentation référence du modèle OAM dans l’écosystème Kubernetes, nous allons voir dans les grandes lignes comment est faite cette implémentation.
2.1 Présentation des concepts de KubeVela
Voici un tableau récapitulatif des concepts de l’OAM et leur correspondance dans KubeVela.
| Concept OAM | Equivalence dans KubeVela |
| Component | ComponentDefinition |
| Trait | TraitDefinition |
| ApplicationScope | PolicyDefinition |
| Application | Application |
On peut noter que le concept d’ApplicationScope porte le nom de Policy dans KubeVela.
L’utilisateur est libre de définir des Components, Traits, et Policy comme il le souhaite, mais KubeVela propose aussi un panel de définitions « built-in » qui peuvent subvenir à la plupart des besoins généraux. On peut aussi télécharger des extensions développées par KubeVela ou par la communauté afin de bénéficier d’autres types prédéfinis.
2.2 Description de l’application d’exemple
Nous allons présenter les bases de l’utilisation de KubeVela à travers un exemple d’application basique composée de :
- **Deux Components:**
- **Un Component custom** représentant un serveur HTTP qui sera notre backend.
- **Un Component built-in de type «webservice»**
correspondant à un frontend qui sera chargé d’envoyer des requêtes HTTP vers notre backend.
- **Deux Traits:**
- **Un Trait custom** chargé d’injecter des variables d’environnement. Pour vérifier son fonctionnement il sera utilisé pour insérer l’url de notre backend dans le pod de notre front.
- **Un Trait built-in de type scaler** permettant de configurer le nombre de replicas de notre backend.
- **Une Policy built-in de type “override”** afin de surcharger la valeur du Trait scaler de notre backend lors d’un déploiement dans l’environnement de test.
Nous verrons aussi comment utiliser les Workflows de KubeVela pour déployer notre application dans différents environnements.
2.3 Déploiement de l’application - La partie opérateurs
Comme le veut la séparation des responsabilités du modèle OAM, l’équipe opérateur doit dans un premier temps définir les Components, Traits, et Policies (Scopes) nécessaires au déploiement de l’application. Dans cet exemple, nous n’utilisons pas de Policy custom, nous aborderons simplement la définition du Component et du Trait customs. Certaines parties des Yaml seront cachées dans une section repliable, mais vous pouvez les reconstruire en les mettant bout à bout si vous voulez reproduire l’exemple.
2.3.1 Installation de KubeVela
```bash
curl -fsSl https://kubevela.io/script/install.sh | bash # Installation de la CLI vela
vela install # Installation de KubeVela
vela addon enable velaux # Ajout du plugin velaux donnant accès à une interface utilisateur
```
2.3.2 Définition du Component custom
```yaml
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: backend-service
namespace: vela-system
annotations:
definition.oam.dev/description: “Backend de notre super app révolutionnaire”
spec:
workload:
definition:
apiVersion: apps/v1
kind: Deployment
schematic:
cue:
template: |
parameter: {
name: string
image: string
port: *8080 | int
cpu: *“100m” | string
memory: *“128Mi” | string
}
```
Les parties qui nous intéressent dans la définition du Component sont:
- La section **workload** qui permet de définir le type de la ressource principale qui portera notre Component. Cette section est utilisée pour savoir quels types de Traits sont applicables au Component.
- La section **parameter** du template, qui permet de définir les paramètres de notre Component ainsi que leurs éventuelles valeurs par défaut.
Vous pouvez retrouver dans les parties Workload principal et Ressources auxiliaires les templates Yaml des ressources de notre Component. Cette templatisation est faite avec l’outil Cue (pour Configure Unify Execute), nous ne intéresserons pas aux détails du langage ces sections seront laissées à titre informatif pour pouvoir suivre l’exemple.
Workload principal (Deployment)
```yaml
output: {
apiVersion: “apps/v1”
kind: “Deployment”
metadata: {
name: parameter.name
}
spec: {
selector: matchLabels: { app: parameter.name }
template: {
metadata: labels: { app: parameter.name }
spec: containers: [{
name: parameter.name
image: parameter.image
ports: [{
containerPort: parameter.port
}]
resources: {
requests: {
cpu: parameter.cpu
memory: parameter.memory
}
}
}]
}
}
}
```
Ressources auxiliaires (Service)
```yaml
outputs: service: {
apiVersion: “v1”
kind: “Service”
metadata: {
name: parameter.name
}
spec: {
selector: { app: parameter.name }
ports: [{
port: parameter.port
targetPort: parameter.port
}]
}
}
```
2.3.3 Définition du Trait custom
Le Trait utilisé ici sert simplement à injecter des variables d’environnement aux Pods de notre Deployment, son champ description est légèrement mensonger mais ce Trait nous servira tout de même à montrer la section **appliesToWorkloads** qui définit à quels types de workloads il peut s’appliquer. Ici on a la valeur **deployments.apps**, notre Trait pourra donc bien s’appliquer à notre Component dont le Workload est de type Deployment.
```yaml
apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
name: add-environment
namespace: vela-system
annotations:
definition.oam.dev/description: “Le Trait qui va révolutionner l’informatique”
spec:
appliesToWorkloads:
- deployments.apps
podDisruptive: false
```
Template Yaml du Trait
```yaml
schematic:
cue:
template: |
parameter: {
env: [string]: string
}
patch: {
spec: {
template: {
spec: {
containers: [{
env: [
for k, v in parameter.env {
{
name: k
value: v
}
}
]
}]
}
}
}
}
```
2.3.4 Création des environnements et des Targets associées
KubeVela possède une notion d’environnements, qui permet de regrouper des Targets qui correspondent aux endroits où sera effectivement déployée l’application. On peut par exemple imaginer un environnement dev-test, qui aurait une Target vers le namespace dev et une Target vers le namespace test, qui permettrait donc de déployer vers ces deux environnements en même temps.
**Il faut noter que les Targets peuvent pointer vers des clusters différents permettant le déploiement dans plusieurs environnement simultanément dans un contexte multicloud.**
Dans notre exemple, nous allons créer deux environnements distincts Dev et Test avec leurs Targets respectives étant les namespaces dev et test du cluster local (celui où est installé KubeVela) pour déployer de manière indépendante notre application dans ces deux namespaces.
Un défaut actuel de KubeVela est que les environnements créés via la CLI vela n’apparaissent pas dans la UI tant qu’une application n’y a pas été déployée. Pour permettre aux développeurs de déployer leur application via l’interface utilisateur, il faut donc créer les environnements depuis cette dernière.
C’est comme cela que nous allons procéder pour notre exemple:
2.4 Déploiement de l’application - La partie développeurs
Ça y est, les ressources liées à notre application sont prêtes, il ne reste plus qu’à la déployer.
Pour ce faire, se rendre dans l’onglet **Applications** de l’interface utilisateur et cliquer sur **New Application**.

On configure dans un premier temps Component principal de notre application (ici le Component Custom backend-service que nous avons créé précédemment) ainsi que les environnements liés à cette application.
Ensuite il faut choisir les valeurs des paramètres du Component, notamment l’image qui dans cet exemple est celle d’un serveur http qui log les requêtes qu’il reçoit.

C’est bon, l’application est créée, nous pouvons maintenant ajouter des Components ainsi qu’appliquer nos fameux Traits et Policies avant de finalement déployer l’application.
La capture d’écran suivante montre le menu depuis lequel on peut effectuer toutes ces actions, on retrouve bien notre Component principal **my-app**. On peut aussi noter que 2 Policies **dev** et **test** sont déjà configurées, elles sont chacune associées à un Workflow de déploiement dans les namespaces correspondant que nous verrons après.

Nous allons maintenant ajouter le Component Webservice qui nous servira de Frontend. Ce Component built-in contient un Deployment ainsi qu’un Service pour l’exposer, le service ne sera pas utilisé dans cet exemple car nous simulons les requêtes utilisateur avec un curl automatique vers le backend. En plus des paramètres visibles sur la capture d’écran, nous ajoutons en options avancées des lignes CMD:
``` sh -c while true; do curl -X POST -H “Content-Type: application/json” -d ”{“donnée_confidentielle”:”${ECHO_STRING}”}” http://${BACKEND_URL}:8080; sleep 5;done
``` On peut noter l’utilisation des 2 variables d’environnement **ECHO_STRING** et **BACKEND_URL** qui n’étaient pas définies dans notre Component, c’est là que notre Trait révolutionnaire rentre en jeu !
Je vous passe les écrans pour ajouter le Trait, notez simplement que nous avons inséré les varibles $ECHO_STRING=bipboup et $BACKEND_URL=mybackend

Je vous passe les différents écrans pour ajouter les Traits et Policies décrits plus haut qui ne comportent pas de spécificité particulière, voici l’état de notre application prête à être déployée:

Nous voilà enfin prêts … ou presque ! Et oui les plus attentifs d’entre vous auront remarqué que nous ne sommes toujours pas revenus sur les Workflows.
Les Workflows créés automatiquement et associés à leurs environnements/Targets respectifs sont directement fonctionnels, mais très basiques : ils déploient d’une traite tous les Components de l’application dans le namespace cible.
Pour notre exemple, cela suffira amplement, mais il est intéressant de relever que les Workflows proposent de nombreuses fonctionnalités au travers de nombreuses Steps built-in ainsi que la possibilité de créer ses propres Steps custom. On peut par exemple indiquer des dépendances entre des Components pour ordonner leur déploiement ou utiliser des valeurs disponibles uniquement au runtime dans des Secrets ou des Configmap. Les Workflows sont configurables eux aussi à travers une interface graphique permettant d’ajouter des steps et de les ordonner comme on le souhaite. Ici notre Workflow comporte seulement une Step de type **deploy** qui se chargera du déploiement de l’application.

Finalement, nous pouvons cliquer sur deploy et sélectionner un Workflow qui sera celui de notre environnement de test. S’il n’y a pas d’erreur de configuration, cela redirige sur l’écran du Workflow correspondant depuis lequel on peut observer le bon déploiement des ressources ou encore accéder aux logs des conteneurs, même pas besoin de connaître la commande kubectl get pods pour les développeurs les plus allergiques à Kubernetes !

On voit que la Policies override s’est bien appliquée car le Trait scaler de notre backend était configuré à 1 replica par défaut mais nous avons bien 2 backends, et ceux qui ont suivi l’exemple pourront aller vérifier dans la section Logs que le backend reçoit bien un curl avec comme body **{“donnée_confidentielle”:“bipboup”}** pour confirmer que notre Trait custom s’est bien appliqué.
3. Adopter KubeVela pour son entreprise ?
Bon, cet exemple était bien sympathique, mais il est loin d’une réelle application, potentiellement critique, qui serait amenée à tourner en production, la question se pose donc: peut-on vraiment utiliser KubeVela dans un contexte professionnel ?
Bien que la technologie soit relativement récente elle figure déjà parmi les projets “Incubating” de la CNCF ce qui assure une certaine robustesse de la technologie pour une utilisation en production. Elle est toujours activement développée et soutenue par la communauté qui développe de nombreux plugins donnant accès à une très grosse base de ressources pré-existantes.
On peut donc totalement imaginer utiliser KubeVela dans une entreprise pour pousser au niveau supérieur l’approche DevOps aujourd’hui largement démocratisée.
Pour des entreprises de taille intermédiaire, un système comme décrit au travers de notre exemple peut suffire pour avoir rapidement un bon moyen de déployer et gérer son application autant via la CLI que via l’interface utilisateur fournie.
Pour des plus grosses entreprises possédant des normes strictes et des infrastructures plus complexes et volumineuses, KubeVela seul peut avoir des limites, mais il est facile de l’interfacer avec d’autres outils comme ArgoCd pour la partie GitOps, Kyverno pour la validation des ressources déployées ou encore un Vault pour une meilleure gestion des secrets. Cela permet d’utiliser KubeVela en tant que cœur de son IDP et de profiter des avantages du modèle OAM ainsi que des nombreuses ressources déjà existantes dans KubeVela ou installables via les différentes plugins.
