Categorie: English articles only RSS feed for this category

Deploying Symfony2 Apps via Scalarium: Improved Methodology

5 Jan 2012

Some weeks ago I wrote about deploying Symfony2 Applications to Amazon AWS with Scalarium. It turned out that the described methodology can be improved in several ways. Here’s how.

First, let’s discuss what’s suboptimal with the previously described approach. The basic idea was to provide a custom Chef recipe which is executed on our instances whenever our Symfony2 application gets deployed. This recipe took care of

  • executing the tasks which need to be done whenever the application is deployed, like installing the Symfony2 vendors or cleaning the application cache
  • configuring Apache to correctly serve the application

Well, the problem is that these are really two very different tasks which shouldn’t be mixed together. Updating the web server configuration every time you release a new version of your application simply doesn’t make sense.

Thanks to Chef deployment hooks, we can separate these tasks. Whatever needs to be done upon application deployment can be provided within the application itself, making it much more self-contained. This way, application business logic and application deployment logic live in the same source tree.

On the other hand, system configuration steps which aren’t specific to deploying a new version of your application, but are specific to hosting your application in a given system context, shouldn’t be bundled with your application, but with your system context.

Thus, we are going to separate the deployment recipes and the system setup recipes. We will provide the deploy recipes from our application, and the system setup recipes through a custom Chef cookbook, just as we did in the first version of this tutorial.

Let’s look at the old version of our deploy.rb recipe, and decide which parts are related to the deployment of our application, and which parts are related to hosting our application.

Well, it’s actually quite simple – everything from the beginning of the file through line 44 is stuff that needs to be done upon every single deployment, or else we wouldn’t end up with a working application.

Let’s move this part of the deployment recipe into our application. Where does it belong? When Scalarium’s Chef deploys our application, it looks for certain scripts in the /deploy directory of our application:

  • /deploy/before_migrate.rb
  • /deploy/before_symlink.rb
  • /deploy/before_restart.rb
  • /deploy/after_restart.rb
As their names imply, these scripts are triggered at certain points of the deployment lifecycle. They are closely related to the steps that are necessary when deploying Ruby on Rails applications, and thus not all of them are useful for us when deploying a Symfony2 application.

For the steps we want to execute with our recipe (installing the vendors, clearing the app cache, executing db migrations, installing the assets, and chowning app cache and log dirs), the before_symlink.rb is just fine – it hooks into the deployment process the moment before Chef, after downloading the application source code from Github, changes the symbolic link at /srv/www/symfonyexample/current to the newly downloaded release. At this moment, we have all the source code available, but it is not yet put into production, thus it’s the most sensible moment for additional setup steps.

Moving the deployment-specific parts of our recipe into this hook gives us a before_symlink.rb script as it’s available in our ScalariumExampleSymfony2Application repository on GitHub.

The rest of the original recipe is all about configuring Apache in a way that gives us a working vhost for serving our application – this configuration may change, but it isn’t related to any specific deployment. Thus, these steps should be done only when our Scalarium/AWS instance is set up, and not on every deployment.

And as with the deployment steps, there is a better way to set up Apache for our application, too. Turns out, we don’t need a recipe at all. The reason is that Scalarium implements a very convenient substitution logic – if our own cookbook provides a file with the same name at the same location as one from the Scalarium-provided cookbooks, the file from our own cookbook “wins” and is used instead.

The Scalarium file we are going to substitute is located at /mod_php5_apache2/templates/default/web_app.conf.erb. By providing this file in our own cookbook repository, it’s used as the template for our Symfony2 application vhost – we don’t even need to define “symfony2::deploy” as a Custom Recipe anymore.

And that’s it. As described in my previous post on this topic, we need to configure our Scalarium cloud with the information on our custom cookbook and our application, but instead of manually hooking our custom recipe into the configure and deploy events in Scalarium, our newly created deploy hook now lives in the application itself, and is automatically triggered on every deployment, and our newly created web_app.conf.erb Apache vhost template is automatically used by Scalarium’s Chef when setting up new PHP application server instances.

Cocoa: What to do if outlineView: objectValueForTableColumn: byItem never gets called

15 Nov 2011

If you set up an OutlineView in Interface Builder and connect your Controller as its dataSource and delegate (and provide the methods there accordingly), you will notice that

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item

