Pour ce premier article dans la série sur la plateforme data, on va d’abord installer quelques outils, démarrer le cluster Kubernetes, puis lancer la partie infrastructure de la plateforme.
Prérequis
Je le rappelle, cette plateforme de donnée fonctionne mieux sous un OS de type Linux. Tous les outils peuvent fonctionner sous Windows (avec WSL) ou sur Mac, mais cela nécessite quelques configurations supplémentaires pour pouvoir accéder aux différentes interfaces web et API.
De plus Docker doit être installé, ainsi que la commande jq (avec sudo apt install jq ou sudo dnf install jq).
Présentation et installation des outils
Tout est indiqué dans le répertoire git dont on va récupérer les sources, je vais ajouter ici quelques détails supplémentaires.
Kind
Kind (initialement "Kubernetes IN Docker") est un logiciel pour déployer un cluster Kubernetes sur base de conteneurs. Chaque nœud est représenté par un conteneur, avec un réseau virtuel dédié au cluster. Kind était d’abord développé pour tester les développements du projet Kubernetes lui-même, mais peut maintenant servir à tester ses propres applications dans un environnement Kubernetes local.
Pour l’installer, il y a deux façons. A la mode de go, il suffit de lancer la commande suivante :
go install sigs.k8s.io/kind@latest
Ou bien vous pouvez télécharger le binaire et le placer dans un dossier compris dans le $PATH.
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-${ARCH}
chmod +x ./kind
mv ./kind $HOME/.local/bin/kind
Le cluster de démo est composé d’un nœud pour le controle-plane et de deux nœuds worker, dont l’un sera utilisé pour recevoir les connexions externes, grâce au load-balancer de MetalLB.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: data-platform
networking:
ipFamily: ipv4
nodes:
- role: control-plane
image: kindest/node:v1.33.1
- role: worker
image: kindest/node:v1.33.1
labels:
net: metallb-gateway
- role: worker
image: kindest/node:v1.33.1
Kubectl
Kubectl est l’outil de ligne de commande utilisé pour interagir avec les clusters Kubernetes. Il permet de déployer des applications, de gérer les ressources du cluster et d’obtenir des informations sur l’état des ressources.
Pour l’installer, il faut télécharger le binaire. Des repositories apt et rpm existent aussi.
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
VERSION=$(curl -L -s https://dl.k8s.io/release/stable.txt)
curl -LO "https://dl.k8s.io/release/${VERSION}/bin/linux/${ARCH}/kubectl"
chmod +x ./kubectl
mv ./kubectl $HOME/.local/bin/kubectl
Helm
Déployer des applications dans un cluster Kubernetes peut être laborieux. Il faut définir les différents composants nécessaires (pods, services, pv …), le type (Deployments/DaemonSets, ClusterIP/LoadBalancer, …), les accès réseaux (Ingress, HTTPRoute, …). C’est là qu’intervient Helm, un gestionnaire de packages pour Kubernetes qui simplifie le déploiement et la gestion des applications. Les développeurs de l’application, ou la communauté, peuvent créer des "charts" Helm, qui sont l’équivalent des paquets APT/RPM pour Kubernetes. A ceci près que toute la configuration des applications Helm peut (doit) être définie avant l’installation, via les "values".
Un repository Helm est mis à disposition, chaque repository peut contenir des charts de plusieurs applications. Lorsqu’on installe une application dans le cluster, cela devient une "release".
Helm stocke la configuration des applications dans le cluster Kubernetes lui-même, en utilisant des objets Kubernetes tels que ConfigMaps et Secrets.
Pour l’installer, plusieurs méthodes sont disponibles. J’en reprends ici deux :
# Pour les développeurs golang
go install helm.sh/helm/v3/cmd/helm@latest
# Ou télécharger un binaire compilé
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
VERSION=$(curl -s https://api.github.com/repos/helm/helm/releases/latest | jq -r '.tag_name')
curl -L "https://get.helm.sh/helm-${VERSION}-linux-${ARCH}.tar.gz" | tar -xz --strip-components=1 linux-${ARCH}/helm
mv ./helm $HOME/.local/bin/helm
Helmfile
Une plateforme est généralement composée de plusieurs applications, et donc de plusieurs release Helm. Pour simplifier et centraliser les values et configurations, on peut utiliser Helmfile. Cet outil permet de définir l’ensemble des releases Helm dans un fichier YAML, et de les gérer de manière cohérente.
On a le choix entre un fichier helmfile.yaml par plateforme, ou de découper avec un fichier par application. En allant dans les détails de la configuration helmfile, on pourrait même gérer plusieurs environnements différents. Tout comme Helm, on peut utiliser des templates Golang, ce qui démultiplie encore les possibilités.
Pour l’installer, encore et toujours la page de documentation, et deux possibilités reprises ci-dessous :
# Pour les développeurs golang
go install github.com/helmfile/helmfile@latest
# Ou télécharger un binaire
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
VERSION=$(curl -s https://api.github.com/repos/helmfile/helmfile/releases/latest | jq -r '.tag_name')
VERSION=${VERSION#v}
curl -L "https://github.com/helmfile/helmfile/releases/download/v${VERSION}/helmfile_${VERSION}_linux_${ARCH}.tar.gz" | tar -xz -C $HOME/.local/bin helmfile
| 👇 Après l’installation, il faut télécharger tous les plugins helm dont helmfile a besoin. |
helmfile init
Installation de la plateforme
En premier lieu, il faut cloner le repository git et se placer à l’intérieur du dossier 01-infra.
git clone https://github.com/xreveillon/data-platform-demo.git
cd data-platform-demo/01-infra
Démarrage du cluster Kind
kind create cluster --config kind-config.yaml
On peut vérifier que le cluster est bien démarré avec la commande kubectl get nodes.
Personnalisation de la plateforme
Pendant que le cluster démarre, on va personnaliser un peu la plateforme. Dans le fichier .env, je propose de définir quelques paramètres via des variables d’environnement.
Le plus important est le nom de domaine principal, qui sera utilisé pour accéder aux différentes applications. Chaque application, avec une interface web ou avec un certificat SSL, aura son propre sous-domaine, par exemple minio.GLOBAL_DOMAIN pour Minio, ou airbyte.GLOBAL_DOMAIN pour Airbyte.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Domaine global, sous lequel chaque application prendra un sous-domaine
# Exemple, minio serait accessible sous minio.GLOBAL_DOMAIN,
# soit minio.data-platform.xreveillon.eu
GLOBAL_DOMAIN=data-platform.xreveillon.eu
MINIO_ACCESS_KEY=adminuser
MINIO_SECRET_KEY=adminpassword
AIRBYTE_S3_ACCESS_KEY=airbyte
AIRBYTE_S3_SECRET_KEY=airbytepassword
REGISTRY_USER=registry
REGISTRY_PASSWORD=registrypassword
REGISTRY_S3_ACCESS_KEY=registry
REGISTRY_S3_SECRET_KEY=registrypassword
Une fois modifiées, chargeons la configuration en mémoire.
set -a ; . .env ; set +a
Récupération d’informations réseau
Maintenant que le cluster est démarré, on va récupérer quelques informations réseau, qui serviront à configurer le réseau pour MetalLB (cf. plus bas le paragraphe sur MetalLB).
# Extraction du CIDR du réseau IPv4 du cluster kind
export KIND_IPV4_CIDR=$(docker network inspect kind | jq -r '.[0].IPAM.Config[] | select(.Subnet | test(":") | not) | .Subnet')
# Calcul de la plage d'adresses IP pour MetalLB
export METALLB_IP_RANGE=$(./last10range.sh $KIND_IPV4_CIDR)
Installation de l’infrastructure
On commence par installer les ressources de la Gateway API, et enfin on installe toute l’infra en une seule commande.
# Installer les CRD de la Gateway API depuis la branche expérimentale.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/experimental-install.yaml
# Installer les applications
helmfile apply
Cela va durer plusieurs minutes, le temps de récupérer les images Docker et démarrer les applications. Si un timeout survient, il suffit de relancer la commande helmfile apply.
En attendant, lisons le contenu de ce que l’on déploie 👇
Contenu de l’infrastructure
MetalLB
helmfile.yaml
24
25
26
27
28
29
30
31
32
33
34
35
36
37
releases:
- name: metallb
namespace: metallb-system
createNamespace: true
chart: metallb/metallb
wait: true
- name: kubedeploy-metallb
namespace: metallb-system
chart: sysbee/kubedeploy
disableValidationOnInstall: true
needs:
- metallb-system/metallb
values:
- values/metallb-extraobjects.yaml.gotmpl
Comme son nom l’indique, MetalLB est un load-balancer pour Kubernetes. Il existe 4 types de services pour gérer le réseau dans Kubernetes. Le service de type LoadBalancer est le seul à permettre des connections réseau depuis l’extérieur du cluster vers un port "habituel" (80, 443, 5432, …), au moyen d’un load-balancer situé à l’extérieur. Dans un environnement cloud, le LoadBalancer externe est automatiquement approvisionné, configuré et géré par le fournisseur cloud (AWS ELB, GCP LB, Azure LB, …). Dans un environnement on-premise ou local, il n’y a pas de load-balancer natif. MetalLB comble cette lacune en fournissant une implémentation logicielle de load-balancer, par exemple au moyen de l’allocation d’une adresse IP virtuelle sur un des noeuds.
Les adresses IP présentées sont propres à ma configuration. J’ai choisi le mode Layer 2.
Cert-manager
helmfile.yaml
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
- name: cert-manager
namespace: cert-manager
createNamespace: true
chart: jetstack/cert-manager
wait: true
disableValidationOnInstall: true
values:
- crds:
enabled: true
prometheus:
enabled: false
config:
apiVersion: controller.config.cert-manager.io/v1alpha1
kind: ControllerConfiguration
enableGatewayAPI: true
- name: cert-manager-extra-objects
namespace: cert-manager
chart: sysbee/kubedeploy
disableValidationOnInstall: true
wait: true
needs:
- cert-manager/cert-manager
values:
- values/cert-manager-extraObjects.yaml.gotmpl
Cert-manager est un gestionnaire de certificats SSL pour Kubernetes. Il automatise la gestion et le renouvellement des certificats TLS, en s’intégrant avec des autorités de certification comme Let’s Encrypt ou même privées. Cert-manager surveille les ressources de certificat dans le cluster et s’assure que les certificats sont valides et à jour.
Quand je ferai évoluer la plateforme vers un mode "production-ready", Cert-manager sera très utile pour chiffrer toutes les communications internes du cluster. Là maintenant, Cert-Manager est utilisé pour sécuriser votre accès aux interfaces web.
| Expliquer le pourquoi et le comment d’une PKI (public Key Infrastucture) fait partie de mes futurs articles de blog. |
| Si vous en avez marre de voir des avertissements de certificats dans votre navigateur en visitant les pages de la plateforme, vous pouvez installer le certificat racine de la PKI dans vos autorités de confiance. Mais je le DECONSEILLE FORTEMENT. |
Trust-manager
helmfile.yaml
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
- name: trust-manager
namespace: cert-manager
chart: jetstack/trust-manager
disableValidationOnInstall: true
wait: true
needs:
- cert-manager/cert-manager-extra-objects
values:
- crds:
enabled: true
secretTargets:
enabled: false
- name: trust-manager-extra-objects
namespace: cert-manager
chart: sysbee/kubedeploy
disableValidationOnInstall: true
wait: true
needs:
- cert-manager/trust-manager
values:
- values/trust-manager-extraObjects.yaml.gotmpl
Lorsque Cert-manager gère lui-même la PKI, Trust-manager est très pratique pour distribuer le certificat public, pour que les différentes applications puissent faire confiance aux certificats émis par Cert-manager.
Traefik
helmfile.yaml
83
84
85
86
87
88
89
90
91
- name: traefik
namespace: traefik
createNamespace: true
chart: traefik/traefik
disableValidationOnInstall: true
values:
- values/traefik-values.yaml.gotmpl
needs:
- cert-manager/cert-manager
Quand des applications web sont hébergées à l’intérieur d’un cluster Kubernetes, il faut pouvoir y accéder depuis l’extérieur. On l’a déjà vu avec MetalLb, des services de type LoadBalancer le permettent, quel que soit le protocole d’échange utilisé. Mais cela donne un accès direct aux applications, sans gestion des noms de domaines, ni des certificats SSL, ni de politiques de sécurité.
Pour le protocole HTTP(S), la meilleure méthode pour le moment est d’utiliser les Ingress avec un Ingress Controller (pour simplifier, c’est le reverse-proxy de Kubernetes). Dans ma plateforme, j’utilise Traefik comme Ingress Controller.
Traefik est aussi compatible avec la Gateway API, qui complètera les Ingress pour les applications nécessitant des configurations plus complexes.
Minio
helmfile.yaml
103
104
105
106
107
108
109
110
111
112
- name: minio
namespace: minio
createNamespace: true
chart: minio/minio
disableValidationOnInstall: true
wait: true
needs:
- minio/minio-extra-objects-pre
values:
- values/minio-values.yaml.gotmpl
Minio est une solution de stockage objet compatible avec l’API S3 d’Amazon. Elle est conçue pour être hautement disponible, évolutive et performante, et peut être déployée sur site ou dans le cloud. Minio est souvent utilisé pour stocker des données non structurées telles que des images, des vidéos, des sauvegardes et des fichiers journaux.
Le stockage objet est devenu prédominant dans le monde de la data, avec des solutions comme les Lakehouse.
Les lakehouse reposent sur le principe de la séparation du stockage et du calcul. Le stockage est assuré par un système de fichiers distribué ou un stockage objet, accessibles par plusieurs clients et query engines de manière concurrentielle.
Registre d’images Docker
helmfile.yaml
121
122
123
124
125
126
127
128
- name: registry
namespace: registry
createNamespace: true
chart: twuni/docker-registry
needs:
- minio/minio
values:
- values/docker-registry-values.yaml.gotmpl
Parmi les outils installés, il y a au moins Dagster qui nécessitera de créer ses propres images Docker. Et pour inclure le certificat public de l’autorité racine de la PKI privée, il faudra peut-être aussi procéder à la création d’images.
Instance PostgreSQL avec des données source
helmfile.yaml
113
114
115
116
117
118
119
120
- name: pg-source
namespace: postgresql
createNamespace: true
chart: bitnami/postgresql
needs:
- traefik/traefik
values:
- values/pg-source-values.yaml.gotmpl
Il s’agit de l’instance PostgreSQL qui fournira certaines données sources à Airbyte, Dagster ou Olake.
Structure de la database source
La base de données source contient 5 tables, dont 3 pouvant servir de dimension, et 2 de fait, nécessitant quelques transformations. Credits à drawdb.app et lilith pour le logiciel de diagramme ER
Finalisation
Vérifions déjà que tout est démarré correctement.
kubectl get daemonsets.apps,deployments.apps -A
## Résultat attendu
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system daemonset.apps/kindnet 3 3 3 3 3 kubernetes.io/os=linux 6h49m
kube-system daemonset.apps/kube-proxy 3 3 3 3 3 kubernetes.io/os=linux 6h49m
metallb-system daemonset.apps/metallb-speaker 3 3 3 3 3 kubernetes.io/os=linux 6h46m
traefik daemonset.apps/traefik 2 2 2 2 2 <none> 6h45m
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
cert-manager deployment.apps/cert-manager 1/1 1 1 6h46m
cert-manager deployment.apps/cert-manager-cainjector 1/1 1 1 6h46m
cert-manager deployment.apps/cert-manager-webhook 1/1 1 1 6h46m
cert-manager deployment.apps/trust-manager 1/1 1 1 6h45m
kube-system deployment.apps/coredns 2/2 2 2 6h49m
local-path-storage deployment.apps/local-path-provisioner 1/1 1 1 6h49m
metallb-system deployment.apps/metallb-controller 1/1 1 1 6h46m
minio deployment.apps/minio 1/1 1 1 6h45m
registry deployment.apps/registry-docker-registry 1/1 1 1 6h44m
Ensuite, si l’on veut pouvoir accéder à nos services via des noms de domaine plutôt que par adresse IP, il faut ajouter une entrée dans le fichier /etc/hosts de votre machine, avec l’adresse IP du nœud du LoadBalancer créé par MetalLB.
# Pour Traefik et toutes les interfaces web
kubectl get services -n traefik -o wide
# Pour PostgreSQL
kubectl get services -n postgresql -o wide pg-source-postgresql
Il faut relever l’adresse IP. En théorie, elle restera toujours la même, on peut donc la mettre dans le fichier /etc/hosts de la machine hôte.
Dans la ligne suivante, remplacez data-platform.xreveillon.eu par la valeur GLOBAL_DOMAIN que vous avez mise dans le fichier .env.
/etc/hosts<EXTERNAL-IP> traefik.data-platform.xreveillon.eu airbyte.data-platform.xreveillon.eu minio-console.data-platform.xreveillon.eu s3.data-platform.xreveillon.eu dagster.data-platform.xreveillon.eu registry.data-platform.xreveillon.eu pg-source.data-platform.xreveillon.eu
Une fois que c’est fait, on peut vérifier que tout fonctionne en navigant vers différentes URL pour voir les différentes interfaces web.

