Une vue d'ensemble du framework Java natif de Kubernetes Quarkus

introduction

Le 7 mars 2019, Red Hat a annoncé le framework Java natif de Kubernetes "Quarkus".

Introducing Quarkus: a next-generation Kubernetes native Java framework https://developers.redhat.com/blog/2019/03/07/quarkus-next-generation-kubernetes-native-java-framework/

Avec l'utilisation croissante de Kubernetes et le passage aux microservices et à l'absence de serveur, la conteneurisation des applications est de plus en plus courante et un démarrage lent par rapport à d'autres langages était un inconvénient majeur pour Java. D'autre part, Quarkus a une copie de capture de "Supersonic Subatomic Java (Java plus petit que atom)" en démarrant le binaire Linux Native créé à l'aide de GraalVM sur le conteneur. Cela réduit considérablement le temps de démarrage de Java.

Je pense que plusieurs personnes ont déjà écrit des blogs sur Quarkus, donc dans cet article j'écrirai également sur "Contexte de l'apparition de Quarkus" et "Déploiement d'applications utilisant Quarkus sur Kubernetes". ..

Contexte de l'apparition de Quarkus

En raison de la popularité de Docker / Kubernetes et de la tendance aux microservices / sans serveur, la conteneurisation des applications devient courante. Pour le développement de ces applications de conteneur, des langages légers avec un temps de démarrage court et une faible utilisation de la mémoire tels que Golang et Ruby sont souvent adoptés, et l'utilisation de Java avec un temps de démarrage lent et une utilisation importante de la mémoire a été évitée. J'ai fait.

Cependant, l'écosystème Java existe depuis plus de 20 ans et reste l'un des langages les plus populaires utilisés par de nombreux développeurs en 2019.

«Quarkus» a été introduit pour déployer des applications de conteneur natives Kubernetes à l'aide de Java tout en utilisant les connaissances et les compétences que les développeurs Java ont cultivées jusqu'à présent. Quarkus peut réduire considérablement le temps de démarrage, réduire l'utilisation de la mémoire et obtenir des images de conteneur de petite taille.

Nous pensons que Quarkus a été lancé dans le but d'intégrer de nombreux développeurs Java dans l'écosystème Kubernetes et de rendre les applications conteneurs plus générales et l'écosystème Kubernetes plus grand. ..

Qu'est-ce que GraalVM

GraalVM est un runtime à usage général publié par Oracle en avril 2018 en tant que open source qui exécute plusieurs langages tels que Java, JavaScript, Ruby et Python sur un seul runtime intégré.

architecture.png

Citation: https://www.graalvm.org/docs/img/architecture.png

Pour les développeurs d'applications Java, la nouvelle technologie de compilation Just-In-Time permet aux applications Java de s'exécuter plus rapidement. GraalVM a également la capacité de créer des binaires Nativ e, une machine qui peut être exécutée immédiatement en utilisant l'analyse statique pour trouver du code accessible et effectuer une compilation Ahead-Of-Time (AOT). Vous pouvez inclure le code dans un binaire natif.

Restrictions à partir de mars 2019

Statut de support / non support de la mise en œuvre CDI

Dans Quarkus, CDI (Contexts and Dependency Injection) peut être utilisé, mais toutes les spécifications CDI ne peuvent pas être implémentées. Les fonctionnalités prises en charge et non prises en charge sont les suivantes.

Fonctionnalités prises en charge

Restrictions

Référence: https://quarkus.io/guides/cdi-reference.html

Temps de construction

Quarkus utilise GraalVM pour créer un binaire natif pour Linux, mais dans mon environnement, il faut environ "9 minutes" entre l'exécution de la commande Maven et son exécution, même s'il s'agit d'une application simple. C'est parti. Puisque le "mode de développement" qui réalise le déploiement à chaud est fourni, lors du développement dans un environnement local, il ne sera pas conteneurisé, mais pour le moment, il sera développé en utilisant le "mode de développement".

Déployons l'application sur Kubernetes à l'aide de Quarkus

Ici, créons une application JAX-RS simple en suivant le Get Started présenté à l'URL suivante.

QUARKUS - GET STARTED https://quarkus.io/get-started/

getting-started-architecture.png

Préparation préalable

Pour déployer une application sur Kubernetes à l'aide de Quarkus, vous devez préparer l'environnement suivant à l'avance.

Création de la première application

Créons un projet Maven

