Build & deploy JBoss EAP 8 images in OpenShift with Galleon & Helm charts



In Red Hat JBoss Enterprise Application Platform (JBoss EAP) 8, Galleon is the tool for provisioning server images for Red Hat OpenShift 4 via Podman for build images. You can use Galleon to create runtime server images, which combine the server and the application to be deployed. 

Learn more: How to use JBoss EAP 8.0’s new provisioning system

This build process can be done either locally—via Dockerfile, for example—or in a Red Hat OpenShift Container Platform 4 build via Helm charts (instead of the template builds, as in JBoss EAP 7), which also deploys the server plus application image. For deployments (and not builds), there is also an option to deploy the JBoss EAP image via JBoss EAP Operator 3.

For details on the Galleon layers, refer to the Red Hat Knowledgebase solution JBoss EAP 7 thin image and Capability Trimming in JBoss EAP for OpenShift. The cloud-default-config layer mimics what used to be present in the JBoss EAP 7.4.x image’s default installed server. 

Full examples and explanations

First, we’ll take a look at the local Dockerfile build, which provisions the JBoss EAP 8 server in a runtime image together with the image. Then I will explain a Helm chart build, which creates the BuildConfig and then deployments. Finally, we’ll walk through a simple example with the JBoss EAP Operator 3, which does not build (as in provision) images, but you can use it to deploy JBoss EAP images.

Local Dockerfile build

The following code shows a complete example of image provisioning:  

# Use EAP 8 Builder image to create a JBoss EAP 8 server with its default configuration
FROM registry.redhat.io/jboss-eap-8/eap8-openjdk17-builder-openshift-rhel8:latest AS builder
ENV GALLEON_PROVISION_FEATURE_PACKS=org.jboss.eap:wildfly-ee-galleon-pack,org.jboss.eap.cloud:eap-cloud-galleon-pack
ENV GALLEON_PROVISION_LAYERS=cloud-default-config
ENV GALLEON_PROVISION_CHANNELS=org.jboss.eap.channels:eap-8.0
ENV GALLEON_MAVEN_ARGS="-X -e" <---------- troubleshooting
RUN /usr/local/s2i/assemble
## EAP 8 Runtime image
FROM registry.redhat.io/jboss-eap-8/eap8-openjdk17-runtime-openshift-rhel8:latest AS runtime
# Set appropriate ownership and permissions.
COPY --from=builder --chown=jboss:root $JBOSS_HOME $JBOSS_HOME
# Ensure appropriate permissions for the copied files.
#RUN $JBOSS_HOME/bin/jboss-cli.sh --commands="core-service=/management-interface=http-interface/:remove" <--- in case a command must be set
COPY --chown=jboss:root helloworld.war $JBOSS_HOME/standalone/deployments/
#ENV CONFIG_IS_FINAL=true <--- in case the configuration doesn't need any deployment change
RUN chmod -R ug+rwX $JBOSS_HOME

Here is an explanation of this multi-stage build Dockerfile:

  1. First, the builder JBoss EAP image is fetched.
  2. Then, a few Galleon environment variables are set:
    • ENV GALLEON_PROVISION_FEATURE_PACKS: This is a required step for provisioning the feature packs for the deployment. In this example, the selected feature packs are org.jboss.eap:wildfly-ee-galleon-pack and org.jboss.eap.cloud:eap-cloud-galleon-pack.
    • ENV GALLEON_PROVISION_LAYERS=cloud-default-config: Another required step, this is the provisioning layer for deployment. In this example, cloud-default-config is selected, which mimics what used to be present in the JBoss EAP 7.4.x images default installed server. 
    • ENV GALLEON_PROVISION_CHANNELS=org.jboss.eap.channels:eap-8.0: This is a required step for setting the provisioning channel, which is the channel that brings the jars for the loading. 
    • ENV GALLEON_MAVEN_ARGS="-X -e": This is an optional step for troubleshooting.
  3. The assembled script within the JBoss EAP 8 image is triggered.
  4. As a segue from the above, the JBoss EAP 8 is moved to the builder image after the runtime image is loading.
  5. Finally, the application helloworld.war is deployed by copying from local to /deployments.

The JBoss EAP 8 image will be created using the runtime image, so it is suitable for runtime deployment. You can add extra tools and scripts inside the image if needed, such as an instrumentation agent.

Helm chart build/deployment

To build and deploy the Helm charts, there are three steps:

  1. Add the Helm repo—for example: helm repo add jboss-eap https://jbossas.github.io/eap-charts/
  2. Create the YAML value file with the details for the build and deployment settings. This value file is used by the chart for the build/deployment and you can customize it—for instance, adding settings like MAVEN_OPTS.
  3. Given a value file, use the chart configuration in the HelloWorld project. For example, helm install helloworld -f charts/helm.yaml jboss-eap/eap8, given a value file as below:

    build:
      uri: https://github.com/jboss-developer/jboss-eap-quickstarts.git
      ref: 8.0.x
      contextDir: helloworld
      env:
      - name: MAVEN_OPTS_APPEND <- vs MAVEN_OPTS
        value: '-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m'
    deploy:
      replicas: 1

