{"id":485,"date":"2017-04-13T08:25:00","date_gmt":"2017-04-13T08:25:00","guid":{"rendered":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/?p=485"},"modified":"2020-06-08T13:12:57","modified_gmt":"2020-06-08T13:12:57","slug":"launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale","status":"publish","type":"post","link":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/","title":{"rendered":"Launch a Kubernetes cluster on AWS with kube-up and let it autoscale"},"content":{"rendered":"\n<p>In the following we will walk through how to launch a <a href=\"https:\/\/kubernetes.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Kubernetes <\/a>(k8s) cluster on <a href=\"https:\/\/aws.amazon.com\" target=\"_blank\" rel=\"noreferrer noopener\">AWS<\/a> using kube-up, push a <a href=\"https:\/\/www.docker.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Docker <\/a>image to ECR, start a server in k8s based on that image, and autoscale the cluster. The <code>kube-up<\/code> scripts needs a proper GNU\/Linux system to operate. Therefore, if you usually use Windows you either need a VM running GNU\/Linux or Windows 10 Anniversary update with Windows Subsystem for Linux (WSL).<\/p>\n\n\n\n<p>You need a Docker host up and running. Depending on whether you are using pure GNU\/Linux, GNU\/Linux in a VM, or WSL installing and using Docker differs. In the first two cases you may see <a href=\"https:\/\/docs.docker.com\/engine\/installation\/linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a> on how to install Docker. If you are using WSL then you need to install Docker in Windows (either Docker Toolbox, or \u2013 preferably \u2013 Docker CE). If you can install Docker CE then there may be a way to have a <a href=\"https:\/\/www.reddit.com\/r\/docker\/comments\/5eggwo\/running_docker_on_windows_subsystem_for_linux_wsl\/\" target=\"_blank\" rel=\"noreferrer noopener\">Docker host within WSL<\/a>. If you can only use Docker Toolbox in Windows then, at this juncture, there is no way to have a Docker host within WSL.<\/p>\n\n\n\n<p>In my case I use WSL and I am bound to Docker Toolbox. Thus, I need to switch between WSL and Windows at some point in order to build the docker image. If you can use a proper GNU\/Linux, or have GNU\/Linux running within a VM you can stay there and can ignore the [In WSL] \/ [In Windows] switches later on.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">[In WSL &amp; Windows]<\/h2>\n\n\n\n<p>First, we need kubectl on both, Windows and WSL. To install kubectl see<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/kubernetes.io\/docs\/user-guide\/prereqs\/\">https:\/\/kubernetes.io\/docs\/user-guide\/prereqs\/<\/a><\/li><li><a href=\"https:\/\/kubernetes.io\/docs\/tasks\/kubectl\/install\/\">https:\/\/kubernetes.io\/docs\/tasks\/kubectl\/install\/<\/a><\/li><\/ul>\n\n\n\n<p>The awscli is also needed on both Windows and WSL. To install awscli see<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/docs.aws.amazon.com\/cli\/latest\/userguide\/installing.html\">https:\/\/docs.aws.amazon.com\/cli\/latest\/userguide\/installing.html<\/a><\/li><\/ul>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">[In WSL]<\/h3>\n\n\n\n<p>Now that kubectl and awscli are installed we can get the kube-up script. We will to some extent follow the instructions given <a rel=\"noreferrer noopener\" href=\"https:\/\/kubernetes.io\/docs\/getting-started-guides\/aws\/\" target=\"_blank\">here<\/a>. However, since we need to make some adaptions to the script and its guts we will first download the script suite, but do not start the cluster immediately. Therefore<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ mkdir ~\/scripts\n    $ cd\n    $ export KUBERNETES_RELEASE=v1.4.0 #later versions do not work\n    $ export KUBERNETES_PROVIDER=aws\n    $ export KUBERNETES_SKIP_CREATE_CLUSTER=true\n    $ wget -q -O - https:\/\/get.k8s.io >~\/k8s_setup.sh &amp;&amp; chmod +x ~\/k8s_setup.sh &amp;&amp; ~\/k8s_setup.sh<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>This will download a lot of scripts to a folder <code>~\/kubernetes<\/code>. To use AWS as provider we need to adapt some variables. To save work later we write a helper in <code>~\/scripts\/prepare_k8s_aws.sh<\/code> and put the following stuff and make sure to change the value of <em><code>AWS_S3_BUCKET<\/code><\/em> to something unique):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    # edit to your liking\n    # and particularly CHANGE the value of AWS_S3_BUCKET\n    export KUBERNETES_PROVIDER=aws\n    echo \"setting KUBERNETES_PROVIDER=$KUBERNETES_PROVIDER\"\n    export KUBE_AWS_ZONE=eu-central-1a\n    echo \"setting KUBE_AWS_ZONE=$KUBE_AWS_ZONE\"\n    export NUM_NODES=2\n    echo \"setting NUM_NODES=$NUM_NODES\"\n    export NUM_NODES_MIN=2   # needed for autoscaling\n    echo \"setting NUM_NODES_MIN=$NUM_NODES_MIN\"\n    export NUM_NODES_MAX=5   # needed for autoscaling\n    echo \"setting NUM_NODES_MIN=$NUM_NODES_MAX\"\n    export MASTER_SIZE=m3.medium\n    echo \"setting MASTER_SIZE=$MASTER_SIZE\"\n    export NODE_SIZE=m3.medium\n    echo \"setting NODE_SIZE=$NODE_SIZE\"\n    export AWS_S3_REGION=eu-central-1\n    echo \"setting AWS_S3_REGION=$AWS_S3_REGION\"\n    export AWS_S3_BUCKET=yourProjectUniqueName-kubernetes-artifacts\n    echo \"setting AWS_S3_BUCKET=$AWS_S3_BUCKET\"\n    export KUBE_AWS_INSTANCE_PREFIX=k8s\n    echo \"setting KUBE_AWS_INSTANCE_PREFIX=$KUBE_AWS_INSTANCE_PREFIX\"<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>To make kube-up actually using these variables we do<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ sed -i '2i. ~\/scripts\/prepare_k8s_aws.sh' ~\/k8s_setup.sh\n    $ sed -i '2i. ~\/scripts\/prepare_k8s_aws.sh' ~\/kubernetes\/cluster\/kube-down.sh\n    $ sed '\/--vpc-zone-identifier\/i\\      --min-size ${NUM_NODES_MIN} \\\\' -i \\\n      ~\/kubernetes\/cluster\/aws\/util.sh\n    $ sed '\/--vpc-zone-identifier\/i\\      --max-size ${NUM_NODES_MAX} \\\\' -i \\\n      ~\/kubernetes\/cluster\/aws\/util.sh<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>To enable autoscaling later, we need the IAM role that is assigned to the minions during cluster startup to have some more permissons. Edit a file e.g. <code>~\/as_policy.json<\/code> and insert the following content (be sure to have no empty lines in the file):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    {\n        \"Effect\": \"Allow\",\n        \"Action\": &#91;\n            \"autoscaling:DescribeAutoScalingGroups\",\n            \"autoscaling:DescribeAutoScalingInstances\",\n            \"autoscaling:SetDesiredCapacity\",\n            \"autoscaling:TerminateInstanceInAutoScalingGroup\"\n        ],\n        \"Resource\": \"*\"\n    }<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Then add the content to the policy template:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ cd ~ # or change to the directory where as_policy.json resides\n    $ sed -i '43s|}|},|' ~\/kubernetes\/cluster\/aws\/templates\/iam\/kubernetes-minion-policy.json\n    $ sed -i -e '43r as_policy.json' ~\/kubernetes\/cluster\/aws\/templates\/iam\/kubernetes-minion-policy.json<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Now we are ready to start the cluster:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ unset KUBERNETES_SKIP_CREATE_CLUSTER\n    $ ~\/k8s_setup.sh<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Answer Y to the question, i.e. keep the <code>~\/kubernetes<\/code> directory, since otherwise all your previous changes will be lost. If anything fails during the process and you need to start over you need to run<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ ~\/kubernetes\/cluster\/kube-down.sh<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>first.<\/p>\n\n\n\n<p>The cluster setup will take up to ten minutes. In the meantime, we will implement a Hello-World service that we will use later on to hog the pod\u2019s CPU capacity and trigger a scale-out. Take e.g. the Getting-Started Actuator Service as described <a href=\"https:\/\/spring.io\/guides\/gs\/actuator-service\/\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>. Clone the project from <a href=\"https:\/\/github.com\/spring-guides\/gs-actuator-service.git\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a> and change into <code>gs-actuator-service\/complete<\/code>. In <code>src\/main\/java\/hello\/Greeting.java<\/code> add the following methods<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    private int ackermann(int n, int m) {\n        if (n == 0) return m + 1;\n        if (m == 0) return ackermann(n - 1, 1);\n        return ackermann(n - 1, ackermann(n, m - 1));\n    }\n    private void hogCPU() {\n        ExecutorService executor = Executors.newWorkStealingPool();\n        List&lt;Callable&lt;Integer>> callables = Collections.nCopies(35, () -> ackermann(3, 11));\n        try {\n            executor.invokeAll(callables)\n                    .stream()\n                    .map(future -> {\n                        try {\n                            return future.get();\n                        }\n                        catch (Exception e) {\n                            throw new IllegalStateException(e);\n                        }\n                    })\n                    .forEach(System.out::println);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>and call <code>hogCPU()<\/code> in the last line of the constructor. You may reduce (or increase) the number of parallel processes depending on the instance type you chose in <em><code>NODE_SIZE<\/code><\/em> above. In our case, <em><code>NODE_SIZE<\/code><\/em> is <code>m3.medium<\/code> which has one virtual CPU. You also need to import the following packages:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    import java.util.Collections;\n    import java.util.List;\n    import java.util.concurrent.Callable;\n    import java.util.concurrent.ExecutorService;\n    import java.util.concurrent.Executors;<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>To build Docker images for this project one may use the fabric8 maven plugin. See <a rel=\"noreferrer noopener\" href=\"https:\/\/maven.fabric8.io\/#zero-config\" target=\"_blank\">here<\/a> on how to install it. (At the time of writing the latest version is 3.2.7 rather than 3.2.28.). Since I cannot have a Docker host within WSL I need to switch to Windows for building the image. This has one more implication: Since I start the cluster within WSL all configuration that is generated by <code>kube-up<\/code> will be written to <code>~\/.kube\/config<\/code> within WSL. However, I need that configuration in Windows as well in order to use kubectl properly. So, after the cluster has been brought up successfully, I copy the generated kubectl config from WSL to Windows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cp ~\/.kube\/config \/mnt\/c\/Users\/&lt;yourUserName>\/.kube\/config<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Also, after the cluster has been brought up a few URIs will be printed to the terminal. Find the URI for Kubernetes-dashboard and open it in a browser. You will get an SSL warning. After you accepted the warning you will be presented a login form. To login change back to the terminal and type<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ CTX=$(kubectl config view | grep current-context | sed 's|current-context: ||')\n    $ kubectl config view | grep -A2 $CTX-basic-auth | grep password | \\\n      sed 's| *password: ||'<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>This will print the password. The username is always <em><code>admin<\/code><\/em>. After logging in to the dashboard navigate to <em>Workloads-&gt;Deployments<\/em> and then change back to the terminal.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">[In Windows]<\/h3>\n\n\n\n<p>Remember that I only need to switch to Windows since I am bound to Docker Toolbox for technical reasons. I start Docker Toolbox and use the provided shell.<\/p>\n\n\n\n<p>Change to the Hello-World project and build it using fabric8:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ cd ~\/path\/to\/gs-actuator-service\/complete\n    $ mvn clean package fabric8:build<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>You can check the image that has been created using<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ docker images<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>In our case there should be an output similar to<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    REPOSITORY                              TAG                IMAGE ID            CREATED             SIZE\n    springframework\/gs-actuator-service     0.1.0              e3b475c4e906        17 hours ago        112.3 MB<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Since we want to use Amazon\u2019s Elastic Container Registry (ECR) to store our image we need to tag the image accordingly. First, you should create a repository for the project:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ ECR_ID=$(aws ecr create-repository --repository-name hellorepo --query repository.registryId --output text)<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Then we tag the image:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ docker tag springframework\/gs-actuator-service:0.1.0 \\\n      ${ECR_ID}.dkr.ecr.eu-central-1.amazonaws.com\/hellorepo:0.1.0<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>To actually upload the image to ECR we need Docker to authenticate against ECR. As described <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.aws.amazon.com\/AmazonECR\/latest\/userguide\/Registries.html#registry_auth\" target=\"_blank\">here <\/a>this _shall_ be (it\u2019s NOT) as simple as<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ $(aws ecr get-login)<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>However, the login command that is returned by the awscli is, at this junction, indeed wrong: The repository URI contains an <code>https:\/\/<\/code> which will later lead to a message that there is \u201cno such repository\u201d if you try to push the image with Docker. (This was a thing that drove me nuts for an entire day until I figured out what was <em>actually<\/em> going wrong). See on <a rel=\"noreferrer noopener\" href=\"https:\/\/stackoverflow.com\/questions\/40107203\/unable-to-use-the-docker-push-command-with-ecr\/40107204#40107204\" target=\"_blank\">stackoverflow<\/a> for the solution. Be sure to have <a rel=\"noreferrer noopener\" href=\"http:\/\/gnuwin32.sourceforge.net\/\" target=\"_blank\">GnuWin32<\/a> installed in Windows at this point. The <em>\u201ccorrect\u201d<\/em> way to authenticate Docker against ECR is then<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ $(aws ecr get-login | sed 's|https:\/\/||' | sed 's|-e none ||')<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Now push the image to ECR:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ docker push ${ECR_ID}.dkr.ecr.eu-central-1.amazonaws.com\/hellorepo:0.1.0<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>At this point we could make a deployment and expose it as a service. But we want to demonstrate autoscaling. In order to make that work we need to understand two things: (1) Deployments (and thus pods) can have explicit resource requirements. If there are no nodes available in the k8s cluster that could fulfil these requirements, a new node (i.e. a minion, i.e. an EC2 instance) would need to be instantiated. (2) This horizontal autoscaling for nodes is not yet built-in to kubernetes for AWS. But there is a <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/kubernetes\/contrib\/tree\/master\/cluster-autoscaler\/cloudprovider\/aws\" target=\"_blank\">cluster autoscaler<\/a> available as deployment.<\/p>\n\n\n\n<p>So we edit a file <code>~\/autoscaler.yml<\/code> with the following content:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    apiVersion: extensions\/v1beta1\n    kind: Deployment\n    metadata:\n      name: cluster-autoscaler\n      labels:\n        app: cluster-autoscaler\n    spec:\n      replicas: 1\n      selector:\n        matchLabels:\n          app: cluster-autoscaler\n      template:\n        metadata:\n          labels:\n            app: cluster-autoscaler\n        spec:\n          containers:\n            - image: gcr.io\/google_containers\/cluster-autoscaler:v0.4.0\n              name: cluster-autoscaler\n              resources:\n                limits:\n                  cpu: 100m\n                  memory: 300Mi\n                requests:\n                  cpu: 100m\n                  memory: 300Mi\n              command:\n                - .\/cluster-autoscaler\n                - --v=4\n                - --cloud-provider=aws\n                - --skip-nodes-with-local-storage=false\n                - --scale-down-delay=10m\n                - --nodes=2:5:k8s-minion-group-eu-central-1a\n              env:\n                - name: AWS_REGION\n                  value: eu-central-1\n              volumeMounts:\n                - name: ssl-certs\n                  mountPath: \/etc\/ssl\/certs\/ca-certificates.crt\n                  readOnly: true\n              imagePullPolicy: \"Always\"\n          volumes:\n            - name: ssl-certs\n              hostPath:\n                path: \"\/etc\/ssl\/certs\/ca-certificates.crt\"<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>This configuration will scale the minions in the autoscaling group <em><code>k8s-minion-group-eu-central-1a<\/code><\/em> between 2 and 5 nodes. And it will take a node out of the cluster after it has been underutlized for 10 minutes.&nbsp; Be sure to edit the value of <em><code>AWS_REGION<\/code><\/em> (in the example above <em><code>eu-central-1<\/code><\/em>), and the autoscaling group name (in the above example <em><code>k8s-minion-group-eu-central-1a<\/code><\/em>) to fit your config. The name of your autoscaling group name can be determined using<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ aws autoscaling describe-auto-scaling-groups \\\n      --query AutoScalingGroups&#91;].AutoScalingGroupName --output text<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Deploy the cluster autoscaler:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ kubectl create -f ~\/autoscaler.yml<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>You can check the successful deployment in the Kubernetes-dashboard: refresh the Deployments page; the autoscaling deployment should be visible.<\/p>\n\n\n\n<p>Now we can deploy the image to the k8s cluster:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ kubectl run gs-actuator \\\n      --image ${ECR_ID}.dkr.ecr.eu-central-1.amazonaws.com\/hellorepo:0.1.0 \\\n      --requests='cpu=700m,memory=150Mi' \\\n      --limits='cpu=900m,memory=200Mi'<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>The requests and limits parameters are essential to trigger the autoscaling: We state that the deployment needs a pod with (at least) 70% CPU time and 150 MiB memory available. If you refresh the Deployments page you will see an error message that no node has enough capacity to take the pod. In the background it will launch a new EC2 instance and after ca. 6 minutes the new node will be available and the pod gets deployed on that node. Wait until the deployment is successful. It should not take longer than two more minutes, but depending on how fast AWS initializes the instance it can take up to 10 minutes in total.<\/p>\n\n\n\n<p>Now let\u2019s start a service of the gs-actuator deployment and make port 9000 available to the public (check that this meets the server.port in the <code>application.properties<\/code> of <em>gs-actuator<\/em>):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ kubectl expose deployment gs-actuator --type=LoadBalancer --port=9000<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>This will start an Elastic Load Balancer (ELB) and you get the public DNS name with<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ ELB_DNS_NAME=$(aws elb describe-load-balancers \\\n      --query LoadBalancerDescriptions&#91;0].DNSName --output text) &amp;&amp; \\\n      echo $ELB_DNS_NAME<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>It may take a while until the DNS name can be resolved.<\/p>\n\n\n\n<p>The last step for full autoscaling is to enable <a href=\"https:\/\/kubernetes.io\/docs\/user-guide\/horizontal-pod-autoscaling\/\" target=\"_blank\" rel=\"noreferrer noopener\">Horizontal Pod Autoscaling<\/a> (HPA) within the cluster:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ kubectl autoscale deployment gs-actuator --min=1 --max=3 --cpu-percent=80<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>This will run at least one pod and at most three pods where a new pod gets launched as soon the (average) CPU utilization of the already running pods exceeds 80%.<\/p>\n\n\n\n<p>Now generate a request for the service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ curl http:\/\/${ELB_DNS_NAME}:9000\/hello-world<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>This will utilize the pod\u2019s CPU fully for more than a minute which should then trigger the HPA. (If the service responds earlier in your case you may need to fire more requests in parallel or consider to adapt Greetings.hogCPU() to start more parallel processes.) This will start a new pod which \u2013 due to the specified resource requirements \u2013 will trigger a scale out at the nodes. Watch the kubernetes Dashboard <em>Workloads -&gt; Pods<\/em> and <em>Admin -&gt; Nodes<\/em>. A new pod will be created that does not fit in any node. Eventually (after 2 minutes or so), a new node will appear.<\/p>\n\n\n\n<p>Let the service rest. HPA will eventually remove the pod. 10 minutes later the cluster autoscaler will remove the additional node.<\/p>\n\n\n\n<p>To clean up run<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ ~\/kubernetes\/cluster\/kube-down.sh<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Remove the registry in ECR:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ aws ecr delete-repository --repository-name hellorepo --force<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Optionally, you may remove the S3 bucket. Do <em>NOT<\/em> use this if you have other buckets than the one created using the kube-up script): Be <em>CAREFUL<\/em> and double check. To be safe use the values you have set for <em><code>AWS_S3_REGION<\/code><\/em> and <em><code>AWS_S3_BUCKET<\/code><\/em> in <code>~\/scripts\/prepare_k8s_aws.sh<\/code>. (You cannot plainly use <code>$AWS_S3_REGION<\/code> and <code>$AWS_S3_BUCKET<\/code> since these variables were set in a subprocess and are not known to the parent process: i.e. the child Bash that actually <em>executes<\/em> <code>k8s_setup.sh<\/code> cannot set variables in the parent Bash which <em>called <\/em><code>k8s_setup.sh<\/code>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    $ S3_BUCKET=$(aws --region eu-central-1 s3api list-buckets --query Buckets&#91;].Name --output text)\n    $ aws s3 rm s3:\/\/$S3_BUCKET --recursive # only deletes content but not bucket itself\n    $ aws s3api delete-bucket --bucket $S3_BUCKET<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>This concludes our walkthrough. You<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>started a kubernetes cluster on AWS<\/li><li>set up kubernetes for autoscaling<\/li><li>built a Docker image and pushed it to ECR<\/li><li>let kubernetes use the image to start a deployment<\/li><li>exposed the deployment as a service<\/li><li>generated requests to the service in order to trigger autoscaling<\/li><li>let the cluster scale-out and scale-in<\/li><li>teared down the cluster<\/li><li>cleaned up after you<\/li><\/ul>\n\n\n\n<p>I am eager to get your comments how this was helpful to you or receive your questions.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to launch a kubernetes cluster on AWS using kube-up, and enable cluster and horizonal pod autoscaling, and deploy a service that triggers autoscaling.<\/p>\n","protected":false},"author":55,"featured_media":598,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","footnotes":""},"categories":[8,9],"tags":[231,232,233,234,235,236,237,238,239,227,228,229,230],"topics":[],"class_list":["post-485","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web","category-cloud","tag-autoscale","tag-wsl","tag-windows","tag-autoscaling","tag-docker","tag-docker-image","tag-ecr","tag-scale-out","tag-scale-in","tag-kubernetes-cluster","tag-kubernetes","tag-aws","tag-kube-up"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Launch a Kubernetes cluster on AWS ... - ZEISS Digital Innovation Blog<\/title>\n<meta name=\"description\" content=\"How to launch a kubernetes cluster on AWS using kube-up, and enable cluster and horizonal pod autoscaling, and deploy a service that triggers autoscaling.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Launch a Kubernetes cluster on AWS ... - ZEISS Digital Innovation Blog\" \/>\n<meta property=\"og:description\" content=\"How to launch a kubernetes cluster on AWS using kube-up, and enable cluster and horizonal pod autoscaling, and deploy a service that triggers autoscaling.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/\" \/>\n<meta property=\"og:site_name\" content=\"Digital Innovation Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-04-13T08:25:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-06-08T13:12:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/04\/201704_kubernetes_aws_fi.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1281\" \/>\n\t<meta property=\"og:image:height\" content=\"734\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Christoph M\u00f6bius\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Christoph M\u00f6bius\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/\",\"name\":\"Launch a Kubernetes cluster on AWS ... - ZEISS Digital Innovation Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/04\/201704_kubernetes_aws_fi.png\",\"datePublished\":\"2017-04-13T08:25:00+00:00\",\"dateModified\":\"2020-06-08T13:12:57+00:00\",\"author\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/ed376116f113cc137c20494e03d14ddf\"},\"description\":\"How to launch a kubernetes cluster on AWS using kube-up, and enable cluster and horizonal pod autoscaling, and deploy a service that triggers autoscaling.\",\"breadcrumb\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#primaryimage\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/04\/201704_kubernetes_aws_fi.png\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/04\/201704_kubernetes_aws_fi.png\",\"width\":1281,\"height\":734},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Launch a Kubernetes cluster on AWS with kube-up and let it autoscale\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/\",\"name\":\"Digital Innovation Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/ed376116f113cc137c20494e03d14ddf\",\"name\":\"Christoph M\u00f6bius\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/05\/moebius_christoph-150x150.jpg\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/05\/moebius_christoph-150x150.jpg\",\"caption\":\"Christoph M\u00f6bius\"},\"description\":\"Christoph M\u00f6bius holds a PhD in Computer Science and has been working with ZEISS Digital Innovation since 2017 as a Scrum Master and ETEO Coach. He concerns himself with all agile methods and process frameworks (Scrum, Kanban, XP, OKR, etc.) as well as scaling approaches. Notably, he is interested in distributed software development. Here he is responsible for the thematic structure of the in-house ETEO approach for distributed agile teams. He shares his knowledge and experiences with the community in workshops, meetups and on conferences.\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/author\/enchristophmoebius\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Launch a Kubernetes cluster on AWS ... - ZEISS Digital Innovation Blog","description":"How to launch a kubernetes cluster on AWS using kube-up, and enable cluster and horizonal pod autoscaling, and deploy a service that triggers autoscaling.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/","og_locale":"en_US","og_type":"article","og_title":"Launch a Kubernetes cluster on AWS ... - ZEISS Digital Innovation Blog","og_description":"How to launch a kubernetes cluster on AWS using kube-up, and enable cluster and horizonal pod autoscaling, and deploy a service that triggers autoscaling.","og_url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/","og_site_name":"Digital Innovation Blog","article_published_time":"2017-04-13T08:25:00+00:00","article_modified_time":"2020-06-08T13:12:57+00:00","og_image":[{"width":1281,"height":734,"url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/04\/201704_kubernetes_aws_fi.png","type":"image\/png"}],"author":"Christoph M\u00f6bius","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Christoph M\u00f6bius","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/","name":"Launch a Kubernetes cluster on AWS ... - ZEISS Digital Innovation Blog","isPartOf":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#primaryimage"},"image":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/04\/201704_kubernetes_aws_fi.png","datePublished":"2017-04-13T08:25:00+00:00","dateModified":"2020-06-08T13:12:57+00:00","author":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/ed376116f113cc137c20494e03d14ddf"},"description":"How to launch a kubernetes cluster on AWS using kube-up, and enable cluster and horizonal pod autoscaling, and deploy a service that triggers autoscaling.","breadcrumb":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#primaryimage","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/04\/201704_kubernetes_aws_fi.png","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/04\/201704_kubernetes_aws_fi.png","width":1281,"height":734},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/launch-a-kubernetes-cluster-on-aws-with-kube-up-and-let-it-autoscale\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/"},{"@type":"ListItem","position":2,"name":"Launch a Kubernetes cluster on AWS with kube-up and let it autoscale"}]},{"@type":"WebSite","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/","name":"Digital Innovation Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/ed376116f113cc137c20494e03d14ddf","name":"Christoph M\u00f6bius","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/image\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/05\/moebius_christoph-150x150.jpg","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/05\/moebius_christoph-150x150.jpg","caption":"Christoph M\u00f6bius"},"description":"Christoph M\u00f6bius holds a PhD in Computer Science and has been working with ZEISS Digital Innovation since 2017 as a Scrum Master and ETEO Coach. He concerns himself with all agile methods and process frameworks (Scrum, Kanban, XP, OKR, etc.) as well as scaling approaches. Notably, he is interested in distributed software development. Here he is responsible for the thematic structure of the in-house ETEO approach for distributed agile teams. He shares his knowledge and experiences with the community in workshops, meetups and on conferences.","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/author\/enchristophmoebius\/"}]}},"author_meta":{"display_name":"Christoph M\u00f6bius","author_link":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/author\/enchristophmoebius\/"},"featured_img":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/04\/201704_kubernetes_aws_fi-600x344.png","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">Web<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">Cloud<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">Web<\/span>","<span class=\"advgb-post-tax-term\">Cloud<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">autoscale<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">wsl<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">windows<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">autoscaling<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">Docker<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">Docker image<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">ECR<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">scale-out<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">scale-in<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">kubernetes cluster<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">kubernetes<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">aws<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/cloud\/\" class=\"advgb-post-tax-term\">kube-up<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">autoscale<\/span>","<span class=\"advgb-post-tax-term\">wsl<\/span>","<span class=\"advgb-post-tax-term\">windows<\/span>","<span class=\"advgb-post-tax-term\">autoscaling<\/span>","<span class=\"advgb-post-tax-term\">Docker<\/span>","<span class=\"advgb-post-tax-term\">Docker image<\/span>","<span class=\"advgb-post-tax-term\">ECR<\/span>","<span class=\"advgb-post-tax-term\">scale-out<\/span>","<span class=\"advgb-post-tax-term\">scale-in<\/span>","<span class=\"advgb-post-tax-term\">kubernetes cluster<\/span>","<span class=\"advgb-post-tax-term\">kubernetes<\/span>","<span class=\"advgb-post-tax-term\">aws<\/span>","<span class=\"advgb-post-tax-term\">kube-up<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 9 years ago","modified":"Updated 6 years ago"},"absolute_dates":{"created":"Posted on April 13, 2017","modified":"Updated on June 8, 2020"},"absolute_dates_time":{"created":"Posted on April 13, 2017 8:25 am","modified":"Updated on June 8, 2020 1:12 pm"},"featured_img_caption":"","series_order":"","_links":{"self":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts\/485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/users\/55"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/comments?post=485"}],"version-history":[{"count":8,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts\/485\/revisions"}],"predecessor-version":[{"id":596,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts\/485\/revisions\/596"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/media\/598"}],"wp:attachment":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/media?parent=485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/categories?post=485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/tags?post=485"},{"taxonomy":"topics","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/topics?post=485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}