Skip to content

Commit 87c63da

Browse files
AI generated initial content by Rapid Codebase Builder (RCB)
Transcript text generated using Gemini via RCB.
1 parent 5407386 commit 87c63da

31 files changed

Lines changed: 491 additions & 0 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
In this module, we will cover how to launch and access your lab environment using the Red Hat Demo Platform, or RHDP.
2+
3+
To get started with your lab, first log in to the RHDP portal. Once logged in, search for the specific lab catalog entry by name. Select that entry from the search results, and on the catalog page, click the "Order" button. You will be prompted to fill out the required details in the order form.
4+
5+
Before completing your request, please carefully review the warning at the bottom of the form, and then check the box labeled, “I confirm that I understand the above warnings.” Finally, click the "Order" button to place your request.
6+
7+
There are a few important details to keep in mind. First, please note that the lab may take a few minutes to provision and become ready for use. Once it is prepared, you will receive an email containing your access details. You can also retrieve these access details directly from the RHDP portal at any time.
8+
9+
To access your lab through the portal, simply click on the "Services" option located in the left-hand menu. From there, select your lab from the list on the right side of the page to view your specific access information.
10+
11+
If you need to revisit the portal, Red Hat associates can navigate to demo dot red hat dot com, while Red Hat partners should visit partner dot demo dot red hat dot com. You can find these links in the referenced documentation.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
To begin this training, you will need to access your lab environment. Please follow the instructions provided for your specific platform to ensure you are properly set up for these hands-on exercises.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
To get started with your training, you will need to set up your lab environment using the Red Hat Online Learning, or ROLE, platform. Please follow these steps to launch your lab:
2+
3+
First, log in to the ROLE platform. You can find the appropriate portal links for Red Hat associates and partners in the resource section of this course.
4+
5+
Once you are logged in, search the catalog for the entry labeled "FIXME Lab Catalog Name." When you see it in your search results, click the "Launch" button.
6+
7+
From the course page, select the "Lab Environment" tab, and then click the "Create" button to begin the launch process.
8+
9+
Please wait a few moments for the system to complete the lab creation. Once it is ready, refer to the "SSH Private Key & Instructions" section provided on the page. These details contain everything you need to access your lab environment.
10+
11+
If you need to access the portal again, remember that Red Hat associates should use the internal role dot r-h-u dot red hat dot com address, while Red Hat partners should use the standard role dot red hat dot com portal.

‎modules/LABENV/images/index.txt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Welcome to the lab environment. In this section, we will cover the instructions for accessing the environment you will use for this hands-on training.
2+
3+
To complete these exercises, you do not need any special or highly specific OpenShift cluster features. A standard OpenShift Container Platform environment is perfectly sufficient, provided you have the necessary permissions to deploy an application. Whether you choose to deploy via a StatefulSet, a pod YAML file, or a standard deployment, you will have everything you need to successfully test Java container awareness, as well as its associated features and limitations.

