{"id":50333,"date":"2020-02-03T19:06:10","date_gmt":"2020-02-03T16:06:10","guid":{"rendered":"https:\/\/www.altoros.com\/blog\/?p=50333"},"modified":"2021-01-13T16:01:40","modified_gmt":"2021-01-13T13:01:40","slug":"running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks","status":"publish","type":"post","link":"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/","title":{"rendered":"Running a Cloud Foundry Spring Boot App on Azure Kubernetes Service (AKS)"},"content":{"rendered":"<p>When working with various systems and cloud platforms, an engineer aims to avoid the burden of rewriting or even customizing legacy apps. With the rise of Kubernetes and its distributions, developers and operators are exploring the ways to integrate these platforms with their development environments and existing code base.<\/p>\n<p>In this tutorial, we describe the steps needed to take the <em>de-facto<\/em> sample <a href=\"https:\/\/github.com\/cloudfoundry-samples\/spring-music\">Spring Music app<\/a> designed for Cloud Foundry and run it on the Kubernetes distribution from Microsoft without any changes. The article also highlights the differences between the environments, workflows, and configurations.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/aks-cluster-architecture-version1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/aks-cluster-architecture-version1.png\" alt=\"\" width=\"662\" height=\"245\" class=\"alignnone size-full wp-image-54487\" \/><\/a><small>AKS cluster architecture (<a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/aks\/concepts-clusters-workloads\" rel=\"noopener noreferrer\" target=\"_blank\">Image credit<\/a>)<\/small><\/center><\/p>\n<p>&nbsp;<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_79_2 counter-hierarchy ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#How_to_prepare_an_app_for_AKS\" >How to prepare an app for AKS<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#Preparing_the_app\" >Preparing the app<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#Running_the_app_on_Azure_Kubernetes_Service\" >Running the app on Azure Kubernetes Service<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#Alternative_ways_to_configure_the_Spring_Music_app\" >Alternative ways to configure the Spring Music app<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#Observations_on_AKS_and_Cloud_Foundry\" >Observations on AKS and Cloud Foundry<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#Further_reading\" >Further reading<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#About_the_authors\" >About the authors<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"How_to_prepare_an_app_for_AKS\"><\/span>How to prepare an app for AKS<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>&nbsp;<br \/>\n<strong>PaaS vs. CaaS workflow<\/strong><\/p>\n<p>In a platform-as-a-service (PaaS) environment such as <a href=\"https:\/\/www.altoros.com\/blog\/tag\/oss-cloud-foundry\/\">Cloud Foundry<\/a>, the base unit is the application. Workflows and tooling are focused on applications. In our case, we provide the <code style=\"color: black; background-color: #e6e6e6;\">spring-music.jar<\/code> file and Cloud Foundry\u2019s buildpack then wraps the application with any dependencies and places everything in a container called a Droplet. Cloud Foundry then schedules the droplet on a node for execution, binding services to the application. More on this binding later.<\/p>\n<p><a href=\"https:\/\/azure.microsoft.com\/en-us\/free\/kubernetes-service\/\">Azure Kubernetes Service<\/a> is described as container as a service (CaaS). In this case, we place the <code style=\"color: black; background-color: #e6e6e6;\">spring-music.jar<\/code> file into a container image that is based on an image with the JVM already installed. After that, we describe a pod that uses this container as a Kubernetes object. The orchestration platform (Kubernetes) then schedules the pod for execution on a node. To connect the app to services, we provide configuration to Kubernetes telling it to expose the environment variables and files that our application can understand.<\/p>\n<p>&nbsp;<br \/>\n<strong>Service binding, Spring Boot, and profiles<\/strong><\/p>\n<p>At runtime, Cloud Foundry will expose the environment variable <code style=\"color: black; background-color: #e6e6e6;\">VCAP_SERVICES<\/code> to the application, providing service names, service types, and connection information for all the services bound to an application. Spring Boot Cloud Foundry libraries provide connectors that work with <code style=\"color: black; background-color: #e6e6e6;\">VCAP_SERVICES<\/code> to automatically wire the application for the use of these services. Spring Boot provides a \u201ccloud\u201d profile to enable using the runtime configuration specific to Cloud Foundry. It is common practice to have runtime-specific profiles for local development vs. cloud deployment, which is consistent with the <a href=\"https:\/\/12factor.net\/\">12-factor<\/a> application development.<\/p>\n<p>Although Azure Kubernetes Service does not provide a feature like <code style=\"color: black; background-color: #e6e6e6;\">VCAP_SERVICES<\/code>, the platform provides mechanisms for exposing environment variables and files into containers. We can make use of these two methods to provide service information to the application in a similar fashion as Cloud Foundry.<\/p>\n<p>Exposing the <code style=\"color: black; background-color: #e6e6e6;\">VCAP_SERVICES<\/code> environment variable with a JSON of all needed services\u2014along with <code style=\"color: black; background-color: #e6e6e6;\">SPRING_PROFILES_ACTIVE=cloud<\/code>\u2014creates an environment similar to Cloud Foundry, which can actually work. However, Spring Boot does not require such complex manipulations. Making use of Spring profiles and Kubernetes <a href=\"https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/configure-pod-configmap\/\">ConfigMaps<\/a> and <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/configuration\/secret\/\">Secrets<\/a> is a more elegant solution.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/kubernetes-services-on-azure.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/kubernetes-services-on-azure-1024x601.png\" alt=\"\" width=\"640\" class=\"aligncenter size-large wp-image-50423\" \/><\/a><small>Kubernetes services on Azure (<a href=\"https:\/\/azure.microsoft.com\/en-us\/free\/kubernetes-service\/\" rel=\"noopener noreferrer\" target=\"_blank\">Image credit<\/a>)<\/small><\/center><\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Preparing_the_app\"><\/span>Preparing the app<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The following steps are required to prepare the Spring Music app to run on AKS:<\/p>\n<ul>\n<li>Dockerize the application in a standard Java 8 runtime.<\/li>\n<li>MySQL is deployed as a pod and used as a data store. This could run in another pod or come from a managed service.<\/li>\n<li>Our Spring profile is exposed as the file <code style=\"color: black; background-color: #e6e6e6;\">application-aks.properties<\/code>, which is mounted inside the Spring Music container. The file contains boilerplate configuration and references environment variables for more environment-specific configuration, such as database credentials.<\/li>\n<li>The active Spring profile is set with the environment variable <code style=\"color: black; background-color: #e6e6e6;\">SPRING_PROFILES_ACTIVE=aks<\/code>.<\/li>\n<li>Additional environment variables are exposed in the container providing an environment-specific configuration.<\/li>\n<\/ul>\n<p>Now that we understand how to deploy the app on Cloud Foundry and have a strategy for dealing with services in Azure Kubernetes Service, we will go through the steps outlined above.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Running_the_app_on_Azure_Kubernetes_Service\"><\/span>Running the app on Azure Kubernetes Service<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In this article, we will not go over the instructions on how to deploy an Azure Kubernetes Service cluster. You can refer to <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/aks\/kubernetes-walkthrough-portal\">this tutorial<\/a> for help.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/the-spring-music-app-main-page.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/the-spring-music-app-main-page-1024x869.png\" alt=\"\" width=\"640\" class=\"aligncenter size-large wp-image-50424\" \/><\/a><small>The Spring Music App main page<\/small><\/center><\/p>\n<p>&nbsp;<br \/>\n<strong>Building a Spring Music Docker image<\/strong><\/p>\n<p>Unlike Kubernetes, Cloud Foundry builds a container image internally. Since Kubernetes is a CaaS platform, we need to make and provide a container image.<\/p>\n<p>This Dockerfile starts with Java 8 and copies in the <code style=\"color: black; background-color: #e6e6e6;\">spring-music.jar<\/code> file. The CMD line runs the jar according to the Spring Music documentation.<\/p>\n<pre>\r\nFROM openjdk:8u232-jdk\r\nCOPY spring-music.jar \/app\/\r\nEXPOSE 8080\r\nWORKDIR \/app\r\n \r\nCMD java -jar spring-music.jar\r\n<\/pre>\n<p>&nbsp;<br \/>\n<strong>Configuration strategy<\/strong><\/p>\n<p>We will expose configuration with environment variables in combination with a properties file. The following file will be created in the container before the application starts. (File location: <code style=\"color: black; background-color: #e6e6e6;\">\/app\/config\/application-aks.properties<\/code>)<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nspring.datasource.url=spring.datasource.url=jdbc:mysql:\/\/${MYSQLDB_SERVICE_HOST}:${MYSQLDB_SERVICE_PORT}\/spring_music\r\nspring.datasource.username=${MYSQL_USERNAME}\r\nspring.datasource.password=${MYSQL_PASS}\r\n \r\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\r\nspring.datasource.testOnBorrow=true\r\nspring.datasource.validationQuery=SELECT 1\r\nspring.datasource.platform=mysql\r\n<\/pre>\n<p>We will also set the environment variable <code style=\"color: black; background-color: #e6e6e6;\">SPRING_PROFILES_ACTIVE=aks<\/code>, which is seen in the Deployment spec a little later. This ensures Spring Music will use our exposed properties file.<\/p>\n<p>In Kubernetes, when we create our <code style=\"color: black; background-color: #e6e6e6;\">mysqldb<\/code> Kubernetes Service (not shown), it exposes basic connection information about the service to our pods automatically using the environment variables <code style=\"color: black; background-color: #e6e6e6;\">MYSQLDB_SERVICE_HOST<\/code> and <code style=\"color: black; background-color: #e6e6e6;\">MYSQLDB_SERVICE_PORT<\/code>. This follows an exact convention, so we know that as long as we name our service <code style=\"color: black; background-color: #e6e6e6;\">mysqldb<\/code> the information about this service will get exposed the same way every time, even if the host or port changes.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/kubernetes-objects-depicting-the-management-of-configuration.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/kubernetes-objects-depicting-the-management-of-configuration-1024x866.png\" alt=\"\" width=\"640\"  class=\"aligncenter size-large wp-image-50425\" \/><\/a><small>Kubernetes objects depicting the management of configuration<\/small><\/center><\/p>\n<p>&nbsp;<br \/>\n<strong>ConfigMaps and Secrets<\/strong><\/p>\n<p>In Kubernetes, we will use both ConfigMaps and Secrets to expose the configuration. Below is the YAML file for the MySQL Secret. It contains a username and password for our database.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\napiVersion: v1\r\nkind: Secret\r\nmetadata:\r\n  name: mysql-secret\r\ndata:\r\n  # notapassword\r\n  password: bm90YXBhc3N3b3Jk\r\n \r\n  # root\r\n  username: cm9vdA==\r\n<\/pre>\n<p>With this ConfigMap, we will expose <code style=\"color: black; background-color: #e6e6e6;\">application-aks.properties<\/code> as a file in the container.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\napiVersion: v1\r\nkind: ConfigMap\r\nmetadata:\r\n  name: sm-config\r\ndata:\r\n  application-aks.properties: |\r\n     spring.datasource.url=jdbc:mysql:\/\/${MYSQLDB_SERVICE_HOST}:${MYSQLDB_SERVICE_PORT}\/spring_music\r\n    spring.datasource.username=${MYSQL_USERNAME}\r\n    spring.datasource.password=${MYSQL_PASSWORD}\r\n \r\n    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\r\n    spring.datasource.testOnBorrow=true\r\n    spring.datasource.validationQuery=SELECT 1\r\n    spring.datasource.platform=mysql\r\n<\/pre>\n<p>Below is the Spring Music Deployment. Note that the MySQL username and password properties get exposed as environment variables, and the <code style=\"color: black; background-color: #e6e6e6;\">application-aks.properties<\/code> file is exposed as a volume. The properties file will seldom change and is more boilerplate, which reduces the maintenance on the ConfigMap. We also set <code style=\"color: black; background-color: #e6e6e6;\">SPRING_PROFILES_ACTIVE<\/code> without using a Secret or ConfigMap.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\napiVersion: apps\/v1\r\nkind: Deployment\r\nmetadata:\r\n  name: sm\r\nspec:\r\n  selector:\r\n    matchLabels:\r\n      app: sm\r\n  template:\r\n    metadata:\r\n      labels:\r\n        app: sm\r\n      name: sm\r\n    spec:\r\n      containers:\r\n      - name: sm\r\n        image: altorosbarrywilliams\/spring-music:1.0\r\n        env:\r\n        - name: SPRING_PROFILES_ACTIVE\r\n          value: aks\r\n        - name: MYSQL_USERNAME\r\n          valueFrom:\r\n            secretKeyRef:\r\n              key: username\r\n              name: mysql-secret\r\n        - name: MYSQL_PASSWORD\r\n          valueFrom:\r\n            secretKeyRef:\r\n              key: password\r\n              name: mysql-secret\r\n        volumeMounts:\r\n        - mountPath: \/app\/config\r\n          name: sm-config-vol\r\n        ports:\r\n        - containerPort: 8080\r\n          name: http\r\n          protocol: TCP\r\n      volumes:\r\n      - configMap\r\n          name: sm-config\r\n        name: sm-config-vol\r\n<\/pre>\n<p>Here\u2019s the response from the console.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/deploying-the-spring-music-app-to-aks-using-azure-cloud-shell.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/deploying-the-spring-music-app-to-aks-using-azure-cloud-shell.png\" alt=\"\" width=\"640\" class=\"aligncenter size-full wp-image-50421\" \/><\/a><small>Deploying the Spring Music app to AKS using Azure Cloud Shell<\/small><\/center><\/p>\n<p>&nbsp;<br \/>\n<strong>Abstractions due to ConfigMaps and Secrets<\/strong><\/p>\n<p>There are some common differences between environments, including sensitive information (such as passwords) and possibly environment-specific optimizations (such as JVM heap size). It is recommended to store the configuration in Secrets and ConfigMaps, as appropriate, and use the same name for each Secret and ConfigMap across all environments. By doing this, you do not need to modify config-object names across environments, only their contents. Pods are automatically wired to the right configuration for a particular environment, because it efficiently looks up those objects by name.<\/p>\n<p>The approach should be applied to naming other objects, as well, such as <code style=\"color: black; background-color: #e6e6e6;\">mysqldb<\/code> for the database service. This way, you can confidently promote an application across environments, knowing that it will not have an issue at the Kubernetes object level.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Alternative_ways_to_configure_the_Spring_Music_app\"><\/span>Alternative ways to configure the Spring Music app<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>&nbsp;<br \/>\n<strong>Expose with just ENV vars<\/strong><\/p>\n<p>Spring allows you to represent all configuration found in a properties file as environment variables. For example, setting the environment variable <code style=\"color: black; background-color: #e6e6e6;\">SPRING_DATASOURCE_USERNAME<\/code> is the same as using <code style=\"color: black; background-color: #e6e6e6;\">spring.datasource.username<\/code>spring.datasource.username in the properties file. This means that you would also need to set boilerplate variables, such as <code style=\"color: black; background-color: #e6e6e6;\">SPRING_DATASOURCE_VALIDATIONQUERY<\/code>. In other words, using just environment variables could become rather tedious and complex.<\/p>\n<p>&nbsp;<br \/>\n<strong>Expose with just a file<\/strong><\/p>\n<p>Providing that the file contains all data, including sensitive information, and excluding the use of environment variables, it is possible to expose configuration directly in the file. However, there are some disadvantages to this approach. As now we have a single configuration file that contains sensitive data, it should be stored in a Secret.<\/p>\n<p>When an object is stored as a Secret, the information remains opaque, which means only those with privileges can directly view the Secret\u2019s contents. This seems overbearing, as users without privilege will be unable to view or edit any of the less sensitive data. Even still, with privileges, using <code style=\"color: black; background-color: #e6e6e6;\">kubectl get secret my-secret -o yaml<\/code> brings back a base64-encoded version of the data, which is not very handy to work with for all the information we are placing in the Secret. Ultimately, throwing all configuration in a Secret may be very inconvenient.<\/p>\n<p>&nbsp;\t<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Observations_on_AKS_and_Cloud_Foundry\"><\/span>Observations on AKS and Cloud Foundry<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>A major advantage of Cloud Foundry is that Spring can benefit from how the platform exposes configuration. The <code style=\"color: black; background-color: #e6e6e6;\">VCAP_SERVICES<\/code> environment variable exposes service configuration that Spring uses to bind itself to services at runtime. Kubernetes does not use this type of mechanism for exposing configuration, and a user has to set up the exposure of configuration through Secrets and ConfigMaps. In Kubernetes, however, the service discovery provided to each pod, allowing us to automatically wire some configuration.<\/p>\n<p>Cloud Foundry is modeled with a focus on applications, which is great for new apps, but it is difficult to run existing software. Kubernetes is modeled similar to running traditional servers, which keeps things familiar for both new and existing applications. Moreover, Kubernetes allows you to describe complex workloads, some of which would be difficult to describe in Cloud Foundry.<\/p>\n<p>Spring Boot allows many ways to provide configuration (we\u2019ve only covered a couple in this article). This configurability allows Spring Boot applications to fit in virtually any environment. As we have seen, configuration on Cloud Foundry is rather simple\u2014due to the ability of Spring Boot to match the opinions of Cloud Foundry. There are still many improvements to be done in Kubernetes, but once configured, it can be nearly as simple to maintain as Cloud Foundry. With the ability of Cloud Foundry and Kubernetes following similar workflows, engineers can easily build new apps, as well as support legacy software, by reusing existing artifacts.<\/p>\n<p>For the source code used in this tutorial, refer to <a href=\"https:\/\/github.com\/Altoros\/spring-music-cf-to-aks-blog-2019\">our GitHub repository<\/a> containing all the artifacts, including a Docker image and Kubernetes objects.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Further_reading\"><\/span>Further reading<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li><a href=\"https:\/\/www.altoros.com\/research-papers\/a-comparative-analysis-of-kubernetes-deployment-tools-kubespray-kops-and-conjure-up\/\">A Comparative Analysis of Kubernetes Deployment Tools: Kubespray, kops, and conjure-up<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/research-papers\/a-comparative-analysis-of-kubernetes-cluster-monitoring-tools-kube-prometheus-elastic-zabbix\/\">A Comparative Analysis of Kubernetes Cluster Monitoring Tools: Kube-prometheus, Elastic, and Zabbix<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/research-papers\/a-comparative-analysis-of-kubernetes-testing-tools-kube-bench-test-infra-sonobuoy-and-powerfulseal\/\">A Comparative Analysis of Kubernetes Testing Tools: kube-bench, test-infra, Sonobuoy, and PowerfulSeal<\/a><\/li>\n<\/ul>\n<p>&nbsp;\t \t<\/p>\n<h3><span class=\"ez-toc-section\" id=\"About_the_authors\"><\/span>About the authors<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/barry-williams-bio-1.png\" alt=\"\" width=\"120\" height=\"120\" class=\"alignright size-full wp-image-50375\" \/><\/a><\/p>\n<div style=\"width: 650px;\">\n<p><small><b>Barry Williams<\/b> is a Cloud Solutions Architect with 17+ years of experience in IT and software development. He has designed and implemented architectures for various microservices-based applications, focusing on all things automation across cloud platforms. Technologies Barry works with include Kubernetes, Cloud Foundry, Docker, Linux, Concourse, ELK, Shell Script, Python, Java, Go, Ruby, etc. He is a Certified Kubernetes Administrator and a Google Cloud Certified Professional Cloud Architect.<\/small><\/p>\n<\/div>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/bob-combs-bio-1.png\" alt=\"\" width=\"120\" height=\"120\" class=\"alignright size-full wp-image-50376\" \/><\/a><\/p>\n<div style=\"width: 650px;\">\n<p><small><b>Bob Combs<\/b> is a Cloud-Native Solutions Architect with 30+ years in the software development industry\u2014as a developer, solutions architect, and engineering manager. He has focused the majority of his career on industries spanning nearly all market segments, including financial services, IT forensics, healthcare, and advertising. Some of the companies he has delivered solutions for include Oracle, Expedia, Boeing, IBM, EMC, and Visa.<\/small><\/p>\n<\/div>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/tim-flagg-bio-1.png\" alt=\"\" width=\"120\" height=\"120\" class=\"alignright size-full wp-image-50377\" \/><\/a><\/p>\n<div style=\"width: 650px;\">\n<p><small><b>Tim Flagg<\/b> is a Cloud Solutions Architect with 30+ years in software engineering and consulting. He founded multiple companies working in the IT automation space. Tim has a strong background in Kubernetes, Linux, cloud-native, and networking, having taught classes in the U.S., Asia, and Latin America. Some of the companies he has consulted to are AT&#038;T, CitiCorp, IBM, Hong Leong Bank, General Electric, and Ford Motor Company. Tim holds a number of patents in networking and software.<\/small><\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<hr\/>\n<p><center><small>The post was written by Barry Williams, Bob Combs, and Tim Flagg;<br \/>\nedited by <a href=\"https:\/\/www.altoros.com\/blog\/author\/alex\/\">Alex Khizhniak<\/a>.<\/small><\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When working with various systems and cloud platforms, an engineer aims to avoid the burden of rewriting or even customizing legacy apps. With the rise of Kubernetes and its distributions, developers and operators are exploring the ways to integrate these platforms with their development environments and existing code base.<\/p>\n<p>In this [&#8230;]<\/p>\n","protected":false},"author":5,"featured_media":54496,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":"","_links_to":"","_links_to_target":""},"categories":[214],"tags":[873,912,206],"class_list":["post-50333","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-cloud-native","tag-kubernetes","tag-oss-cloud-foundry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Running a Cloud Foundry Spring Boot App on Azure Kubernetes Service (AKS) | Altoros<\/title>\n<meta name=\"description\" content=\"Using the sample Spring Music app, this tutorial explains how to take the same artifact pushed to Cloud Foundry and run it on AKS unchanged.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Running a Cloud Foundry Spring Boot App on Azure Kubernetes Service (AKS) | Altoros\" \/>\n<meta property=\"og:description\" content=\"When working with various systems and cloud platforms, an engineer aims to avoid the burden of rewriting or even customizing legacy apps. With the rise of Kubernetes and its distributions, developers and operators are exploring the ways to integrate these platforms with their development environments and existing code base. In this [...]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/\" \/>\n<meta property=\"og:site_name\" content=\"Altoros\" \/>\n<meta property=\"article:published_time\" content=\"2020-02-03T16:06:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-01-13T13:01:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-featured-image.gif\" \/>\n\t<meta property=\"og:image:width\" content=\"640\" \/>\n\t<meta property=\"og:image:height\" content=\"376\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/gif\" \/>\n<meta name=\"author\" content=\"Alex Khizhniak\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alex Khizhniak\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/\",\"name\":\"Running a Cloud Foundry Spring Boot App on Azure Kubernetes Service (AKS) | Altoros\",\"isPartOf\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-featured-image.gif\",\"datePublished\":\"2020-02-03T16:06:10+00:00\",\"dateModified\":\"2021-01-13T13:01:40+00:00\",\"author\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/3d914db6ad1b2908c32c0dc5dcabc420\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#primaryimage\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-featured-image.gif\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-featured-image.gif\",\"width\":640,\"height\":376},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.altoros.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Running a Cloud Foundry Spring Boot App on Azure Kubernetes Service (AKS)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\",\"url\":\"https:\/\/www.altoros.com\/blog\/\",\"name\":\"Altoros\",\"description\":\"Insight\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.altoros.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/3d914db6ad1b2908c32c0dc5dcabc420\",\"name\":\"Alex Khizhniak\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2017\/06\/druzya-edit1-150x150.jpg\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2017\/06\/druzya-edit1-150x150.jpg\",\"caption\":\"Alex Khizhniak\"},\"description\":\"Alex Khizhniak is Director of Technical Content Strategy at Altoros and a cofounder of a local Java User Group. Managing distributed teams since 2004, he has gained experience as a journalist, an editor-in-chief, a technical writer, a technology evangelist, a project manager, and a product owner. Alex is obsessed with AI\/ML, data science, data integration, ETL\/DWH, data quality, databases (SQL\/NoSQL), big data, IoT, and BI. The articles and industry reports he created or helped to publish reached out to 3,000,000+ tech-savvy readers. Some of the pieces were covered on TechRepublic, ebizQ, NetworkWorld, CIO.com, etc. Find him on Twitter at @alxkh.\",\"sameAs\":[\"https:\/\/x.com\/https:\/\/twitter.com\/alxkh\"],\"url\":\"https:\/\/www.altoros.com\/blog\/author\/alex\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Running a Cloud Foundry Spring Boot App on Azure Kubernetes Service (AKS) | Altoros","description":"Using the sample Spring Music app, this tutorial explains how to take the same artifact pushed to Cloud Foundry and run it on AKS unchanged.","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:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/","og_locale":"en_US","og_type":"article","og_title":"Running a Cloud Foundry Spring Boot App on Azure Kubernetes Service (AKS) | Altoros","og_description":"When working with various systems and cloud platforms, an engineer aims to avoid the burden of rewriting or even customizing legacy apps. With the rise of Kubernetes and its distributions, developers and operators are exploring the ways to integrate these platforms with their development environments and existing code base. In this [...]","og_url":"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/","og_site_name":"Altoros","article_published_time":"2020-02-03T16:06:10+00:00","article_modified_time":"2021-01-13T13:01:40+00:00","og_image":[{"width":640,"height":376,"url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-featured-image.gif","type":"image\/gif"}],"author":"Alex Khizhniak","twitter_misc":{"Written by":"Alex Khizhniak","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/","url":"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/","name":"Running a Cloud Foundry Spring Boot App on Azure Kubernetes Service (AKS) | Altoros","isPartOf":{"@id":"https:\/\/www.altoros.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#primaryimage"},"image":{"@id":"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#primaryimage"},"thumbnailUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-featured-image.gif","datePublished":"2020-02-03T16:06:10+00:00","dateModified":"2021-01-13T13:01:40+00:00","author":{"@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/3d914db6ad1b2908c32c0dc5dcabc420"},"breadcrumb":{"@id":"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#primaryimage","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-featured-image.gif","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/02\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-featured-image.gif","width":640,"height":376},{"@type":"BreadcrumbList","@id":"https:\/\/www.altoros.com\/blog\/running-a-cloud-foundry-spring-boot-app-on-azure-kubernetes-service-aks\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.altoros.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Running a Cloud Foundry Spring Boot App on Azure Kubernetes Service (AKS)"}]},{"@type":"WebSite","@id":"https:\/\/www.altoros.com\/blog\/#website","url":"https:\/\/www.altoros.com\/blog\/","name":"Altoros","description":"Insight","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.altoros.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/3d914db6ad1b2908c32c0dc5dcabc420","name":"Alex Khizhniak","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2017\/06\/druzya-edit1-150x150.jpg","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2017\/06\/druzya-edit1-150x150.jpg","caption":"Alex Khizhniak"},"description":"Alex Khizhniak is Director of Technical Content Strategy at Altoros and a cofounder of a local Java User Group. Managing distributed teams since 2004, he has gained experience as a journalist, an editor-in-chief, a technical writer, a technology evangelist, a project manager, and a product owner. Alex is obsessed with AI\/ML, data science, data integration, ETL\/DWH, data quality, databases (SQL\/NoSQL), big data, IoT, and BI. The articles and industry reports he created or helped to publish reached out to 3,000,000+ tech-savvy readers. Some of the pieces were covered on TechRepublic, ebizQ, NetworkWorld, CIO.com, etc. Find him on Twitter at @alxkh.","sameAs":["https:\/\/x.com\/https:\/\/twitter.com\/alxkh"],"url":"https:\/\/www.altoros.com\/blog\/author\/alex\/"}]}},"_links":{"self":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/50333","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/comments?post=50333"}],"version-history":[{"count":60,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/50333\/revisions"}],"predecessor-version":[{"id":59681,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/50333\/revisions\/59681"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media\/54496"}],"wp:attachment":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media?parent=50333"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/categories?post=50333"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/tags?post=50333"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}