Here is an example:

### Example:
###$ helm install helloworld -f custom-helm.yaml jboss-eap/eap8
NAME: helloworld
LAST DEPLOYED: Wed Jun 19 16:49:40 2024
NAMESPACE: eap8
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Your EAP 8 application is building! To follow the build, run:
###
###
### This will create the buildconfig:
$ oc get bc
NAME                         TYPE     FROM         LATEST
helloworld                   Docker   Dockerfile   2
helloworld-build-artifacts   Source   [email protected]    1
###
### Show pods:
### oc get pod
NAME                                 READY   STATUS      RESTARTS   AGE
helloworld-2-build                   0/1     Completed   0          4m9s <---- build
helloworld-66f857dfbf-92lzj          1/1     Running     0          3m28s
helloworld-66f857dfbf-l2m6n          1/1     Running     0          3m28s
helloworld-66f857dfbf-xmfwz          1/1     Running     0          3m28s
helloworld-build-artifacts-1-build   0/1     Completed   0          7m5s <---- build

Above is a fairly trivial example of a value file passing just the URI and the contextDir for reference, but also Maven extra arguments, which will be added in the BuildConfig called -build-artifacts. See below:

$ oc get bc helloworld-build-artifacts -o yaml  | grep -a1 MAVEN
        value: extensions
      - name: MAVEN_OPTS_APPEND
        value: -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m

More complex deployments (as in value files) can include more specifications on the build, setting the output as ImageStream, but also—and very importantly—deployment settings, such as probes and route details, which include the type of termination (passthrough, re-encrypt, edge). See the example below:

image:
 tag: latest
build:
 enabled: true
 mode: bootable-jar
 bootableJar:
   builderImage: registry.access.redhat.com/ubi8/openjdk-11:latest
 s2i:
   version: latest
   jdk: "11"
   arch: amd64
   amd64:
     jdk11:
       builderImage: registry.redhat.io/jboss-eap-7/eap-xp3-openjdk11-openshift-rhel8
       runtimeImage: registry.redhat.io/jboss-eap-7/eap-xp3-openjdk11-runtime-openshift-rhel8
 output:
   kind: "ImageStreamTag"
 triggers: {}
deploy:
 enabled: true
 replicas: 1
 route:
   enabled: true
   tls:
     enabled: true
     termination: edge
     insecureEdgeTerminationPolicy: Redirect
 livenessProbe:
   httpGet:
     path: /health/live
     port: admin
   initialDelaySeconds: 60
 readinessProbe:
   httpGet:
     path: /health/ready
     port: admin
   initialDelaySeconds: 60

JBoss EAP Operator 3 deployment

For the sake of completeness in terms of OCP 4 deployment, here is the core about deploying EAP 8 using the JBoss EAP Operator 3.

First of all, although you cannot provision JBoss EAP 8 via JBoss EAP Operator 3 (JBoss EAP Operator version 3 for JBoss EAP 8 necessarily), you can build the JBoss EAP 8 images (local build using Podman or OpenShift’s build via BuildConfig for example) and then use the JBoss EAP Operator 3 to deploy the built image directly. 

Therefore, a JBoss EAP 8 image—combining the JBoss EAP and the application—is a requirement here. So that this image can be deployed via JBoss EAP 3 Operator as well, as an option for deployment.

To accomplish this—having a JBoss EAP 8 image already with the application:

  1. Install the JBoss EAP Operator via the Operator Hub, following the solution described in How to deploy Red Hat EAP 7 in OpenShift 4 using Operator, the operator will provide the WildflyServer Custom Resource, which is the API this operator provides extending OpenShift Container Platform 4 resources.
  2. Create a WildflyServer Custom Resource passing the image the JBoss EAP 8 image is built as an image in the spec field.

    Example:

    apiVersion: wildfly.org/v1alpha1
                    kind: WildFlyServer
                    metadata:
                      name: example
                      namespace: openshift-operators
                    spec:
                      replicas: 0
                      applicationImage: image-registry.openshift-image-registry.svc:5000/eap-demo/eap-app-build-artifacts:latest

Again, note the JBoss EAP 8 Operator does not provision the JBoss EAP 8 image, but it does the deployment of that image, which can be a good option for deployments instead of using Helm charts given how simple it is to use the WildflyServer Custom Resource.

Other provisioning approaches

There are several methods for provisioning JBoss EAP 8:

  • Provisioning with Dockerfile passing Galleon env variables (shown above).
  • Provisioning using a pom.xml, which should include the eap-maven-plugin, where the layers are set in the pom.xml. See more details here.
  • Provisioning using a provisioning.xml file, where the layers are set in the provisioning.xml file rather than a pom.xml or the Dockerfile/build file. More details for those can be found here.

