Apache Karaf : Docker, Kubernetes

Apache Karaf : Docker, Kubernetes

Apache Karaf™ n’est pas seulement un serveur, il peut être aussi utilisé de manière « statique ». La plupart des utilisateurs connaissent la distribution « standard ». Découvrez les autres approches de la solution.

Adaptation de l’article :  «Apache Karaf dynamic and static approach, docker and kubernetes» du blog Nanthrax écrit par Jean-baptiste Onofré (Technical Advisor)

Docker

Si Docker est installé sur votre machine, vous pouvez utiliser le profil docker pour créer directement l’image Docker :$ mvn clean install -Pdocker

Si vous n’avez pas de docker sur votre machine, la compilation crée au moins un Dockerfile. Par défaut, le nom de l’image du docker est karaf. Vous pouvez passer aussi le nom de l’image en utilisant la configuration imageName :

<configuration>
  <imageName>${project.artifactId}</imageName>
</configuration>

Vous pouvez utiliser ce dossier Dockerfile (et l’ensemble du dossier cible) pour créer l’image Docker avec :

$ cd target
$ docker build -t mykaraf .
Sending build context to Docker daemon  57.41MB
Step 1/7 : FROM openjdk:8-jre
 ---> d60154a7d9b2
Step 2/7 : ENV KARAF_INSTALL_PATH /opt
 ---> Running in 9518c5e2141e
Removing intermediate container 9518c5e2141e
 ---> c49033d75fef
Step 3/7 : ENV KARAF_HOME $KARAF_INSTALL_PATH/apache-karaf
 ---> Running in 6a8f314162ea
Removing intermediate container 6a8f314162ea
 ---> 6bd1124f27c9
Step 4/7 : ENV PATH $PATH:$KARAF_HOME/bin
 ---> Running in ab00f87fda1d
Removing intermediate container ab00f87fda1d
 ---> cfa06b1e5bce
Step 5/7 : COPY assembly $KARAF_HOME
 ---> c74c5a3adda3
Step 6/7 : EXPOSE 8101 1099 44444 8181
 ---> Running in 667de77413bc
Removing intermediate container 667de77413bc
 ---> ee720e290d7f
Step 7/7 : CMD ["karaf", "run"]
 ---> Running in d283a0c53d93
Removing intermediate container d283a0c53d93
 ---> 23eb3c781a39
Successfully built 23eb3c781a39
Successfully tagged mykaraf:latest

Votre image Docker est prête.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mykaraf             latest              23eb3c781a39        26 seconds ago      463MB

Si vous avez utilisé le profil du docker, vous avez une image karaf Docker prête :

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
karaf               latest              f12b3148c33e        3 seconds ago       463MB

Par défaut, le runtime s’exécute en avant-plan. Nous pouvons utiliser -d pour exécuter en mode deamon :

$ docker run --name mykaraf -p 8181:8181 -d karaf
c05645357cd17a0828ef7acaf619071cc3c94f316ca605217890371c0c1e4ab0

Nous pouvons voir le journal de bord de notre conteneur :

