Kubernetes Tips & Tricks
This blog post is adapted in november of 2025 from a presentation I did in back in 2022.
I've learned a few things about Kubernetes over the years, and how to deploy specifically JVM apps on them.
In my examples, I'm using Spring Boot apps as an example (because I'm familiar with them), but the concepts are of course more widely applicable.
Tip 1: Use probes
Probes are essentially meant to keep track of the liveness of your application, and to act when it is not.
Links:
Startup Probes
startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
failureThreshold: 30
periodSeconds: 5
- Used when you start the pod, never again afterward.
- High failure threshold: You might want to give your pod some time (perhaps you need to perform a flyway data migration).
- Low period seconds: You want to know as soon as possible that your pod is up.
Liveness Probe
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8081
failureThreshold: 3
periodSeconds: 20
- Is your pod "alive"? In other words, healthy.
- Give this probe its own thread: you don't want k8s to kill your pod because it's busy.
Readiness Probe
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
failureThreshold: 3
periodSeconds: 20
Is your pod available to handle requests?
Tip 2: Use graceful shutdowns
For Java spring boot applications:
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=20s
Since Spring 3.5 or so, graceful shutdowns are the default.
Tip 3: Read Only File system
If at all possible, make your file system read only (Reference). Some images, like Spring boot apps, require a temp folder to write data to. An example config below:
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
...
containers:
- image: <spring-boot-image>
volumeMounts:
- mountPath: /tmp
name: tmp
volumes:
- name: tmp
emptyDir: {}
Tip 4: Service accounts
Through service accounts the container you run has access to the Kubernetes api. With too many privileges, you could give your container control over your entire cluster. This is sometheing you probably do not want. So sensible settings are to not use the default service account, but create one for each workload. And make sure the roles are limited to what's required (usually none).
Tip 5: Manage your resources
Commonly, cpu usage is quite variable, while memory usage is quite stable. So a sensible starting point is to leave cpu alone, while setting memory request and limits to the same value.
Why the same value? Assuming your memory usage is relatively stable, and you want an as stable pod as possible, you simply want to make sure the memory you require (the limit) is actually reserved for this pod on startup (the request). If you reserve less than required, the node you run on may schedule more pods than it is able to serve (fully). Which will lead to instability.
resources:
requests:
memory: 1024Mi
limits:
memory: 1024Mi
refs:
Tip 6: Manage the JVM
Default HEAP in a container is 1/4 of the available memory. That generally makes no sense in a container. I advise you to set this to 75% as a starting point: -XX:MaxRAMPercentage=75
links: