{"id":4574,"date":"2023-12-11T01:01:31","date_gmt":"2023-12-11T01:01:31","guid":{"rendered":"https:\/\/www.javaadvent.com\/?p=4574"},"modified":"2023-12-09T14:07:34","modified_gmt":"2023-12-09T14:07:34","slug":"production-grade-kubernetes-for-java-developers","status":"publish","type":"post","link":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html","title":{"rendered":"Production-Grade Kubernetes for Java Developers"},"content":{"rendered":"<p><span style=\"font-weight: 400\">What does it mean to be a good Java Cloud Citizen? It&#8217;s definitely more than just putting an application in a container and deploying it. It is essential to consider factors such as providing real-time health status through fine-grained metrics to optimize your Java application&#8217;s performance and resilience in the cloud, . You\u2019ll also need to ensure fast startup, and avoid excessive resource consumption within the cluster.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Being a good Cloud Citizen also involves streamlining configuration, deployment and upgrade processes. By integrating these tasks seamlessly, the application can facilitate smooth deployments and upgrades. This will lead to more efficiency and ease of management. This article gives a concise and opinionated overview of the Kubernetes basics from a Java developer\u2019s perspective and learn step-by-step how to get your application production ready on Kubernetes.<\/span><\/p>\n<h1><span style=\"font-weight: 400\">Startup time and small footprint<\/span><\/h1>\n<p><span style=\"font-weight: 400\">Kubernetes is a highly sophisticated orchestration engine for containerized applications. Usually organizations install Kubernetes clusters across several nodes (servers). Kubernetes automatically and dynamically spreads out workloads across these different nodes for optimal usage. Typically you will want to create multiple instances\/pods of your application for high availability. When one pod gets killed, stopped, moved to a different node or what have you, your application is still up and running from your user\u2019s perspective. This is called \u201chorizontal scaling\u201d.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Because pods can stop and start relatively frequently, it is important that the applications inside those pods can start up quickly as well. The longer it takes to start up, the less flexible Kubernetes will be at scheduling its workloads and the less advantage you have of using a cloud solution. Similarly, it is important that your applications have an as small as possible footprint. This allows Kubernetes to schedule applications across nodes more flexibly. For example, if your application\u2019s resources take up 60% of your node\u2019s available capacity, Kubernetes will not be able to schedule another instance on that same node, even though 40% of its capacity goes underused. If however, your application uses 40%, it\u2019s able to spread the load to multiple instances of one or more of your applications. Only 20% of that node would go to waste. Imagine if your workloads would be even smaller. Kubernetes would have a lot more flexibility of scheduling pods, as well as increase the node\u2019s usage and efficiency.\u00a0<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Java<\/span><\/h3>\n<p><span style=\"font-weight: 400\">What does this mean for your Java applications? Java was (unsurprisingly) not originally built for cloud deployments. The typical deployment target for \u201ctraditional\u201d Java applications is rather large. They usually have dedicated servers with the goal to keep the applications running as long as possible. If the application needs to scale, it\u2019s usually done by adding more hardware resources to these servers (vertical scaling) instead of creating more instances (horizontal scaling). Because of this, startup time and footprint were not a top priority for Java developers. With Kubernetes however, Java has had to reinvent itself.<\/span><\/p>\n<p><span style=\"font-weight: 400\">There are several initiatives in the Java world to reduce the startup time and footprint of Java applications. There are eg. OpenJDK projects like<\/span><a href=\"https:\/\/openjdk.org\/projects\/leyden\/\"> <span style=\"font-weight: 400\">Leyden<\/span><\/a><span style=\"font-weight: 400\"> and<\/span><a href=\"https:\/\/openjdk.org\/projects\/crac\/\"> <span style=\"font-weight: 400\">CRaC<\/span><\/a><span style=\"font-weight: 400\">, or projects like<\/span><a href=\"https:\/\/www.graalvm.org\/latest\/reference-manual\/native-image\/\"> <span style=\"font-weight: 400\">GraalVM Native Image<\/span><\/a><span style=\"font-weight: 400\"> that compile Java applications down to very fast and compact native binaries. There are newer frameworks\/stacks like<\/span><a href=\"https:\/\/quarkus.io\/\"> <span style=\"font-weight: 400\">Quarkus<\/span><\/a><span style=\"font-weight: 400\">,<\/span><a href=\"https:\/\/micronaut.io\/\"> <span style=\"font-weight: 400\">Micronaut<\/span><\/a><span style=\"font-weight: 400\"> and<\/span><a href=\"https:\/\/helidon.io\/\"> <span style=\"font-weight: 400\">Helidon<\/span><\/a><span style=\"font-weight: 400\">. These have been conceived with cloud native and kubernetes deployment targets in mind. Even the more traditional Spring (Boot) or JakartaEE have been making a lot of improvements to make applications more Kubernetes friendly.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Quarkus<\/span><\/h3>\n<p><span style=\"font-weight: 400\">We\u2019ll focus in this article on Quarkus because it makes working with \u201cKube-Native\u201d Java quite a bit easier and more performant. Feel free to explore the other stacks and compare and see what makes the most sense for your project.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Quarkus moves as much \u201cheavy lifting\u201d, such as classpath scanning, resolving annotations, etc to the application build time instead of during the application startup. This reduces both the startup time and the amount of memory needed. Actually, this is just the tip of the iceberg, you can read more about<\/span><a href=\"https:\/\/quarkus.io\/container-first\/\"> <span style=\"font-weight: 400\">Quarkus optimization for container workloads here<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Optimizing your Java application for Kubernetes is the first, but also one of the most important steps to create a production-grade, Kubernetes-native Java application. Let\u2019s now take a look at some tips and tricks to create production-grade cloud native Java workloads.<\/span><\/p>\n<h1><span style=\"font-weight: 400\">Containerize your application<\/span><\/h1>\n<p><span style=\"font-weight: 400\">To deploy an application to Kubernetes, you will need to package it up as a container image first. A few years ago that meant creating or finding a Dockerfile, adding commands to copy your artifacts and dependencies, and building the container image with a docker build command. While this is still a valid way of building containers, there are now many more ways and tools to create container images, such as Podman, Jib, BuildPacks, Kaniko, Buildah, etc.<\/span><\/p>\n<p><span style=\"font-weight: 400\">While each of these tools have their advantages and challenges, you will likely use a base image which you can customize to your needs. It is important to be very conscious of where this base image comes from. There are a surprising amount of container images out in the wild. While probably not purposefully malignant, these images often contain vulnerabilities that can be exploited relatively easily. To create a production-grade container image, it is thus very important that you start from a verified\/certified base container image. Ideally one that comes from a source you trust and that you can expect to maintain the base images you\u2019re using going forward as well.<\/span><a href=\"https:\/\/catalog.redhat.com\/software\/containers\/search?product_listings_names=Red%20Hat%20build%20of%20OpenJDK&amp;p=1\"> <span style=\"font-weight: 400\">Red Hat\u2019s Universal Base Images (UBI)<\/span><\/a><span style=\"font-weight: 400\"> are an example of base images you can use and redistribute (license free).<\/span><\/p>\n<h1><span style=\"font-weight: 400\">Deploying to Kubernetes<\/span><\/h1>\n<p><span style=\"font-weight: 400\">Once you have a container image, the next step is for you (or someone else in your organization) to deploy it to Kubernetes. To build and release a production-grade application it makes sense to test your applications in an environment as similar to the production environment as possible. This will help you to get ahead of discrepancies between your local environment and production as soon as possible as well. It is however not a trivial task to learn all the ins and outs of Kubernetes and its ecosystem. Fortunately there are solutions for Java developers to be able to deploy applications to a local or remote Kubernetes instance.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Quarkus for instance makes things painless through the use of a \u2018quarkus-kubernetes\u2019 extension. Adding this dependency to your project will generate Kubernetes manifests for you automatically (in an aptly named target\/kubernetes\/ folder). You can then deploy these manifests by either applying the (yaml or json) file, or calling a <code>quarkus deploy<\/code> command. Quarkus supports remote debugging on Kubernetes out of the box as well. Even its Dev Mode can work with a Kubernetes deployment.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Alternatively, projects like<\/span><a href=\"https:\/\/eclipse.dev\/jkube\/\"> <span style=\"font-weight: 400\">JKube<\/span><\/a><span style=\"font-weight: 400\"> are worth checking out as well to work with Kubernetes in an easy and straightforward way.\u00a0<\/span><\/p>\n<h1><span style=\"font-weight: 400\">Is my application actually ready to receive requests?<\/span><\/h1>\n<p><span style=\"font-weight: 400\">A production-grade Kubernetes application needs more than just a deployment though. If you deploy a container (in a pod), a Kubernetes Service will by default start sending traffic to it as soon as the container starts. However the application inside the container might still be starting up. Even if you\u2019ve optimized your application to start up super fast, there will still be a gap of (milli)seconds where it is not available. It might for example also be establishing connections to a database or a messaging system, so requests coming are likely to fail during this startup time. Fortunately Kubernetes has a concept of \u201chealth probes\u201d that can point to an endpoint in your application where you can advertise whether your application is actually able to receive requests. There are 3 different health probes:\u00a0<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Startup Probe<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Readiness Probe<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Liveness Probe<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">Quarkus leverages the<\/span><a href=\"https:\/\/microprofile.io\/\"> <span style=\"font-weight: 400\">MicroProfile<\/span><\/a><span style=\"font-weight: 400\"> Health spec through the<\/span><a href=\"https:\/\/smallrye.io\/\"> <span style=\"font-weight: 400\">Smallrye<\/span><\/a><span style=\"font-weight: 400\"> implementation. Adding the \u201csmallrye-health\u201d extension will, in combination with the \u2018kubernetes\u2019 extension, add the 3 health endpoints to your application\u2019s Kubernetes manifests automatically. You can create custom health endpoints using simple MicroProfile-based annotations. You can also modify the parameters of the health endpoints by adding configuration values to the application.properties file.<\/span><\/p>\n<h1><span style=\"font-weight: 400\">Declare your application\u2019s needs and limits<\/span><\/h1>\n<p><span style=\"font-weight: 400\">As mentioned before, organizations typically deploy a Kubernetes cluster across several nodes. They each have a certain amount of processing power (CPU) and memory (RAM) available. If you do not specify any limits to your application\u2019s pods, they will by default be able to consume as much of the resources of the node they\u2019re running on. This can become problematic when you have multiple applications running and they start competing for the available resources. When resource starvation starts to occur on a node, the Kubernetes controller will step in and effectively kill pods on this node. If it\u2019s not able to reschedule the killed pods on a different node, these workloads will not be able to start up anymore. This will result in a degraded user experience (at best).\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">To avoid these kinds of scenarios, you can leverage the concepts of \u201crequests\u201d and \u201climits\u201d in Kubernetes. Adding a \u201crequest\u201d parameter to your deployment will communicate to the Kubernetes controller that your application needs a minimum amount of resources (memory and\/or cpu) to work correctly. This helps the Kubernetes controller to schedule your pod appropriately on one (or more) of its nodes. \u201climits\u201d on the other hand tell Kubernetes that if your application goes beyond a given amount of resource usage it should kill and restart the pod. This helps avoid situations where your application is unexpectedly starting to use more resources than you anticipated. Eg. due to a memory leak or another unforeseen buildup of resource usage. Instead of the pod taking up more and more resources and eventually potentially bringing down an entire node or cluster, the \u201cblast radius\u201d of a resource issue is now contained to just one instance.\u00a0<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Adding Limits<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Adding limits and resources is therefore likely a good practice. Your kubernetes admin might have defined some default limits and requests already for each pod. It is however also a good idea for the developer to be aware of the (predicted) resource usage of their application and specify the request and limit values they would like for the application.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">For Quarkus, you can specify these values to the generated Kubernetes manifest by adding request and limit values to the application.properties file. eg.\u00a0<\/span><\/p>\n<pre><span style=\"font-weight: 400\">quarkus.kubernetes.resources.limits.cpu=300m<\/span>\n\n<span style=\"font-weight: 400\">quarkus.kubernetes.resources.limits.memory=300Mi<\/span><\/pre>\n<h1><span style=\"font-weight: 400\">Security considerations<\/span><\/h1>\n<p><span style=\"font-weight: 400\">No production-ready application and deployment is complete without considering the security implications of such an endeavor. At the minimum you should scan your application\u2019s source code and dependencies for vulnerabilities. An IDE plugin like Dependency Analytics (for<\/span><a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=redhat.fabric8-analytics\"> <span style=\"font-weight: 400\">VScode<\/span><\/a><span style=\"font-weight: 400\"> or<\/span><a href=\"https:\/\/plugins.jetbrains.com\/plugin\/12541-red-hat-dependency-analytics\"> <span style=\"font-weight: 400\">IntelliJ<\/span><\/a><span style=\"font-weight: 400\">) gives you feedback while you\u2019re developing your code. You should integrate code and container scanning in your CI\/CD pipeline as well and fail your pipeline if critical vulnerabilities are found. Think of code scanning tools like SonarQube, or container scanning tools like<\/span><a href=\"https:\/\/github.com\/quay\/clair\"> <span style=\"font-weight: 400\">Clair<\/span><\/a><span style=\"font-weight: 400\"> and\/or<\/span><a href=\"https:\/\/trivy.dev\/\"> <span style=\"font-weight: 400\">Trivy<\/span><\/a><span style=\"font-weight: 400\">. Your Kubernetes admins or security team should also have runtime scanning capabilities installed as well.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Secrets<\/span><\/h3>\n<p><span style=\"font-weight: 400\">You should also make sure to keep sensitive data safe. Passwords and other sensitive information are stored in Kubernetes in the form of \u201cSecrets\u201d. Though authenticated users and service accounts have access to these objects in Kubernetes, they are typically encrypted at rest, making them less vulnerable to be exploited. Unless a hacker somehow gets admin access to a cluster, or is able to exploit a container that has viewing privileges to the secrets.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Accessing and using secrets is again straightforward with Quarkus. Adding the \u201ckubernetes-config\u201d extension gives you the ability to interact with Kubernetes configuration options such as secrets. All you have to do is set the \u201csecrets.enabled\u201d flag to true such as in the following example. After that, specify which secrets you would like to interact with (the \u2018postgresql\u2019 secret in this case). Quarkus creates the necessary Kubernetes constructs such as a ServiceAccount, Role and RoleBinding in the background that allow the application to access the secret.<\/span><\/p>\n<pre><span style=\"font-weight: 400\">%prod.quarkus.kubernetes-config.secrets.enabled=true<\/span>\n\n<span style=\"font-weight: 400\">%prod.quarkus.kubernetes-config.secrets=postgresql<\/span><\/pre>\n<p><span style=\"font-weight: 400\">To further encrypt secrets, there are tools such as<\/span><a href=\"https:\/\/www.vaultproject.io\/\"> <span style=\"font-weight: 400\">Vault<\/span><\/a><span style=\"font-weight: 400\"> and<\/span><a href=\"https:\/\/github.com\/bitnami-labs\/sealed-secrets\"> <span style=\"font-weight: 400\">Sealed Secrets<\/span><\/a><span style=\"font-weight: 400\">.\u00a0<\/span><\/p>\n<h1><span style=\"font-weight: 400\">Observe and measure your application on Kubernetes<\/span><\/h1>\n<p><span style=\"font-weight: 400\">Once your application has landed on a Kubernetes instance, you\u2019ll want to keep an eye on how it is behaving and whether your requests and limits are set appropriately. Exposing metrics from your application to an observability stack is a must when you have distributed loads and ephemeral containers that can come and go. From a Java perspective, the<\/span><a href=\"https:\/\/opentelemetry.io\/docs\/instrumentation\/java\/\"> <span style=\"font-weight: 400\">OpenTelemetry<\/span><\/a><span style=\"font-weight: 400\"> and<\/span><a href=\"https:\/\/micrometer.io\/\"> <span style=\"font-weight: 400\">MicroMeter<\/span><\/a><span style=\"font-weight: 400\"> projects are good solutions to add observability to your application. With Micrometer for example, you can expose a \u201cmetrics\u201d endpoint to your application that a monitoring tool (eg.<\/span><a href=\"https:\/\/prometheus.io\/\"> <span style=\"font-weight: 400\">Prometheus<\/span><\/a><span style=\"font-weight: 400\">) collects metrics from. This allows you to search through or create graphs and dashboards with (eg. with<\/span><a href=\"https:\/\/grafana.com\/\"> <span style=\"font-weight: 400\">Grafana<\/span><\/a><span style=\"font-weight: 400\">). You can also see in detail all the various metrics coming out of the JVM running inside your application (memory used, statistics related to the garbage collector, etc). This in turn will allow you to proactively make modifications to your code, or your deployment manifests.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Observability is also important to be able to access logs in a centralized place, and trace through requests in case issues are happening. The OpenTelemetry project supports Java. It integrates easily into your code to forward traces and logs to a collector that you can plug in to a tracing tool such as<\/span><a href=\"https:\/\/www.jaegertracing.io\/\"> <span style=\"font-weight: 400\">Jaeger<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<h1><span style=\"font-weight: 400\">Automate your deployments<\/span><\/h1>\n<p><span style=\"font-weight: 400\">Setting up container builds, kubernetes deployments, configuring your application, adding observability are all important steps. The most important of all is perhaps to automate your application\u2019s configuration and deployment as much as possible. Automation is important to release your application in a smooth and controlled manner that is repeatable. It is also important because it allows you, your team, and those who come after you, to know exactly how to build and deploy the application, and with what kind of configurations.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">You should make sure even your CI\/CD tool itself, as well as its pipelines can be automated as well. This allows you to (re)create entire stacks with ease and enable you to create new production-grade applications without much hassle.<\/span><a href=\"https:\/\/tekton.dev\/\"> <span style=\"font-weight: 400\">Tekton<\/span><\/a><span style=\"font-weight: 400\"> for example is a CI\/CD solution that can be fully defined as a set of Custom Resources in Kubernetes. It allows you to automate your pipeline creation as well as the creation of Tekton instances. In addition, it integrates with signing tools such as Sigstore. With this you can sign not only your artifacts, but each task that\u2019s part of your pipelines as well. In a new world of<\/span><a href=\"https:\/\/www.cisa.gov\/sites\/default\/files\/publications\/defending_against_software_supply_chain_attacks_508_1.pdf\"> <span style=\"font-weight: 400\">Software Supply Chain Attacks<\/span><\/a><span style=\"font-weight: 400\">, this is another invaluable step on your way to productizing applications.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Gitops<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Finally, GitOps tools such as<\/span><a href=\"https:\/\/argoproj.github.io\/cd\/\"> <span style=\"font-weight: 400\">ArgoCD<\/span><\/a><span style=\"font-weight: 400\"> or<\/span><a href=\"https:\/\/fluxcd.io\/\"> <span style=\"font-weight: 400\">FluxCD<\/span><\/a><span style=\"font-weight: 400\"> can help you define a desired state of your environment, deployment and configuration, and make sure your Kubernetes environment actually matches this desired state. This helps you to know exactly what your environment and deployments should look like. With GitOps, you can see (in your source repository) who changed something, what they changed, and when it changed. GitOps and adjacent tools such as Argo Rollouts also allow you to roll out applications in advanced ways. With it you can use blue\/green or canary rollouts and release in progressive way that minimizes the impact to your users.<\/span><\/p>\n<h1><span style=\"font-weight: 400\">This is just the beginning<\/span><\/h1>\n<p><span style=\"font-weight: 400\">Productizing Java applications for Kubernetes can seem like a daunting task. With some careful consideration and planning it can make developer\u2019s lives easier and vastly more productive. It can also make a huge difference for your organization\u2019s ability to execute and deliver applications faster, more secure and more robust.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">This article tried to give you a quick and concise overview as well as some pointers to Open Source projects you could use to build and deploy production-grade, Kubernetes-native Java applications. This should get you well on your way to becoming a good Cloud-Native citizen.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>What does it mean to be a good Java Cloud Citizen? It&#8217;s definitely more than just putting an application in a container and deploying it. It is essential to consider factors such as providing real-time health status through fine-grained metrics to optimize your Java application&#8217;s performance and resilience in the cloud, . You\u2019ll also need [&hellip;]<\/p>\n","protected":false},"author":252,"featured_media":3214,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[693,388,183,11,4],"tags":[],"coauthors":[694],"class_list":["post-4574","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-693","category-ci-cd","category-cloud","category-java","category-java-advent"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Production-Grade Kubernetes for Java Developers - JVM Advent<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Production-Grade Kubernetes for Java Developers - JVM Advent\" \/>\n<meta property=\"og:description\" content=\"What does it mean to be a good Java Cloud Citizen? It&#8217;s definitely more than just putting an application in a container and deploying it. It is essential to consider factors such as providing real-time health status through fine-grained metrics to optimize your Java application&#8217;s performance and resilience in the cloud, . You\u2019ll also need [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html\" \/>\n<meta property=\"og:site_name\" content=\"JVM Advent\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Java-Advent-Calendar-229536173843473\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-12-11T01:01:31+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"800\" \/>\n\t<meta property=\"og:image:height\" content=\"800\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Kevin Dubois\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@kevindubois\" \/>\n<meta name=\"twitter:site\" content=\"@javaadvent\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kevin Dubois\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html\"},\"author\":{\"name\":\"Kevin Dubois\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/ae57be464a08acf4482d2507dae16f51\"},\"headline\":\"Production-Grade Kubernetes for Java Developers\",\"datePublished\":\"2023-12-11T01:01:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html\"},\"wordCount\":2636,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2021\\\/12\\\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1\",\"articleSection\":[\"2023\",\"CI\\\/CD\",\"Cloud\",\"java\",\"Java Advent\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html\",\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html\",\"name\":\"Production-Grade Kubernetes for Java Developers - JVM Advent\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2021\\\/12\\\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1\",\"datePublished\":\"2023-12-11T01:01:31+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/ae57be464a08acf4482d2507dae16f51\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2021\\\/12\\\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2021\\\/12\\\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1\",\"width\":800,\"height\":800},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2023\\\/12\\\/production-grade-kubernetes-for-java-developers.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javaadvent.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Production-Grade Kubernetes for Java Developers\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/\",\"name\":\"JVM Advent\",\"description\":\"The JVM Programming Advent Calendar\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javaadvent.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/ae57be464a08acf4482d2507dae16f51\",\"name\":\"Kevin Dubois\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2023\\\/11\\\/kevin-dubois_avatar-96x96.jpgaddce356bf115be8df74565e934c1b6f\",\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2023\\\/11\\\/kevin-dubois_avatar-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2023\\\/11\\\/kevin-dubois_avatar-96x96.jpg\",\"caption\":\"Kevin Dubois\"},\"description\":\"Kevin is a software engineer, author and international speaker with a passion for Open Source, Java, and Cloud Native Development &amp; Deployment practices. He currently works as developer advocate at Red Hat where he gets to enjoy working with Open Source projects and improving the developer experience. He previously worked as a (Lead) Software Engineer at a variety of organizations across the world ranging from small startups to large enterprises and even government agencies. Kevin is actively involved in Open Source communities, contributing to projects such as Quarkus, Knative, Apache Camel, and Podman (Desktop); and as a member of the Belgian CNCF chapter as well as the Belgian Java User Group. Kevin speaks English, Dutch, French and Italian fluently and is currently based in Belgium, having lived in Italy and the USA as well. In his free time you can find Kevin somewhere in the wild hiking, gravel biking, snowboarding or packrafting.\",\"sameAs\":[\"https:\\\/\\\/www.kevindubois.com\",\"https:\\\/\\\/linkedin.com\\\/in\\\/kevindubois\",\"https:\\\/\\\/x.com\\\/kevindubois\",\"https:\\\/\\\/youtube.com\\\/@thekevindubois\"],\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/author\\\/kduboisredhat-com\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Production-Grade Kubernetes for Java Developers - JVM Advent","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html","og_locale":"en_US","og_type":"article","og_title":"Production-Grade Kubernetes for Java Developers - JVM Advent","og_description":"What does it mean to be a good Java Cloud Citizen? It&#8217;s definitely more than just putting an application in a container and deploying it. It is essential to consider factors such as providing real-time health status through fine-grained metrics to optimize your Java application&#8217;s performance and resilience in the cloud, . You\u2019ll also need [&hellip;]","og_url":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html","og_site_name":"JVM Advent","article_publisher":"https:\/\/www.facebook.com\/Java-Advent-Calendar-229536173843473\/","article_published_time":"2023-12-11T01:01:31+00:00","og_image":[{"width":800,"height":800,"url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1","type":"image\/png"}],"author":"Kevin Dubois","twitter_card":"summary_large_image","twitter_creator":"@kevindubois","twitter_site":"@javaadvent","twitter_misc":{"Written by":"Kevin Dubois","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html#article","isPartOf":{"@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html"},"author":{"name":"Kevin Dubois","@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/ae57be464a08acf4482d2507dae16f51"},"headline":"Production-Grade Kubernetes for Java Developers","datePublished":"2023-12-11T01:01:31+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html"},"wordCount":2636,"commentCount":0,"image":{"@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1","articleSection":["2023","CI\/CD","Cloud","java","Java Advent"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html","url":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html","name":"Production-Grade Kubernetes for Java Developers - JVM Advent","isPartOf":{"@id":"https:\/\/www.javaadvent.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html#primaryimage"},"image":{"@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1","datePublished":"2023-12-11T01:01:31+00:00","author":{"@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/ae57be464a08acf4482d2507dae16f51"},"breadcrumb":{"@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html#primaryimage","url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1","contentUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1","width":800,"height":800},{"@type":"BreadcrumbList","@id":"https:\/\/www.javaadvent.com\/2023\/12\/production-grade-kubernetes-for-java-developers.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javaadvent.com\/"},{"@type":"ListItem","position":2,"name":"Production-Grade Kubernetes for Java Developers"}]},{"@type":"WebSite","@id":"https:\/\/www.javaadvent.com\/#website","url":"https:\/\/www.javaadvent.com\/","name":"JVM Advent","description":"The JVM Programming Advent Calendar","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javaadvent.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/ae57be464a08acf4482d2507dae16f51","name":"Kevin Dubois","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javaadvent.com\/content\/uploads\/2023\/11\/kevin-dubois_avatar-96x96.jpgaddce356bf115be8df74565e934c1b6f","url":"https:\/\/www.javaadvent.com\/content\/uploads\/2023\/11\/kevin-dubois_avatar-96x96.jpg","contentUrl":"https:\/\/www.javaadvent.com\/content\/uploads\/2023\/11\/kevin-dubois_avatar-96x96.jpg","caption":"Kevin Dubois"},"description":"Kevin is a software engineer, author and international speaker with a passion for Open Source, Java, and Cloud Native Development &amp; Deployment practices. He currently works as developer advocate at Red Hat where he gets to enjoy working with Open Source projects and improving the developer experience. He previously worked as a (Lead) Software Engineer at a variety of organizations across the world ranging from small startups to large enterprises and even government agencies. Kevin is actively involved in Open Source communities, contributing to projects such as Quarkus, Knative, Apache Camel, and Podman (Desktop); and as a member of the Belgian CNCF chapter as well as the Belgian Java User Group. Kevin speaks English, Dutch, French and Italian fluently and is currently based in Belgium, having lived in Italy and the USA as well. In his free time you can find Kevin somewhere in the wild hiking, gravel biking, snowboarding or packrafting.","sameAs":["https:\/\/www.kevindubois.com","https:\/\/linkedin.com\/in\/kevindubois","https:\/\/x.com\/kevindubois","https:\/\/youtube.com\/@thekevindubois"],"url":"https:\/\/www.javaadvent.com\/author\/kduboisredhat-com"}]}},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-11.png?fit=800%2C800&ssl=1","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":4542,"url":"https:\/\/www.javaadvent.com\/2023\/12\/multicloud-communication-for-kubernetes-but-with-applications-in-charge.html","url_meta":{"origin":4574,"position":0},"title":"Multicloud Communication for Kubernetes &#8211; But with Applications in Charge","author":"Markus Eisele","date":"December 1, 2023","format":false,"excerpt":"We almost reached the end of another calendar year and the wonderful tradition of the Java Advent Calendar continues into another year. I\u2019ve had the pleasure of either opening or at least contributing to the 24 yearly surprise articles for a few years now and it always lets me be\u2026","rel":"","context":"In &quot;2023&quot;","block_context":{"text":"2023","link":"https:\/\/www.javaadvent.com\/category\/2023"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-1.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-1.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-1.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-1.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":5451,"url":"https:\/\/www.javaadvent.com\/2024\/12\/portable-serverless-functions-with-java-and-quarkus.html","url_meta":{"origin":4574,"position":1},"title":"Portable Serverless Functions with Java (and Quarkus)","author":"Kevin Dubois","date":"December 20, 2024","format":false,"excerpt":"You have probably already heard of serverless functions. If you've played around with them, it might have been on a platform like AWS Lambda, Azure Functions, Google Cloud Functions or similar. The vendors behind these platforms offer solutions specifically for Java as well. The libraries and deployment methodologies are typically\u2026","rel":"","context":"In &quot;2017&quot;","block_context":{"text":"2017","link":"https:\/\/www.javaadvent.com\/category\/2017"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-20.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-20.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-20.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-20.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":3327,"url":"https:\/\/www.javaadvent.com\/2021\/12\/easily-debug-java-apps-running-on-kubernetes-with-telepresence-and-intellij-idea.html","url_meta":{"origin":4574,"position":2},"title":"Easily Debug Java Apps Running on Kubernetes with Telepresence and IntelliJ IDEA","author":"Daniel Bryant","date":"December 22, 2021","format":false,"excerpt":"Many Java-based organizations adopt cloud native development practices with the goal of shipping features faster. The technologies and architectures may change when we move to the cloud, but the fact remains that we all still add the occasional bug to our code. The challenge here is that many of your\u2026","rel":"","context":"In &quot;2021&quot;","block_context":{"text":"2021","link":"https:\/\/www.javaadvent.com\/category\/2021"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-22.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-22.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-22.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-22.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":3120,"url":"https:\/\/www.javaadvent.com\/2021\/12\/you-need-more-than-containers-a-short-history-of-the-mess-were-in.html","url_meta":{"origin":4574,"position":3},"title":"You need more than containers. A short history of the mess we&#8217;re in.","author":"Markus Eisele","date":"December 7, 2021","format":false,"excerpt":"Lean microservice infrastructures continue to replace classic 3-tier architectures in \u200b\u200benterprise software. Pushing enterprise developers who lived in the fully integrated world of application servers towards dealing with new methodologies and technologies in a cloud-native world. As a matter of fact, distributed architectures differ fundamentally from known, monolithic applications. And\u2026","rel":"","context":"In &quot;2021&quot;","block_context":{"text":"2021","link":"https:\/\/www.javaadvent.com\/category\/2021"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1362,"url":"https:\/\/www.javaadvent.com\/2018\/12\/docker-and-the-jvm.html","url_meta":{"origin":4574,"position":4},"title":"Docker and the JVM","author":"Cesar Tron-Lozai","date":"December 7, 2018","format":false,"excerpt":"Even though Docker was a 2016 thing, it is still relevant today. It is the foundation of Kubernetes, the most popular Orchestration platform, that has become the go-to solution for cloud deployment. Docker is the defacto standard solution to containerise applications\/(micro)services. If you run Java application you need to beaware\u2026","rel":"","context":"In &quot;2018&quot;","block_context":{"text":"2018","link":"https:\/\/www.javaadvent.com\/category\/2018"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2018\/12\/image-300x161.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":4118,"url":"https:\/\/www.javaadvent.com\/2022\/12\/components-of-cloud-native-java.html","url_meta":{"origin":4574,"position":5},"title":"Components of Cloud Native Java","author":"Alexander Gruev","date":"December 15, 2022","format":false,"excerpt":"WHAT IS CLOUD NATIVE JAVA\u00a0 Cloud native is a software approach to building, deploying and managing modern applications in cloud computing environments.\u00a0 It allows companies to build highly scalable and resilient applications that can easily be enhanced to meet customer needs without breaking existing functionality. The cloud native approach involves\u2026","rel":"","context":"In &quot;2022&quot;","block_context":{"text":"2022","link":"https:\/\/www.javaadvent.com\/category\/jvm-advent-2022"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-15.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-15.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-15.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-15.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]}],"jetpack_likes_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/4574","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/users\/252"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/comments?post=4574"}],"version-history":[{"count":7,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/4574\/revisions"}],"predecessor-version":[{"id":4592,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/4574\/revisions\/4592"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/media\/3214"}],"wp:attachment":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/media?parent=4574"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/categories?post=4574"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/tags?post=4574"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/coauthors?post=4574"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}