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:
- First, the builder JBoss EAP image is fetched.
- 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 areorg.jboss.eap:wildfly-ee-galleon-pack
andorg.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.
- The assembled script within the JBoss EAP 8 image is triggered.
- As a segue from the above, the JBoss EAP 8 is moved to the builder image after the runtime image is loading.
- 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:
- Add the Helm repo—for example:
helm repo add jboss-eap https://jbossas.github.io/eap-charts/
- 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
. -
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
. 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:
- 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. -
Create a
WildflyServer Custom Resource
passing the image the JBoss EAP 8 image is built as an image in thespec
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 theeap-maven-plugin
, where the layers are set in thepom.xml
. See more details here. - Provisioning using a
provisioning.xml
file, where the layers are set in theprovisioning.xml
file rather than apom.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 whenGALLEON_PROVISION_LAYERS
is set. - For Helm chart deployment, you can use
MAVEN_OPTS
andMAVEN_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 evenMaxRAM
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 BuildConfig
s 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.