Maven details

Although not the main focus of this article, which is about the generic usage of Galleon for JBoss EAP 8 provisioning, I will also explain some details about the Maven settings. 

First, for simple argument setting when invoking Maven on the build, MAVEN_OPTS or MAVEN_OPTS_APPEND should cover most use cases. 

For more advanced manipulation, you can provide a custom settings.xml file in the directory /tmp/src/galleon. It is advisable to copy the one in /home/jboss/.m2 and improve from there with the specific settings required. This can come in handy, for instance, in setting custom timeouts and other Maven details:

120000 
10000 

By the Source-to-Image (S2I) logic, it is expected the /tmp/src directory to contain application sources but also Maven settings for galleon can be located as well. 

Finally, when using the /tmp/src/galleon/settings.xml be aware of conflicts: if both files exist, their contents will get merged, with the user-specific settings.xml being dominant. 

This impacts situations where the user has conflicting environment variables such as custom proxy settings such as MAVEN_MIRROR_URL that may conflict with Red Hat’s building proxy settings. To prevent those clashes with Red Hat’s env variables in the S2I build necessarily, use unique environment names to be injected into the settings.xml

Troubleshooting details

To troubleshoot the Maven build itself, you can set the following:

  • For Podman/Docker builds, use ENV GALLEON_MAVEN_ARGS="-X -e", which is useful for debugging settings when GALLEON_PROVISION_LAYERS is set.
  • For Helm chart deployment, you can use MAVEN_OPTS and MAVEN_ARGS_APPEND, for overwriting (less recommended) and appending the Maven settings, respectively. 

To troubleshoot the Podman/Docker build process, you can set the following:

  • For Podman/Docker verbose debugging: 

    podman build --log-level debug.
  • To capture a pprof profile, start the Podman service with the following: 

    $ podman system service --log-level=debug --time 0 --pprof-address=localhost:9999. 

    This will have the pprof service listen on the localhost port of 9999, via TCP; we can restart the process with this, and when the CPU raises again we can gather a performance profile: 

    $ curl -o trace.out http://localhost:9090/debug/pprof/trace?seconds=60. 

    That will get a 60-second performance profile and callgraph from podman-system-service which should tell us what we’re spending our time in. Replace with an adequate port for your use case.

Container details

In terms of container deployment, JBoss EAP images are based on the Red Hat build of OpenJDK, so they are container-aware. This means the container size will dictate the heap size in a 50% or 80% percentage of the container size. Therefore, we usually suggest deploying the JBoss EAP containers with memory and CPU limits, which are the ones OpenJDK will take into consideration and set the adequate pod Quality of Service (QoS) for the criticality of the application within the cluster.

This means, from the user’s perspective:

  • The CPU settings will be automatically deducted from the deployment’s limits.
  • The heap allocation is deduced from MaxRAMPercentage, which already comes by default in OpenJDK images at 50% heap (or 80% heap).
  • There is no need to set Xmx, Xms, or even MaxRAM directly. The heap is deduced as a percentage of the container size and the native region is deduced as the remainder part.

Conclusion

In JBoss EAP 8, there is a paradigm shift where the JBoss EAP images will not bring the JBoss EAP server, but rather the server is provisioned by Galleon via the Source-to-Image process: the server itself is provisioned via S2I on both runtime and builder images and cannot be deployed directly as in EAP 7 images.

Also, for container builds (Podman), this means you can perform a multi-stage build as long as the correct Galleon settings are provided via environment variables in the Dockerfile.

As a consequence of the above, the images will be lighter but also easier to patch, given the images are not correlated with the JBoss EAP jars directly but via Galleon channels, which bring the most updated jars.

This might contrast with JBoss EAP 7’s template usage where not (just) the application is built. Underneath, however, there were indeed two BuildConfigs already, as explained on Troubleshooting EAP 7 local BuildConfig in OCP 4

Finally, in terms of containers, given that JBoss EAP 8 is a Java application that is container-aware (i.e., the Java virtual machine (JVM) can detect container limits and impose those limits at runtime), you do not need to worry about setting Xmx/Xms in the container as JVM flags, but rather just the container setting. Given the specific target on the Galleon tool and the scope of this article, we did not cover other build methods such as Tekton and Shipwreck.

Additional resources

To learn more, read Using Java Container awareness  and Java 17: What’s new in OpenJDK’s container awareness.

For any other specific inquiries, please open a case with Red Hat support. Our global team of experts can help you with any issues.

A big merci to Jean Francois Denise for his contributions to this article/discussions on Galleon and Alexander Barbosa for his great input on Helm charts deployments and review of this article. 



Source link

Related Posts

About The Author

Add Comment