Cloud App Migration Between Instances
Introduction
At the time of writing this article we were allocating a single VM to run a single Nodejs cloud app as there was no way as per our understanding to run multiple Nodejs cloud apps on a single vm. This had become a serious limitation as far as the allocation of resources were concerned as allocating a full vm to a single cloud app would mean assigning more capacity to a app which really doesn’t need it and depriving other apps which really would help with sharing the resources.
Java was able to run multiple apps using the tomcat container in a single VM even on the vm which already had Nodejs app running on it
Now in order to achieve this behavior of running multiple apps inside a single VM we had to make changes to the most important part of the application which connects UI running Atlassian cloud instance to backend, Local Base Url.
In the below sections we cover the details of how this can be achieved.
Current Architecture for Nodejs and Java Apps
In the current architecture we have the Nodejs App1 and Nodejs App2 deployed to two different virtual machine which leads to wastage of resources as they both could be deployed to same virtual machine if we could resolve the issue at hand.
Proposed Architecture Diagram
In the architecture diagram above we have all the components on a single virtual machine. We will be planning to split this architecture to multiple VMs in the near future.
Whenever a request is made from the outside world it goes through the NGinx which acts as a reverse proxy. Depending on the path of the web resource it is routed internally to different application server(nodejs apps or the tomcat container)
All of these apps interact with a postgres database server which again is on the same virtual machine.
This way we can have multiple NodeJS apps running in the same virtual machine which leads to better utilization of resource available with a single virtual machine.
Configurations
Configurations at the app level - There is only one configuration which is required at the NodeJS app level and that is to set the local base url for the application at the time of starting the application using environment variables. There are different ways of doing this in different operating system. Basically we have to set AC_LOCAL_BASE_URL environment variable with the value of the url at which the NodeJs app is running. Basically it means that when you try to access this url you should get the app descriptor for the app running at that location. Following are the ex. of setting environment variables,
In Windows we can set it with the following command
#> set AC_LOCAL_BASE_URL=https://cloudapps.empyra.com/nodeapp1
In Linux we can set it with the following command
#> export AC_LOCAL_BASE_URL=https://cloudapps.empyra.com/nodeapp1
These command will set the local environment variables in the command prompt/terminal session only, which is the recommended way of doing it.
Configuration at the Reverse Proxy level - Doing the configurations at proxy level is a little bit tricky and requires more in depth knowledge of the infrastructure and different patterns of urls which are exposed by the apps. These configurations are done per app basis in the configuration file of the NGINX(path conf/nginx.conf). Below are some of the examples of such configurations,
We will consider cloudapps.empyra.com as the base url for our discussion from hereon.
The above configuration redirects all the requests coming to https://cloudapps.empyra.com/ to https://atlassian.empyra.com. If we do not do this then the Nginx server will serve the tomcat manager’s landing page and which will expose critical information to the end user.
Next is the configuration per app basis, First we will look at NodeJS app
The above configuration will redirect all the requests coming to https://cloudapps.empyra.com/csv_importer/ to the http://localhost:6000/. This is the local location at which the csv_importer is running.
There are two special cases of urls that we have to handle also apart from the generic redirection of app urls above. These are redirection for Atlassian lifecycle hooks and Atlassian app descriptor json file.
Below is the configuration for '/installed' Atlassian hook. We have to repeat the same block for each lifecycle hook that an application implements
Below is an example of configuration for the Atlassian app descriptor file,
Now we have to repeat these configurations for each NodeJS app.
We have added the following configurations to redirect all the request coming to java apps to tomcat,
Now that we have our Nginx apps and tomcat configured within Nginx its time to follow the steps to do the actual migration.
We have to follow the following steps to do the migration,
Case 1 - Target server is not currently running Nginx
Get Access to the source server(server from which the app is planed to be migrated) and Target server(server to which the app is planned to be migrated)
Bring the apps running in source server down
Take the dump of the database from the source server(Take dump only for the app to be migrated)
Restore the dump to the target server
Checkout the code for the app to be migrated from the code repository
Configure the app on the target server and test it locally on that server if possible
Configure Nginx as reverse proxy on the target machine with the configuration steps in this article
Bring the target server apps down for maintenance
Start all the apps on the target server including the new app and set the base url properly
Create startup scripts for each NodeJS app and tomcat and add it to the system startup
Now restart the target server for the configurations to take effect
Test all of the apps on the target server
Release new app descriptor files for the migrated apps(and the other apps for which the base urls have changed) to the marketplace
Case 2 - Target server is running Nginx
Get Access to the source server(server from which the app is planed to be migrated) and Target server(server to which the app is planned to be migrated)
Bring the apps running in source server down
Take the dump of the database from the source server(Take dump only for the app to be migrated)
Restore the dump to the target server
Checkout the code for the app to be migrated from the code repository
Configure the app on the target server and test it locally on that server if possible
Add the configuration specific to the app(app to be migrated) to the Nginx
Start the app on the target server and set the base url properly
Restart the Nginx server
Create startup scripts for the new app if it is not a java app. On the next restart of the vm all the apps will run as a system processes including the newer one.
Test all of the apps on the target server
Release new app descriptor file for the app to the marketplace
Sample nginx.conf file