never get’s called. The reason might very simple: in Interface Builder, in the attributes inspector for your OutlineView, you can define the Content Mode as View Based or Cell Based.

If you simply want to display the content of NSStrings, choose Cell Based, and objectValueForTableColumn will be called.

Only took me 3 hours to find out.

How hosting MyHammer started in a devops way back in the day

7 Nov 2011

This here is just me, bragging about myself. You have been warned.

Manuel Kiessling in front of the very first MyHammer FAI server cluster

This guy with the psychopathic look standing in a room full of rubbish in front of something that vaguely looks like computers is me standing in front of the first MyHammer server cluster, only days before the whole system went into production.

It was 2005, and I had set up the whole system in a way I’m still quite proud of. Being the only systems administrator at the company at that time, I knew that I wouldn’t face happy times if I would set up the cluster in a traditional way, that is, machine by machine. Although it started small, the system was supposed to grow, especially regarding the web servers, and even I knew that while managing 13 servers individually was doable, it wasn’t fun, and managing several dozen machines just sounded like total nightmare.

Which is why I thought about better ways to setup and manage the whole cluster. I ended up with a central installation server running FAI – Fully Automatic Installation, and hosting a cfengine server. This way, new machines could be automatically provisioned with the operating system (Debian GNU/Linux) they needed by simply booting from their network adaptor, and new as well as existing systems could easily be maintained, configured, and updated via cfengine. No need to ever log in on a specific machine to change configuration or install software. A centralized syslog server completed the picture.

cfengine was a major pain in the ass at times, and with Chef and Puppet there a way more sophisticated tools available today, but the overall system ran extremely well and could easily scale over time.

Years later, the term Devops was coined, and I couldn’t help congratulating myself for getting it right so long ago.

Deploying Symfony2 Applications to Amazon AWS with Scalarium

1 Nov 2011

Important Note

The methodology explained here is outdated, please read Deploying Symfony2 Apps via Scalarium: Improved Methodology for an updated version.

About

This article describes how to use the cloud-based cluster-management platform Scalarium in order to automatically mass-deploy Symfony2 applications with a MySQL database backend onto clusters of Amazon EC2 virtual machines by creating a special Symfony2 environment, using a custom Chef recipe, and making use of Doctrine migrations.

Target audience

Current or soon-to-be Scalarium customers, devops interested in deploying Symfony2 applications using centralized configuration management tools like Chef or Puppet, PHP developers.

Prerequisites

In order to get your Symfony2 application running on Amazon AWS, you need an AWS account, a Scalarium account (correctly set up with your AWS credentials), and a Github account to host your Symfony2 application and your custom Chef recipes. This tutorial assumes that you are already familiar with managing EC2 clusters with Scalarium. It’s tested to work with Symfony 2.0.4 on Ubuntu 11.04 instances.

Overview

The above diagram is here to illustrate how the different parts are working together in order to deploy a running application. The virtual machines hosting our Symfony2 application and the database are EC2 instances running in the Amazon AWS cloud. We will use Scalarium to define the layout of our cluster (called a “cloud” in Scalarium), to configure the application which will be deployed onto the application servers within this cluster, and to configure the custom Chef recipes which need to be applied to our application server instances in order to finalize the deployment and setup of our application.

Looking at the diagram, we could say that Scalarium manages, Amazon runs, and Github provides – Scalarium uses what Github provides in order to run the application on Amazon.

Because Scalarium already provides the setup logic and recipes that allow us to set up basic Apache/PHP application servers and MySQL database servers on AWS, we will only need to provide what is needed in order to finalize the deployment and setup of our specific Symfony2 application – setting up a basic Ubuntu server, installing software packages like PHP, Apache, MySQL, and checking out our Symfony2 application code from Github is all done by Scalarium without the need to provide additional means.

The example application

It makes sense to follow this tutorial using your own Symfony2 application. However, an example application hosted at Github.com → MyHammer → ScalariumExampleSymfony2Application is used to illustrate the process – you are free to use this repository to deploy the application to your Scalarium cloud. The commit history of this repository also shows step by step which changes need to be applied to a Symfony2 application to prepare it for running on a Scalarium cloud.

Setting up a Scalarium cloud for our application

