Klaster OKD (OpenShift) – Projekt OpenShift java-cpu-burner

Testowy klaster OKD (OpenShift)

Poniższy wpis bazuje na konfiguracji klastra przeprowadzonej wg. wpisu https://itadmin.vblog.ovh/klaster-okd-openshift-na-maszynach-wirtualnych-proxmox-opis-instalacji/ oraz konfiguracji serwera NFS opisanej na stronie https://itadmin.vblog.ovh/klaster-okd-openshift-na-maszynach-wirtualnych-proxmox-przygotowanie-maszyny-storage-nfs/

Opis projektu OpenShift : java-cpu-burner

Projekt ma na celu kontrolowane wywołanie mechanizmu autoscalera HPA w OpenShift przez liniowe zwiększanie obciążenia CPU.

CPU będzie rosnąć liniowo → HPA spokojnie przekroczy target i zeskaluje repliki.

Plateau 90% → HPA utrzyma wyższe repliki przez kilka minut.

Spadek do 30% → HPA po chwili zmniejszy liczbę podów.

Cykl zacznie się od nowa → w konsoli OpenShift zobaczysz idealny test autoskalowania (góra–plateau–dół).

Utworzenie nowego projektu OpenShift o nazwie java-cpu-burner

Najpierw należy przygotować kod aplikacji Java , która w pętli zwiększa zużycie CPU. Pełen scenariusz testowy pod HPA:

Start na 40%

Liniowy wzrost co +5% aż do 90%

Utrzymanie 90% przez 5 minut (300 s) → HPA ma czas, żeby spokojnie zeskalować w górę

Liniowy spadek co -5% aż do 30%

cięższe obliczenia (Math.sin, Math.tan w pętli) zamiast lekkiego Math.sqrt

większa intensywność (load * 100_000 zamiast load * 10_000) → CPU faktycznie się „męczy”

więcej wątków (cores * 2 zamiast cores) → szybciej widać obciążenie na całym node

cykl: wzrost → plateau (5 min) → spadek → od nowa

Cykl powtarza się w nieskończoność

public class CpuBurnerCycle {

