Monday, March 30, 2009

Simple means of syncing IIS7 settings in a webfarm

Here's our issue:

We have dozens of IIS servers in our webfarms. Each webfarm handles specific sets of applications. All members of each webfarm are supposed to be identical.

With IIS6 this was really simple. We would:
  1. Remove one node from the webfarm
  2. Make IIS changes on one node
  3. Robocopy the code to that node
  4. Test against that node
If successful we would:
  1. Bring that node back and take out a second node
  2. robocopy code to that node
  3. run "cscript c:\windows\system32\iiscnfg.vbs /copy /ts \\targetserver /tu domain\user /tp password" to sync the metabase to that second nodebring that node back into the webfarm
  4. repeat for other nodes
This may sound like a lot of steps but I'm simply writing out what our script does for us automatically.

With IIS7, we could keep the same process if we installed the IIS6 metabase compatibility. But, I'm not one for holding onto the past without a really good reason and while this functionality seems like a good reason, I'd rather have a more supported method that uses today's functionality.

Microsoft's management for IIS7 is . . . interesting in my opinion. They make an excellent step towards scriptable management by putting everything in .xml files instead of binary metabase. You can read these settings in c:\windows\system32\inetsrv\config\ApplicationHost.config. The "interesting" part is that Microsoft for some reason decided to keep machine specific settings in this file (notably, the encryption keys). This means if you simply copy this applicationHost.config to a sister server, you'll find IIS won't even start.

Okay, so what about scripting? Well, Microsoft no longer includes iiscnfg.vbs (unless you include IIS6 compatability). They have the rather nice appcmd.exe tool, but it doesn't work against remote systems. They have the "Web Deployment Tool" but that requires re-packaging your application.

I decided instead we should standardize on as little customization as possible, so Web Deployment Tool is out unless our developers will be sending us packaged deployments (which I think is a terrible idea for a production webfarm as you lose control over your server to whatever development thinks are appropriate settings). Instead, we opted on a slight bastardization of Microsoft's official webfarm setup.

You'll want to read Microsoft's IIS7 Shared Configuration guide for more details, especially for the nice screen shots. We followed those with one exception: We are using a local folder for the "central UNC path" instead.

This gives us two advantages over Microsoft's shared configuration recommendation:
  1. Immunity from issues with a UNC share (credentials changing, share going down, etc)
  2. The ability to make changes to just one node for testing before synchronizing, or for troubleshooting
It was really the second advantage that made us go this route as a pre-flight test is required prior to making a change live.

Since all of our code goes to D:\applications\[appname] which we use Robocopy to sync to all sister nodes, we just created a "D:\applications\iis_settings" folder and set that as the shared configuration path. Now, when we robocopy our code, the IIS7 settings get immediately replicated to the sister nodes as well. Our original process is actually a step shorter.