{"id":24500719,"url":"https://github.com/inseefrlab/devoxx-2023","last_synced_at":"2025-08-21T16:27:10.516Z","repository":{"id":212598141,"uuid":"622557494","full_name":"InseeFrLab/devoxx-2023","owner":"InseeFrLab","description":null,"archived":false,"fork":false,"pushed_at":"2023-12-15T05:08:04.000Z","size":373,"stargazers_count":10,"open_issues_count":1,"forks_count":1,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-01-21T22:24:17.013Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/InseeFrLab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-04-02T13:23:49.000Z","updated_at":"2024-05-15T06:45:27.000Z","dependencies_parsed_at":"2023-12-15T06:26:18.910Z","dependency_job_id":"4fd38be1-2622-4d24-b5f4-816a55fea2e4","html_url":"https://github.com/InseeFrLab/devoxx-2023","commit_stats":null,"previous_names":["inseefrlab/devoxx-2023"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InseeFrLab%2Fdevoxx-2023","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InseeFrLab%2Fdevoxx-2023/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InseeFrLab%2Fdevoxx-2023/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InseeFrLab%2Fdevoxx-2023/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/InseeFrLab","download_url":"https://codeload.github.com/InseeFrLab/devoxx-2023/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243697396,"owners_count":20332943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-21T22:21:42.837Z","updated_at":"2025-03-15T07:23:15.700Z","avatar_url":"https://github.com/InseeFrLab.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Construisons ensemble de A à Z un cloud opensource pour le datascientist\n\nPour poser des questions pendant la conférence : https://hebdo.framapad.org/p/devoxx-2023-conf-datalab-a0cu?lang=fr\n\n## Contexte et objectif\n\nhttps://minio.lab.sspcloud.fr/projet-onyxia/diffusion/Presentation/devoxx-intro.pdf\n\nPlan de jeu :\n\n1. [Provisionner un cluster Kubernetes](#provisionner-un-cluster-kubernetes)\n2. [Prise en main \"admin\" du cluster](#prise-en-main-admin-du-cluster)\n3. [Datascience 101: déploiement d'un service](#datascience-101--déploiement-dun-service)\n4. [Packaging, reproductibilité et configuration: Helm](#packaging-reproductibilité-et-configuration--helm)\n5. [Exposition des services vers l'extérieur](#exposition-des-services-vers-lextérieur)\n6. [Bilan d'étape](#bilan-détape)\n7. [Onyxia, notre sauveur](#onyxia-notre-sauveur)\n8. [Installation d'Onyxia](#installation-donyxia)\n9. [Multi utilisateurs: authentification](#multi-users--authentification)\n10. [Stockage S3](#stockage-s3)\n11. [Catalogue de services](#catalogue-de-services)\n12. [Gestion des secrets](#gestion-des-secrets)\n13. [Customisation](#customisation)\n14. [Bonus](#bonus)\n\n## Provisionner un cluster Kubernetes\n\n### `Théorie`\n\n- Un prérequis : un cluster Kubernetes\n- \"Agnostique de la distribution / cloud provider\"\n- Aujourd'hui : cluster managé chez OVH\n\n### `Pratique`\n\n- Création d'un cluster Kubernetes sur OVH\n\n## Prise en main \"admin\" du cluster\n\n### `Théorie`\n\n![](img/kube.png)\n\n- Interaction avec l'API Server\n\n### `Pratique`\n\n- Installation de `kubectl` (https://kubernetes.io/docs/tasks/tools/), attention au [Version skew policy](https://kubernetes.io/releases/version-skew-policy/) : respecter `+/- 1` par rapport au cluster pour éviter les problèmes. Le mettre dans le `PATH`.\n- Téléchargement du `kubeconfig` depuis l'interface du provider (ou récupération en fonction de la distribution), le placer dans `~/.kube/config`\n- Confirmer avec `kubectl get nodes` la présence des noeuds\n\n## Datascience 101 : déploiement d'un service\n\n### `Théorie`\n\n- On a un cluster, on déploie et c'est fini, non ?\n\n### `Pratique`\n\n- Déploiement d'un jupyter notebook basique. `kubectl apply -f manifests/jupyter-basique`\n- `kubectl get pods` pour suivre la création du pod\n- `kubectl logs podname` une fois `Running` pour consulter les logs et récupérer le token d'accès (on ne l'a pas précisé donc il est généré dynamiquement à chaque lancement)\n- `kubectl port-forward podname 8888:8888` pour ouvrir un tunnel entre `localhost:8888` et le port 8888 du Jupyter\n- Accès et utilisation du Jupyter via `localhost:8888`\n\nSuperbe infra datascience :thumbsup:\n\n## Packaging, reproductibilité et configuration : Helm\n\n### `Théorie`\n\nIntérêt du packaging, principes de [Helm](https://helm.sh/)\n\n### `Pratique`\n\nDésinstallation et réinstallation du service précédent\n\n- `kubectl delete -f manifests/jupyter-basique` pour nettoyer le service précédent\n- Recherche d'un `chart` Helm pour jupyterlab ...\n- https://github.com/inseefrlab/helm-charts-interactive-services\n\n```\nhelm repo add helm-charts-interactive-services https://inseefrlab.github.io/helm-charts-interactive-services\nhelm repo update\nhelm install jupyter helm-charts-interactive-services/jupyter-python\n```\n\n- Pratique : faire un `chart` \"coquille\" avec une dépendance vers le `chart` réel (cf `manifests/jupyter-helm`)\n- Bonne pratique : Utiliser `helm template` AVANT d'installer pour contrôler ce qui va être installé. (à défaut, `helm get manifest \u003creleasename\u003e` pour voir les manifests après installation)\n- Bonne pratique : Externaliser les values dans un `values.yaml` (`helm install -f values.yaml`)\n- Bonne pratique : `helm uninstall jupyter`\n\n## Exposition des services vers l'extérieur\n\n### `Théorie`\n\n![](img/reverse-proxy.png)\n\n### `Pratique`\n\n- `cd manifests/ingress-nginx`, `helm dependencies build` pour télécharger les dépendances (`helm dependencies update` pour les mettre à jour)\n- `kubectl create namespace ingress-nginx`\n- `helm template ingress-nginx . -f values.yaml -n ingress-nginx` pour prévisualisation\n- `helm install ingress-nginx . -f values.yaml -n ingress-nginx` pour l'installation\n- `kubectl get pods -n ingress-nginx` pour suivre l'avancée des pods, `kubectl get service -n ingress-nginx` pour suivre l'affectation de l'IP loadbalancer\n- Récupérer l'IP externe (après affectation par le cloud provider)\n\n### `Théorie`\n\nUne adresse IP c'est bien, un nom de domaine c'est mieux\n\n### `Pratique`\n\n- Configuration d'un champ DNS `A` `*.devoxx.insee.io` =\u003e `ipexterne`\n- Modifier le jupyter pour utiliser le reverse proxy (`helm upgrade jupyter helm-charts-interactive-services/jupyter-python --set ingress.enabled=true --set ingress.hostname=devoxx.insee.io`)\n\n### `Théorie`\n\n- `HTTP` brut en 2023 :vomiting_face:\n- 2 approches : `cert-manager` et `wildcard`\n\n### `Pratique`\n\n- Wildcard (via [let's encrypt](https://letsencrypt.org/)) : `certbot certonly --manual --preferred-challenges dns`\n- `kubectl create secret tls wildcard --key privkey.pem --cert fullchain.pem -n ingress-nginx`\n- Ou cert-manager : https://cert-manager.io/docs/installation/helm/\n\n## Bilan d'étape\n\nOn a un cluster, accessible aux admins avec possibilité de déployer des services de façon technique.  \n**Nécessité d'industrialisation et de proposer une UX**\n\n## Onyxia, notre sauveur 🙏🏻\n\n\u003ca href=\"https://youtu.be/2aewcmK8kmk\"\u003e\n  \u003cimg width=\"1712\" alt=\"image\" src=\"https://user-images.githubusercontent.com/6702424/231314534-2eeb1ab5-5460-4caa-b78d-55afd400c9fc.png\"\u003e\n\u003c/a\u003e\n\u003cp align=\"center\"\u003e\n    \u003cbr/\u003e\n    \u003ca https=\"https://www.onyxia.sh\"\u003e\u003cb\u003eonyxia.sh\u003c/b\u003e\u003c/a\u003e\n    \u003cbr/\u003e\n    \u003cbr/\u003e\n\u003c/p\u003e\n\n\n\nVidéo + présentation de l'appli + démo sspcloud (J)\n\n## Installation d'Onyxia\n\n### `Théorie`\n\n- https://www.onyxia.sh/\n- Pattern \"namespace as a service\"\n\n### `Pratique`\n\n- `cd manifests/onyxia-brut`, `helm dependencies build`, `helm install onyxia . -f values.yaml -n onyxia --create-namespace`\n- ...\n- `https://datalab.devoxx.insee.io`\n\n## Multi utilisateurs : authentification\n\n### `Théorie`\n\n![](img/oidc.jpeg)\n\n### `Pratique`\n\nInstallation d'un [Keycloak](https://github.com/keycloak/keycloak)\n\n- `cd manifests/keycloak`, `helm dependencies build`, `helm install keycloak . -f values.yaml -n keycloak --create-namespace`\n\n* Interface d'admin : https://auth.devoxx.insee.io/auth\n* Création d'un realm `datalab`, onglet `login` activation de `User registration`\n* Création d'un client `onyxia` avec `Root URL` : `https://datalab.devoxx.insee.io`, `Valid redirect URIs` : `https://datalab.devoxx.insee.io/*` et `Web origins` : `+`\n\nConfiguration d'onyxia :\n\n- `cd manifests/onyxia-oidc`, `helm dependencies build`, `helm upgrade onyxia . -f values.yaml -n onyxia`\n\n## Stockage S3\n\n### `Théorie`\n\nIntérêt du stockage S3 (F)\n\n### `Pratique`\n\nInstallation d'un [minIO](https://github.com/minio/minio)\n\n- `cd manifests/minio`, `helm dependencies build`, `helm install minio . -f values.yaml -n minio --create-namespace`\n- Utilisation de [mc](https://min.io/download#/linux)\n- `mc alias set devoxx https://minio.devoxx.insee.io admin changeme`\n- `mc admin info devoxx`\n- `mc ls devoxx`\n\nAuthentification OpenIDConnect :\n\n- Création d'un client `minio`, `Root URL` : `https://minio.devoxx.insee.io`, `Valid redirect URIs` : `https://minio.devoxx.insee.io/*` et `https://minio-console.devoxx.insee.io/*`, `Web origins` : `+`\n- Ajout d'un mapper pour ce client : `clients` =\u003e `minio` =\u003e `client scopes` =\u003e `minio-dedicated` =\u003e `configure a new mapper` =\u003e `hardcoded claim` :  \n   _ Name: `stsonly`\n  _ Token claim name: `policy` \\* Claim value : `stsonly`  \n  Console disponible sur [https://minio-console.devoxx.insee.io](https://minio-console.devoxx.insee.io)\n\nIntégration avec Onyxia :\n\n- Création d'un client `onyxia-minio`, `Root URL` : `https://datalab.devoxx.insee.io`, `Valid redirect URIs` : `https://datalab.devoxx.insee.io/*`, `Web origins` : `+`\n- Ajout d'un mapper pour ce client : `clients` =\u003e `onyxia-minio` =\u003e `client scopes` =\u003e `minio-dedicated` =\u003e `configure a new mapper` =\u003e `hardcoded claim` :\n  - Name: `stsonly`\n  - Token claim name: `policy`\n  - Claim value : `stsonly`\n- Ajout d'une audience spécifique pour ce client : `clients` =\u003e `onyxia-minio` =\u003e `client scopes` =\u003e `onyxia-minio-dedicated` =\u003e `add mapper by configuration` =\u003e `audience` :\n  - Name: `audience-minio`\n  - Included Custom Audience : `minio`\n  - Add to ID token: `true`\n- `cd manifests/onyxia-s3-minio`, `helm dependencies build`, `helm upgrade onyxia . -f values.yaml -n onyxia`\n\nMinio intégré dans Onyxia :)\n\n## Catalogue de services\n\n### `Théorie`\n\nFonctionnement du catalogue (J)\n\n## Gestion des secrets\n\n### `Théorie`\n\nLa gestion des secrets avec Vault (F)\n\n### `Pratique`\n\nhttps://github.com/InseeFrLab/onyxia/tree/main/step-by-step#configuring-keycloak-for-vault\n\n## Customisation\n\n### `Théorie`\n\nDesign, cohérence de l'expérience utilisateur ... (J)\n\n### `Pratique`\n\nhttps://www.keycloakify.dev/\n\n## Bonus\n\n- [Catalogue de formations](https://www.sspcloud.fr/formation)\n- [Gitops avec argocd](https://argo-cd.readthedocs.io/en/stable/)\n- [Monitoring / billing](https://github.com/opencost/opencost)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finseefrlab%2Fdevoxx-2023","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finseefrlab%2Fdevoxx-2023","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finseefrlab%2Fdevoxx-2023/lists"}