July 29, 2015
Docker hasn’t been around very long, but already it’s all the rage in the tech world. Amazon is supporting Docker through a number of offerings, one of which is Elastic Beanstalk. Google has also been offering support, and one of those new services is called Google App Engine Managed VM’s.
App Engine Managed VM is a Google service situated between an IaaS (such as Compute Engine) and a PaaS (such as the traditional App Engine sandbox). It also is similar to Google’s container service, Container Engine, in that it uses Docker. This makes it pretty confusing to understand what Managed VM’s are.
Let’s define MVM’s as a Google service that provides HTTP(S) load balancing and auto scaling of ephemeral Docker instances.
Traditionally, App Engine has been considered a very restrictive service since it forces you to only use the environment Google provides. This prevents you from having freedom over API’s relating to requests, sockets, threads, filesystem, etc. In my previous post about reverse proxies, I had to hack a solution together using Google’s App Engine requests API. With MVM’s, this hack is no longer necessary.
Docker is a “container” solution for packaging and distributing a server’s software environment. It allows you to build onto existing containers and create snapshots as you progress in development. For example, you might start with a Debian image, and then create a Golang image by adding all the files that Go needs. Then, you might take that image and add the files you need for your specific software project.
There are a number of other helpful supporting technologies that allow multiple docker containers to operate in the same environment in an isolated way similar to VMs but with reduced overhead. By avoiding OS virtualization, you entrust the operating system (Linux) to efficiently and securely isolated tenants from one another. This makes it very similar to PaaS solutions such as Red Hat OpenShift.
NOTE: At the time of writing (2015/6/17), these steps are based on a Beta service that is subject to change. Instructions taken from Google’s “Getting Started” guide.
gcloud components update app
Managed VM’s also require Docker, and Docker is a bit of a struggle on a Mac due to the Linux requirement. To get around this, Docker provides a development tool called Boot2Docker that uses VirtualBox as the hypervisor to run a minimal Linux environment. Google provides the following instructions:
Google provides a Docker image that includes a base environment for using their supported langauges and libraries. We’ll be installing the Golang flavor. Enter the following command in the Boot2Docker terminal window:
docker pull gcr.io/google_appengine/go-compat
Now that we have our development environment set up, we can play with our Docker image. We are going to create an app by adding 3 files (originally provided by Google):
cdto the location of the folder containing the above 3 files.
gcloud preview app run ./app.yaml
The last step will generate a Docker image and begin serving the application on your computer. By default, the web app will be accessible from http://localhost:8080. The webpage simply displays the uptime of the instance.
To deploy this application to Google’s cloud in PREVIEW mode:
gcloud auth login
gcloud config set project <project-id>
gcloud preview app deploy ./app.yaml
Now, your app is accessible at: https://module1.PROJECT_ID.appspot.com/
There are a few disadvantages to Managed VM’s. At least one Managed VM must always be running in order to respond to requests in a timely fasion. Sandbox instances are capable of “sleeping” where no costs are incurred and being awakened in as fast as milliseconds. Managed VM’s require a few minutes to be brought online, thus missing the oppurtunity to serve webpages. Google recommends that your front end should be served by sandbox instances whenever possible, and other tasks that require more flexability (e.g. background workers) to be performed on managed VM’s.
There’s another option: mix both sandbox instances and managed VM’s using modules and a dispatch file.
In order to mix multiple apps in an App Engine project, we need to designate each app as a distinct module. Modules allow us to break up the code base and assign specific tasks (e.g. front end or background tasks). It also allows the mixing of languages/runtimes. In the case of the new MVM’s, it also allows us to mix sandbox and MVM instances.
Our second module contains the Go code for the sandbox instance. It does the exact same thing as the MVM instance, except it will print “Module 2” instead of “Module 1”. It will also include a different app.yaml file and a dispatch file.
Note: Go web apps in the sandbox require an “init” function as an entry point rather than the “main” function used in the MVM demo.
The dispatch file, dispatch.yaml, tells Google App Engine’s HTTP routers how to direct traffic in our app. By using string patterns to describe our URL’s, we can indicate which URL’s go to which modules.
Each module may be a different language/runtime or can be either a sandbox instance or MVM.
Note: The dispatch rules do not strip away the URL prefix before delivering the request to the proper module.
In order to deploy, first make sure that the application name matches the project ID you previously set up. Then, to deploy the app to App Engine, enter the following command:
goapp deploy /path/to/myapp/
/path/to/myapp is the location of the directory containing the 3 application files.
This new module should be accessible from https://module2.PROJECT_ID.appspot.com/
Here’s the fun part, try accessing the following URLs:
Depending on the URL path, you will get routed to the appropriate module.
Whether you have an app that fits within the confines of the App Engine sandbox, or if you need the freedom of a custom Linux stack, Google has you covered. The biggest question moving forward is how they will price the MVM service. This major detail will be an important factor in the decision making for whether to build specific modules in the sandbox or an MVM.
This post was inspired by this article written about Go on AWS Elastic Beanstalk