Le but de cette série de billets est de montrer comment on peut simplement, facilement et gratuitement (à partir du moment ou vous avez un ordinateur suffisamment performant pour développer) faire du Kubernetes et déployer des applications conteneurisées. Et concernant ces dernières, je montrerai en quoi Quarkus est le candidat idéal (A Kubernetes Native Java stack).
Lors du précédent article, nous avons vu comment installer et configurer un Microk8s single-node et multi-node, le but à présent est de déployer dans Microk8s.
Cette seconde partie sera plus focus sur Quarkus et nous allons voir comment déployer une application Quarkus avec une base de donnée PosgreSQL dans notre Microk8s précédemment installé et configuré lors de la part1.
Note : vous pouvez travailler avec n’importe quel cluster Kubernetes, il faut juste pour cela que votre cli kubectl soit bien configuré en local. Dans cet article les exemples se base sur l’utilisation d’un Microk8s single node.
PostgreSQL
Commençons par installer la BDD PostgreSQL, au préalable il nous faut récupérer le code sur github, dans le répertoire /microk8s vous trouverez tous les fichiers de déploiement k8s nécessaires.
Pour rappel il vous faut d’abord avoir bien créer le namespace quarkus-apero-code, si ce n’est pas fait vous pouvez jouer la commande suivante à la racine du projet github (en ayant pensé aussi à monter un volume à l’aide de Multipass, voir article précédent)
1 2 |
$ kubectl apply -f microk8s/k8s/namespace/apero-code-ns.yaml namespace/quarkus-apero-code created |
A présent jouons le fichier de déploiement de notre BDD à l’aide de la commande kubectl apply
1 2 3 4 5 6 7 |
$ kubectl apply -f microk8s/db/postgresql/postgresql-deployment.yaml configmap/postgres-config created secret/postgres-secret created persistentvolume/postgres-pv-new unchanged persistentvolumeclaim/postgres-claim created deployment.apps/postgres created service/postgres created |
Vérifions que notre BDD est bien déployée et fonctionnelle en accédant au dashboard k8s en naviguant à https://192.168.64.2:10443
Tout est au vert, nous avons déployé une base de données Postgresql que nous allons pouvoir utiliser avec Quarkus dans notre kube, attaquons-nous à présent à notre application Quarkus que nous déploierons dans Microk8s
Quarkus
Génération de l’application
L’initialisation du projet a été fait en ligne de commande (mais vous pouvez aussi vous appuyer sur le generator Quarkus) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
$ mvn io.quarkus:quarkus-maven-plugin:1.13.2.Final:create \ > -DprojectGroupId=org.acme \ > -DprojectArtifactId=kubernetes-quickstart \ > -DclassName="org.acme.rest.GreetingResource" \ > -Dpath="/greeting" \ > -Dextensions="quarkus-kubernetes, quarkus-container-image-docker" [INFO] Scanning for projects... [INFO] [INFO] ------------------< org.apache.maven:standalone-pom >------------------- [INFO] Building Maven Stub Project (No POM) 1 [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- quarkus-maven-plugin:1.13.3.Final:create (default-cli) @ standalone-pom --- ----------- selected extensions: - io.quarkus:quarkus-kubernetes - io.quarkus:quarkus-container-image-docker applying codestarts... 🔠 java 🧰 maven 🗃 quarkus 📜 config-properties 🛠 dockerfiles 🛠 maven-wrapper 🐒 resteasy-example ----------- [SUCCESS] ✅ quarkus project has been successfully generated in: --> /Users/coloneld/dev/git/sedona/apero-code/working/kubernetes-quickstart ----------- [INFO] [INFO] ======================================================================================== [INFO] Your new application has been created in /Users/coloneld/dev/git/sedona/apero-code/working/kubernetes-quickstart [INFO] Navigate into this directory and launch your application with mvn quarkus:dev [INFO] Your application will be accessible on http://localhost:8080 [INFO] ======================================================================================== [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.792 s [INFO] Finished at: 2021-05-04T18:13:50+02:00 [INFO] ------------------------------------------------------------------------ |
J’ai par la suite enrichi ce projet avec les extensions kotlin pour le language de programmation, quarkus-jdbc-h2 pour le connecteur jdbc de la base h2 (pour le dev et les tests unitaires), quarkus-jdbc-postgresql pour le connnecteur jdbc de postgresql (pour Microk8s) et enfin quarkus-hibernate-orm-panache-kotlin pour utiliser notre ORM favori avec la ligne de commande suivante :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ cd kubernetes-quickstart $ mvn quarkus:add-extension -Dextensions=kotlin,quarkus-jdbc-h2,quarkus-jdbc-postgresql,quarkus-hibernate-orm-panache-kotlin [INFO] Scanning for projects... [INFO] [INFO] -------------------< org.acme:kubernetes-quickstart >------------------- [INFO] Building kubernetes-quickstart 1.0.0-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- quarkus-maven-plugin:1.13.3.Final:add-extension (default-cli) @ kubernetes-quickstart --- [SUCCESS] ✅ Extension io.quarkus:quarkus-hibernate-orm-panache-kotlin has been installed [SUCCESS] ✅ Extension io.quarkus:quarkus-jdbc-postgresql has been installed [SUCCESS] ✅ Extension io.quarkus:quarkus-kotlin has been installed [SUCCESS] ✅ Extension io.quarkus:quarkus-jdbc-h2 has been installed [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.626 s [INFO] Finished at: 2021-05-04T18:19:21+02:00 [INFO] ------------------------------------------------------------------------ |
J’ai ensuite développé les services REST (Resource) et la couche de persistance (Repository) pour exposer les données de la base via des apis.
Lançons l’application
Enfin, notre application développée, je vais d’abord m’assurer que tout est OK en la testant en local de la manière suivante
1 2 3 4 5 6 7 8 9 10 11 |
$ ./mvnw compile quarkus:dev ... __ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 2021-05-04 16:59:59,529 WARN [io.qua.hib.orm.run.pro.ProxyDefinitions] (Quarkus Main Thread) Could not generate an enhanced proxy for entity 'org.acme.beer.domain.Beer' (class='org.acme.beer.domain.Beer') as it's final. Your application might perform better if we're allowed to extend it. 2021-05-04 17:00:00,100 INFO [io.quarkus] (Quarkus Main Thread) kubernetes-quickstart 1.0.0-SNAPSHOT on JVM (powered by Quarkus 1.13.3.Final) started in 2.537s. Listening on: http://localhost:2000 2021-05-04 17:00:00,102 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated. 2021-05-04 17:00:00,102 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache-kotlin, jdbc-h2, jdbc-postgresql, kotlin, kubernetes, kubernetes-client, mutiny, narayana-jta, resteasy, resteasy-jackson, smallrye-context-propagation] ^C2021-05-04 18:00:43,721 INFO [io.quarkus] (Shutdown thread) kubernetes-quickstart stopped in 0.014s |
L’application est bien démarrée en moins de trois secondes et écoute sur le port 2000, vérifions qu’elle répond correctement allant sur http://localhost:2000
et vérifions que l’accès à la base H2 se fait bien en allant sur http://localhost:2000/beers
Déploiement de l’application
A présent je sais que mon application fonctionne bien en local, je vais compiler, tester, packager, déployer nos images docker dans un registry et déployer dans k8s via les lignes de commande ci-dessous
1 2 |
$ cd kubernetes-quickstart $ ./mvnw package -Dquarkus.profile=microk8s -Pnative -Dquarkus.kubernetes.deploy=true |
Je lance donc un maven package de l’application sur le profil microk8s (voir dans le application.properties ci-dessous) avec un paramètre -Pnative qui indique que je veux construire un exécutable natif (et non un jar pour une cible JVM) et enfin je précise que je veux que ce soit déployé directement dans mon Microk8s avec l’option -Dquarkus.kubernetes.deploy=true.
Profil Quarkus
Pour rappel un profil Quarkus est un prefix (« %myProfile.property« ) sur les propriétés du fichier de configuration et peut être activé lorsque je lance un commande maven avec l’option -Dquarkus.profile=myProfile. Dans cet exemple j’ai défini trois profil dev, test et microk8s.
Note : Le profil dev est activé par défaut lorsque je lance un mvn compile quarkus:dev et le profil test est activé par défaut lorsque les tests unitaires sont lancés (mvn test)
Le profil microk8s est spécifique pour le déploiement d’image native dans Microk8s. La base de données en dev et en test sera une base in memory H2 alors que en profil microk8s on travaillera avec une base postgreSQL préalablement déployée dans k8s.
Focus sur la configuration Quarkus
Revenons un peu plus en détails sur la configuration du fichier application.properties qui se trouve :
Voici ce qu’il contient
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# http port quarkus.http.port=2000 # native %microk8s.quarkus.native.container-build=true # docker image %microk8s.quarkus.container-image.group=elamotte %microk8s.quarkus.container-image.tag=${quarkus.application.version} %microk8s.quarkus.container-image.name=${quarkus.application.name} %microk8s.quarkus.container-image.push=true %microk8s.quarkus.container-image.build=true # Docker Registry %microk8s.quarkus.container-image.registry=${K8S_REGISTRY_URL:docker.io} %microk8s.quarkus.container-image.insecure=true %microk8s.quarkus.container-image.username=${K8S_REGISTRY_USERNAME:elamotte} %microk8s.quarkus.container-image.password=${K8S_REGISTRY_PASSWORD:XXXXXXX} # Kubernetes ## Expose via node %microk8s.quarkus.kubernetes.service-type=node-port %microk8s.quarkus.kubernetes.namespace=quarkus-apero-code ## readiness kubernetes %microk8s.quarkus.kubernetes.readiness-probe.initial-delay=10s %microk8s.quarkus.kubernetes.readiness-probe.period=20s ## k8s config %microk8s.quarkus.kubernetes-config.enabled=true %microk8s.quarkus.kubernetes.env.secrets=postgres-secret %microk8s.quarkus.kubernetes.env.configmaps=postgres-config ## Kubernetes client %microk8s.quarkus.kubernetes-client.master-url=https://192.168.64.2:16443 %microk8s.quarkus.kubernetes-client.trust-certs=true %microk8s.quarkus.kubernetes-client.namespace=quarkus-apero-code ## Kubernetes deploy %microk8s.quarkus.kubernetes.deployment-target=kubernetes %microk8s.quarkus.kubernetes.image-pull-policy=Always %microk8s.quarkus.kubernetes.image-pull-secrets=${K8S_REGISTRY_PASSWORD:XXXXXXX} # Database ## default H2 quarkus.datasource.db-kind=h2 quarkus.datasource.username=sa quarkus.datasource.password=password quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb ## PostgreSQL for microk8S %microk8s.quarkus.datasource.db-kind=postgresql %microk8s.quarkus.datasource.username=${POSTGRES_USER} %microk8s.quarkus.datasource.password=${POSTGRES_PASSWORD} %microk8s.quarkus.datasource.jdbc.url=jdbc:postgresql://${POSTGRES_HOST}:5432/${POSTGRES_DB} # H2 for dev %dev.quarkus.datasource.db-kind=h2 %dev.quarkus.datasource.username=sa %dev.quarkus.datasource.password=password %dev.quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb # H2 for test %test.quarkus.datasource.db-kind=h2 %test.quarkus.datasource.username=sa %test.quarkus.datasource.password=password %test.quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb # Hibernate ## drop and create the database at startup (use `update` to only update the schema) ## default quarkus.hibernate-orm.database.generation=drop-and-create quarkus.hibernate-orm.sql-load-script=import-dev.sql ## dev %dev.quarkus.hibernate-orm.database.generation=drop-and-create %dev.quarkus.hibernate-orm.sql-load-script=import-dev.sql ## test %test.quarkus.hibernate-orm.database.generation=drop-and-create %test.quarkus.hibernate-orm.sql-load-script=import-test.sql ## microk8s %microk8s.quarkus.hibernate-orm.database.generation=drop-and-create %microk8s.quarkus.hibernate-orm.log.sql=${HIBERNATE_LOG_SQL:true} %microk8s.quarkus.hibernate-orm.sql-load-script=import.sql |
Analysons un peu plus en détail de cette configuration qui est le nerf de la guerre pour déployer dans k8s (mais pas que)
1 2 3 4 5 |
# http port quarkus.http.port=2000 # native %microk8s.quarkus.native.container-build=true |
Ces deux lignes me permettent de configurer le port http et d’indiquer que je veux que mon exécutable soit construite dans une image Docker spécifique et non en utilisant un GraalVM local à mon poste de travail. Pourquoi? Et bien tout simplement je ne veux pas générer un exécutable pour mon macOS. Quarkus offre un moyen très pratique de créer un exécutable Linux natif en tirant parti d’un moteur de conteneur tel que Docker ou podman. Un avantage avec cette option est que je n’ai pas à installer GraalVM sur ma machine, Quarkus se charge de tout.
1 2 3 4 5 6 7 8 9 10 11 12 |
# docker image %microk8s.quarkus.container-image.group=elamotte %microk8s.quarkus.container-image.tag=${quarkus.application.version} %microk8s.quarkus.container-image.name=${quarkus.application.name} %microk8s.quarkus.container-image.push=true %microk8s.quarkus.container-image.build=true # Docker Registry %microk8s.quarkus.container-image.registry=${K8S_REGISTRY_URL:docker.io} %microk8s.quarkus.container-image.insecure=true %microk8s.quarkus.container-image.username=${K8S_REGISTRY_USERNAME:elamotte} %microk8s.quarkus.container-image.password=${K8S_REGISTRY_PASSWORD:XXXXXXX} |
Les lignes ci-dessus sont pour la génération de la future image docker de notre application. Les 5 premières lignes me servent à fournir les informations de mon image (group, tag, nom) et à indiquer que je veux que mon image soit construite et aussi déployée dans un registry docker. Dans mon example de code sur github je déploie mes images dans le hub docker. Ce registry sera utilisé par microk8s pour installer les bonnes images.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# Kubernetes ## Expose via node %microk8s.quarkus.kubernetes.service-type=node-port %microk8s.quarkus.kubernetes.namespace=quarkus-apero-code ## readiness kubernetes %microk8s.quarkus.kubernetes.readiness-probe.initial-delay=10s %microk8s.quarkus.kubernetes.readiness-probe.period=20s ## k8s config %microk8s.quarkus.kubernetes-config.enabled=true %microk8s.quarkus.kubernetes.env.secrets=postgres-secret %microk8s.quarkus.kubernetes.env.configmaps=postgres-config ## Kubernetes client %microk8s.quarkus.kubernetes-client.master-url=https://192.168.64.2:16443 %microk8s.quarkus.kubernetes-client.trust-certs=true %microk8s.quarkus.kubernetes-client.namespace=quarkus-apero-code ## Kubernetes deploy %microk8s.quarkus.kubernetes.deployment-target=kubernetes %microk8s.quarkus.kubernetes.image-pull-policy=Always %microk8s.quarkus.kubernetes.image-pull-secrets=${K8S_REGISTRY_PASSWORD:XXXXXXX} |
Cette partie de la configuration va nous servir pour la configuration de notre fichier de déploiement k8s (généré automatiquement par quarkus) et pour configurer le client k8s qui sera en charge de communiquer avec les APIs k8s pour appliquer un déploiement en remote.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# Database ## default H2 quarkus.datasource.db-kind=h2 quarkus.datasource.username=sa quarkus.datasource.password=password quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb ## PostgreSQL for microk8S %microk8s.quarkus.datasource.db-kind=postgresql %microk8s.quarkus.datasource.username=${POSTGRES_USER} %microk8s.quarkus.datasource.password=${POSTGRES_PASSWORD} %microk8s.quarkus.datasource.jdbc.url=jdbc:postgresql://${POSTGRES_HOST}:5432/${POSTGRES_DB} # H2 for dev %dev.quarkus.datasource.db-kind=h2 %dev.quarkus.datasource.username=sa %dev.quarkus.datasource.password=password %dev.quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb # H2 for test %test.quarkus.datasource.db-kind=h2 %test.quarkus.datasource.username=sa %test.quarkus.datasource.password=password %test.quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb |
Enfin ci-dessus concerne la base de donnée que nous allons utiliser selon les différents profils de quarkus. %dev et %test pour la configuration d’une base H2 in memory pour le développement local et pour les tests unitaires, et %microk8s pour la cible de déploiement final c’est à dire une base PostgreSQL dans un k8s.
ConfigMap & Secret k8s
Concernant le login mot de passe de la base de données cible dans k8s, vous pouvez voir que je vais m’appuyer sur deux variables d’environnements que sont POSTGRES_DB, POSTGRES_USER, POSTGRES_HOST et POSTGRES_PASSWORD. Ces quatre variables sont fournies par une ConfigMap et un Secret déployer avec le fichier de la base (rappel des logs du déploiement de postgreSQL: configmap/postgres-config created et secret/postgres-secret created)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
apiVersion: v1 kind: ConfigMap metadata: name: postgres-config namespace: quarkus-apero-code labels: app: postgres data: POSTGRES_DB: quarkus POSTGRES_USER: quarkus POSTGRES_HOST: postgres --- apiVersion: v1 kind: Secret metadata: name: postgres-secret namespace: quarkus-apero-code labels: app: postgres data: POSTGRES_PASSWORD: YWRtaW4xMjM= |
Donc pour s’appuyer sur ces informations, il me suffit de le préciser dans le fichier de configuration et d’indiquer quel Secret et quelle ConfigMap je vais avoir besoin d’utiliser en ayant bien sur activer kuberntes-config comme suit
1 2 3 4 |
## k8s config %microk8s.quarkus.kubernetes-config.enabled=true %microk8s.quarkus.kubernetes.env.secrets=postgres-secret %microk8s.quarkus.kubernetes.env.configmaps=postgres-config |
Injection de Data dans la BDD
Dans ces dernières options ci-dessous, nous définissons donc la stratégie d’intégration du modèle de données et des données dans les bases de nos différents environnements par l’intermédiaire de Hibernate (dev, test, microk8s). Je définis que à chaque déploiement de l’application, le schéma doit être supprimé et créé (drop-and-create) et que les données de fichier sql doivent être chargées dans le schéma créé (scripts import-X.sql). Vous pouvez constater dans le projet que j’ai un fichier SQL par environnement donc par profil.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# Hibernate ## drop and create the database at startup (use `update` to only update the schema) ## default quarkus.hibernate-orm.database.generation=drop-and-create quarkus.hibernate-orm.sql-load-script=import-dev.sql ## dev %dev.quarkus.hibernate-orm.database.generation=drop-and-create %dev.quarkus.hibernate-orm.sql-load-script=import-dev.sql ## test %test.quarkus.hibernate-orm.database.generation=drop-and-create %test.quarkus.hibernate-orm.sql-load-script=import-test.sql ## microk8s %microk8s.quarkus.hibernate-orm.database.generation=drop-and-create %microk8s.quarkus.hibernate-orm.log.sql=${HIBERNATE_LOG_SQL:true} %microk8s.quarkus.hibernate-orm.sql-load-script=import.sql |
Note : Pour avoir un listing complet de toutes les propriétés de configuration Quarkus voir ici
Quarkus build steps
Où en sommes nous donc de notre déploiement? Nous avons donc lancé la commande maven pour déployer notre application dans kube. Que disent les logs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
$ ./mvnw clean package -Dquarkus.profile=microk8s -Pnative -Dquarkus.kubernetes.deploy=true [INFO] Scanning for projects... [INFO] [INFO] -------------------< org.acme:kubernetes-quickstart >------------------- [INFO] Building kubernetes-quickstart 1.0.0-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ kubernetes-quickstart --- [INFO] Deleting /Users/coloneld/dev/git/sedona/apero-code/mk8s-quarkus-ac/kubernetes-quickstart/target [INFO] [INFO] --- quarkus-maven-plugin:1.13.3.Final:generate-code (default) @ kubernetes-quickstart --- Downloading from sedona-redshift-snapshot: https://repo.cicd.sedona.fr/artifactory/redshift-snapshot/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/maven-metadata.xml Downloading from sedona-java-public: https://repo.cicd.sedona.fr/artifactory/java-public/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/maven-metadata.xml Downloading from sedona-java-snapshot: https://repo.cicd.sedona.fr/artifactory/java-snapshot/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/maven-metadata.xml Downloading from sedona-php-snapshot: https://repo.cicd.sedona.fr/artifactory/php-snapshot/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/maven-metadata.xml Downloading from sedona-gradle-snapshot: https://repo.cicd.sedona.fr/artifactory/gradle-snapshot/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/maven-metadata.xml [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ kubernetes-quickstart --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 5 resources [INFO] [INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ kubernetes-quickstart --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- kotlin-maven-plugin:1.4.32:compile (compile) @ kubernetes-quickstart --- [INFO] Applied plugin: 'all-open' WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by com.intellij.util.ReflectionUtil (file:/Users/coloneld/dev/repository/org/jetbrains/kotlin/kotlin-compiler/1.4.32/kotlin-compiler-1.4.32.jar) to method java.util.ResourceBundle.setParent(java.util.ResourceBundle) WARNING: Please consider reporting this to the maintainers of com.intellij.util.ReflectionUtil WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release [INFO] [INFO] --- quarkus-maven-plugin:1.13.3.Final:generate-code-tests (default) @ kubernetes-quickstart --- [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ kubernetes-quickstart --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory /Users/coloneld/dev/git/sedona/apero-code/mk8s-quarkus-ac/kubernetes-quickstart/src/test/resources [INFO] [INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ kubernetes-quickstart --- [INFO] Changes detected - recompiling the module! [INFO] [INFO] --- kotlin-maven-plugin:1.4.32:test-compile (test-compile) @ kubernetes-quickstart --- [INFO] Applied plugin: 'all-open' [INFO] [INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ kubernetes-quickstart --- [INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running org.acme.rest.GreetingResourceTest 2021-05-05 14:32:50,772 WARN [io.qua.hib.orm.run.pro.ProxyDefinitions] (main) Could not generate an enhanced proxy for entity 'org.acme.beer.domain.Beer' (class='org.acme.beer.domain.Beer') as it's final. Your application might perform better if we're allowed to extend it. 2021-05-05 14:32:51,868 INFO [io.quarkus] (main) Quarkus 1.13.3.Final on JVM started in 3.637s. Listening on: http://localhost:8081 2021-05-05 14:32:51,868 INFO [io.quarkus] (main) Profile test activated. 2021-05-05 14:32:51,868 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache-kotlin, jdbc-h2, jdbc-postgresql, kotlin, kubernetes, kubernetes-client, mutiny, narayana-jta, resteasy, resteasy-jackson, smallrye-context-propagation] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 8.886 s - in org.acme.rest.GreetingResourceTest 2021-05-05 14:32:53,383 INFO [io.quarkus] (main) Quarkus stopped in 0.039s [INFO] [INFO] Results: [INFO] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ kubernetes-quickstart --- [INFO] Building jar: /Users/coloneld/dev/git/sedona/apero-code/mk8s-quarkus-ac/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT.jar [INFO] [INFO] --- quarkus-maven-plugin:1.13.3.Final:build (default) @ kubernetes-quickstart --- [INFO] [org.jboss.threads] JBoss Threads version 3.2.0.Final [INFO] [org.hibernate.Version] HHH000412: Hibernate ORM core version 5.4.29.Final [INFO] [io.quarkus.kubernetes.deployment.KubernetesDeploy] Kubernetes API Server at 'https://192.168.64.2:16443/' successfully contacted. [INFO] Checking for existing resources in: /Users/coloneld/dev/git/sedona/apero-code/mk8s-quarkus-ac/kubernetes-quickstart/src/main/kubernetes. [INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building native image source jar: /Users/coloneld/dev/git/sedona/apero-code/mk8s-quarkus-ac/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT-native-image-source-jar/kubernetes-quickstart-1.0.0-SNAPSHOT-runner.jar [INFO] Adding existing Namespace with name: quarkus-apero-code. [INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Building native image from /Users/coloneld/dev/git/sedona/apero-code/mk8s-quarkus-ac/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT-native-image-source-jar/kubernetes-quickstart-1.0.0-SNAPSHOT-runner.jar [INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildContainerRunner] Using docker to run the native image builder [INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildContainerRunner] Checking image status quay.io/quarkus/ubi-quarkus-native-image:21.0-java11 21.0-java11: Pulling from quarkus/ubi-quarkus-native-image 8f403cb21126: Pull complete 65c0f2178ac8: Pull complete a1160cb39698: Pull complete Digest: sha256:251a0044a9827d25b8cbbb57f6eeb5a0eaf75ffa4cafe9e7b611c8d870fd9aa2 Status: Downloaded newer image for quay.io/quarkus/ubi-quarkus-native-image:21.0-java11 quay.io/quarkus/ubi-quarkus-native-image:21.0-java11 [INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Running Quarkus native-image plugin on GraalVM Version 21.0.0.2 (Java Version 11.0.10+8-jvmci-21.0-b06) [INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] docker run --env LANG=C --rm -v /Users/coloneld/dev/git/sedona/apero-code/mk8s-quarkus-ac/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT-native-image-source-jar:/project:z quay.io/quarkus/ubi-quarkus-native-image:21.0-java11 -J-DCoordinatorEnvironmentBean.transactionStatusManagerEnable=false -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=1 -J-Duser.language=fr -J-Duser.country=FR -J-Dfile.encoding=UTF-8 --initialize-at-build-time= -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy\$BySpaceAndTime -H:+JNI -H:+AllowFoldMethods -jar kubernetes-quickstart-1.0.0-SNAPSHOT-runner.jar -H:FallbackThreshold=0 -H:+ReportExceptionStackTraces -H:-AddAllCharsets -H:EnableURLProtocols=http,https --enable-all-security-services --no-server -H:-UseServiceLoaderFeature -H:+StackTrace kubernetes-quickstart-1.0.0-SNAPSHOT-runner [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] classlist: 36 709,05 ms, 1,20 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] (cap): 691,09 ms, 1,20 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] setup: 3 551,41 ms, 1,20 GB 12:35:18,535 INFO [org.hib.Version] HHH000412: Hibernate ORM core version 5.4.29.Final 12:35:18,564 INFO [org.hib.ann.com.Version] HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 12:35:18,701 INFO [org.hib.dia.Dialect] HHH000400: Using dialect: io.quarkus.hibernate.orm.runtime.dialect.QuarkusPostgreSQL10Dialect 12:35:18,889 WARN [io.qua.hib.orm.run.pro.ProxyDefinitions] Could not generate an enhanced proxy for entity 'org.acme.beer.domain.Beer' (class='org.acme.beer.domain.Beer') as it's final. Your application might perform better if we're allowed to extend it. 12:36:38,025 INFO [org.jbo.threads] JBoss Threads version 3.2.0.Final [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] (clinit): 2 151,08 ms, 3,76 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] (typeflow): 97 977,56 ms, 3,76 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] (objects): 194 717,58 ms, 3,76 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] (features): 3 323,50 ms, 3,76 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] analysis: 303 797,89 ms, 3,76 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] universe: 5 812,48 ms, 3,75 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] (parse): 52 417,46 ms, 4,26 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] (inline): 28 343,69 ms, 5,33 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] (compile): 112 066,04 ms, 5,59 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] compile: 197 495,82 ms, 5,59 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] image: 12 054,61 ms, 5,44 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] write: 5 641,85 ms, 5,44 GB [kubernetes-quickstart-1.0.0-SNAPSHOT-runner:25] [total]: 565 706,59 ms, 5,44 GB [WARNING] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] objcopy executable not found in PATH. Debug symbols will not be separated from executable. [WARNING] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] That will result in a larger native image with debug symbols embedded in it. [INFO] [io.quarkus.container.image.docker.deployment.DockerWorking] Docker daemon found. Version:'20.10.5' [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Starting docker image build [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Executing the following command to build docker image: 'docker build -f /Users/coloneld/dev/git/sedona/apero-code/mk8s-quarkus-ac/kubernetes-quickstart/src/main/docker/Dockerfile.native -t docker.io/elamotte/kubernetes-quickstart:1.0.0-SNAPSHOT /Users/coloneld/dev/git/sedona/apero-code/mk8s-quarkus-ac/kubernetes-quickstart' [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #1 [internal] load build definition from Dockerfile.native [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #1 sha256:9a6f4c4969dc25d971efe076405d15764570d631318098b68e34d7ff94a2bee9 [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #1 transferring dockerfile: 44B done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #1 DONE 0.0s [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #2 [internal] load .dockerignore [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #2 sha256:3862e08734add1c89eba5da67bd047414e141df30f33a75407a7e8265e3113a2 [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #2 transferring context: 34B done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #2 DONE 0.0s [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #3 [internal] load metadata for registry.access.redhat.com/ubi8/ubi-minimal:8.3 [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #3 sha256:583b288e8801cd521602da7d67e17b4babff42d4747f032b0ed283b5b984e6e1 [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #3 DONE 1.1s [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #4 [1/4] FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3@sha256:2f6b88c037c0503da7704bccd3fc73cb76324101af39ad28f16460e7bce98324 [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #4 sha256:13e38af79a59609a32a2edb04217dfd12effc07d3bbe5f67d8af0a6d95f4e18e [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #4 resolve registry.access.redhat.com/ubi8/ubi-minimal:8.3@sha256:2f6b88c037c0503da7704bccd3fc73cb76324101af39ad28f16460e7bce98324 0.0s done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #4 sha256:a62d408337bb50546019e2334fdd43ec1ecc150d60f5f195fd324c578c25ab3a 737B / 737B done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #4 sha256:332744c1854d8e87f41dc67bf3d7e1c08d7a6b1322b5b5bd0b126bf8282ca1f8 4.33kB / 4.33kB done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #4 sha256:2f6b88c037c0503da7704bccd3fc73cb76324101af39ad28f16460e7bce98324 1.47kB / 1.47kB done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #4 DONE 0.1s [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 [internal] load build context [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 sha256:51993da97a2f81b57a518abb921d2552e115698b4f66419e150810a681c5fa9f [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 ... [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #5 [2/4] WORKDIR /work/ [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #5 sha256:77683e322d3155d10b4351b2dcd7acec766d4a4d8a6dbde26b5de2fcaaeccd4d [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #5 DONE 0.1s [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 [internal] load build context [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 sha256:51993da97a2f81b57a518abb921d2552e115698b4f66419e150810a681c5fa9f [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 ... [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #6 [3/4] RUN chown 1001 /work && chmod "g+rwX" /work && chown 1001:root /work [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #6 sha256:b4d25a24b9b5125a780fee23957a99fefc288945ea536741ff011e21415115a8 [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #6 DONE 0.8s [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 [internal] load build context [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 sha256:51993da97a2f81b57a518abb921d2552e115698b4f66419e150810a681c5fa9f [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 transferring context: 114.80MB 2.9s done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #7 DONE 2.9s [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #8 [4/4] COPY --chown=1001:root target/*-runner /work/application [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #8 sha256:f64cd15107d090319ed224f39875f16cb2d6a3167d43de2f00c574e7ef547bb0 [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #8 DONE 0.3s [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #9 exporting to image [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #9 sha256:e8c613e07b0b7ff33893b694f7759a10d42e180f2b4dc349fb57dc6b71dcab00 [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #9 exporting layers [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #9 exporting layers 0.5s done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #9 writing image sha256:7f7a554f80f3fbeec1949eed8e9d271477ffe9e6709bd679ffab404d9a93759e done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #9 naming to docker.io/elamotte/kubernetes-quickstart:1.0.0-SNAPSHOT done [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] #9 DONE 0.5s [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Built container image docker.io/elamotte/kubernetes-quickstart:1.0.0-SNAPSHOT (null) [INFO] [io.quarkus.deployment.util.ExecUtil] WARNING! Using --password via the CLI is insecure. Use --password-stdin. [INFO] [io.quarkus.deployment.util.ExecUtil] Login Succeeded [INFO] [io.quarkus.deployment.util.ExecUtil] The push refers to repository [docker.io/elamotte/kubernetes-quickstart] [INFO] [io.quarkus.deployment.util.ExecUtil] 6849d51b7091: Preparing [INFO] [io.quarkus.deployment.util.ExecUtil] 9916f7a469fe: Preparing [INFO] [io.quarkus.deployment.util.ExecUtil] 1342d6c13d07: Preparing [INFO] [io.quarkus.deployment.util.ExecUtil] 144a43b910e8: Preparing [INFO] [io.quarkus.deployment.util.ExecUtil] 4a2bc86056a8: Preparing [INFO] [io.quarkus.deployment.util.ExecUtil] 144a43b910e8: Pushed [INFO] [io.quarkus.deployment.util.ExecUtil] 1342d6c13d07: Pushed [INFO] [io.quarkus.deployment.util.ExecUtil] 9916f7a469fe: Pushed [INFO] [io.quarkus.deployment.util.ExecUtil] 4a2bc86056a8: Pushed [INFO] [io.quarkus.deployment.util.ExecUtil] 6849d51b7091: Pushed [INFO] [io.quarkus.deployment.util.ExecUtil] 1.0.0-SNAPSHOT: digest: sha256:0f33659c2becb59fff0ae13bbf2aaa14bb2166dcf9c9ce24d026a2de56b59a3e size: 1363 [INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Successfully pushed docker image docker.io/elamotte/kubernetes-quickstart:1.0.0-SNAPSHOT [INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Deploying to kubernetes server: https://192.168.64.2:16443/ in namespace: quarkus-apero-code. [INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Namespace quarkus-apero-code. [INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: ServiceAccount kubernetes-quickstart. [INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Service kubernetes-quickstart. [INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: RoleBinding kubernetes-quickstart-view. [INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Deployment kubernetes-quickstart. [INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 693618ms [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 11:54 min [INFO] Finished at: 2021-05-05T14:44:27+02:00 [INFO] ------------------------------------------------------------------------ |
La commande maven lance donc le clean et la compilation (ligne 2-44), les tests unitaires (ligne 45-62), build le jar (ligne 63-65). Jusqu’ici rien de nouveau sous le soleil.
L’étape intéressante se lance, la génération de l’image native (NativeImageBuildStep, ligne 66-107). C’est là que une particularité Quarkus entre en jeu. La première étape, avant de générer l’exécutable natif, consiste en de la compilation « Ahead of Time ». Lorsqu’une application Quarkus est créée, certains traitement qui se produisent généralement au moment de l’exécution d’une application Java classique (run time) sont effectués au moment de la construction (phase dite d’augmentation). Ainsi, lorsque l’application s’exécute, tout a été pré-calculé et l’analyse des annotations, l’analyse XML, etc. ne seront plus exécutées. Il a deux avantages : sur le temps de démarrage (beaucoup plus rapide) et sur la consommation de mémoire (beaucoup plus faible). La finalité de cette première étape est de produire un runner.jar. Vous pouvez constater qu’un répertoire de travail est créé dans /target, /kubernetes-quickstart-1.0.0-SNAPSHOT-native-image-source-jar, il y est copié les librairies utiles à l’application et le fameux runner.jar est crée en ayant fait les optimisations. Par la suite les élément de ce répertoire sont utilisés dans l’image Docker de build natif (quay.io/quarkus/ubi-quarkus-native-image:21.0.0-java11, grâce à cela pas besoin de GraalVM en local), afin de générer l’exécutable natif Linux qui permet de réduire d’environ 99% le temps de boot et d’environ 86% l’empreinte mémoire par rapports à des applications Java classiques.
La finalité de cette étape est le fichier /target/ kubernetes-quickstart-1.0.0-SNAPSHOT-runner, c’est l’exécutable proprement dit qui est destiné à fonctionner sur un OS Linux.
Une fois notre exécutable généré, l’étape de build de l’image Docker cible se lance (DockerProcessor, ligne 108-168).
Une fois l’image créée, celle-ci va être déployée dans notre registry Docker (ligne 169-183).
Note : Quarkus vient avec son propre DockerFile basé sur ubi, universal base image (c’est une RHEL minimale, Red Hat enterprise Linux), il y a un DockerFile par cible de build, une pour la JVM (fast-Jar par défaut à partir de la 1.12) et une pour une application native. Rien ne vous empêche d’utiliser vos DockerFile customisées.
Et enfin dernière étape (KubernetesDeployer, ligne 184-190), le fichier de déploiement, kubernetes.yml, généré par Quarkus va être appliqué dans k8s via le client k8S qui se connecte aux APIs du serveur.
Pour info voici le fichier de déploiement qui est généré par Quarkus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
--- apiVersion: v1 kind: ServiceAccount metadata: annotations: app.quarkus.io/vcs-url: https://github.com/elamotte7/mk8s-quarkus-ac.git app.quarkus.io/build-timestamp: 2021-05-05 - 12:32:55 +0000 app.quarkus.io/commit-id: ae3d9a9cd16479337ce312d2930fb4e840ab0c74 labels: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT name: kubernetes-quickstart namespace: quarkus-apero-code --- apiVersion: v1 kind: Service metadata: annotations: app.quarkus.io/vcs-url: https://github.com/elamotte7/mk8s-quarkus-ac.git app.quarkus.io/build-timestamp: 2021-05-05 - 12:32:55 +0000 app.quarkus.io/commit-id: ae3d9a9cd16479337ce312d2930fb4e840ab0c74 labels: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT name: kubernetes-quickstart namespace: quarkus-apero-code spec: ports: - name: http port: 2000 targetPort: 2000 selector: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT type: NodePort --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kubernetes-quickstart-view namespace: quarkus-apero-code roleRef: kind: ClusterRole apiGroup: rbac.authorization.k8s.io name: view subjects: - kind: ServiceAccount name: kubernetes-quickstart --- apiVersion: apps/v1 kind: Deployment metadata: annotations: app.quarkus.io/vcs-url: https://github.com/elamotte7/mk8s-quarkus-ac.git app.quarkus.io/build-timestamp: 2021-05-05 - 12:32:55 +0000 app.quarkus.io/commit-id: ae3d9a9cd16479337ce312d2930fb4e840ab0c74 labels: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT name: kubernetes-quickstart namespace: quarkus-apero-code spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT template: metadata: annotations: app.quarkus.io/vcs-url: https://github.com/elamotte7/mk8s-quarkus-ac.git app.quarkus.io/build-timestamp: 2021-05-05 - 12:32:55 +0000 app.quarkus.io/commit-id: ae3d9a9cd16479337ce312d2930fb4e840ab0c74 labels: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT namespace: quarkus-apero-code spec: containers: - env: - name: KUBERNETES_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace envFrom: - secretRef: name: postgres-secret - configMapRef: name: postgres-config image: docker.io/elamotte/kubernetes-quickstart:1.0.0-SNAPSHOT imagePullPolicy: Always name: kubernetes-quickstart ports: - containerPort: 2000 name: http protocol: TCP imagePullSecrets: - name: Thorgal7! serviceAccount: kubernetes-quickstart |
La fin des logs nous a bien indiqué un « BUILD SUCCESS », tout semble s’être bien déroulé, donc à présent vérifions dans le Dashboard que notre application Quarkus est bien déployée dans le namespace quarkus-apero-code
Une fois de plus tout est au vert, notre PostgreSQL et notre Quarkus semble fonctionner, donc nous devrions pouvoir accéder sans difficultés à notre application fraichement déployée.
Note : le build d’image native est très couteux en temps, si vous voulez aller plus vite pour déployer dans votre Microk8s vous avez simplement à ne pas positionner l’option -Pnative lors du lancement de la commande de package. /!\ Attention si vous faites une mise à jour de votre application Quarkus d’une version inférieur à la 1.12 sur une supérieur ou égal à la 1.12, par défaut en mode jvm c’est le concept de fast-jar qui est adopté (démarre plus rapidement que l’ancien uber-jar), il faut donc mettre à jour vos DockerFile.jvm avec celui-ci, et voir la note de migration ici pour plus de détails.
Ingress
Mais comment accéder à notre application, sur quelle URL, sur quel port? Pour rappel, ce qui est déployé dans k8s n’est pas exposé par défaut à l’extérieur du réseau interne kube. Pour cela nous avons besoin de déployer une « Ingress » qui sera la passerelle d’accès à notre service kubernetes-quickstart. Pour rappel
Ingress
Un Ingress est un objet Kubernetes qui gère l’accès externe aux services dans un cluster, généralement du trafic HTTP.
Un Ingress peut fournir un équilibrage de charge, une terminaison TLS et un hébergement virtuel basé sur un nom.
Un fichier de déploiement d’Ingress k8s est dans le projet Github, vous pouvez le voir ci-dessous
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: k8s-quickstart-ingress namespace: quarkus-apero-code annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - http: paths: - path: /k8s-quickstart(/|$)(.*) pathType: Prefix backend: service: name: kubernetes-quickstart port: number: 2000 |
Et donc, vous pouvez constater que pour le service kubernetes-quickstart (le point d’accès interne kube à l’application Quarkus), j’indique que via le path /k8s-quickstart nous allons pouvoir y accéder depuis cette Ingress
A présent déployons notre Ingress à l’aide de la commande suivante
1 2 |
$ kubectl apply -f microk8s/k8s/ingress/k8s-quickstart-ingress.yaml ingress.networking.k8s.io/k8s-quickstart-ingress created |
Vérifions si notre application est disponible à l’adresse du point d’entrée du cluster à savoir 192.168.64.2 sur le path définie dans mon fichier de déploiement qui est /k8s-quickstart, naviguons donc sur http://192.168.64.2/k8s-quickstart
Comme vous pouvez le constater notre application Quarkus est bien accessible depuis l’extérieur du cluster single-node Microk8s.
Il nous reste un point à vérifier toute fois, la page d’acceuil est bien accessible, mais qu’en est-il des données de la base qui ont été chargées au déploiement de notre application. Vérifions que Quarkus communique bien avec sa base de données en accédant à l’API Rest /beers qui expose les données de la base PostgreSQL, naviguons sur https://192.168.64.2/k8s-quickstart/beers
Well done! Cela fonctionne également.
Pour rappel, nous avons crée un BDD avec une table BEER_TABLE, que nous avons populé grâce à Quarkus qui intègre automatiquement les données au démarrage de l’application en s’appuyant sur un script SQL (cf application.properties), et on voit bien ci-dessus que les données sont accessibles.
En résumé, nous avons donc déployé une base de données PostgreSQL dans k8s, créé et déployé une application Quarkus, intégré des données à la base de données lors du déploiement de notre application, déployé une Ingress pour accéder à notre nouvelle application depuis l’extérieur du cluster k8s et enfin accédé à celle-ci via le navigateur.
Ce sera tout pour cette partie, vous pouvez retrouver le code de cette application sur mon github.
Lors de la prochaine partie nous verrons comment déployer un client et un serveur gRPC dans notre Microk8S.
Références