$ docker logs mykaraf
docker logs mykaraf
karaf: Ignoring predefined value for KARAF_HOME
Mar 21, 2019 3:56:45 PM org.apache.karaf.main.Main launch
INFO: Installing and starting initial bundles
Mar 21, 2019 3:56:45 PM org.apache.karaf.main.Main launch
INFO: All initial bundles installed and set to start
Mar 21, 2019 3:56:45 PM org.apache.karaf.main.Main$KarafLockCallback lockAcquired
INFO: Lock acquired. Setting startlevel to 100
15:56:45.831 INFO  [FelixStartLevel] Logging initialized @946ms to org.eclipse.jetty.util.log.Slf4jLog
15:56:45.844 INFO  [FelixStartLevel] EventAdmin support is not available, no servlet events will be posted!
15:56:45.845 INFO  [FelixStartLevel] LogService support enabled, log events will be created.
15:56:45.847 INFO  [FelixStartLevel] Pax Web started
15:56:46.055 INFO  [paxweb-config-1-thread-1] No ALPN class available
15:56:46.055 INFO  [paxweb-config-1-thread-1] HTTP/2 not available, creating standard ServerConnector for Http
15:56:46.071 INFO  [paxweb-config-1-thread-1] Pax Web available at [0.0.0.0]:[8181]
15:56:46.075 INFO  [paxweb-config-1-thread-1] Binding bundle: [org.apache.karaf.examples.karaf-docker-example-app [15]] to http service
15:56:46.093 INFO  [paxweb-config-1-thread-1] will add org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer to ServletContainerInitializers
15:56:46.093 INFO  [paxweb-config-1-thread-1] added ServletContainerInitializer: org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer
15:56:46.094 INFO  [paxweb-config-1-thread-1] will add org.apache.jasper.servlet.JasperInitializer to ServletContainerInitializers
15:56:46.094 INFO  [paxweb-config-1-thread-1] Skipt org.apache.jasper.servlet.JasperInitializer, because specialized handler will be present
15:56:46.094 INFO  [paxweb-config-1-thread-1] will add org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer to ServletContainerInitializers
15:56:46.132 INFO  [paxweb-config-1-thread-1] added ServletContainerInitializer: org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer
15:56:46.163 INFO  [paxweb-config-1-thread-1] registering context DefaultHttpContext [bundle=org.apache.karaf.examples.karaf-docker-example-app [15], contextID=default], with context-name: 
15:56:46.174 INFO  [paxweb-config-1-thread-1] registering JasperInitializer
15:56:46.203 INFO  [paxweb-config-1-thread-1] No DecoratedObjectFactory provided, using new org.eclipse.jetty.util.DecoratedObjectFactory[decorators=1]
15:56:46.272 INFO  [paxweb-config-1-thread-1] DefaultSessionIdManager workerName=node0
15:56:46.273 INFO  [paxweb-config-1-thread-1] No SessionScavenger set, using defaults
15:56:46.274 INFO  [paxweb-config-1-thread-1] node0 Scavenging every 660000ms
15:56:46.284 INFO  [paxweb-config-1-thread-1] Started HttpServiceContext{httpContext=DefaultHttpContext [bundle=org.apache.karaf.examples.karaf-docker-example-app [15], contextID=default]}
15:56:46.289 INFO  [paxweb-config-1-thread-1] jetty-9.4.12.v20180830; built: 2018-08-30T13:59:14.071Z; git: 27208684755d94a92186989f695db2d7b21ebc51; jvm 1.8.0_181-8u181-b13-2~deb9u1-b13
15:56:46.324 INFO  [paxweb-config-1-thread-1] Started default@28e475cc{HTTP/1.1,[http/1.1]}{0.0.0.0:8181}
15:56:46.324 INFO  [paxweb-config-1-thread-1] Started @1444ms
15:56:46.326 INFO  [paxweb-config-1-thread-1] Binding bundle: [org.ops4j.pax.web.pax-web-extender-whiteboard [48]] to http service
15:56:46.328 INFO  [paxweb-config-1-thread-1] Binding bundle: [org.apache.karaf.http.core [16]] to http service

Nous avons accès à http://localhost:8181/servlet-example dans votre navigateur. Ensuite, vous voyez les journaux mis à jour dans le conteneur Docker :

$ docker logs mykaraf
...
15:58:24.068 INFO  [qtp117150641-37] Client 172.17.0.1 request received on http://localhost:8181/servlet-example

Nous pouvons arrêter le conteneur Docker:

$ docker stop mykaraf
mykaraf

Fonctionnement de AWS avec Kubernetes

Maintenant que nous avons notre image Docker prête, nous pouvons passer à AWS ECR (Docker container Registry).

Tout d’abord, nous créons un référentiel ECR sur AWS :

yupiik-article-blog-apache-karaf-docker-kubernetes-2

Ensuite, nous marquons et poussons notre image vers AWS ECR (en prenant l’utilisateur IAM) :

