Container memory usage with spring boot not low after testing with Jmeter - Kubernetes

11/3/2020

Good morning. I have a query, I am relatively new to Kubernetes and Java (spring boot) and I am currently deploying a pod with three containers with spring boot, the question is that I am testing with Jmeter to measure metrics and scale automatically with HPA in Kubernetes, but I am getting that when you stress the memory of the containers increases, however when I finish doing the tests, the containers do not lower the memory use. I don't know if this topic is typical of Java because of the JVM, or if the Garbage Collector is failing, and I must define it in the docker image. I give him a resource limit in terms of CPU and memory in the container in the yaml manifest

This is how my containers were before starting the test with Jmeter

enter image description here

After testing with Jmeter, and the passage of about 15 minutes, so are the containers in terms of memory:

enter image description here

This is how I am defining my Dockerfile:

FROM openjdk:8-alpine
RUN rm -rf /var/cache/apk/*
RUN rm -rf /tmp/*
RUN apk update
RUN apk add busybox-extras
ENV UBICATION_CERTIFICATE_SSL=/etc/letsencrypt/tmp224.p12
ENV PASSWORD_CERTIFICATE_SSL=xxxxx
ENV ALIAS_CERTIFICATE_SSL=tmp224
ADD FindAccountNumber-0.0.1-SNAPSHOT.jar /home/app.jar
ADD tmp224.p12 /etc/letsencrypt/tmp224.p12
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/home/app.jar"]

And my manifest yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: find-complementary-account-info-1
  labels:
    app: find-complementary-account-info-1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: find-complementary-account-info-1
  template:
    metadata:
      labels:
        app: find-complementary-account-info-1
    spec:
      containers:
      - name: find-account-number-1
        image: find-account-number:latest
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            cpu: "250m"
            memory: "350Mi"
          requests:
            cpu: "150m"
            memory: "300Mi"
        ports:
        - containerPort: 8081
        env:
        - name: URL_CONNECTION_BD
          value: jdbc:oracle:thin:@xxxxxxxx:1531/DEFAULTSRV.WORLD
        - name: USERNAME_CONNECTION_BD
          valueFrom:
            secretKeyRef:
              name: credentials-bd-pers
              key: user_pers
        - name: PASSWORD_CONNECTION_BD
          valueFrom:
            secretKeyRef:
              name: credentials-bd-pers
              key: password_pers
      - name: find-account-validators-1
        image: find-account-validators:latest
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            cpu: "250m"
            memory: "350Mi"
          requests:
            cpu: "150m"
            memory: "300Mi"
        ports:
        - containerPort: 8082
        env:
        - name: URL_CONNECTION_BD
          value: jdbc:oracle:thin:@xxxxxxxx:1522/DEFAULTSRV.WORLD
        - name: USERNAME_CONNECTION_BD
          valueFrom:
            secretKeyRef:
              name: credentials-bd-billing
              key: user_billing
        - name: PASSWORD_CONNECTION_BD
          valueFrom:
            secretKeyRef:
              name: credentials-bd-billing
              key: password_billing
      - name: find-complementary-account-info-1
        image: find-complementary-account-info:latest
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            cpu: "250m"
            memory: "350Mi"
          requests:
            cpu: "150m"
            memory: "300Mi"
        ports:
        - containerPort: 8083
        env:
        - name: UBICATION_URL_ACCOUNT_NUMBER
          value: "https://localhost:8081/api/FindAccountNumber"
        - name: UBICATION_URL_ACCOUNT_VALIDATORS
          value: "https://localhost:8082/api/FindAccountValidator"
---

apiVersion: v1
kind: Service
metadata:
  name: svc-find-complementary-account-info-1
  labels:
    app: find-complementary-account-info-1
  annotations:
    metallb.universe.tf/allow-shared-ip: shared-ip
  namespace: default
spec:
  selector:
    app: find-complementary-account-info-1
  externalTrafficPolicy: Cluster
  loadBalancerIP: 10.161.174.68
  type: LoadBalancer
  ports:
   -
    protocol: TCP
    port: 8083
    targetPort: 8083
    nodePort: 30025
---

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: find-complementary-account-info-1
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: find-complementary-account-info-1
  minReplicas: 2
  maxReplicas: 5
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

How can I reduce the memory in use of spring boot in a container, since so I imagine it will keep increasing as it is subjected to stress

-- Cesar Justo
docker
jvm
kubernetes
memory
spring-boot

1 Answer

11/3/2020

I'd argue that the difference is pretty small (~220 MB vs 250-290 MB) and you should not bother with that.

But it seems you are talking about the java app (not) returning memory to the OS. This has been a common behavior for a very long time and it depends on the garbage collector - it doesn't mean the GC doesn't work. You're using JDK 8 so you don't have many choices, but in later versions there are improved collectors, e.g.

You can find more information here: https://stackoverflow.com/questions/30458195/does-gc-release-back-memory-to-os

-- Juraj Martinka
Source: StackOverflow