Our very first step is to set up a new cloud in Scalarium which manages the EC2 instances, server roles, application configuration and custom Chef cookbooks needed to deploy and run our Symfony2 application.

In order to do so, click on Add Cloud in the upper right corner of the main Scalarium administration interface. Choose whatever name you like (I will stick with “Symfony”), define a region that makes sense for you (Europe in my case), and choose “Ubuntu 11.04″ as the default operating system. Please choose “Role Dependent” as the Hostname Theme, because this will make it much easier to follow my explanations whenever I’m talking about specific machine instances.

Assuming that you have already set up Amazon AWS in your Scalarium account, please choose the AWS credentials and SSH keys accordingly.

You now have an empty cloud. Let’s define these three things in order to host our application:

  • An application
  • Custom Cookbooks
  • An application server and a database server role

Let’s start with our application. Later, we are going to make some modifications to our application that are necessary for hosting it with Scalarium, but we can already configure it into our cloud. Clicking on Add Application gives us a dialogue in which we can configure where EC2 instances will be able to pull our application from upon bootup or application deployment.

I’m going to choose “SymfonyExample” as the name. Please choose “PHP” as the Application Type. If you are going to use the sample application that resides on Github, please choose a Repository Type of “Git”, and enter the following Repository URL: “git://github.com/MyHammer/ScalariumExampleSymfony2Application.git”. All other parameters are not important for now – however, if you are configuring your own private repository, you will need to provide a deploy SSH key.

Although this is sufficient to deploy the code from Github onto our instances, it’s not enough to actually get a running application. Additional steps are necessary after the code has been pulled from Github, and those steps need to be performed using a custom Chef recipe. We are going to write this recipe later, but we can already configure the cookbook that contains the recipe into our cloud. On the cloud overview page, select Manage Cookbooks from the Actions dropdown.

In the new dialogue, check Enable custom cookbooks, and configure as follows:

  • Repository Type: “Git”
  • Repository URL: “git://github.com/MyHammer/ScalariumExampleSymfony2ChefRecipes.git”
Deploy SSH Key and Branch / Revision don’t need to be filled out.

As a last step, our cloud needs two machine roles: one for our application servers, and one for our database server. We will start with the application server role. On the cloud overview page, select Add role, and choose the PHP Application Server role.

Once you have added it, an additional configuration is necessary: In Custom Recipes, please add the recipe “symfony2::deploy” for the Scalarium actions configure and deploy. This makes sure that our recipe is run everytime our application is deployed to an instance, or whenever the cloud changes.

Last but not least, create an additional role MySQL Master. Additional configuration is not needed here. If you like, you can already add and boot an instance for this role.

Modifying the Symfony2 application

Our Symfony2 application doesn’t need to be re-programmed in any way in order to run via Scalarium – however, its configuration needs to be specifically modified. You can either modify your existing “prod” environment configuration, or you may want to create a new environment called “scalarium”, which is what I did for the example application.

The nice thing about Scalarium and Symfony2 is that the former provides a very nice PHP interface to the layout of the current cluster, and the latter provides an easy way to make use of this interface.

This allows us to dynamically configure our application’s database setup, avoiding the need to hard code e.g. the IP address of our MySQL master into the application. Here is a step by step description on how to achieve this:

First, create a new and empty file /app/config/config_scalarium.yml. This is going to be the main configuration file for the new “scalarium” environment. Fill the file with the following content: imports: - { resource: parameters_scalarium.php } - { resource: config.yml } This makes our new environment use 99% of it’s settings based on those from the “prod” environment – however, an additional file is imported, /app/config/parameters_scalarium.php – this is where we are going to dynamically define our database settings using the power of Scalarium.

Let’s fill /app/config/parameters_scalarium.php with life: <?php include_once(__DIR__ . '/../../scalarium.php'); $scalarium = new Scalarium(); $container->setParameter('database_driver', 'pdo_mysql'); $container->setParameter('database_host', $scalarium->db->host); $container->setParameter('database_port', '3306'); $container->setParameter('database_name', $scalarium->db->database); $container->setParameter('database_user', $scalarium->db->username); $container->setParameter('database_password', $scalarium->db->password); $container->setParameter('database_path', null); unset($scalarium); What happens here is that the database parameter placeholders like %database_host%, which are used in /app/config/config.yml to configure the database for our application, are programmatically defined based on the current state of the Scalarium cloud. Leveraging the power of the scalarium.php script, which is available in the root directory of our application per default (a symlink is created whenever our application is deployed on an instance), this makes our database config dynamic and therefore always up to date.