$ docker tag karaf:latest 295331841498.dkr.ecr.eu-west-1.amazonaws.com/karaf:latest
$ aws ecr get-login --no-include-email --region eu-west-1 
$ docker push 295331841498.dkr.ecr.eu-west-1.amazonaws.com/karaf:latest

Maintenant, nous pouvons voir notre image Karaf dans ECR.

yupiik-article-blog-apache-karaf-docker-kubernetes-3

Maintenant que nous avons notre image Docker sur ECR, nous pouvons créer un cluster utilisable.

Utiliser ECS

ECS gère directement les conteneurs des dockers (tâches).

Nous créons un cluster ECS.

yupiik-article-blog-apache-karaf-docker-kubernetes-4

Nous ajoutons ici une nouvelle tâche (conteneur Docker)

Nous pouvons voir l’adresse IP publique sur la tâche et donc l’utiliser directement dans un navigateur :

yupiik-article-blog-apache-karaf-docker-kubernetes-9

Nous pouvons voir les journaux mis à jour :

yupiik-article-blog-apache-karaf-docker-kubernetes-10

Nous pouvons mettre à jour le service pour avoir plusieurs conteneurs en cours d’exécution :

yupiik-article-blog-apache-karaf-docker-kubernetes-11
yupiik-article-blog-apache-karaf-docker-kubernetes-12

Nous pouvons voir le service en utilisant 5 instances maintenant :

yupiik-article-blog-apache-karaf-docker-kubernetes-13

Au lieu d’ECS, vous pouvez utiliser Kubernetes sur le cluster EKS.

Utiliser EKS

Tout d’abord, créons le cluster EKS sur AWS :

yupiik-article-blog-apache-karaf-docker-kubernetes-14

Nous pouvons maintenant accéder à cette grappe à l’aide de notre kubectl local.

$ aws eks update-kubeconfig ...
$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   50m

Nous créons maintenant quelques nœuds dans notre cluster :

yupiik-article-blog-apache-karaf-docker-kubernetes-15

Une fois que les nœuds font partie de notre cluster, nous créons un descripteur POD avec notre image Karaf :

apiVersion: v1
kind: Pod
metadata:
  name: karaf-docker-example-dist
spec:
  containers:
    - name: karaf-docker-example-dist-ct
      image: 295331841498.dkr.ecr.eu-west-1.amazonaws.com/karaf:latest
      resources:
        limits:
          memory: "500Mi"
        requests:
          memory: "250Mi"
      command: ["karaf", "run"]
      args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]

Ensuite, nous créons le POD dans le cluster EKS :

$ kubectl create -f karaf-docker-example-dist.yaml 
pod/karaf-docker-example-dist created

Nous pouvons voir notre POD boostrappé dans EKS :

$ kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
karaf-docker-example-dist   0/1     Pending   0          2m

Conclusion

Nous pouvons voir la flexibilité d’Apache Karaf  puisqu’il supporte deux approches complètement différentes :

  1. L’approche « dynamic/container » (alias distribution « standard ») : permet de démarrer Karaf en tant que « conteneur » et de déployer dynamiquement de nouvelles applications au moment de l’exécution.
  2. L’approche « statique » : permet de tout packager au moment de la compilation et d’amorcer facilement votre application alimentée par Karaf.

Vos applications sont capables de fonctionner dans les deux modes, ce n’est qu’une question d’assemblage, de package et de distribution.

Nous pouvons voir ici l’aspect « polymorphe » où vous pouvez l’utiliser sur place, sur le cloud, en tant que conteneur, en tant que bootstrapper, pour les petites et grandes plateformes de production.

Dans les prochaines versions, l’équipe d’Apache Karaf travaillent à fournir un meilleur outillage pour dev et devops.

Restez à l’écoute !

Bloqué dans vos roadmaps ?

Vous souhaitez former vos équipes ?

fr_FRFrançais
en_GBEnglish (UK) fr_FRFrançais