‎modules/ROOT/images/index.txt‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Welcome to the course on Java Container Awareness. This training provides in-depth details and explanations regarding how Java functions within containerized environments. You can expect to complete this course in approximately one to two hours.
2+
3+
Throughout this program, we will cover several key areas, starting with an introduction to containerized Java. We will then examine how containers detect resources, explore the risks and best practices for memory management, and look at integration with OpenShift and Kubernetes. Finally, we will cover essential troubleshooting techniques and tooling, and wrap up with a hands-on lab to put your knowledge into practice.
4+
5+
Before we begin, please ensure you meet the course prerequisites. This training assumes you have a general understanding of Java, including how heap and off-heap memory allocation works. Additionally, you should have some experience with OpenShift, specifically regarding the deployment process, though expert knowledge of operators is not required.
6+
7+
Let's get started.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
To wrap up this course, we have compiled a list of complementary materials to help you further your learning. These resources cover essential topics such as Java container awareness, middleware troubleshooting in OpenShift 4, and troubleshooting Spring Boot applications. We also include guides on understanding the impact of cgroups v2 on your applications and how to resolve application issues following an OpenShift upgrade. You can find these articles by consulting the documentation links provided in the course materials.
2+
3+
Finally, for a complete reference guide, you can download the course PDF, which is available in the resources section.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
In this session, we will look at container resource detection. This feature is essential for ensuring the Java Virtual Machine can accurately identify the resource constraints imposed by your container environment, rather than defaulting to the limits of the underlying host node.
2+
3+
To understand why this is so important, let's look at the key concepts:
4+
5+
First, consider the evolution of the JVM. Starting with Java 8 update 191, the JVM gained the built-in ability to parse control group files, also known as cgroups. This allows the Java process to correctly determine its resource boundaries.
6+
7+
Second, this applies directly to memory limit detection. The JVM can now identify the specific memory limit assigned to the container. This enables it to scale the heap size appropriately based on the actual resources available to that container.
8+
9+
Third, the JVM also detects the number of CPU cores allocated to the container. This is a significant improvement, as it prevents over-provisioning and ensures efficient thread management within your containerized environment.
10+
11+
Finally, there are clear operational benefits to using these features. By accurately detecting these limits, you prevent "out-of-memory" errors that often occur when the JVM incorrectly defaults to the host’s physical memory instead of respecting your container-specific limits.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
In modern Java deployments, it is critical that the Java Virtual Machine correctly identifies the memory boundaries imposed by your container orchestration platform. If the JVM fails to do so, it can lead to performance degradation, inefficient resource use, or unexpected pod terminations.
2+
3+
Let’s look at why container awareness is so important. Before the integration of a specific fix in Java 8 update 191, the JVM relied on standard operating system utilities to detect available memory. In a containerized environment, those utilities often reported the total memory of the underlying physical host rather than the restricted memory assigned to the specific container.
4+
5+
If the JVM perceives the host node's total memory instead of your container's limit, it might try to allocate a heap size that exceeds the container's threshold. This leads to an "Out of Memory" exception or, more commonly, a "SIGKILL" signal from the Linux kernel’s OOM killer, which shuts down your application abruptly.
6+
7+
To avoid this, the JVM inspects the control group filesystem when running in a container-aware environment. By reading files under the "/sys/fs/cgroup/memory" directory, the JVM determines the hard limits imposed by the orchestrator.
8+
9+
When verifying these limits, you should rely on built-in JVM diagnostic flags rather than standard Linux utilities like "free," "top," or "lscpu."
10+
11+
It is important to remember that these standard utilities are not container-aware. They will report the resources of the physical host node, which will lead you to incorrect diagnostic conclusions. Instead, you should use container-aware tools like "jcmd" or the JVM flag "-XshowSettings:system."
12+
13+
The most direct way to verify what the JVM has detected is to pass the "-XshowSettings:system" flag during application startup. When you do this, the JVM outputs operating system metrics. You will see specific lines reflecting the memory limit, soft limit, and CPU metrics. If the memory limit value matches your OpenShift or Kubernetes configuration, you can be confident that the JVM is successfully performing container detection.
14+
15+
If your application is failing to respect these limits, you might notice two specific symptoms. First, host-level reporting where standard commands show memory values matching the physical node. Second, frequent "OOM Killer" terminations, where the pod restarts despite your heap settings appearing reasonable.
16+
17+
There are two primary scenarios to watch out for. The first is underutilization, where the application heap is significantly smaller than the container limit because it defaulted to a fraction of the host's massive memory. This often leads to frequent garbage collection pauses. The second is overutilization, where the application heap and off-heap memory are larger than the container limit, which will eventually trigger an OOMKill event.
18+
19+
To analyze these resource constraints effectively, follow this diagnostic strategy:
20+
First, inspect your pod logs to confirm if your startup scripts are correctly calculating heap sizes based on container limits.
21+
Second, verify the output of "jcmd" with the "VM.info" command to ensure the JVM has correctly parsed the memory controller settings.
22+
Finally, always compare the memory limit reported by the JVM against the resource limits defined in your OpenShift deployment configuration.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
In this lesson, we will explore how to determine CPU availability within containerized environments.
2+
3+
In traditional virtualized or bare-metal setups, the Java Virtual Machine, or JVM, simply queries the operating system to see how many physical CPUs are available on the host. However, in modern containerized environments like Red Hat OpenShift or Kubernetes, a container is restricted to only a subset of those host resources. If the JVM is not container-aware, it may incorrectly identify the host’s total CPU count rather than the container's allocated limit. This mismatch can lead to inefficient thread pool sizing and improper garbage collection configuration, which often results in performance degradation.
4+
5+
Modern versions of the JDK, specifically Java 8 update 191 and all subsequent versions, are designed to be container-aware. They use cgroups, or Control Groups, to determine CPU availability by reading the cgroup filesystem to calculate the active processor count.
6+
7+
When running inside a container, the JVM looks at two primary metrics. The first is CPU shares, which represent the relative weight of the container. The second is the CPU quota and period, which define a hard limit on resources. The JVM calculates the final number of processors by taking the minimum value between the host’s total processors and the calculated limit imposed by these cgroup values.
8+
9+
When diagnosing your environment, it is important to distinguish between non-container-aware tools and container-aware tools. Tools like `lscpu` or `nproc` are non-container-aware; they return the total CPU count of the underlying OpenShift node, which is often misleading for capacity planning. In contrast, JVM-specific tools like `jcmd` or the `-XX:+PrintFlagsFinal` flag provide the active processor count as the JVM actually perceives it.
10+
11+
To verify this yourself, you can use the `jcmd` utility. First, access your pod terminal using the `oc rsh` command, followed by your pod name. Next, run the `jcmd` command with your process ID to request the VM information. When you review the output, look specifically for the container section. A container-aware JVM will report an `active_processor_count` that matches the CPU limit you have set for that container.
12+
13+
To keep your applications running efficiently, follow these best practices. Always explicitly define your CPU limits in your OpenShift deployment YAML to ensure cgroup values are populated correctly. Avoid oversizing your CPU limits; if you set a very high limit but your application is single-threaded, the JVM might spawn excessive garbage collection threads, leading to unnecessary overhead. Finally, always monitor the active processor count. If it does not match your expectations, ensure you are running a supported OpenJDK version. If you are ever forced to use an older version that is not container-aware, you must manually set the `ActiveProcessorCount` flag to match your container limit.
14+
15+
Now, let's look at a hands-on exercise to inspect CPU awareness. First, identify your Java process ID by running the `jps` command inside your container. Second, query the VM metadata by running `jcmd` with your process ID, and pipe that into a grep command to search for `active_processor_count`. Finally, compare this result with the output of the `nproc` command in the same terminal. If `nproc` returns the host’s total CPU count, such as 64, but your active processor count correctly identifies your container limit, such as 2, then your application is correctly container-aware.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Before the introduction of specific container-aware updates, the Java Virtual Machine, or JVM, lacked the ability to natively see the resource boundaries imposed by container runtimes. This caused significant operational friction in cloud-native environments.
2+
3+
Let’s look at the challenge caused by this JVM resource blindness. In early containerized environments, the JVM would query the underlying host operating system for available resources, such as total system memory and available CPU cores, rather than the specific cgroup limits applied to the container.
4+
5+
This behavior led to a critical disconnect. First, regarding memory miscalculation: the JVM would attempt to size its heap based on the host's physical RAM, often exceeding the container's hard memory limit set by Kubernetes or OpenShift. Second, this frequently triggered the OOM Killer. Once the Java process exceeded the container's cgroup memory limit, the node kernel's Out-Of-Memory Killer would terminate the process, leading to unexpected pod restarts. Finally, CPU throttling issues occurred because the JVM would perceive all host cores as available, leading to inefficient thread pool sizing and potential overhead, such as context-switching and threads competing for resources.
6+
7+
To address these issues, the OpenJDK community introduced a critical enhancement known as JDK8146115. This provided the necessary infrastructure for the JVM to correctly read and respect cgroup memory and CPU limits. Instead of querying system files that reflect host-level resources, the JVM was updated to inspect the cgroup filesystem directly. This allows the JVM to identify the specific constraints applied to its own process namespace.
8+
9+
While JDK8146115 provided the foundational logic, the release of Java 8u191 served as the catalyst for widespread adoption. This update backported the container-awareness features, effectively bringing modern cloud-native capabilities to long-standing Java 8 applications.
10+
11+
Several key changes were introduced in 8u191. First, the JVM now features native cgroup awareness, meaning it automatically detects container limits at startup. Second, the default ergonomics were improved; the default heap size calculation logic was updated to use a fraction of the container’s memory limit instead of the host's physical memory. Finally, new JVM flags were introduced, such as dash-XX-colon-Max-RAM-Percentage, dash-XX-colon-Min-RAM-Percentage, and dash-XX-colon-Initial-RAM-Percentage. These allow developers to define heap sizes as a ratio of the container limit rather than using hard-coded values.
12+
13+
This had a significant impact on modern deployments. With Java 8u191 and later, the relationship between the container and the JVM became coupled. In the legacy, pre-8u191 environment, the JVM queried host RAM, required manual dash-X-m-x configuration, and changing container sizes required manual JVM tuning. By contrast, modern behavior sees the JVM querying cgroups directly, automatically scaling the heap based on memory percentage flags, and automatically adjusting the heap whenever container limits are scaled.
14+
15+
By aligning the JVM's view of resources with the container orchestration layer, these updates eliminated the decoupling problem. Developers no longer need to manually synchronize heap settings with pod resource limits, which significantly simplifies the management of Java applications in Red Hat OpenShift and Kubernetes environments.

0 commit comments

Comments
 (0)