{"id":358,"date":"2022-11-24T11:05:24","date_gmt":"2022-11-24T11:05:24","guid":{"rendered":"https:\/\/ntlx.org\/?p=358"},"modified":"2022-11-24T11:07:08","modified_gmt":"2022-11-24T11:07:08","slug":"pod-autoscaling-in-openshift-and-kubernetes","status":"publish","type":"post","link":"https:\/\/ntlx.org\/de\/2022\/11\/pod-autoscaling-in-openshift-and-kubernetes.html","title":{"rendered":"Pod Autoscaling in OpenShift and Kubernetes"},"content":{"rendered":"<p>To test out the horizontal pod autoscaling I built a simple example application that shares &#8220;load&#8221; across instances. The load is as simple as allocating a configurable chunk of memory.<\/p>\n\n\n\n<p>When the load increases, the pod autoscaler would spin up new instances so the chunks get smaller and the target is reached.<\/p>\n\n\n\n<p>You can find the example application on <a href=\"https:\/\/github.com\/NautiluX\/pod-autoscaler-example\">Github<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Run locally<\/h2>\n\n\n\n<p>Check out the repository, run&nbsp;<code>make build<\/code>&nbsp;and start&nbsp;<code>.\/pod-autoscaler-example<\/code>.<\/p>\n\n\n\n<p>It will allocate the default 100MiB of RAM and wait for additional instances to connect:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/pod-autoscaler-example \nCan't connect to main instance at localhost:8081, assuming there is none and acting as mainWaiting for server to be responding...\nInstance ID: main\nAllocating 100 Mi\nInstance ID: main Variable size: 100 Mi Allocated: 100 Mi\nInstance ID: main Variable size: 100 Mi Allocated: 100 Mi\nInstance ID: main Variable size: 100 Mi Allocated: 100 Mi\n<\/code><\/pre>\n\n\n\n<p>Starting a second instance will share the &#8220;load&#8221; across instances:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/pod-autoscaler-example \nInstance ID: nXii9k5RhdcdwYcBKw6hRT\nCan't run worker server, assuming we run on one host: listen tcp :8081: bind: address already in useAllocating 50 Mi\nInstance ID: nXii9k5RhdcdwYcBKw6hRT Variable size: 50 Mi Allocated: 50 Mi\nInstance ID: nXii9k5RhdcdwYcBKw6hRT Variable size: 50 Mi Allocated: 50 Mi\nInstance ID: nXii9k5RhdcdwYcBKw6hRT Variable size: 50 Mi Allocated: 50 Mi\nInstance ID: nXii9k5RhdcdwYcBKw6hRT Variable size: 50 Mi Allocated: 50 Mi\n<\/code><\/pre>\n\n\n\n<p>Increase the workload (this is what should trigger the autoscaler later) using curl:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ curl localhost:8081\/set?mem=300\n<\/code><\/pre>\n\n\n\n<p>All instances should get the new workload size now:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Allocating 150 Mi\nInstance ID: nXii9k5RhdcdwYcBKw6hRT Variable size: 150 Mi Allocated: 150 Mi\nInstance ID: nXii9k5RhdcdwYcBKw6hRT Variable size: 150 Mi Allocated: 150 Mi\nInstance ID: nXii9k5RhdcdwYcBKw6hRT Variable size: 150 Mi Allocated: 150 Mi\n<\/code><\/pre>\n\n\n\n<p>Stopping the main instance will result in a re-election workflow (not too suffisticated, yet, but it should keep the workload size):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Error sending request to getInstanceInfo: Get \"http:\/\/192.168.178.46:8082\/getInstanceInfo\": dial tcp 192.168.178.46:8082: connect: connection refused\nAssuming main is not responding anymore. Checking who can take over.\nNew main: nXii9k5RhdcdwYcBKw6hRT My ID: nXii9k5RhdcdwYcBKw6hRT\nTaking over...\nWaiting for server to be responding...\nInstance ID: main\nAllocating 300 Mi\nInstance ID: main Variable size: 300 Mi Allocated: 300 Mi\nInstance ID: main Variable size: 300 Mi Allocated: 300 Mi\n<\/code><\/pre>\n\n\n\n<p>Since there are only two instances left, the workload per instance is increased.<\/p>\n\n\n\n<p>A metrics endpoint is available so you can observe the application using prometheus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ curl localhost:8081\/metrics\ninstances_count 2\nworkload_mib 300\nchunksize_mib 150\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/NautiluX\/pod-autoscaler-example#running-on-openshiftkubernetes\"><\/a>Running on OpenShift\/Kubernetes<\/h2>\n\n\n\n<p>Resources in the deploy folder can be used to run it on a Kubernetes or OpenShift cluster.<\/p>\n\n\n\n<p>The deployment in&nbsp;<a href=\"https:\/\/github.com\/NautiluX\/pod-autoscaler-example\/blob\/main\/deploy\/deploy.yaml\"><code>deploy.yaml<\/code><\/a>&nbsp;will create a single instance, the service and route (<a href=\"https:\/\/github.com\/NautiluX\/pod-autoscaler-example\/blob\/main\/deploy\/svc.yaml\"><code>svc.yaml<\/code><\/a>&nbsp;and&nbsp;<a href=\"https:\/\/github.com\/NautiluX\/pod-autoscaler-example\/blob\/main\/deploy\/route.yaml\"><code>route.yaml<\/code><\/a>) are used to expose it. Note that the command passes the service hostname and port to the containers so they can initiate communication when new instances come up.<\/p>\n\n\n\n<p>The horizontal pod autoscaler in&nbsp;<a href=\"https:\/\/github.com\/NautiluX\/pod-autoscaler-example\/blob\/main\/deploy\/hpa.yaml\"><code>hpa.yaml<\/code><\/a>&nbsp;will increase and decrease instances as necessary when the load increases\/decreases.<\/p>\n\n\n\n<p>Using the route, you can scale the workload with curl as shown above:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ curl pod-autoscaler-example-autoscaler-example.apps.mycluster.com\/set?mem=200\n<\/code><\/pre>\n\n\n\n<p>The servicemonitor in&nbsp;<a href=\"https:\/\/github.com\/NautiluX\/pod-autoscaler-example\/blob\/main\/deploy\/servicemonitor.yaml\"><code>servicemonitor.yaml<\/code><\/a>&nbsp;makes the metrics available for Prometheus. When using OpenShift, you can query them in the OpenShift console:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"700\" height=\"358\" src=\"https:\/\/ntlx.org\/wp-content\/uploads\/2022\/11\/metrics-700x358.png\" alt=\"\" class=\"wp-image-361\" srcset=\"https:\/\/ntlx.org\/wp-content\/uploads\/2022\/11\/metrics-700x358.png 700w, https:\/\/ntlx.org\/wp-content\/uploads\/2022\/11\/metrics-250x128.png 250w, https:\/\/ntlx.org\/wp-content\/uploads\/2022\/11\/metrics-768x393.png 768w, https:\/\/ntlx.org\/wp-content\/uploads\/2022\/11\/metrics-1536x785.png 1536w, https:\/\/ntlx.org\/wp-content\/uploads\/2022\/11\/metrics-18x9.png 18w, https:\/\/ntlx.org\/wp-content\/uploads\/2022\/11\/metrics-120x61.png 120w, https:\/\/ntlx.org\/wp-content\/uploads\/2022\/11\/metrics.png 1616w\" sizes=\"(max-width: 700px) 100vw, 700px\" \/><\/figure>\n\n\n\n<p>you can see how the chunk size first went up when the workload was increased, and then back down when the autoscaler kicked in and scaled the deployment.<\/p>","protected":false},"excerpt":{"rendered":"To test out the horizontal pod autoscaling I built a simple example application that shares &#8220;load&#8221; across instances. The load is as simple as allocating a configurable chunk of memory. When the load increases, the pod autoscaler would spin up new instances so the chunks get smaller and the target is reached. You can find&#8230; <a class=\"view-article\" href=\"https:\/\/ntlx.org\/de\/2022\/11\/pod-autoscaling-in-openshift-and-kubernetes.html\">Artikel ansehen<\/a>","protected":false},"author":1,"featured_media":360,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/posts\/358"}],"collection":[{"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/comments?post=358"}],"version-history":[{"count":2,"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/posts\/358\/revisions"}],"predecessor-version":[{"id":362,"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/posts\/358\/revisions\/362"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/media\/360"}],"wp:attachment":[{"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/media?parent=358"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/categories?post=358"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ntlx.org\/de\/wp-json\/wp\/v2\/tags?post=358"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}