{"id":5967,"date":"2025-03-04T09:41:44","date_gmt":"2025-03-04T08:41:44","guid":{"rendered":"https:\/\/gpmfactory.com\/?p=5967"},"modified":"2025-03-04T17:58:20","modified_gmt":"2025-03-04T16:58:20","slug":"pool-dinstances-apex-sous-kubernetes","status":"publish","type":"post","link":"https:\/\/gpmfactory.com\/index.php\/2025\/03\/04\/pool-dinstances-apex-sous-kubernetes\/","title":{"rendered":"Pool d\u2019instances APEX sous Kubernetes"},"content":{"rendered":"\n<p>V1.0 \u2013 mars 2025<\/p>\n\n\n\n<p>Cet article rassemble mes notes et remarques pour la mise en place d\u2019un pool d\u2019instances Oracle APEX dans un cluster Kubernetes (k8s).<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Pr\u00e9ambule<\/h1>\n\n\n\n<p>Demander une douzaine d\u2019APEX comme on passe commande d\u2019un plateau de fruits de mer, c\u2019est un peu la promesse de Kubernetes, sans compter que <em>K8s<\/em> est un \u00ab&nbsp;Terminator&nbsp;\u00bb qui va jusqu\u2019au bout de son contrat.<\/p>\n\n\n\n<p>Mon objectif \u00e9tait de b\u00e2tir, \u00e0 partir du produit <em>Oracle Database 23ai Free<\/em>, une solution Oracle APEX sans couts de licence, capable de supporter un tr\u00e8s grand nombre d\u2019utilisateurs. Pour r\u00e9sumer&nbsp;: une Database \u00ab&nbsp;applicative&nbsp;\u00bb et une arm\u00e9es d\u2019&nbsp;Oracle APEX en frontal.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Pourquoi un pool d\u2019instances Oracle APEX&nbsp;?<\/h1>\n\n\n\n<p>Quand on souhaite utiliser Oracle APEX \u00e0 une large \u00e9chelle, il faut adapter les ressources en cons\u00e9quence et cela conduit \u00e0 utiliser un serveur de plus en plus puissant. Cette augmentation \u00e9limine au passage tout recours \u00e0 des licences Oracle Database de type <em>free<\/em> en raison des limitations de ces versions (2Go RAM, 2 cores, 12 Go disk \u2026) mais \u2026 il existe des cas de figure o\u00f9 Oracle APEX peut \u00eatre utilis\u00e9 de fa\u00e7on partitionn\u00e9e, c\u2019est-\u00e0-dire plusieurs <strong>instances APEX ind\u00e9pendantes<\/strong> acc\u00e9dant \u00e0 une m\u00eame Database de donn\u00e9es via des DB Links par exemple, ou via des API REST.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Rappel sur la plateforme de d\u00e9veloppement Oracle APEX<\/h2>\n\n\n\n<p>Le produit Oracle APEX est une plateforme de d\u00e9veloppement dont les pr\u00e9requis sont :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Une Database Oracle avec une licence payante ou gratuite, <em>on-premis<\/em>e ou bien en cloud. Une Database Oracle est obligatoire dans tous les cas.<\/li>\n\n\n\n<li>Le produit Oracle ORDS, dont la licence est gratuite. Il s\u2019agit d\u2019un serveur qui embarque <em>Jetty<\/em>, un serveur web et container de servlets assurant la communication entre les requ\u00eates http et le code PL\/SQL constituant Oracle APEX.<\/li>\n\n\n\n<li>Le code Oracle APEX qui se compose de divers objets \u00e0 installer dans la Database. Sa licence est gratuite.<\/li>\n<\/ul>\n\n\n\n<p>Une <strong>instance APEX<\/strong> correspond \u00e0 l\u2019installation physique du code APEX dans une Database. Une instance peut h\u00e9berger des&nbsp;espaces logiques de travail appel\u00e9s <em>workspaces<\/em>. Les d\u00e9veloppeurs et les utilisateurs travailleront toujours dans le contexte d\u2019un <em>workspace<\/em>.<\/p>\n\n\n\n<p>Habituellement, l\u2019instance APEX et &nbsp;les donn\u00e9es applicatives sont colocalis\u00e9es dans la m\u00eame Database et de ce fait, une question int\u00e9ressante est de savoir comment se r\u00e9partit la consommation de ressources. En effet, il y a l\u2019activit\u00e9 relative \u00e0 la manipulation des donn\u00e9es applicatives et puis celle qui est sp\u00e9cifique au fonctionnement d\u2019APEX (acc\u00e8s aux metadata et g\u00e9n\u00e9ration dynamique des pages). Si l\u2019on s\u00e9pare l\u2019activit\u00e9 d\u2019APEX de celle li\u00e9e aux DATA applicatives, la mise a l\u2019\u00e9chelle pourra \u00eatre r\u00e9alis\u00e9e de fa\u00e7on plus rationnelle.<\/p>\n\n\n\n<p>Voici quelques cas d\u2019usage pour notre pool APEX&nbsp;:&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>D\u00e9marrer rapidement un grand nombre d\u2019instances APEX, y d\u00e9ployer une ou plusieurs applications et acc\u00e9der \u00e0 une Database commune pour les data applicatives partag\u00e9es.<\/li>\n\n\n\n<li>Organiser un atelier de formation avec plusieurs centaines de participants<\/li>\n\n\n\n<li>Lancer une application <em>online<\/em> sur internet sans avoir une connaissance exacte de l\u2019audience attendue et pouvoir r\u00e9agir rapidement pour adapter les ressources. Par exemple, dans le cas d\u2019une application que j\u2019avais faite r\u00e9cemment, <em>Quiz Louvre<\/em>, cette architecture convient tr\u00e8s bien car il n\u2019y a aucune donn\u00e9e partag\u00e9e, l\u2019application est en <em>read-only<\/em> et cela devient simple de <em>scaler<\/em> horizontalement.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Approche et choix techniques<\/h1>\n\n\n\n<p>Je me suis impos\u00e9 la contrainte de n\u2019utiliser que les licences gratuites disponibles chez Oracle tout en sachant les limitations d\u2019Oracle Database <em>Free&nbsp;:<\/em><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Se limite automatiquement \u00e0 2 cores, 2 Go RAM et 12 Go disque<\/li>\n\n\n\n<li>Une seule installation par <em>node<\/em> (ou vm)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Contenu d\u2019un <em>pod<\/em><\/h2>\n\n\n\n<p>Dans l\u2019approche initiale, j\u2019ai consid\u00e9r\u00e9 que le tandem \u00ab&nbsp;database d\u00e9di\u00e9e \u00e0 APEX + ORDS&nbsp;\u00bb constituait l\u2019entit\u00e9 qui ferait l\u2019objet de la <em>clusterisation<\/em>. Je n\u2019ai donc pas fait un d\u00e9coupage entre la database APEX d\u2019une part et plusieurs ORDS en frontal d\u2019autre part. Par cons\u00e9quent, le <em>pod <\/em>(au sens Kubernetes) relatif \u00e0 l\u2019activit\u00e9 APEX est constitu\u00e9 de deux containers&nbsp;:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>free<\/em> utilis\u00e9 pour la Database APEX<\/li>\n\n\n\n<li><em>ords-developer<\/em> utilis\u00e9 pour ORDS.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Sch\u00e9ma simplifi\u00e9 du cluster<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"841\" height=\"632\" src=\"https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/Capture-decran-2025-03-03-221621.png\" alt=\"\" class=\"wp-image-5970\" srcset=\"https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/Capture-decran-2025-03-03-221621.png 841w, https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/Capture-decran-2025-03-03-221621-300x225.png 300w, https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/Capture-decran-2025-03-03-221621-768x577.png 768w\" sizes=\"auto, (max-width: 841px) 100vw, 841px\" \/><\/figure>\n\n\n\n<p>Dans le sch\u00e9ma ci-dessus, Les <em>pods<\/em> sont mat\u00e9rialis\u00e9s par une boite de couleur grise. la database DATA est de type <em>free<\/em>. Elle pr\u00e9sente des limitations, comme indiqu\u00e9 pr\u00e9c\u00e9demment, mais cette database DATA peut tr\u00e8s bien \u00eatre une database Oracle avec une licence de type Standard ou Enterprise, et se situer dans un environnement <em>on-premise<\/em> ou sur le cloud. APEX communiquera avec la database DATA via un database link.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Mise en place du cluster<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Etapes pour cr\u00e9er un pool de pods APEX et un pod DB centrale (DATA)<\/h2>\n\n\n\n<p>J\u2019ai test\u00e9 le concept chez OVH en utilisant leur support de Kubernetes.<\/p>\n\n\n\n<p>Les <em>nodes<\/em> sont de type&nbsp;D2-8 (4 CPU 8 GB RAM 50 GB disk)<\/p>\n\n\n\n<p>Remarque&nbsp;: La configuration D2-4 (2 CPU 4 GB RAM 50 GB disk n\u2019est pas adapt\u00e9e car le <em>pod<\/em> sort en status \u00ab&nbsp;<em>evicted<\/em>&nbsp;\u00bb au bout de quelques secondes (m\u00e9moire insuffisante&nbsp;?).<\/p>\n\n\n\n<p>Cf tableau des couts pour avoir une estimation du budget<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Etapes pr\u00e9liminaires au niveau d\u2019OVH<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Cr\u00e9er un cluster Kubernetes<\/li>\n\n\n\n<li>Ajouter un pool&nbsp; de plusieurs <em>nodes<\/em><\/li>\n\n\n\n<li>Lab\u00e9liser les <em>nodes<\/em>&nbsp;: (n-1) de type <em>front<\/em> et un seul de type <em>back<\/em> (cf script en PowerShell nodes.ps1)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Choix des images pour les containers<\/h3>\n\n\n\n<p>Afin de limiter les taches de setup, je m\u2019appuie sur les images docker suivantes <a href=\"https:\/\/container-registry.oracle.com\/\">deux images docker qui sont fournies par oracle<\/a>&nbsp;:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>free 23ai<\/em><\/li>\n<\/ul>\n\n\n\n<p>Je pr\u00e9f\u00e8re prendre <em>free 23ai<\/em> plut\u00f4t que <em>express<\/em> car <em>free23ai<\/em>, parmi ses fonctionnalit\u00e9s nouvelles,&nbsp;\u00e9limine le besoin de g\u00e9rer un wallet db pour acc\u00e9der \u00e0 des ressources web et c\u2019est un tr\u00e8s grand avantage. Parmi les variantes, il faut choisir <em>full<\/em>. La version <em>Lite<\/em> rend l\u2019installation d\u2019APEX impossible car il manque des packages.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>ords-developer<\/em><br>Il s\u2019agit de l\u2019image qui&nbsp; se charge de l\u2019installation d\u2019APEX, \u00e0 la diff\u00e9rence de celle qui s\u2019appelle <em>ords<\/em> et qui n\u2019installe que la partie ords.<\/li>\n<\/ul>\n\n\n\n<p>Pour l\u2019image <em>free<\/em>, j\u2019ai choisi de la faire d\u00e9marrer avec sa base \u00abpre-built\u00bb.<\/p>\n\n\n\n<p>Pour la base centrale, il s\u2019agit d\u2019un singleton qui pourrait \u00eatre d\u00e9ploy\u00e9e sous forme de <em>ReplicaSet<\/em> avec un niveau r\u00e9plica=1 mais dans mon cas, j\u2019ai choisi l\u2019option <em>statefulSet<\/em> (nom DNS stable m\u00eame apr\u00e8s un red\u00e9marrage). Cf db.yaml<\/p>\n\n\n\n<p>Comme chaque <em>pod<\/em> d\u00e9di\u00e9 \u00e0 APEX doit \u00eatre d\u00e9ploy\u00e9 <strong>une seule fois<\/strong> sur chacun des trois <em>nodes<\/em> poss\u00e9dant le label \u00ab\u00a0front\u00a0\u00bb, j\u2019ai choisi un type <em>Daemonset<\/em>. Un s\u00e9lecteur installe le pod sur tous les <em>nodes<\/em> poss\u00e9dant le label \u00ab\u00a0front\u00a0\u00bb. \u00a0cf pod-apex.yaml et le script nodes.ps1.<br>Si on choisit un type ReplicaSet ou Deployement, le controleur k8s peut \u00eatre amen\u00e9 \u00e0 instancier deux pods sur le m\u00eame node.<\/p>\n\n\n\n<p>Ensuite, on cr\u00e9e un service nomm\u00e9 \u00ab&nbsp;apex&nbsp;\u00bb de type clusterIP qui s\u2019appliquera \u00e0 tous les pods pod-apex instanci\u00e9s. Cf apex.yaml. Je ne l\u2019ai pas cr\u00e9\u00e9 de type LoadBalancer car cette t\u00e2che sera accomplie par un <em>ingress<\/em> et c\u2019est au niveau de cet <em>ingress<\/em> que l\u2019on demandera de l\u2019affinit\u00e9 de session.<\/p>\n\n\n\n<p>Ajouter un Nginx Ingress Controller au cluster k8s.<\/p>\n\n\n\n<p><a href=\"https:\/\/help.ovhcloud.com\/csm\/fr-public-cloud-kubernetes-install-nginx-ingress?id=kb_article_view&amp;sysparm_article=KB0055171\">OVH fournit un chart Helm<\/a> pour r\u00e9aliser cette op\u00e9ration.<\/p>\n\n\n\n<p>Cr\u00e9er un ingress cf Ingress.yaml<\/p>\n\n\n\n<p>Ici je demande de l\u2019affinit\u00e9 de session bas\u00e9e sur la pr\u00e9sence d\u2019un cookie qui est enti\u00e8rement g\u00e9r\u00e9 par Ingress et que j\u2019ai nomm\u00e9 \u00ab&nbsp;kub-apex&nbsp;\u00bb.<\/p>\n\n\n\n<p>J\u2019avais tent\u00e9 d\u2019utiliser un service de type <em>LoadBalancer<\/em> mais je ne suis pas parvenu \u00e0 obtenir un niveau satisfaisant d\u2019affinit\u00e9 de session. Le seul mode qui fonctionnait \u00e9tait l\u2019affinit\u00e9 d\u2019adresse IP, ce qi ne me convenait pas enti\u00e8rement puisque je voulais des <em>sticky sessions<\/em> bas\u00e9es sur la valeur d\u2019un cookie.<\/p>\n\n\n\n<p>Au bout d\u2019un quart d\u2019heure (parfois une demi-heure) le cluster est op\u00e9rationnel. On peut d\u00e9marrer encore plus vite comme c\u2019est discut\u00e9 plus loin.<\/p>\n\n\n\n<p>R\u00e9cup\u00e9rer l\u2019adresse IP du contr\u00f4leur Ingress&nbsp;:<\/p>\n\n\n\n<p>kubectl get svc ingress-nginx-controller -n ingress-nginx -o &nbsp;wide<\/p>\n\n\n\n<p>Produits tierces utiles<\/p>\n\n\n\n<p>Le <a href=\"https:\/\/k8slens.dev\/\">produit Lens de Mirantis <\/a>&nbsp;pour disposer d\u2019&nbsp;un tableau de bord permettant de visualiser d\u2019un coup d\u2019\u0153il l\u2019\u00e9tat des ressources du cluster Kubernetes. Sinon, il faut enchainer \u00e0 l\u2019infini des commandes kubectl.<\/p>\n\n\n\n<p>Ci-dessous la console Lens montrant l\u2019\u00e9tat des dix pods lanc\u00e9s sur le cluster. Un pod pour DB DATA et neuf pods APEX.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"937\" height=\"360\" src=\"https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/image-1.png\" alt=\"\" class=\"wp-image-5969\" srcset=\"https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/image-1.png 937w, https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/image-1-300x115.png 300w, https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/image-1-768x295.png 768w\" sizes=\"auto, (max-width: 937px) 100vw, 937px\" \/><\/figure>\n\n\n\n<p>R\u00e9sum\u00e9 de l\u2019ordre de lancement des fichiers yaml&nbsp;:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Tache<\/strong><strong><\/strong><\/td><td><strong>Commande<\/strong><strong><\/strong><\/td><td><strong>Ordre<\/strong><strong><\/strong><\/td><\/tr><tr><td>Affecter label aux nodes<\/td><td>Powsershell label_nodes.ps1<\/td><td>1<\/td><\/tr><tr><td>Cr\u00e9er les secrets<\/td><td>Kubectl create secret ords-secret<\/td><td>2<\/td><\/tr><tr><td>Cr\u00e9er les CongigMaps<\/td><td>kubectl create configmap \u2026<\/td><td>3<\/td><\/tr><tr><td>Cr\u00e9er DB DATA<\/td><td>Kubectl apply -f db.yaml<\/td><td>4<\/td><\/tr><tr><td>Cr\u00e9er les pod Apex<\/td><td>Kubectl apply -f pod-apex.yaml<\/td><td>5<\/td><\/tr><tr><td>Cr\u00e9er le service Apex<\/td><td>Kubectl apply -f apex-run.yaml<\/td><td>6<\/td><\/tr><tr><td>Cr\u00e9er le Ingress<\/td><td>Kubectl apply -f ingress-run.yaml<\/td><td>7<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>On suppose que le <em>Ingress Controler<\/em> a d\u00e9j\u00e0 \u00e9t\u00e9 ajout\u00e9 juste apr\u00e8s la cr\u00e9ation du cluster K8s.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Remarque \u00e0 propos des d\u00e9pendances entre containers&nbsp;:<\/h3>\n\n\n\n<p>L\u2019image ords-developer v\u00e9rifie au startup la pr\u00e9sence d\u2019un fichier conn_string.txt et teste une connexion bas\u00e9e sur la chaine qui se trouve \u00e0 l\u2019int\u00e9rieur de ce fichier. Si cela \u00e9choue, la cr\u00e9ation du container est abandonn\u00e9e. Dans <em>Docker compose<\/em> il existe une directive qui permet de pr\u00e9ciser quelle est la condition de d\u00e9marrage, mais pas dans Kubernetes. J\u2019ai choisi donc de ne pas avoir recours \u00e0 un container interm\u00e9diaire mais plut\u00f4t de laisser faire la nature. C\u2019est \u00e0 dire que le contr\u00f4leur K8S&nbsp;, dont il faut saluer l\u2019opini\u00e2tret\u00e9, fera autant de tentatives qu\u2019il est &nbsp;n\u00e9cessaire jusqu\u2019\u00e0 ce que la BD soit pr\u00eate \u00e0 recevoir des connexions. C\u2019est la raison pour laquelle on observera un nombre de <em>restart<\/em> de l\u2019ordre de 2 ou 3. Cela est sans cons\u00e9quence.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Diminuer le temps de d\u00e9marrage de la plateforme APEX<\/h3>\n\n\n\n<p>Pour un chargement plus rapide, il est int\u00e9ressant de pr\u00e9alimenter la base APEX avec les objets sp\u00e9cifiques \u00e0 APEX. Cette op\u00e9ration dure en effet une quinzaine de minutes.<\/p>\n\n\n\n<p>Apr\u00e8s avoir fait un <em>commit<\/em> du container de DB Apex dans son \u00e9tat \u00ab&nbsp;install\u00e9e, j\u2019ai obtenu un nouvelle image que j\u2019ai pouss\u00e9e sur un registre priv\u00e9 chez OVH.<\/p>\n\n\n\n<p>Un d\u00e9ploiement de la configuration pod-apex ne prend alors que &nbsp;moins de deux minutes au lieu de quinze. A chaque nouvelle version de l\u2019image ords-developer, il faudra r\u00e9g\u00e9n\u00e9rer cette image pour conserver l\u2019avantage de gain de temps.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Mode de routage vers le pool en fonction du sc\u00e9nario<\/h3>\n\n\n\n<p>Lorsqu\u2019il s\u2019agit d\u2019un sc\u00e9nario de d\u00e9ploiement d\u2019une application, c\u2019est-\u00e0-dire un contexte dans lequel c\u2019est essentiellement le runtime d\u2019APEX qui sera sollicit\u00e9, alors on privil\u00e9giera un load balancing bas\u00e9 sur l\u2019affinit\u00e9 de session. Ici, l\u2019objectif est de garantir l\u2019utilisation la plus sym\u00e9trique possible et ce n\u2019est pas l\u2019utilisateur qui choisit son pod.<\/p>\n\n\n\n<p>S\u2019il s\u2019agit en revanche d\u2019un sc\u00e9nario o\u00f9 l\u2019on utilise les capacit\u00e9s de d\u00e9veloppement d\u2019APEX, alors il est primordial de pouvoir travailler dans la dur\u00e9e sur une instance (dur\u00e9e \u00e9lev\u00e9e de cookie) ou mieux, connaitre l\u2019instance sur laquelle on travaille, de fa\u00e7on \u00e0 pouvoir y revenir ult\u00e9rieurement \u00e0 partir d\u2019un autre <em>device,<\/em> par exemple. Ici, on cr\u00e9era autant de services qu\u2019il y a de <em>pods<\/em> et on fixera des r\u00e8gles de routage au niveau de l\u2019Ingress, bas\u00e9es sur le nom de host virtuel. Par exemple, http:\/host1.mydomain\/ords\/apex sera rout\u00e9e syst\u00e9matiquement vers le service associ\u00e9 au pod_1 et http:\/host1.mydomain\/ords\/apex sera dirig\u00e9 vers pod_2., etc. Cela implique donc de cr\u00e9er des noms de host au niveau de son DNS.<br>Sinon, il faudra cr\u00e9er des services de type NodePort, r\u00e9cup\u00e9rer les adresses IP affect\u00e9s et utiliser ces adresses distinctes dans l\u2019url.<\/p>\n\n\n\n<p>J\u2019ai essay\u00e9 d\u2019utiliser un routage bas\u00e9 sur un path d\u2019url mais je n\u2019ai pas obtenu de r\u00e9sultat correct.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Scripts <em>custom<\/em> ajout\u00e9s dans le container ords-developer<\/h3>\n\n\n\n<p>Afin de disposer d\u2019une instance la plus op\u00e9rationnelle possible, j\u2019ai rajout\u00e9 plusieurs scripts qui r\u00e9alisent les taches additionnelles suivantes&nbsp;:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Cr\u00e9ation d\u2019un workspace par d\u00e9faut qui s\u2019appelle DEMO<\/li>\n\n\n\n<li>Ajouts des ACL pour permettre un acc\u00e8s \u00e0 des ressources externes sur internet depuis une application APEX.<\/li>\n\n\n\n<li>Ajout d\u2019une banni\u00e8re avec le nom du <em>node<\/em> pour identifier rapidement sur quelle instance on se situe<\/li>\n\n\n\n<li>Modification de certaines directives ORDS dans le cas d\u2019une utilisation d\u2019Ingress en proxy https.<\/li>\n\n\n\n<li>Cr\u00e9ation d\u2019un <em>database Link<\/em> vers la base DATA<\/li>\n\n\n\n<li>Import optionnel d\u2019une application APEX existante<\/li>\n<\/ul>\n\n\n\n<p>Tous les scripts sh et sql sont enregistr\u00e9s dans un configmap (ords-configmap) qui est mont\u00e9 comme un volume et mapp\u00e9 sur un r\u00e9pertoire. Pour rappel, la taille maximale d\u2019un configMap est de 1 Mo.<\/p>\n\n\n\n<p>La banni\u00e8re de type \u00ab&nbsp;instance&nbsp;\u00bb est cr\u00e9\u00e9e \u00e0 partir d\u2019un api plsql fournie avec APEX. On prend le nom du node ainsi que son num\u00e9ro d\u2019index qui servira pour fixer une couleur arbitraire entre 1et 16.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"944\" height=\"497\" src=\"https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/image.png\" alt=\"\" class=\"wp-image-5968\" srcset=\"https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/image.png 944w, https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/image-300x158.png 300w, https:\/\/gpmfactory.com\/wp-content\/uploads\/2025\/03\/image-768x404.png 768w\" sizes=\"auto, (max-width: 944px) 100vw, 944px\" \/><\/figure>\n\n\n\n<p>Ci-dessous, une r\u00e9p\u00e9tition de connexions dans des <em>Private Wind<\/em>ows a abouti \u00e0 neuf sessions sur chacun des neuf pods APEX disponibles.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Authentification<\/h3>\n\n\n\n<p>Chaque Workspace poss\u00e8de son annuaire d\u2019utilisateurs autoris\u00e9s \u00e0 se connecter. Dans le cas d\u2019un pool, il sera plus pertinent de d\u00e9l\u00e9guer la phase d\u2019authentification \u00e0 un module tiers, comme un annuaire LDAP, par exemple ou un OAUTH.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">TLS<\/h3>\n\n\n\n<p>Je n\u2019ai pas mis en place TLS dans mon prototype.<\/p>\n\n\n\n<p>Les \u00e9tapes sont d\u00e9crites dans un <a href=\"https:\/\/help.ovhcloud.com\/csm\/en-public-cloud-kubernetes-secure-nginx-ingress-cert-manager?id=kb_article_view&amp;sysparm_article=KB0049952\">document OVH<\/a>.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Couts de fonctionnement<\/h1>\n\n\n\n<p>Pour trois instances APEX et une base partag\u00e9e, voici les couts minimums escompt\u00e9s en euros avec une projection pour une dur\u00e9e d\u2019une journ\u00e9e de dix heures ou une dur\u00e9e d\u2019un mois .<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>El\u00e9ment<\/strong><\/td><td><strong>Description<\/strong><\/td><td><strong>Nombre<\/strong><\/td><td><strong>Tarif horaire<\/strong><\/td><td><strong>Tarif<\/strong> <strong>mensuel<\/strong><\/td><td><strong>Montant \/heure<\/strong><\/td><td><strong>Montant<\/strong> <strong>\/jour<\/strong><\/td><td><strong>Montant \/mois<\/strong><\/td><\/tr><tr><td><strong>Nodes<\/strong><\/td><td>D2-8 (4 CPU 8 GB RAM 50 GB disk)<\/td><td>4<\/td><td>0,0357<\/td><td>19,8<\/td><td>0,1428<\/td><td>1,428<\/td><td>79,2<\/td><\/tr><tr><td><strong>Load Balancer<\/strong><\/td><td>Size Small<\/td><td>1<\/td><td>0,0083<\/td><td>6,059<\/td><td>0,0083<\/td><td>0,083<\/td><td>6,059<\/td><\/tr><tr><td><strong>Adresse IP<\/strong><\/td><td>Adresse IP<\/td><td>1<\/td><td>0,0025<\/td><td>1,5<\/td><td>0,0025<\/td><td>0,025<\/td><td>1,5<\/td><\/tr><tr><td><strong>Registry (*)<\/strong><\/td><td>200 Go, 15 connexions<\/td><td>1<\/td><td>0,0237<\/td><td><\/td><td>0,0237<\/td><td>0,237<\/td><td>17,064<\/td><\/tr><tr><td><strong>TOTAL<\/strong><\/td><td><\/td><td><\/td><td><\/td><td><\/td><td>0,1536<\/td><td>1,536<\/td><td>103,823<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>* La Registry est optionnelle.<\/p>\n\n\n\n<p>Les <em>nodes<\/em> qui ont \u00e9t\u00e9 utilis\u00e9s chez OVH sont r\u00e9f\u00e9renc\u00e9s dans la cat\u00e9gorie <em>Discovery<\/em>, ce qui signifie que leur cout horaire est attractif mais que leurs performances peuvent \u00eatre variables. Ces <em>shapes<\/em> sont id\u00e9ales pour faire des tests.<\/p>\n\n\n\n<p>Pour un sc\u00e9nario avec un nombre raisonnable d\u2019utilisateurs (une cinquantaine&nbsp;?), l\u2019offre Oracle nomm\u00e9e &nbsp;<em><a href=\"https:\/\/www.oracle.com\/fr\/application-development\/apex\/pricing\/\">Oracle APEX Service<\/a><\/em> est plut\u00f4t comp\u00e9titive (122 USD\/mois \u00e0 la date de mars 2025).<\/p>\n\n\n\n<p>En <em>compute<\/em>, une instance Oracle \u00e9quivalente VM.Standard.E4.Flex (2 OCPU, 8 Go RAM, 100 Go disk) revient \u00e0 46,85 euros\/mois. Comparable \u00e0 la B2-15 de chez OVH qui est \u00e0 46,20 \u20ac\/mois. Celle que j\u2019ai utilis\u00e9e chez OVH &nbsp;est une instance de cat\u00e9gorie Discovery, donc moins pr\u00e9dictible qu\u2019une B2-15.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Fichiers de configuration<\/h1>\n\n\n\n<p>J\u2019ai regroup\u00e9 les fichiers principaux. <a href=\"https:\/\/github.com\/patrickmonaco\/pool-apex-k8s\">Ces fichiers sont \u00e9galement accessibles depuis github<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Quelques liens utiles<\/h2>\n\n\n\n<p>Livre \u00ab&nbsp;Kubernetes&nbsp;\u00bb &nbsp;2ieme \u00e9dition de Kelsey Hightower, Brendan Burns ,Joe Beda et Lachlan Everson<\/p>\n\n\n\n<p>Je remercie mon tuteur ChatGPT pour la mise au point des fichiers de configuration, le debug de toutes les mis\u00e8res rencontr\u00e9es ainsi que pour m\u2019avoir aid\u00e9 dans la compr\u00e9hension g\u00e9n\u00e9rale de Kubernetes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>V1.0 \u2013 mars 2025 Cet article rassemble mes notes et remarques pour la mise en place d\u2019un pool d\u2019instances Oracle APEX dans un cluster&#8230;<\/p>\n","protected":false},"author":1,"featured_media":5973,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"ppma_author":[150],"class_list":["post-5967","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-non-classe"],"authors":[{"term_id":150,"user_id":1,"is_guest":0,"slug":"admin8700","display_name":"Patrick","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/209d5ed69b74d288390621ab4c1d3773?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/posts\/5967","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/comments?post=5967"}],"version-history":[{"count":2,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/posts\/5967\/revisions"}],"predecessor-version":[{"id":5975,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/posts\/5967\/revisions\/5975"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/media\/5973"}],"wp:attachment":[{"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/media?parent=5967"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/categories?post=5967"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/tags?post=5967"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/ppma_author?post=5967"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}