The creators of Scalarium point out that using scalarium.php is just a convenience. The full-stack alternative would be to write a Chef recipe that generates the configuration file and register this recipe on the configure and deploy events. Inside the Chef recipe Scalarium provides you with all necessary information like which hosts exist in the cloud and what their configuration is (e.g. IP addresses, roles, etc.). See http://support.scalarium.com/kb/custom-instance-setup for further information on how to use the Scalarium cloud structure information in your own recipes.

One important thing to consider here is that the settings in /app/config/parameters.ini overwrite settings with the same name in /app/config/parameters_scalarium.php – we therefore need to remove all lines containing “%database” from parameters.ini!

The last step is to create a Frontend Controller for our new “scalarium” environment at /web/app_scalarium.php: <?php require_once __DIR__.'/../app/bootstrap.php.cache'; require_once __DIR__.'/../app/AppKernel.php'; //require_once __DIR__.'/../app/AppCache.php'; use Symfony\Component\HttpFoundation\Request; $kernel = new AppKernel('scalarium', false); $kernel->loadClassCache(); //$kernel = new AppCache($kernel); $kernel->handle(Request::createFromGlobals())->send();

You can look at a visual before-and-after comparison of all these changes on Github:

Putting the parts together

Our cloud now has everything in place it needs. Its roles are defined, our application servers know where to pull our application from, instances of role “PHP Application Server” are configured to use our custom Symfony2 deploy recipe, and our application has been modified to make use of the dynamic cloud configuration in a new environment called “scalarium”.

Let’s take a moment to look at our custom Chef recipe.

What this recipe does is it checks for each application that is going to be deployed if it’s actually a Symfony2 application, and if yes, it starts by updating the vendors (or installing them from scratch if none exist yet), clears the application’s cache, applies database migrations (if any), makes sure that cache and log files and directories are read and writable for those users that need it, installs and configures an Apache vhost file for the app, and disables the default vhost.

Ok, let’s deploy our application! All you need to do is to add an instance of role PHP Application Server and boot it up. Everything else happens automatically:

  • Scalarium requests an EC2 instance from Amazon AWS which is booted with a fresh Ubuntu 11.04 image
  • Scalarium sets this machine up with some basic packages like PHP, Apache etc., and executes its basic setup routines (which are Chef recipes, too)
  • Our Symfony2 application is pulled from Github and deployed to /srv/www/symfonyexample/current
  • The instance executes our custom Chef recipe symfony2::deploy which installs the vendors, clears the app cache, applies the database migrations, installs the web assets, sets users and permissions on cache and log files, and configures an Apache vhost for our application

Once this is done, you can browse to the public IP of the booted application server instance, which will display the Symfony2 welcome page.

Behaviour-driven node.js development with stubbing by combining Vows and node-gently

13 Apr 2011

I’m about 3.5 hours into node.js development, I guess that qualifies me to give advice on it on this Internet thing.

Being the BDD fanatic that I am, I wanted to start off behaviour-driven right from the beginning, and Vows looked like a good choice.

However, I quickly came to the point where I needed to stub out a dependency in one of my modules, and as far as I can see, Vows doesn’t provide mocking/stubbing. But https://github.com/felixge/node-gently does, and here is my approach at combining these two:

This is the Vows spec: var gently = global.GENTLY = new (require("gently")); var vows = require("vows"), assert = require("assert"); var myModule = require("MyModule"); vows.describe("My Module").addBatch({ "when calling its foo() method": { topic: myModule, "it triggers a console message": function (topic) { gently.expect(gently.hijacked.sys, "puts", function(str) { assert.equal(str, "Hello World"); }); topic.foo("Hello World"); } } }).export(module);

And this is the implementation of MyModule: if (global.GENTLY) require = GENTLY.hijack(require); var sys = require("sys"); function foo(message) { sys.puts(message); return true; } exports.foo = foo;

No idea if this makes any sense in the long run – I will tell you when I’m about 14 hours or so into BDD node.js development…