Pour développer une application à l'aide de Quarkus, créez un projet Maven à l'aide de l'exemple de commande suivant.

mvn io.quarkus:quarkus-maven-plugin:0.11.0:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=getting-started \
    -DclassName="org.acme.quickstart.GreetingResource" \
    -Dpath="/hello"

L'exécution de la commande ci-dessus créera un fichier de répertoire similaire au suivant: Ici, un exemple de Dockerfile est également créé automatiquement sous le répertoire src / main / docker.

$ tree getting-started/
getting-started/
├── pom.xml
└── src
    ├── main
    │   ├── docker
    │   │   └── Dockerfile
    │   ├── java
    │   │   └── org
    │   │       └── acme
    │   │           └── quickstart
    │   │               └── GreetingResource.java
    │   └── resources
    │       └── META-INF
    │           ├── microprofile-config.properties
    │           └── resources
    │               └── index.html
    └── test
        └── java
            └── org
                └── acme
                    └── quickstart
                        ├── GreetingResourceTest.java
                        └── NativeGreetingResourceIT.java

Quarkus BOM et quarkus-maven-plugin sont préconfigurés dans le fichier pom.xml généré automatiquement comme indiqué ci-dessous.

pom.xml


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-bom</artifactId>
            <version>${quarkus.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<build>
    <plugins>
        <plugin>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-maven-plugin</artifactId>
            <version>${quarkus.version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>build</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Vérifions le code de l'application

La création d'un projet Maven avec la commande ci-dessus générera l'exemple de code suivant.

src/main/java/org/acme/quickstart/GreetingResource.java


package org.acme.quickstart;
  
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}

Commençons en mode développement

Ensuite, essayez de démarrer l'application en utilisant le "mode développement". En "mode développement", le déploiement à chaud par compilation en arrière-plan est possible, et lorsque vous mettez à jour le fichier Java et mettez à jour le navigateur, le fichier Java sera automatiquement compilé et vous pourrez voir l'application modifiée.

$ mvn compile quarkus:dev

Vous pouvez vérifier le fonctionnement de l'exemple d'application JAX-RS en exécutant la commande suivante.

$ curl http://localhost:8080/hello
hello

Essayons CDI (Contexts and Dependency Injection)

Ensuite, personnalisons l'exemple d'application généré automatiquement. Ici, créez une nouvelle classe de service et ajoutez un appel de classe de service au GreetingResource.java généré automatiquement.

Ajoutez récemment la classe de service suivante.

src/main/java/org/acme/quickstart/GreetingService.java


package org.acme.quickstart;
  
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class GreetingService {

    public String greeting(String name) { 
        return "hello " + name;
    }

}

Modifiez ensuite le fichier GreetingResource.java généré automatiquement.

src/main/java/org/acme/quickstart/GreetingResource.java


package org.acme.quickstart;
  
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.inject.Inject;
import javax.ws.rs.PathParam;

@Path("/hello")
public class GreetingResource {

    @Inject
    GreetingService service;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam("name") String name) {
        return service.greeting(name);
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}

Vérifiez le fonctionnement avec la commande suivante.

$ curl http://localhost:8080/hello/greeting/quarkus
hello quarkus

Créer un binaire Linux natif

Générons un binaire natif

Ensuite, j'utilise GraalVM pour créer un binaire natif pour Linux.Le pom.xml généré automatiquement est livré avec des exécutions préconfigurées dans le profil. Avec les paramètres suivants, vous pouvez créer un binaire Linux natif en exécutant la commande Maven.

pom.xml


<profiles>
    <profile>
        <id>native</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>io.quarkus</groupId>
                    <artifactId>quarkus-maven-plugin</artifactId>
                    <version>${quarkus.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>native-image</goal>
                            </goals>
                            <configuration>
                                <enableHttpUrlHandler>true</enableHttpUrlHandler>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Créez un binaire Linux natif avec la commande Maven suivante.

$ mvn package -Pnative -Dnative-image.docker-build=true

Ici, l'option -Pnative est une option pour générer un binaire qui peut être exécuté par Native, et l'option -Dnative-image.docker-build = true est une option pour générer un binaire natif qui correspond au système d'exploitation sur Docker. C'est une option nécessaire pour le rendre explicite.

À propos, lorsque je l'ai exécuté dans mon environnement, il a fallu "environ 9 minutes" pour exécuter la commande Maven. Si cela prend autant de temps sans exécuter docker build, il ne sera pas possible de construire fréquemment, donc j'aimerais m'attendre à de futures améliorations fonctionnelles.

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 08:48 min
[INFO] Finished at: 2019-03-18T12:16:35+09:00
[INFO] ------------------------------------------------------------------------

Construisons Docker

containerization-process.png

Lorsque vous créez un projet Maven, un exemple de fichier Docker est généré automatiquement, créez donc une image Docker basée sur ce fichier.

FROM registry.fedoraproject.org/fedora-minimal
WORKDIR /work/
COPY target/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]

Créez une image Docker à l'aide de la commande suivante.

$ docker build -f src/main/docker/Dockerfile -t quarkus-quickstart/quickstart .

Vérifions la taille de l'image du conteneur créée. Étant donné que l'image de base est "fedra-minimal", elle fait 125 Mo, mais vous pouvez voir à partir de la différence qu'elle fait "environ 20 Mo" si vous exécutez simplement l'exemple d'application JAX-RS Quarkus. Étant donné qu'il a fallu des centaines de Mo pour installer le JDK, cette taille d'image de conteneur semble assez petite.

$ docker images
REPOSITORY                                  TAG                 IMAGE ID            CREATED              SIZE
quarkus-quickstart/quickstart               latest              d93d89bde0bb        About a minute ago   125MB
registry.fedoraproject.org/fedora-minimal   latest              f0c38118c459        3 weeks ago          105MB

Vérifions le fonctionnement

Ensuite, essayez de démarrer le conteneur Docker.

$ docker run -i --rm -p 8080:8080 quarkus-quickstart/quickstart
2019-03-18 03:21:00,052 INFO  [io.quarkus](main) Quarkus 0.11.0 started in 0.012s. Listening on: http://0.0.0.0:8080
2019-03-18 03:21:00,054 INFO  [io.quarkus](main) Installed features: [cdi, resteasy]

Dans mon environnement, j'ai pu le démarrer en un temps extrêmement court de "0,012 seconde", ce qui est impensable avec une application Java classique, comme dans l'exemple ci-dessus. Vous pouvez également vérifier le fonctionnement avec la commande suivante.

curl http://localhost:8080/hello
hello

En outre, l'utilisation de la mémoire est la suivante et vous pouvez voir que l'exemple d'application JAX-RS n'utilise que 1,2 Mo.

$ docker stats
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
b4d39bbe3159        eloquent_bohr       0.00%               1.281MiB / 1.952GiB   0.06%               1.04kB / 0B         0B / 0B             5

Déployer sur Kubernetes

Jusqu'à présent, vous avez créé un binaire Linux natif à partir du code source Java à l'aide de la commande Maven et démarré le binaire Linux en tant que conteneur. Ensuite, je souhaite déployer une application utilisant Quarkus sur Kuberntetes (minikube).

Créez des ressources Deployment / ReplicaSet / Pod à partir de l'image Docker créée précédemment avec la commande suivante.

$ kubectl run quarkus-quickstart --image=quarkus-quickstart/quickstart:latest --port=8080 --image-pull-policy=IfNotPresent
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/quarkus-quickstart created

Ensuite, créez une ressource Service avec la commande kubectl expose afin de pouvoir vérifier l'opération.

$ kubectl expose deployment quarkus-quickstart --type=NodePort
service/quarkus-quickstart exposed

Les ressources Kubernetes créées par les deux commandes ci-dessus sont les suivantes.

$ kubectl get all
NAME                                      READY   STATUS    RESTARTS   AGE
pod/quarkus-quickstart-7986c7cd95-44k9n   1/1     Running   1          1m

NAME                         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/kubernetes           ClusterIP   10.96.0.1      <none>        443/TCP          5m
service/quarkus-quickstart   NodePort    10.103.25.16   <none>        8080:32179/TCP   27s

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/quarkus-quickstart   1/1     1            1           1m

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/quarkus-quickstart-7986c7cd95   1         1         1       1m

Vous pouvez vérifier le fonctionnement de l'application Quarkus déployée sur Kubernetes (minikube) avec la commande suivante.

$ curl $(minikube service quarkus-quickstart --url)/hello/greeting/quarkus
hello quarkus

à la fin

Dans cet article, j'ai écrit sur "Contexte de l'apparence de Quarkus" et "Déploiement d'applications utilisant Quarkus sur Kubernetes". Comme mentionné ci-dessus, Quarkus accélère non seulement considérablement le démarrage, mais les éléments essentiels pour les applications de conteneur, tels que la petite taille d'image et l'utilisation de la mémoire, se trouvent en Java, qui compte un grand nombre de développeurs, y compris des entreprises. Je pense que c'était une sortie très importante dans le sens où c'est devenu possible.

Cependant, depuis qu'il vient d'être publié, nous avons également constaté qu'il existe diverses restrictions sur CDI et que la construction prend beaucoup de temps.

Quarkus semble être un produit publié par Red Hat, et est développé en tant que logiciel OSS (Open Source Software). Il vient juste de sortir et je pense que nous continuerons d'ajouter et d'améliorer des fonctions à l'avenir, alors j'aimerais continuer à regarder.

Informations de référence

Recommended Posts

Une vue d'ensemble du framework Java natif de Kubernetes Quarkus
J'ai essayé le framework Java "Quarkus"
Mesurer la taille d'un dossier avec Java
Awesome Java: excellent logiciel de bibliothèque de framework Java
[Java] Lors de l'écriture du source ... Mémorandum ①
Une note de révision de l'interface Spring Framework Resource
Un record d'étude du Spring Framework à partir de zéro
Une explication rapide des cinq types de statique Java
Pensez à une stratégie de mise à jour Java
[Java] Supprimer les éléments de la liste
Cause fondamentale du bogue du framework Java
[Édition Java] Histoire de la sérialisation
Trier la liste des objets Java
Un mémorandum du problème FizzBuzz
Considération sur le framework de persistance Java 2017 (1)
Une histoire sur l'utilisation de l'API League Of Legends avec JAVA
Obtenez l'URL publique du fichier privé de Flickr en Java
Une brève description des dépendances JAVA
Créons une application TODO en Java 5 Changer l'affichage de TODO
L'origine des expressions Java lambda
Augmenter dynamiquement le nombre d'éléments dans un tableau bidimensionnel Java (tableau multidimensionnel)
Une collection de phrases qui impressionne le "sentiment différent" de Java et de JavaScript
L'histoire de la création d'un lanceur de jeu avec une fonction de chargement automatique [Java]
Exprimons le résultat de l'analyse du code d'octet Java dans un diagramme de classes
Comment savoir quelle version Java d'un fichier de classe a été compilée
[Java] Comment accéder au début d'une chaîne spécifique à l'aide de la classe String
Exemple de programme qui renvoie la valeur de hachage d'un fichier en Java
Comment obtenir le chemin absolu d'un répertoire s'exécutant en Java
Nommer un groupe d'expressions régulières (Java)
Vérifiez le contenu du magasin de certificats Java
Examiner l'utilisation de la mémoire des éléments Java
[Java] Obtenez le jour d'un jour spécifique
Mémo: [Java] Vérifiez le contenu du répertoire
Comparer les éléments d'un tableau (Java)
Essayez d'exécuter Kubernetes Job à partir de Java
[jour: 5] J'ai résumé les bases de Java
Quelles sont les fonctionnalités mises à jour de Java 13
Mesurez facilement la taille des objets Java
Retour sur les bases de Java
Sortie du livre "Introduction à Java"
Fonctionnalités du framework Spring pour les développeurs Java
Enquête sur la fonction Java 8, consommateur, fournisseur, prédicat
L'histoire de l'écriture de Java dans Emacs
[Java] Vérifiez le nombre d'occurrences de caractères
Trouvez la différence à partir d'un multiple de 10
[Java] [Spring] Tester le comportement de l'enregistreur
framework java
Jusqu'au lancement d'un conteneur Docker construit avec RedHat Quarkus
Une histoire confirmant l'implémentation de la bibliothèque Java SendGrid lorsque la livraison du courrier échoue
Valider le jeton d'ID d'un utilisateur authentifié par AWS Cognito en Java
L'histoire de la comparaison de chaînes de bas niveau en Java
JAVA: jar, aar, affichez le contenu du fichier
L'histoire de la fabrication d'un Othello ordinaire à Java
À propos du guide de démarrage officiel de Spring Framework
A propos de l'ordre de description des propriétés système Java
À propos de l'idée des classes anonymes en Java
Avez-vous besoin d'une implémentation de Java compatible avec la mémoire?
Une histoire sur le JDK à l'ère de Java 11
Faire une marge à gauche du TextField
L'ordre des modificateurs de méthode Java est fixe
[Java] Accéder à l'URL signée de s3 (version signée 2)