    public static void main(String[] args) {
        printBanner();

        int sleepBeforeStart = getEnvAsInt("SLEEP_BEFORE_START", 5);
        int loopDelaySec = getEnvAsInt("LOOP_DELAY", 10); // co ile sekund zmieniamy load
        int minLoad = getEnvAsInt("MIN_LOAD", 40);        // startowe obciążenie (%)
        int maxLoad = getEnvAsInt("MAX_LOAD", 90);        // końcowe obciążenie (%)
        int step = getEnvAsInt("STEP", 10);               // krok zmiany (%)
        int plateauSec = getEnvAsInt("PLATEAU_SEC", 300); // plateau na max load (domyślnie 5 minut)

        System.out.println("Konfiguracja CPU Burner (cykl):");
        System.out.println(" - SLEEP_BEFORE_START = " + sleepBeforeStart + "s");
        System.out.println(" - LOOP_DELAY = " + loopDelaySec + "s");
        System.out.println(" - MIN_LOAD = " + minLoad + "%");
        System.out.println(" - MAX_LOAD = " + maxLoad + "%");
        System.out.println(" - STEP = " + step + "%");
        System.out.println(" - PLATEAU_SEC = " + plateauSec + "s");

        try {
            Thread.sleep(sleepBeforeStart * 1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        int cores = Runtime.getRuntime().availableProcessors();
        int workers = cores * 2; // zwiększamy równoległość

        System.out.println("Wykryto CPU cores = " + cores + ", uruchamiam workerów = " + workers);

        for (int i = 0; i < workers; i++) {
            Thread worker = new Thread(() -> {
                try {
                    int iteration = 0;

                    while (true) {
                        // 1️⃣ Wzrost od MIN_LOAD do MAX_LOAD
                        for (int load = minLoad; load <= maxLoad; load += step) {
                            iteration++;
                            runLoadPhase(iteration, load, loopDelaySec);
                        }

                        // 2️⃣ Plateau na MAX_LOAD
                        int plateauIterations = plateauSec / loopDelaySec;
                        for (int j = 0; j < plateauIterations; j++) {
                            iteration++;
                            runLoadPhase(iteration, maxLoad, loopDelaySec);
                        }

                        // 3️⃣ Spadek od MAX_LOAD do MIN_LOAD
                        for (int load = maxLoad; load >= minLoad; load -= step) {
                            iteration++;
                            runLoadPhase(iteration, load, loopDelaySec);
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            worker.start();
        }

        System.out.println("CPU Burner działa w trybie cyklicznym: wzrost → plateau → spadek → od nowa.");
    }

    private static void runLoadPhase(int iteration, int load, int loopDelaySec) throws InterruptedException {
        System.out.println("Iteracja #" + iteration +
                " → docelowe obciążenie CPU ≈ " + load + "%");

        long endTime = System.currentTimeMillis() + (loopDelaySec * 1000L);

        // utrzymujemy obciążenie na tym poziomie przez loopDelaySec
        while (System.currentTimeMillis() < endTime) {
            long start = System.nanoTime();

            // aktywna część = cięższe spalanie CPU
            while ((System.nanoTime() - start) < (load * 100_000)) {
                double dummy = 0;
                for (int i = 0; i < 1000; i++) {
                    dummy += Math.sin(i) * Math.tan(i);
                }
                if (dummy == 42.0) { // zabezpieczenie przed optymalizacją JIT
                    System.out.print("");
                }
            }

            // pasywna część = odpoczynek CPU
            Thread.sleep((100 - load) * 10L);
        }
    }

    private static int getEnvAsInt(String name, int defaultValue) {
        String value = System.getenv(name);
        if (value != null) {
            try {
                return Integer.parseInt(value);
            } catch (NumberFormatException e) {
                System.err.println("Niepoprawna wartość dla " + name + ": " + value +
                        " (używam domyślnej " + defaultValue + ")");
            }
        }
        return defaultValue;
    }

    private static void printBanner() {
        System.out.println("===================================");
        System.out.println("          J   C   B");
        System.out.println("     JAVA CPU BURNER");
        System.out.println("        wersja 1.0.1.A");
        System.out.println("===================================");
    }
}

Następnie należy przygotować odpowiedni Dockerfile, który posłuży do zbudowania obrazu aplikacji. Będą w nim parametry środowiskowe, które łatwo można nadpisać configmapą z OpenShifta.
W tym projekcie jednak nie będziemy tworzyć i podłączać configmapy tylko skupimy się na HPA.

FROM eclipse-temurin:17-jdk-alpine
# ustawiamy strefę czasową
RUN apk add --no-cache tzdata \
    && cp /usr/share/zoneinfo/Europe/Warsaw /etc/localtime \
    && echo "Europe/Warsaw" > /etc/timezone
WORKDIR /app
# kopiujemy kod źródłowy
COPY CpuBurnerCycle.java /app
# kompilujemy
RUN javac CpuBurnerCycle.java
# zmienne środowiskowe (do sterowania z ConfigMapy / oc set env)
ENV SLEEP_BEFORE_START=5
ENV LOOP_DELAY=10
ENV MIN_LOAD=30
ENV MAX_LOAD=90
ENV PLATEAU_SEC=300
# uruchamiamy aplikację
CMD ["java", "CpuBurnerCycle"]

Teraz możemy przystąpić do utworzenia projektu o nazwie java-cpu-burner oraz build configa i image stream-a o wskazanej dowolnej nazwie np. java-cpu-burner-build

oc new-project java-cpu-burner
# stworzenie build nowego obrazu bazującego na Dockerfile 
oc new-build --strategy=docker --binary --name=java-cpu-burner-build

Następny krokiem jest zbudowanie obrazu czyli builda o nazwie java-cpu-burner-build

cd /home/bastuser/repo/java-cpu-burner
oc start-build java-cpu-burner-build --from-dir=. --follow

Weryfikujemy czy powyższy build wykonał się poprawnie.

# sprawdzenie dostępnych buildów w projekcie
oc get builds
NAME                      TYPE     FROM     STATUS     STARTED          DURATION
java-cpu-burner-build-1   Docker   Binary   Complete   26 seconds ago   20s

# przejrzenie logów z builda
oc logs -f build/java-cpu-burner-build-1

# ostatnie zdarzenia w projekcie gdzie widać szczegóły powstawania builda w projekcie
oc get events --sort-by='{.lastTimestamp}' -n java-cpu-burner

Utworzenie aplikacji OpenShift

Teraz możemy utworzyć aplikację na bazie istniejącego builda jako deployment-config do którego możemy dodać pvc oraz configmap.

# aplikacja czyli pody mają się zaczynąc od java-memoryeater-app
oc new-app java-cpu-burner-build:latest --name=java-cpu-burner-app --as-deployment-config

Monitorowanie logów POD-a

Z poziomu konsoli tekstowej oc logs -f <nazwa poda>

oc logs -f java-cpu-burner-app-1-xlrtb
Konfiguracja CPU Burner (cykl):
 - SLEEP_BEFORE_START = 5s
 - LOOP_DELAY = 10s
 - MIN_LOAD = 30%
 - MAX_LOAD = 90%
 - PLATEAU_SEC = 300s
Wykryto CPU cores = 4
CPU Burner działa w trybie cyklicznym: rośnie, plateau, spada, od nowa.
Iteracja #1 → docelowe obciążenie CPU ≈ 30%
Iteracja #1 → docelowe obciążenie CPU ≈ 30%
Iteracja #1 → docelowe obciążenie CPU ≈ 30%
Iteracja #1 → docelowe obciążenie CPU ≈ 30%
Iteracja #2 → docelowe obciążenie CPU ≈ 35%
Iteracja #2 → docelowe obciążenie CPU ≈ 35%
Iteracja #2 → docelowe obciążenie CPU ≈ 35%
Iteracja #2 → docelowe obciążenie CPU ≈ 35%
Iteracja #3 → docelowe obciążenie CPU ≈ 40%
Iteracja #3 → docelowe obciążenie CPU ≈ 40%
...
Iteracja #14 → docelowe obciążenie CPU ≈ 90%

Z poziomu konsoli graficznej jako Developer – projekt – pod – zakładka Logs

Monitorowanie wykorzystanie CPU przez POD-a

Z poziomu konsoli tekstowej

# sprawdzamy które pody wykorzystują najwięcej zasobów na klastrze
oc adm top pods -n java-cpu-burner
NAME                          CPU(cores)   MEMORY(bytes)
java-cpu-burner-app-1-xlrtb   37m          20Mi

# sprawdzamy na którego workera na klastrze trafił pod
oc get pods -o wide
NAME                            READY   STATUS      RESTARTS   AGE    IP            NODE        NOMINATED NODE   READINESS GATES
java-cpu-burner-app-1-deploy    0/1     Completed   0          5m7s   10.129.2.47   compute-3   <none>           <none>
java-cpu-burner-app-1-xlrtb     1/1     Running     0          5m6s   10.129.2.48   compute-3   <none>           <none>
java-cpu-burner-build-1-build   0/1     Completed   0          7m6s   10.129.2.46   compute-3   <none>           <none>

# sprawdzamy zuzyćie zasobów na workerze w klastrze
oc adm top nodes
NAME              CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
compute-1         244m         6%     3687Mi          24%
compute-2         252m         7%     3442Mi          23%
compute-3         80m          2%     1733Mi          11%
control-plane-1   393m         11%    5611Mi          37%
control-plane-2   348m         9%     4271Mi          28%
control-plane-3   311m         8%     4160Mi          27%

Z poziomu konsoli graficznej jako Developer – projekt – pod

Ustawianie HPA w projekcie

Celem tego zadania jest ustawienie limitów dla CPU oraz parametrów wyzwalania skalowania horyzontalnego HPA.
Najpierw należy ustawić odpowiednie limity na zasoby np. tak jak poniżej.

# ustawiamy parametry, że pod nie moze zużyc więcej niż 500m CPU
oc set resources dc/java-cpu-burner-app  --limits=cpu=500m,memory=512Mi  --requests=cpu=100m,memory=256Mi   -n java-cpu-burner

# wymuszenie nowych wartość w podzie po restarcie
oc rollout latest dc/java-cpu-burner-app -n java-cpu-burner

# weryfikujemy na podzie jakie limity go obowiązują
oc describe pod java-cpu-burner-app-12-x4qjd | grep -A5 "Limits"
    Limits:
      cpu:     500m
      memory:  512Mi
    Requests:
      cpu:        100m
      memory:     256Mi

Rola limits

limits=500m → kontener nie może przekroczyć pół vCPU. Dzięki temu nie „pożre” całego noda.
Ale HPA nie patrzy na limits, tylko na requests.

Jak działa HPA

HorizontalPodAutoscaler (HPA) liczy obciążenie CPU w procentach względem requests.cpu.

Formuła:

CPU% = (aktualne użycie CPU) / (requests.cpu) * 100
limits → określa sufit (ile maksymalnie kontener może zużyć).
requests → to gwarantowane minimum i punkt odniesienia dla HPA.

czyli jeśli pod pokazuje np. 499m to formuła wygląda tak: 499m/ 100m = 499%

oc adm top pods
NAME                           CPU(cores)   MEMORY(bytes)
java-cpu-burner-app-12-46wcq   499m         17Mi

Dodajemy HPA do projektu

# podajemy minimalną i maksymalną liczbę replik podów oraz próg uruchomienia repliki (70%)
oc autoscale dc/java-cpu-burner-app --min=1 --max=5 --cpu-percent=70 -n java-cpu-burner
# po dobrych kilku minutach gdy sprawdzamy stan HPA powinno pojawić się wykorzystanie ponad 500 % CPU i będzie do 5 stopniowa zwiększać się ilośc replik
oc get hpa
NAME                  REFERENCE                              TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
java-cpu-burner-app   DeploymentConfig/java-cpu-burner-app   499%/70%   1         5         4          56m

Sprawdzenie jakie limity RAM / CPU obowiązują danego POD-a. Sprawdzamy sekcję Limits i Requests.

oc describe hpa java-cpu-burner-app -n java-cpu-burner

Name:                                                  java-cpu-burner-app
Namespace:                                             java-cpu-burner
Labels:                                                <none>
Annotations:                                           <none>
CreationTimestamp:                                     Fri, 03 Oct 2025 14:30:36 +0200
Reference:                                             DeploymentConfig/java-cpu-burner-app
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):  501% (501m) / 70%
Min replicas:                                          1
Max replicas:                                          5
DeploymentConfig pods:                                 5 current / 5 desired
Conditions:
  Type            Status  Reason            Message
  ----            ------  ------            -------
  AbleToScale     True    ReadyForNewScale  recommended size matches current size
  ScalingActive   True    ValidMetricFound  the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
  ScalingLimited  True    TooManyReplicas   the desired replica count is more than the maximum replica count

HPA widzi już 500% 🚀
→ czyli działa dokładnie tak, jak zakładaliśmy (usage=499m / requests=100m ≈ 500%).

Target = 70%
→ czyli HPA wie, że trzeba dodać więcej podów.

DeploymentConfig pods: 1 current / 5 desired
→ HPA faktycznie policzył, że powinno być 5 podów, i ustawił taki stan w spec.

Widać na poniższym ekranie 5 uruchomionych podów

Powrót do mniejszej ilości replik

Dlaczego HPA wolno skaluje w dół?

To celowe – żeby uniknąć „flappingu” (ciągłego góra/dół, jeśli obciążenie chwilowo spada).
W Kubernetes/Openshift HPA domyślnie czeka 5 minut (300 sekund) zanim zmniejszy liczbę replik.
Można to ustawienie nadpisać przy poniższym HPA z stabilizationWindowSeconds: 30 zejście z 5→1 pod(a) nastąpi zwykle w ~30–60 s po spadku poniżej targetu.

# hpa-fast-dc.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: java-cpu-burner-app
  namespace: java-cpu-burner
spec:
  scaleTargetRef:
    apiVersion: apps.openshift.io/v1
    kind: DeploymentConfig
    name: java-cpu-burner-app
  minReplicas: 1
  maxReplicas: 5
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
  behavior:
    # Agresywny SCALE-UP: natychmiast (bez stabilizacji), duże skoki
    scaleUp:
      stabilizationWindowSeconds: 0
      selectPolicy: Max
      policies:
        - type: Pods
          value: 4            # może dodać do 4 podów na jedno „okno”
          periodSeconds: 15
        - type: Percent
          value: 100          # lub podwoić liczbę replik w 15 s
          periodSeconds: 15

    # Szybki SCALE-DOWN: krótka stabilizacja i duże redukcje
    scaleDown:
      stabilizationWindowSeconds: 30  # zamiast domyślnych ~300 s
      selectPolicy: Max
      policies:
        - type: Pods
          value: 4            # może zdjąć do 4 podów w 30 s
          periodSeconds: 30
        - type: Percent
          value: 100          # lub zredukować nawet o 100% (do minReplicas)
          periodSeconds: 30

Nadpisanie domyślnych ustawień HPA w projekcie

# Zachowuje Twoją obecną architekturę (DC). Szybko skaluje w górę i w dół.
oc apply -f hpa-fast-dc.yaml
Warning: resource horizontalpodautoscalers/java-cpu-burner-app is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by oc apply. oc apply should only be used on resources created declaratively by either oc create --save-config or oc apply. The missing annotation will be patched automatically.
horizontalpodautoscaler.autoscaling/java-cpu-burner-app configured

Teraz można szybko przetestować skalowanie w górę i w dół. Poniżej opisano jak zmniejszyć wykorzystanie CPU w pod-ach aby obserwować szybkie skalowanie w dół.

# zmnniejszamy radykalnie poziom wykorzystania CPU do 10 %
oc set env dc/java-cpu-burner-app MIN_LOAD=5 MAX_LOAD=10 -n java-cpu-burner
oc rollout latest dc/java-cpu-burner-app -n java-cpu-burner

# zużycie CPU powinno wyraznie spaść
oc adm top pods
NAME                           CPU(cores)   MEMORY(bytes)
java-cpu-burner-app-15-4x67c   43m          17Mi
java-cpu-burner-app-15-772wl   44m          17Mi
java-cpu-burner-app-15-nw8cs   43m          17Mi
java-cpu-burner-app-15-smdfg   45m          17Mi
java-cpu-burner-app-15-thdr8   43m          17Mi

# w logacg poda widac zablokowane do 10% obciazenie
oc logs -f java-cpu-burner-app-15-4x67c
===================================
          J   C   B
     JAVA CPU BURNER
        wersja 1.0.1.B
===================================
Konfiguracja CPU Burner (cykl):
 - SLEEP_BEFORE_START = 5s
 - LOOP_DELAY = 10s
 - MIN_LOAD = 5%
 - MAX_LOAD = 10%
 - STEP = 10%
 - PLATEAU_SEC = 300s
Wykryto CPU cores = 1, uruchamiam workerów = 4
Iteracja #1 → docelowe obciążenie CPU ≈ 5%
CPU Burner działa w trybie cyklicznym: wzrost → plateau → spadek → od nowa.
Iteracja #1 → docelowe obciążenie CPU ≈ 5%
Iteracja #1 → docelowe obciążenie CPU ≈ 5%
Iteracja #1 → docelowe obciążenie CPU ≈ 5%
Iteracja #2 → docelowe obciążenie CPU ≈ 10%
Iteracja #2 → docelowe obciążenie CPU ≈ 10%
Iteracja #2 → docelowe obciążenie CPU ≈ 10%
Iteracja #2 → docelowe obciążenie CPU ≈ 10%
...

# po kilku minutach widać że w kolumnie target zmniejsza się powoli wykorzystanie CPU i ilośc replik podów
watch -n 5 'oc get hpa,dc,rc,pods -n java-cpu-burner'

Warning: apps.openshift.io/v1 DeploymentConfig is deprecated in v4.14+, unavailable in v4.10000+
NAME                                                      REFERENCE                              TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/java-cpu-burner-app   DeploymentConfig/java-cpu-burner-app   44%/70%   1         5         2          126m

NAME                                                     REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfig.apps.openshift.io/java-cpu-burner-app   15         2         2         config,image(java-cpu-burner-build:latest)

NAME                                           DESIRED   CURRENT   READY   AGE
replicationcontroller/java-cpu-burner-app-10   0         0         0       82m
replicationcontroller/java-cpu-burner-app-11   0         0         0       80m
replicationcontroller/java-cpu-burner-app-12   0         0         0       75m
replicationcontroller/java-cpu-burner-app-13   0         0         0       39m
replicationcontroller/java-cpu-burner-app-14   0         0         0       38m
replicationcontroller/java-cpu-burner-app-15   2         2         2       27m
replicationcontroller/java-cpu-burner-app-5    0         0         0       127m
replicationcontroller/java-cpu-burner-app-6    0         0         0       126m
replicationcontroller/java-cpu-burner-app-7    0         0         0       126m
replicationcontroller/java-cpu-burner-app-8    0         0         0       87m
replicationcontroller/java-cpu-burner-app-9    0         0         0       82m

NAME                                READY   STATUS      RESTARTS   AGE
pod/java-cpu-burner-app-10-deploy   0/1     Completed   0          82m
pod/java-cpu-burner-app-11-deploy   0/1     Completed   0          80m
pod/java-cpu-burner-app-12-deploy   0/1     Completed   0          75m
pod/java-cpu-burner-app-13-deploy   0/1     Completed   0          39m
pod/java-cpu-burner-app-14-deploy   0/1     Completed   0          38m
pod/java-cpu-burner-app-15-deploy   0/1     Completed   0          27m
pod/java-cpu-burner-app-15-nw8cs    1/1     Running     0          27m
pod/java-cpu-burner-app-15-smdfg    1/1     Running     0          27m
pod/java-cpu-burner-app-5-deploy    0/1     Completed   0          127m
pod/java-cpu-burner-app-6-deploy    0/1     Completed   0          126m
pod/java-cpu-burner-app-7-deploy    0/1     Completed   0          126m
pod/java-cpu-burner-app-8-deploy    0/1     Completed   0          87m
pod/java-cpu-burner-app-9-deploy    0/1     Completed   0          82m
pod/java-cpu-burner-build-1-build   0/1     Completed   0          177m
pod/java-cpu-burner-build-2-build   0/1     Completed   0          127m
pod/java-cpu-burner-build-3-build   0/1     Completed   0          87m
pod/java-cpu-burner-build-4-build   0/1     Completed   0          80m

# ręczne wyskalowanie do 1 pod-a gdy nie mamy cierpliwości aby poczekać
oc scale dc/java-cpu-burner-app --replicas=1 -n java-cpu-burner

Sam proces skalowania można też podglądać w eventach projektu.

oc get events --sort-by='{.lastTimestamp}' -n java-cpu-burner

15m         Warning   FailedGetResourceMetric        horizontalpodautoscaler/java-cpu-burner-app    failed to get cpu utilization: did not receive metrics for targeted pods (pods might be unready)
11m         Normal    Killing                        pod/java-cpu-burner-app-15-4x67c               Stopping container java-cpu-burner-build
11m         Normal    SuccessfulDelete               replicationcontroller/java-cpu-burner-app-15   Deleted pod: java-cpu-burner-app-15-4x67c
11m         Normal    ReplicationControllerScaled    deploymentconfig/java-cpu-burner-app           Scaled replication controller "java-cpu-burner-app-15" from 5 to 4
6m20s       Normal    Killing                        pod/java-cpu-burner-app-15-772wl               Stopping container java-cpu-burner-build
6m20s       Normal    SuccessfulRescale              horizontalpodautoscaler/java-cpu-burner-app    New size: 3; reason: All metrics below target
6m20s       Normal    ReplicationControllerScaled    deploymentconfig/java-cpu-burner-app           Scaled replication controller "java-cpu-burner-app-15" from 4 to 3
6m20s       Normal    SuccessfulDelete               replicationcontroller/java-cpu-burner-app-15   Deleted pod: java-cpu-burner-app-15-772wl
2m49s       Normal    Killing                        pod/java-cpu-burner-app-15-thdr8               Stopping container java-cpu-burner-build
2m49s       Normal    ReplicationControllerScaled    deploymentconfig/java-cpu-burner-app           Scaled replication controller "java-cpu-burner-app-15" from 3 to 2
2m49s       Normal    SuccessfulDelete               replicationcontroller/java-cpu-burner-app-15   Deleted pod: java-cpu-burner-app-15-thdr8
2m49s       Normal    SuccessfulRescale              horizontalpodautoscaler/java-cpu-burner-app    New size: 2; reason: All metrics below target