{"id":10190,"date":"2020-03-01T17:06:08","date_gmt":"2020-03-01T16:06:08","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=10190"},"modified":"2023-06-18T18:18:06","modified_gmt":"2023-06-18T16:18:06","slug":"autoscaling-of-docker-containers-in-google-kubernetes-engine","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/03\/01\/autoscaling-of-docker-containers-in-google-kubernetes-engine\/","title":{"rendered":"Autoscaling of Docker Containers  in Google Kubernetes Engine"},"content":{"rendered":"\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<p>The name Kubernetes comes originally from the Greek word for helmsman. It is the person who steers a ship or boat. Representing a steering wheel, the Kubernetes logo was most likely inspired by it. [<a href=\"#references\">1<\/a>]&nbsp;<\/p>\n\n\n\n<p>The choice of the name can also be interpreted to mean that Kubernetes (the helmsman) steers a ship that contains several containers (e.g. docker containers). It is therefore responsible for bringing these containers safely to their destination (to ensure that the journey goes smoothly) and for orchestrating them.<\/p>\n\n\n\n<p>Apparently Kubernetes was called <em>Seven of Nine<\/em> within Google. The Star Trek fans under us should be familiar with this reference. Having 7 spikes, there might be a connection between the logo and this name. [<a href=\"#references\">2<\/a>]<\/p>\n\n\n\n<p>This blog post was created during the master lecture <em>System Engineering and Management<\/em>. In this lecture we deal with topics that are of interest to us and with which we would like to conduct experiments. We have already worked with docker containers very often and appreciate the advantages. Of course we have also worked with several containers within a closed system orchestrated by Docker-Compose configurations. Nevertheless, especially in connection with scaling and the big companies like Netflix or Amazon, you hear the buzzword Kubernetes and quickly find out that a distribution of a system to several nodes requires a platform such as Kubernetes.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Who is this blog post for?&nbsp;<\/strong><\/h3>\n\n\n\n<p>If you know what Docker Containers are and how they are built and used, the next step may be to create multiple instances of them and distribute the load. Of course this is possible with a Docker-Compose configuration, but the containers will only run on one computer at a time. So as soon as the computer reaches its physical limits, it is absolutely necessary to distribute the services and the instances thereof to several nodes. This is exactly what Kubernetes is suitable for, as it is used to orchestrate containers in a distributed system. In this blog post we will start exactly at this point and assume that you have basic experience with Docker and Kubernetes. The focus is on scaling containers within a Kubernetes cluster.<\/p>\n\n\n\n<p>Of course all others who found their way to this blog post are also invited to read the blog post in order to learn more about Kubernetes, the autoscaling of services in docker containers plus the visualization of their utilization.<\/p>\n\n\n\n<p>We will share and discuss our experiences about what we have built, what we have learned and difficulties we have encountered during our experiments.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What is our goal?<\/strong><\/h3>\n\n\n\n<p>First of all we just wanted to start with Kubernetes, experiment and build something with as little effort as possible and see results. But even the first question can be a challenge. Where to start?&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Hosted Kubernetes<\/strong><br>Google GKE, Microsoft Azure, Amazon EKS, IBM Cloud Kubernetes Service, Apache Cloudstack and there are many more.&nbsp;<\/li><li><strong>Test playground<\/strong><strong><br><\/strong>Magic Sandbox, Play with Kubernetes or Docker Desktop.<\/li><\/ul>\n\n\n\n<p>One can easily be overwhelmed by all these possibilities just to get started. Anyway, we wanted to expand our knowledge of Kubernetes and experiment a little. So we thought about a small use case. This should be kept as simple as possible so that it can be explained in a comprehensible way in this post.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Use Case<\/h3>\n\n\n\n<p>Imagine yourself being a backend developer or in a dev ops position and that you want to solve the following use case:&nbsp;<\/p>\n\n\n\n<p><strong><em>Kubernetes Autoscaling<\/em><\/strong><\/p>\n\n\n\n<p>First you want to create a service (e.g. a simple hello world website) and containerize this service with Docker. Then you select a Hosted Kubernetes service of your choice and use it to provision and manage your cluster. Once it is set up and running, it should be able to scale based on CPU\/memory usage or any custom metrics. Users requesting your service should then be redirected to the new services created by Kubernetes to balance the load.<\/p>\n\n\n\n<p>For testing purposes and visual feedback it would be great to trigger\/emulate high CPU\/memory-usage to visually see (e.g. monitoring dashboard) the app scaling in both horizontal &amp; vertical directions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What are we not doing<\/strong>?<\/h3>\n\n\n\n<p>It won\u2019t be a fully functioning production-ready step-by-step setup. We are just experimenting and the goal is to learn as much as possible.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<h2 class=\"wp-block-heading\"><strong>Choice of Cloud Provider<\/strong><\/h2>\n\n\n\n<p>As already mentioned, it can be difficult to choose the right provider. The choice of providers is huge and continues to increase. Among them are &#8220;playgrounds&#8221; like Magic Sandbox, Play with Kubernetes or Docker Desktop. These are however very limited in their functionality. Therefore, they were not considered for our experiment. To use Kubernetes without restrictions, we have to use &#8220;Hosted Kubernetes&#8221; providers, which does not make the choice easier. There are many platforms available, e.g.:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/cloud.google.com\/kubernetes-engine\">Google Kubernetes Engine<\/a> (GKE)<\/li><li><a href=\"https:\/\/azure.microsoft.com\/en-us\/services\/kubernetes-service\/\">Microsoft Azure Kubernetes Service<\/a> (AKS)<\/li><li><a href=\"https:\/\/aws.amazon.com\/de\/eks\/\">Amazon Elastic Kubernetes Service<\/a> (EKS)<\/li><li><a href=\"https:\/\/www.ibm.com\/cloud\/container-service\/\">IBM Cloud Kubernetes Service<\/a><\/li><li><a href=\"https:\/\/www.alibabacloud.com\/de\/product\/kubernetes\">Alibaba Container Service for Kubernetes<\/a> (ACK)<\/li><li><a href=\"https:\/\/www.digitalocean.com\/products\/kubernetes\/\">DigitalOcean Kubernetes<\/a><\/li><li>and many more&#8230;<\/li><\/ul>\n\n\n\n<p>Finally, we chose Google Kubernetes Engine because Kubernetes was originally developed by Google, so we assumed that if there were updates or new features, they would be directly supported by the GKE. Furthermore, we have worked a lot with other Google Cloud services like Firebase, Cloud Functions and Cloud Storage in the past. We hope that this will allow us to easily integrate and interact with Google products in the future. GKE delivers the <em>Standard Metric API<\/em> by default and does not need to be explicitly implemented. Google&#8217;s Kubernetes Engine can be tested over 12 months with a budget of $300, which we also took into consideration in our decision.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<h2 class=\"wp-block-heading\">Scaling<\/h2>\n\n\n\n<p>In order to understand the scaling of Docker Containers within a Kubernetes cluster, different scaling options are presented first, which can be applied to various systems independently of Kubernetes. The Scale Cube is suitable for illustrating the different possibilities. [<a href=\"#references\">3<\/a>, p. 8ff.]<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/gRxBm0XeXHPw7JvMWIJI515-JjqrJGJ3tn4fb5RzNZNoYvF4nyKTnY9FurK24m-H3YYQPGjWIy3xjz9FNJPX75dUkFdreYtQjlJdtlb7KPlyM2lpIjs8njAv4ugyoeWZ2Q4AGVrw\" alt=\"\" width=\"519\" height=\"363\" \/><figcaption><strong>Figure 1:<\/strong> Scale Cube [<a href=\"#references\">3<\/a> p. 10, fig. 1.4]<\/figcaption><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">X-Axis<\/h3>\n\n\n\n<p>A scale on the x-axis is called <strong>horizontal scaling<\/strong>.&nbsp; This involves duplicating an existing application and distributing the requests to the available instances with the help of a load balancer. Figure 2 shows three instances of an application whose requests are distributed with the help of a load balancer.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/YVLNzpjOsbnOzFFg0fjIOVteLhkjhJBpf-h6XzmGtRsYqJEUZM80AQbvBc4Ehbiv69StvCJv5rqtpdKs3dRfWqWAHm1twb83sI2oz31mfqgyGEKS2jujXH-R-KcrSqk7x_stu3hw\" alt=\"\" width=\"548\" height=\"295\" \/><figcaption><strong>Figure 2:<\/strong> x-axis scaling  [<a href=\"#references\">3<\/a>, p. 10, fig. 1.4]<\/figcaption><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Z-Axis<\/h3>\n\n\n\n<p>An extension of a system in Z-direction works similar to scaling along the x-axis, because the application is also duplicated. However, the load balancer does not forward the requests arbitrarily, but based on an attribute of the request such as a userId. Figure 3 also shows three instances of an application.&nbsp; In contrast to x-axis scaling, the requests against these instances are forwarded by a load balancer based on the userId, which is known to the system through prior authentication of the user.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/Duz0WleX0CWS8N8JXQnoZUOG4iWygApl6uQOYG_CApM6W-McFth8Daa2oxQtschV8pr1rv1nK8Ov4iVj1nlvQSVx7d1WKFUvPO-Lf0o8hO0J8ebA1IABSJCqkyzOCvFgcKBJS1UD\" alt=\"\" width=\"532\" height=\"262\" \/><figcaption><strong>Figure 3:<\/strong> z-axis scaling [<a href=\"#references\">3<\/a>, p. 10, fix. 1.5]<\/figcaption><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Y-Axis<\/h3>\n\n\n\n<p>If a system is functionally broken down into individual services, this is referred to as scaling in the y-direction. These services often have several instances, which also means scaling in the x-axis or the y-axis. Figure 4 shows a system scaled in x- y- and z-direction.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/Aj54_NGefAH7JsvJ14e9yn5YorNDaETqL7vShYzQh1LUf9os7Zvl5phuU3EV-jXZft8MvOEp9cS2jqxbL4lkhFgc1ejpM6trFE9oFWJa2HyVJiBKy70YESi0INqQ7M9fdtuKF_bF\" alt=\"\" width=\"514\" height=\"298\" \/><figcaption><strong>Figure 4:<\/strong> y-axis scaling [<a href=\"#references\">3<\/a>, p. 11, fig. 1.6]<\/figcaption><\/figure><\/div>\n<\/div><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Scale vertically<\/strong><\/h3>\n\n\n\n<p>Besides the previous options of the Scale Cube, there is often talk of <strong>vertical scalin<\/strong>g. This refers to adding resources to a server, giving it more capacity and performance. However, since the hardware sets the limits, there are limited possibilities. [<a href=\"#references\">4<\/a>] <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Classification of the possibilities in relation to the given system<\/strong><\/h3>\n\n\n\n<p>In a Kubernetes Cluster, all of the mentioned scaling possibilities can be used. Since scaling in z-axis is only a modification of the scaling of the x-axis, this concept is not considered. In addition, the application consists of only one service that fulfils one function. Therefore, a differentiation into several microservices currently makes no sense, but can be implemented at a later time to achieve scaling of the y-axis. In the context of this work, only optimizations for scaling in the x-axis and for vertical scaling are made and worked out. Subsequently, the methods will be compared and evaluated.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Creating a Cluster in GKE<\/strong><\/h2>\n\n\n\n<p>When creating a cluster in Google Kubernetes Engine, we had to decide on some settings. The following is a list of the settings we changed. All other settings were taken over unchanged.<\/p>\n\n\n\n<p>When selecting the Kubernetes version there are two options: <em>Master Version<\/em> or <em>Release Version<\/em>. If you select <em>Release Version<\/em>, Kubernetes is automatically updated by GKE. However, we have selected <em>Master Version<\/em> to make sure that there are no changes to the Kubernetes APIs caused by automatic updates. The setup will select version<em> 1.14.10-gke.17 (default)<\/em> as default. Unfortunately, the API <em>autoscaling\/v2beta2<\/em>, which we need for scaling with custom metrics, is not available there. Therefore, we have chosen the current stable version <em>1.15.9-gke.9<\/em>.<\/p>\n\n\n\n<p>As image we use <em>n1-standard-1<\/em> with 1 vCPU and 3.75 GB memory. We first tried to use smaller images like <em>f1-micro<\/em> with 614 MB memory and <em>g1-small<\/em> with 1.78 GB memory, but we couldn&#8217;t start our application in it.<\/p>\n\n\n\n<p>When creating a cluster, we can decide whether we want to activate Stackdrive or not. Stackdrive is a monitoring solution integrated into the Google Cloud but located outside the cluster. We have therefore chosen to monitor using Grafana and Prometheus, which we operate alongside our other containers within the cluster. This makes us independent of cloud platforms, which implies easy migration between them.<\/p>\n\n\n\n<p>In order for the automatic vertical scaling of Pods to work, it must be activated via the &#8220;Enable Vertical Pod Autoscaling&#8221; checkbox. If this is forgotten, it can be activated later with the following command:<\/p>\n\n\n\n<p><code class=\"\" data-line=\"\">gcloud container clusters update [CLUSTER-NAME] --enable-vertical-pod-autoscaling<\/code><\/p>\n\n\n\n<p>When using the web interface of Google Kubernetes Engine we noticed that it can change from one day to the next. Especially the dialog for creating a cluster was affected. After a short search, however, all items could be found again.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Applications<\/h2>\n\n\n\n<p>Our cluster contains several applications. On the one hand we have a NestJS application which provides a REST API to generate CPU and memory loads. To track the resulting automatic scaling of the cluster, it contains Prometheus to collect the metrics and Grafana to display them visually.<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">NestJS Application<\/h3>\n\n\n\n<p>Since we need at least one container, we decided to develop a small REST API with <a rel=\"noreferrer noopener\" aria-label=\"NestJS (opens in a new tab)\" href=\"https:\/\/nestjs.com\/\" target=\"_blank\">NestJS<\/a>. We use NestJS as we have already gained experience with it. Basically any framework like <a href=\"https:\/\/expressjs.com\/\">ExpressJS<\/a> (JavaScript), <a rel=\"noreferrer noopener\" aria-label=\"Flask (opens in a new tab)\" href=\"https:\/\/palletsprojects.com\/p\/flask\/\" target=\"_blank\">Flask<\/a> (Python), <a rel=\"noreferrer noopener\" aria-label=\"Spring Boot (opens in a new tab)\" href=\"https:\/\/spring.io\/projects\/spring-boot\" target=\"_blank\">Spring Boot<\/a> (Java) etc. is suitable to create an easy (REST-)API.<\/p>\n\n\n\n<p>To test the horizontal scaling by memory and CPU, we created two endpoints. The first endpoint tests the memory usage by appending a string to an array a few thousand times. The CPU test calculates roots in a loop to drive up the CPU load.<\/p>\n\n\n\n<p>For scaling using custom metrics, we have created an endpoint that returns the static metric sem_metric with the value 5.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">Monitoring<\/h3>\n\n\n\n<p>To visualize our monitoring data we used <a href=\"https:\/\/prometheus.io\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Prometheus (opens in a new tab)\">Prometheus<\/a> and <a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Grafana (opens in a new tab)\">Grafana<\/a> as mentioned in the previous chapter. Basically Prometheus is there to retrieve\/collect and store the metrics. Grafana on the other hand retrieves the data from Prometheus and visualizes the metrics in a dashboard. Thereby the workloads and scales are displayed in a clear and simple way. [<a href=\"#references\">5<\/a>, <a href=\"#references\">6<\/a>]<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"10259\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/03\/01\/autoscaling-of-docker-containers-in-google-kubernetes-engine\/1052ebad-d01f-4803-bde6-e943c4598ef9\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/03\/1052ebad-d01f-4803-bde6-e943c4598ef9.jpeg\" data-orig-size=\"1600,690\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"1052ebad-d01f-4803-bde6-e943c4598ef9\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/03\/1052ebad-d01f-4803-bde6-e943c4598ef9-1024x442.jpeg\" src=\"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/03\/1052ebad-d01f-4803-bde6-e943c4598ef9.jpeg?fit=656%2C283&amp;ssl=1\" alt=\"\" class=\"wp-image-10259\" width=\"550\" height=\"237\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/03\/1052ebad-d01f-4803-bde6-e943c4598ef9.jpeg 1600w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/03\/1052ebad-d01f-4803-bde6-e943c4598ef9-300x129.jpeg 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/03\/1052ebad-d01f-4803-bde6-e943c4598ef9-1024x442.jpeg 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/03\/1052ebad-d01f-4803-bde6-e943c4598ef9-768x331.jpeg 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/03\/1052ebad-d01f-4803-bde6-e943c4598ef9-1536x662.jpeg 1536w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><figcaption><strong>Figure 5:<\/strong> Grafana Dashboard<\/figcaption><\/figure><\/div>\n\n\n\n<p>Prometheus belongs to the CNCF (<a href=\"https:\/\/www.cncf.io\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Cloud Native Computing Foundation (opens in a new tab)\">Cloud Native Computing Foundation<\/a>) Graduates and Grafana CNCF Silver-Member [<a href=\"#references\">7<\/a>]. This was one reason for choosing these services.<\/p>\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Horizontal Scaler<\/strong><\/h2>\n\n\n\n<p>Before we scale horizontally, we need to know how the Horizontal Pod Autoscaler (HPA) works. As the name suggests, the HPA provides the basis for any horizontal scaling within a Kubernetes cluster. This means not only scaling based on CPU and memory usage, but also adjusting the number of pods using custom metrics. Of course, these variants can be combined in any combination using a combined scaler.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Horizontal Pod Autoscaler<\/strong><\/h3>\n\n\n\n<p>Before we can talk about scaling based on CPU\/Memory usage, we need to clarify how Kubernetes actually collects these metrics. This will also be important later on for the chapter <a href=\"#custom-scaler\">Custom Scaler<\/a>.<\/p>\n\n\n\n<p>In order to use auto scaling, the files must be equipped with the API version <em>autoscaling\/v2beta2<\/em>, because the stable version only supports the metric CPU. Only since <em>v2beta2<\/em> scaling based on custom and memory metrics was added. In addition, several metrics can be specified simultaneously (type metric is now an array).<\/p>\n\n\n\n<p>The <em>HorizontalPodAutoscaler<\/em> is a loop that retrieves the resource load specified in the files in a certain period (default value of 15 seconds, can also be set with the flag <em>&#8211;horizontalPodAutoscaler-Sync-Period<\/em>).<br>The data can be retrieved from various API&#8217;s (Metrics API, Custom Metrics API and External Metrics API). We will not go into detail about the External Metrics API, as we did not use it in our example. The standard Metrics API can be used to scale by CPU and memory usage. For custom metrics, you must use the Custom Metrics API. This will be discussed later in the chapter <a href=\"#custom-scaler\">Custom Scaler<\/a>. [<a href=\"#references\">8<\/a>]<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Scaling based on the CPU load<\/strong><\/h3>\n\n\n\n<p>In order to scale based on CPU utilization, we need to create a HPA. The blueprint for this HPA is specified via a yaml file which includes different properties. The following gist shows an example for such a configuration file.<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\n<style>.gist table { margin-bottom: 0; }<\/style><div style=\"tab-size: 8\" id=\"gist101525347\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-cpuscaler-yaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-yaml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"cpuScaler.yaml content, created by SpackHack on 06:31PM on February 29, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https:\/\/github.co\/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"cpuScaler.yaml\">\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">apiVersion: autoscaling\/v2beta2<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC2\" class=\"blob-code blob-code-inner js-file-line\">kind: HorizontalPodAutoscaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC3\" class=\"blob-code blob-code-inner js-file-line\">metadata:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC4\" class=\"blob-code blob-code-inner js-file-line\">  name: scaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC5\" class=\"blob-code blob-code-inner js-file-line\">spec:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC6\" class=\"blob-code blob-code-inner js-file-line\">  scaleTargetRef:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC7\" class=\"blob-code blob-code-inner js-file-line\">    apiVersion: apps\/v1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC8\" class=\"blob-code blob-code-inner js-file-line\">    kind: Deployment<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC9\" class=\"blob-code blob-code-inner js-file-line\">    name: resourcetest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC10\" class=\"blob-code blob-code-inner js-file-line\">  minReplicas: 1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC11\" class=\"blob-code blob-code-inner js-file-line\">  maxReplicas: 10<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC12\" class=\"blob-code blob-code-inner js-file-line\">  metrics:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC13\" class=\"blob-code blob-code-inner js-file-line\">    &#8211; type: Resource<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC14\" class=\"blob-code blob-code-inner js-file-line\">      resource:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC15\" class=\"blob-code blob-code-inner js-file-line\">        name: cpu<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC16\" class=\"blob-code blob-code-inner js-file-line\">        target:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC17\" class=\"blob-code blob-code-inner js-file-line\">          type: Utilization<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-cpuscaler-yaml-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-cpuscaler-yaml-LC18\" class=\"blob-code blob-code-inner js-file-line\">          averageUtilization: 50<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/dd7326eb5985814cde95e6b85e672860\/raw\/cca7300aebf3a74a1592f59a5eef7922422250b2\/cpuScaler.yaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/dd7326eb5985814cde95e6b85e672860#file-cpuscaler-yaml\" class=\"Link--inTextBlock\">\n          cpuScaler.yaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https:\/\/github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n\n<\/div><\/figure>\n\n\n\n<p>The most important setting is the metrics property (line 12). The name of the resource must be cpu (line 15). Furthermore, the target type must be Utilization (line 17). By defining the averageUtilization, the threshold on when to scale up or down is set. Example: when the calculated average utilization of all running pods exceeds the given value of the property averageUtilization, the HPA starts a new Pod. It is important that the target deployment is defined correctly so that the autoscaler knows where to scale what (line 6-9). In addition, it must be specified how many instances should run at least (line 10) and how many at most (line 11) simultaneously. This prevents the autoscaler from creating an infinite number of instances. Finally, this also protects the user from unnecessarily high bills.<\/p>\n\n\n\n<p>Now we have to differentiate again between Resource, External and Pods. External was not used in this example. Pods are used for automatic scaling with multiple metrics and custom metrics, which is also used later in the chapter <a href=\"#custom-scaler\">Custom Scaler<\/a>. To access both, CPU and memory, Resource must be used as type. Under the item Type, the name CPU is entered. At this point, the autoscaler knows which metric to look for.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Scaling based on the RAM usage<\/strong><\/h3>\n\n\n\n<p>The configuration file for scaling based on memory has nearly the same structure. Only the name changes from CPU to memory (line 15 of the following gist). With AverageValue (line 17), the values of each pod returned by the metric API are summed up and divided by the number of Pods. Afterwards, this average is compared with the target average value (value that the user typed into the item AverageValue, see line 18) in order to increase or decrease the number of instances.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\n<style>.gist table { margin-bottom: 0; }<\/style><div style=\"tab-size: 8\" id=\"gist101525369\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-memoryscaler-yaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-yaml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"memoryScaler.yaml content, created by SpackHack on 06:33PM on February 29, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https:\/\/github.co\/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"memoryScaler.yaml\">\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">apiVersion: autoscaling\/v2beta2<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC2\" class=\"blob-code blob-code-inner js-file-line\">kind: HorizontalPodAutoscaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC3\" class=\"blob-code blob-code-inner js-file-line\">metadata:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC4\" class=\"blob-code blob-code-inner js-file-line\">  name: scaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC5\" class=\"blob-code blob-code-inner js-file-line\">spec:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC6\" class=\"blob-code blob-code-inner js-file-line\">  scaleTargetRef:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC7\" class=\"blob-code blob-code-inner js-file-line\">    apiVersion: apps\/v1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC8\" class=\"blob-code blob-code-inner js-file-line\">    kind: Deployment<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC9\" class=\"blob-code blob-code-inner js-file-line\">    name: resourcetest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC10\" class=\"blob-code blob-code-inner js-file-line\">  minReplicas: 1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC11\" class=\"blob-code blob-code-inner js-file-line\">  maxReplicas: 10<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC12\" class=\"blob-code blob-code-inner js-file-line\">  metrics:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC13\" class=\"blob-code blob-code-inner js-file-line\">    &#8211; type: Resource<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC14\" class=\"blob-code blob-code-inner js-file-line\">      resource:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC15\" class=\"blob-code blob-code-inner js-file-line\">        name: memory<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC16\" class=\"blob-code blob-code-inner js-file-line\">        target:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC17\" class=\"blob-code blob-code-inner js-file-line\">          type: AverageValue<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-memoryscaler-yaml-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-memoryscaler-yaml-LC18\" class=\"blob-code blob-code-inner js-file-line\">          averageValue: 100Mi<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/ca991498a58280dd5c48b96d43fb81a5\/raw\/9a4f9b4cc2ea5f8d5b4db8f935673b8a62c298ec\/memoryScaler.yaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/ca991498a58280dd5c48b96d43fb81a5#file-memoryscaler-yaml\" class=\"Link--inTextBlock\">\n          memoryScaler.yaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https:\/\/github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n\n<\/div><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Combined Scaler<\/strong><\/h3>\n\n\n\n<p>Since the item <em>Metrics<\/em> in the yaml file is an array, several metrics can be specified, as shown in the example below. In this example, we simply combine the previously mentioned examples CPU and memory in one file. Now the autoscaler can use both values in order to decide how many instances should be started. If we now assume that three new instances are needed due to CPU utilization but only one new instance is needed due to memory load, the autoscaler will always choose the larger value and use it to adjust the number of pods.<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\n<style>.gist table { margin-bottom: 0; }<\/style><div style=\"tab-size: 8\" id=\"gist101525385\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-combinedscaler-yaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-yaml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"combinedScaler.yaml content, created by SpackHack on 06:35PM on February 29, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https:\/\/github.co\/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"combinedScaler.yaml\">\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">apiVersion: autoscaling\/v2beta2<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC2\" class=\"blob-code blob-code-inner js-file-line\">kind: HorizontalPodAutoscaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC3\" class=\"blob-code blob-code-inner js-file-line\">metadata:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC4\" class=\"blob-code blob-code-inner js-file-line\">  name: scaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC5\" class=\"blob-code blob-code-inner js-file-line\">spec:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC6\" class=\"blob-code blob-code-inner js-file-line\">  scaleTargetRef:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC7\" class=\"blob-code blob-code-inner js-file-line\">    apiVersion: apps\/v1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC8\" class=\"blob-code blob-code-inner js-file-line\">    kind: Deployment<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC9\" class=\"blob-code blob-code-inner js-file-line\">    name: resourcetest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC10\" class=\"blob-code blob-code-inner js-file-line\">  minReplicas: 1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC11\" class=\"blob-code blob-code-inner js-file-line\">  maxReplicas: 10<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC12\" class=\"blob-code blob-code-inner js-file-line\">  metrics:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC13\" class=\"blob-code blob-code-inner js-file-line\">    &#8211; type: Resource<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC14\" class=\"blob-code blob-code-inner js-file-line\">      resource:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC15\" class=\"blob-code blob-code-inner js-file-line\">        name: cpu<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC16\" class=\"blob-code blob-code-inner js-file-line\">        target:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC17\" class=\"blob-code blob-code-inner js-file-line\">          type: Utilization<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC18\" class=\"blob-code blob-code-inner js-file-line\">          averageUtilization: 50<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC19\" class=\"blob-code blob-code-inner js-file-line\">    &#8211; type: Resource<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC20\" class=\"blob-code blob-code-inner js-file-line\">      resource:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC21\" class=\"blob-code blob-code-inner js-file-line\">        name: memory<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC22\" class=\"blob-code blob-code-inner js-file-line\">        target:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC23\" class=\"blob-code blob-code-inner js-file-line\">          type: AverageValue<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-combinedscaler-yaml-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-combinedscaler-yaml-LC24\" class=\"blob-code blob-code-inner js-file-line\">          averageValue: 100Mi<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/6c2f37fbaada594b549a0b86e190e3dd\/raw\/c05dbb64b2ffcbff867d69e416605e4ed658c733\/combinedScaler.yaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/6c2f37fbaada594b549a0b86e190e3dd#file-combinedscaler-yaml\" class=\"Link--inTextBlock\">\n          combinedScaler.yaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https:\/\/github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n\n<\/div><\/figure>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\" id=\"custom-scaler\"><strong>Custom Scaler<\/strong><\/h3>\n\n\n\n<p>To scale services in a more controlled way, scaling the Pods based on CPU and memory is usually not sufficient. Therefore Kubernetes offers a possibility to create own metrics with the help of the HPA. Afterwards it is possible to scale based on these metrics.<\/p>\n\n\n\n<p>In order for the HPA to access own metrics, these must be exported to the Kubernetes Custom Metrics API. To achieve this, the Kubernetes API must be extended to include the Custom Metrics API. The Aggregation Layer is responsible for extending the Kubernetes API.<\/p>\n\n\n\n<p>In our example, the metrics from the pods are already collected by Prometheus. To export the custom metrics, we use the <a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/github.com\/directxman12\/k8s-prometheus-adapter\" target=\"_blank\">Prometheus adapter from &#8220;directxman&#8221;<\/a>, which we installed over Helm. <a href=\"https:\/\/helm.sh\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Helm (opens in a new tab)\">Helm<\/a> is package manager for Kubernetes. The installation via Helm has the advantage that the authorization of the adapter in the aggregation layer does not have to be set up manually.<\/p>\n\n\n\n<p>Although the Prometheus adapter from Helm is already preconfigured, it must be adapted to our application. This is done by specifying the URL and port from which the metrics are to be obtained (see line 2 in gist below). We have also adapted the query to capture our metrics (line 8).<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\n<style>.gist table { margin-bottom: 0; }<\/style><div style=\"tab-size: 8\" id=\"gist101525400\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-prometheus-adapter-yaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-yaml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"prometheus-adapter.yaml content, created by SpackHack on 06:36PM on February 29, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https:\/\/github.co\/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"prometheus-adapter.yaml\">\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">prometheus:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC2\" class=\"blob-code blob-code-inner js-file-line\">  url: http:\/\/prometheus-server.default.svc<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC3\" class=\"blob-code blob-code-inner js-file-line\">  port: 80<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC4\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC5\" class=\"blob-code blob-code-inner js-file-line\">rules:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC6\" class=\"blob-code blob-code-inner js-file-line\">  default: false<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC7\" class=\"blob-code blob-code-inner js-file-line\">  custom:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC8\" class=\"blob-code blob-code-inner js-file-line\">  &#8211; seriesQuery: &#39;{__name__= &quot;sem_metric&quot;}&#39;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC9\" class=\"blob-code blob-code-inner js-file-line\">    seriesFilters: []<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC10\" class=\"blob-code blob-code-inner js-file-line\">    resources:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC11\" class=\"blob-code blob-code-inner js-file-line\">      overrides:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC12\" class=\"blob-code blob-code-inner js-file-line\">        kubernetes_namespace:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC13\" class=\"blob-code blob-code-inner js-file-line\">          resource: namespace<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC14\" class=\"blob-code blob-code-inner js-file-line\">        kubernetes_pod_name:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC15\" class=\"blob-code blob-code-inner js-file-line\">          resource: pod<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC16\" class=\"blob-code blob-code-inner js-file-line\">    name:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC17\" class=\"blob-code blob-code-inner js-file-line\">      matches: &quot;sem_metric&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC18\" class=\"blob-code blob-code-inner js-file-line\">      as: &quot;&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prometheus-adapter-yaml-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-prometheus-adapter-yaml-LC19\" class=\"blob-code blob-code-inner js-file-line\">    metricsQuery: &lt;&lt;.Series&gt;&gt;{&lt;&lt;.LabelMatchers&gt;&gt;,container_name!=&quot;POD&quot;}<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/06ddc7e11221ced53d3bbdb52e55f8ff\/raw\/245a868e4fddac857cda70d9c7817d26121f440e\/prometheus-adapter.yaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/06ddc7e11221ced53d3bbdb52e55f8ff#file-prometheus-adapter-yaml\" class=\"Link--inTextBlock\">\n          prometheus-adapter.yaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https:\/\/github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n\n<\/div><\/figure>\n\n\n\n<p>After the Prometheus adapter is installed, the custom metrics are collected. The following figure shows the process flow. Our applications (Nest JS Pods) provide metrics that are collected by Prometheus. With the help of the Prometheus Adapter our metrics are exported from Prometheus to the Custom Metrics API of Kubernetes. The Horizontal Pod Autoscaler accesses our metrics via this API and customizes the deployment. Afterwards,, the required number of pods of this deployment are provided.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/HAlVpPLO4BdUZDpKaUI9AkhbB-P6V5FoaBdBlAfZ17wCQZ9JuAhYhudes9UDtaW5TXafApKEtsdQ2kmd_aHbsV5I6N1eO7vtBRo_pgT_AJtzkyjzACyPqbV3aFiHFPeOqwyN3uhk\" alt=\"\" width=\"504\" height=\"309\" \/><figcaption><strong>Figure 6:<\/strong> How Custom Scaler works<\/figcaption><\/figure><\/div>\n\n\n\n<p>To check if the custom metric is used, the command <code class=\"\" data-line=\"\">kubectl get --raw \/apis\/custom.metrics.k8s.io\/v1beta1<\/code> can be used. If the setup is done correctly, the custom metric will appear in the output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">{\n  &quot;kind&quot;: &quot;APIResourceList&quot;,\n  &quot;apiVersion&quot;: &quot;v1&quot;,\n  &quot;groupVersion&quot;: &quot;custom.metrics.k8s.io\/v1beta1&quot;,\n  &quot;resources&quot;: [\n   ...\n    {\n      &quot;name&quot;: &quot;pods\/sem_metric&quot;,\n      &quot;singularName&quot;: &quot;&quot;,\n      &quot;namespaced&quot;: true,\n      &quot;kind&quot;: &quot;MetricValueList&quot;,\n      &quot;verbs&quot;: [\n        &quot;get&quot;\n      ]\n    },\n    ...\n  ]\n}<\/code><\/pre>\n\n\n\n<p>Finally, a new entry for your own metric must be made in the HPA YAML under the item metrics. As type we choose &#8220;Pods&#8221; (line 13 in the gist below), as we have assigned the metric to a Pod. As name we use <em>sem_metric<\/em>. Since the type is Pod, only <em>AverageValue<\/em> can be selected as target type (line 18). The average of all pods is used to calculate the scaling. The <em>AvarageValue<\/em> (line 19) is the value that should be reached. More details about the scaling algorithm can be found in the <a href=\"https:\/\/kubernetes.io\/docs\/tasks\/run-application\/horizontal-pod-autoscale\/#algorithm-details\">Kubernetes documentation<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\n<style>.gist table { margin-bottom: 0; }<\/style><div style=\"tab-size: 8\" id=\"gist101525432\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-customscaler-yaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-yaml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"customScaler.yaml content, created by SpackHack on 06:38PM on February 29, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https:\/\/github.co\/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"customScaler.yaml\">\n        <tr>\n          <td id=\"file-customscaler-yaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-customscaler-yaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">apiVersion: autoscaling\/v2beta2<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-customscaler-yaml-LC2\" class=\"blob-code blob-code-inner js-file-line\">kind: HorizontalPodAutoscaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-customscaler-yaml-LC3\" class=\"blob-code blob-code-inner js-file-line\">metadata:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-customscaler-yaml-LC4\" class=\"blob-code blob-code-inner js-file-line\">  name: scaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-customscaler-yaml-LC5\" class=\"blob-code blob-code-inner js-file-line\">spec:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-customscaler-yaml-LC6\" class=\"blob-code blob-code-inner js-file-line\">  scaleTargetRef:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-customscaler-yaml-LC7\" class=\"blob-code blob-code-inner js-file-line\">    apiVersion: apps\/v1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-customscaler-yaml-LC8\" class=\"blob-code blob-code-inner js-file-line\">    kind: Deployment<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-customscaler-yaml-LC9\" class=\"blob-code blob-code-inner js-file-line\">    name: resourcetest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-customscaler-yaml-LC10\" class=\"blob-code blob-code-inner js-file-line\">  minReplicas: 1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-customscaler-yaml-LC11\" class=\"blob-code blob-code-inner js-file-line\">  maxReplicas: 10<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-customscaler-yaml-LC12\" class=\"blob-code blob-code-inner js-file-line\">  metrics:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-customscaler-yaml-LC13\" class=\"blob-code blob-code-inner js-file-line\">    &#8211; type: Pods<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-customscaler-yaml-LC14\" class=\"blob-code blob-code-inner js-file-line\">      pods:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-customscaler-yaml-LC15\" class=\"blob-code blob-code-inner js-file-line\">        metric:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-customscaler-yaml-LC16\" class=\"blob-code blob-code-inner js-file-line\">          name: sem_metric<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-customscaler-yaml-LC17\" class=\"blob-code blob-code-inner js-file-line\">        target:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-customscaler-yaml-LC18\" class=\"blob-code blob-code-inner js-file-line\">          type: AverageValue<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-customscaler-yaml-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-customscaler-yaml-LC19\" class=\"blob-code blob-code-inner js-file-line\">          averageValue: 2<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/ea0d7d360500e268c9a7f132ef6ece07\/raw\/96d5df5b42eec6a61779684a33784a03ea0fa126\/customScaler.yaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https:\/\/gist.github.com\/SpackHack\/ea0d7d360500e268c9a7f132ef6ece07#file-customscaler-yaml\" class=\"Link--inTextBlock\">\n          customScaler.yaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https:\/\/github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n\n<\/div><\/figure>\n\n\n\n<p>After creating the HPA, the current status of the autoscaler can be retrieved:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/YFLrzfJv5GYW_ZFFMbc4zSqD43vQi2jAiyy8OuN5zwN8ki557uIhof8XHtVa4FiOmNEe3I_d6bZM08H8Lj4Ujl4sM2t0xxLoWcKGnvMCW6FlhyOR1aWrocBw17vFZCmJAR2biaH_\" alt=\"\" \/><figcaption><strong>Figure 7:<\/strong> Status of HPA<\/figcaption><\/figure>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<p>There are two values under the item <em>Targets<\/em>. The left value is retrieved from the Pods using the Custom Metrics API, so it is the actual value. The right value defines the state which is declared in the HPA YAML file and therefore expected.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Problems that were noticed<\/strong><\/h3>\n\n\n\n<p>While experimenting especially with the CPU and memory metrics and our NestJS applications that are designed to provoke exactly these loads, we noticed when testing the memory usage that the node server shoots itself off after a certain amount of time. This made testing a bit more difficult, but at this point you can clearly see that Kubernetes simply restarts the pod after it was no longer available.<\/p>\n\n\n\n<p>Experimenting sometimes felt like a black box, because there was a lot of trial and error and the monitoring was very slow. We were never able to see exactly at what point it was scaling, because the visualization of the data only showed a change after an indefinite time. Sometimes faster and sometimes slower than usual.<\/p>\n\n\n\n<p>Even though we were able to take a lot with us, we did not reach a point within this semester where we felt very confident so that we could use Kubernetes in real world projects.<\/p>\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Vertical Scaler<\/h2>\n\n\n\n<p>Vertical scaling within a Pod is controlled by the Vertical Pod Autoscaler (VPA). The CPU and memory of a Pod are automatically adjusted if the previous resources are no longer sufficient for the current task or the Pod requires less than it has available. The exact procedure in the cluster is as follows:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The Vertical Pod Autoscaler regularly analyzes the Pod. If a Pod has too many or too few allocated resources, they are adjusted in the next step.<\/li><li>The Pod Autoscaler starts a new pod that is assigned more or less resources than the previous one. This is similar to manually adjusting the limits in the deployment file. However, since these cannot be adjusted at runtime, the Vertical Pod Autoscaler creates a new pod in the Kubernetes Cluster.<\/li><li>As soon as the new pod with the updated resources is available, the old container is shut down.<\/li><\/ol>\n\n\n\n<p>The gist below is a configuration file for a VPA. Declaring the <em>updateMode<\/em> within the <em>updatePolicy<\/em> as <em>Auto<\/em>, lines 10+11 are the most important ones. The other values of the configuration are very similar to the properties specified in the configuration files for horizontal scaling.<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\n<style>.gist table { margin-bottom: 0; }<\/style><div style=\"tab-size: 8\" id=\"gist101537093\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-verticalscaler-yaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-yaml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"verticalScaler.yaml content, created by danelse on 09:52AM on March 01, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https:\/\/github.co\/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"verticalScaler.yaml\">\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">apiVersion: autoscaling.k8s.io\/v1beta2<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC2\" class=\"blob-code blob-code-inner js-file-line\">kind: VerticalPodAutoscaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC3\" class=\"blob-code blob-code-inner js-file-line\">metadata:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC4\" class=\"blob-code blob-code-inner js-file-line\">  name: scaler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC5\" class=\"blob-code blob-code-inner js-file-line\">spec:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC6\" class=\"blob-code blob-code-inner js-file-line\">  targetRef:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC7\" class=\"blob-code blob-code-inner js-file-line\">    apiVersion: apps\/v1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC8\" class=\"blob-code blob-code-inner js-file-line\">    kind: Deployment<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC9\" class=\"blob-code blob-code-inner js-file-line\">    name: resourcetest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC10\" class=\"blob-code blob-code-inner js-file-line\">  updatePolicy:<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-verticalscaler-yaml-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-verticalscaler-yaml-LC11\" class=\"blob-code blob-code-inner js-file-line\">    updateMode: &quot;Auto&quot;<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https:\/\/gist.github.com\/danelse\/cf239cf151c425844b0834162d2d0430\/raw\/c1799cd93f3ed78a7354d0af621466cc808db3e8\/verticalScaler.yaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https:\/\/gist.github.com\/danelse\/cf239cf151c425844b0834162d2d0430#file-verticalscaler-yaml\" class=\"Link--inTextBlock\">\n          verticalScaler.yaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https:\/\/github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n\n<\/div><\/figure>\n\n\n\n<p>By default, vertical scaling is disabled in the Google Kubernetes Engine and the documentation of the Kubernetes page is outdated. Furthermore, some commands did not work or were renamed. We therefore assume that vertical scaling plays a minor role and we recommend horizontal scaling, especially with custom metrics. These are very flexible and can be adapted efficiently for different use cases.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Kubernetes offers various possibilities to scale containers over several nodes. However, it requires a lot of know-how and a long training period. Since the development of Kubernetes is progressing very fast, you often find outdated or no longer working tutorials. Some things had to be found out via trial and error.<\/p>\n\n\n\n<p>In some places Kubernetes seemed to be sluggish or like a black box. Sometimes we didn&#8217;t know whether the scaling had taken place or not because we had to wait for some time until we got updated values in the console or Prometheus.<\/p>\n\n\n\n<p>With regard to REST APIs, one must ask oneself whether scaling is required at all. Within the scope of our small test service, Kubernetes will certainly be overpowered and it will be easier to run a monolithic system on a single server. However, as a backend gets bigger and receives more requests, pushing it to the limits of resources, we can imagine using Kubernetes and splitting a backend into multiple services to get a scalable microservice architecture. However, a microservice architecture has other challenges that we have not considered so far. For example, you have to think about additional features like communication between services.<\/p>\n\n\n\n<p>Considering the huge effort, Kubernetes is unsuitable especially with regard to the time to market. To avoid the effort with Kubernetes and still be able to develop automatically scalable backends, <em>serverless<\/em> can be used. Google with Firebase or Amazon Lambda, for example, offer corresponding solutions for this purpose, which have become more flexible and straightforward to implement.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"references\">References<\/h4>\n\n\n\n[1] Nigel Poulton, 2017 &#8211; The Kubernetes Book<br>\n[2] <a target=\"blank\" href=\"https:\/\/en.wikipedia.org\/wiki\/Kubernetes#History\" rel=\"noopener noreferrer\">https:\/\/en.wikipedia.org\/wiki\/Kubernetes#History<\/a><br>\n[3] Chris Richardson. Microservices Patterns. Manning Publications, 2018.<br>\n[4] <a target=\"blank\" href=\"https:\/\/www.computerweekly.com\/de\/definition\/Horizontale-Skalierung-Scale-out\" rel=\"noopener noreferrer\">https:\/\/www.computerweekly.com\/de\/definition\/Horizontale-Skalierung-Scale-out<\/a><br>\n[5] <a target=\"blank\" href=\"https:\/\/prometheus.io\/docs\/introduction\/overview\/\" rel=\"noopener noreferrer\">https:\/\/prometheus.io\/docs\/introduction\/overview\/<\/a><br>\n[6] <a target=\"blank\" href=\"https:\/\/grafana.com\/grafana\/\" rel=\"noopener noreferrer\">https:\/\/grafana.com\/grafana\/<\/a><br>\n[7] <a target=\"blank\" href=\"https:\/\/www.cncf.io\/\" rel=\"noopener noreferrer\">https:\/\/www.cncf.io\/<\/a><br>\n[8] <a target=\"blank\" href=\"https:\/\/www.cncf.io\/\" rel=\"noopener noreferrer\">https:\/\/kubernetes.io\/docs\/tasks\/run-application\/horizontal-pod-autoscale\/#how-does-the-horizontal-pod-autoscaler-work<\/a>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog post we are taking a look at scaling possibilities within Kubernetes in a cloud environment. We are going to present and discuss various options that all have the same target: increase the availability of a service.<\/p>\n","protected":false},"author":948,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1,120,650,2],"tags":[3,154,48],"ppma_author":[805],"class_list":["post-10190","post","type-post","status-publish","format-standard","hentry","category-allgemein","category-cloud-technologies","category-scalable-systems","category-system-engineering","tag-docker","tag-kubernetes","tag-scaling"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":5175,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/02\/24\/benefiting-kubernetes-part-2-deploy-with-kubectl\/","url_meta":{"origin":10190,"position":0},"title":"Migrating to Kubernetes Part 2 &#8211; Deploy with kubectl","author":"Can Kattwinkel","date":"24. February 2019","format":false,"excerpt":"Written by: Pirmin Gersbacher, Can Kattwinkel, Mario Sallat Migrating from Bare Metal to Kubernetes The interest in software containers is a relatively new trend in the developers world. Classic VMs have not lost their right to exist within a world full of monoliths yet, but the trend is clearly towards\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":21651,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/09\/18\/deploy-random-chat-application-on-aws-ec2-with-kubernetes\/","url_meta":{"origin":10190,"position":1},"title":"Deploying Random Chat Application on AWS EC2 with Kubernetes","author":"dv029","date":"18. September 2021","format":false,"excerpt":"1. Introduction For the examination of the lecture \u201cSoftware Development for Cloud Computing\u201d, I want to build a simple Random Chat Application. The idea of this application is based on the famous chat application called Omegle. Omegle is where people can meet random people in the world and can have\u2026","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/09\/image-19.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":6652,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/07\/24\/how-to-create-a-k8s-cluster-with-custom-nodes-in-rancher\/","url_meta":{"origin":10190,"position":2},"title":"How to create a K8s cluster with custom nodes in Rancher","author":"Sarah Schwab","date":"24. July 2019","format":false,"excerpt":"Don't you find it annoying not to be able to manage all your Kubernetes clusters at a glance? Ranger 2.0 offers an ideal solution.\u00a0 The following article is less a scientific post than a how-to guide to creating a new Kubernetes cluster with custom nodes in Ranger 2.0.\u00a0 But before\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/07\/cluster-1.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/07\/cluster-1.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/07\/cluster-1.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/07\/cluster-1.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/07\/cluster-1.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":9655,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/02\/29\/image-editor-on-kubernetes-with-kompose-minikube-k3s-k3sup-and-helm-part-2\/","url_meta":{"origin":10190,"position":3},"title":"Kubernetes: from Zero to Hero with Kompose, Minikube, k3sup and Helm \u2014 Part 2: Hands-On","author":"Leon Klingele","date":"29. February 2020","format":false,"excerpt":"This is part two of our series on how we designed and implemented a scalable, highly-available and fault-tolerant microservice-based Image Editor. This part depicts how we went from a basic Docker Compose setup to running our application on our own \u00bbbare-metal\u00ab Kubernetes cluster.","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"\/wp-content\/uploads\/2020\/02\/DDD_dependencies-1024x119.png","width":350,"height":200,"srcset":"\/wp-content\/uploads\/2020\/02\/DDD_dependencies-1024x119.png 1x, \/wp-content\/uploads\/2020\/02\/DDD_dependencies-1024x119.png 1.5x, \/wp-content\/uploads\/2020\/02\/DDD_dependencies-1024x119.png 2x"},"classes":[]},{"id":5163,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/02\/24\/migrating-to-kubernetes-part-1-introduction\/","url_meta":{"origin":10190,"position":4},"title":"Migrating to Kubernetes Part 1 &#8211; Introduction","author":"Can Kattwinkel","date":"24. February 2019","format":false,"excerpt":"Written by: Pirmin Gersbacher, Can Kattwinkel, Mario Sallat Introduction The great challenge of collaborative working in a software developer team is to enable a high level of developer activity while ensuring a high product quality. In order to achieve this often CI\/CD processes are utilized. Talking about modern development techniques\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":3342,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/ci-cd-infrastructure-choosing-and-setting-up-a-server-with-jenkins-as-docker-image\/","url_meta":{"origin":10190,"position":5},"title":"CI\/CD infrastructure: Choosing and setting up a server with Jenkins as Docker image","author":"cp054","date":"28. March 2018","format":false,"excerpt":"Related articles:\u00a0\u25baTake Me Home - Project Overview\u00a0 \u25baAndroid SDK and emulator in Docker for testing\u00a0 \u25baAutomated Unit- and GUI-Testing for Android in Jenkins\u00a0 \u25baTesting a MongoDB with NodeJS, Mocha and Mongoose This article will run you through the motivation for a continuous integration and delivery, choosing a corresponding tool and\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/puttygen.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/puttygen.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/puttygen.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/puttygen.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":805,"user_id":948,"is_guest":0,"slug":"de032","display_name":"de032","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/82a2496378f84f62dfcd0ce8248067f663096d43786b05ee348c2d79e573c1b3?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/10190","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/948"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=10190"}],"version-history":[{"count":83,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/10190\/revisions"}],"predecessor-version":[{"id":10275,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/10190\/revisions\/10275"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=10190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=10190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=10190"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=10190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}