This project allows you to easily create an infinitely-scalable farm of IIS 8 / Windows Server 2012 web servers using Windows Azure Web Roles that are deployed to by an OctopusDeploy server.
Logo courtesy of Aoife Doyle (thanks so much - it's awesome!)
It's really easy to get up and running - more details below, but in short:
- Configure a standard Web Role project in Visual Studio
Install-Package AzureWebFarm.OctopusDeploy
- Configure 4 cloud service variables -
OctopusServer
,OctopusApiKey
,TentacleEnvironment
andTentacleRole
- Deploy to Azure and watch the magic happen!
- Pre-requisites
- Installation Instructions
- Local debugging
- Remote debugging
- What if I want to use Web Roles, but don't want to pay for another VM / don't want to use OctopusDeploy?
- What happens when I install the AzureWebFarm.OctopusDeploy NuGet package?
- What if I want to deploy non-.NET applications?
- Why is this needed?
- Contributing
- Stay abreast of the latest changes / releases
- An OctopusDeploy server using at least version 2.1 that is already configured with the environments, projects, users etc.; you will need to record the:
OctopusServer
- Octopus Server URLOctopusApiKey
- API key of a user that has at least the following privileges in the environment you are deploying to: ("Environment manager" and "Project deployer") or ("System administrator")TentacleEnvironment
- Name of the environment that you want to deploy toTentacleRole
- Name of the role you want your web farm servers to have
- Ensure that you open port 10943 on the Octopus Server so that Polling Tentacles can work, for more information view the documentation (http://docs.octopusdeploy.com/display/OD/Polling+Tentacles).
- Ensure that if you are using HTTPS (and you should be) for your OctopusDeploy server that the HTTPS certificate is valid or you include code to trust the invalid certificate
- You will need to set up the website and app pool creation for your OctopusDeploy project (including the hostname for your site in the binding(s)) when using this library (since IIS starts off as a blank slate).
- You can create a CName alias from your domain name to the
<mywebrolename>.cloudapp.net
address - If you want a naked domain then use a DNS provider that allows you to create ALIAS records or use a service like dnsazure.com
- You can create a CName alias from your domain name to the
- A Windows Azure Cloud Service to host the web farm that has a certificate uploaded to it for RDP (and your HTTPS certificate if you are going to configure HTTPS)
- If you are creating a custom install (see below) then you need to have .NET Framework 4.5 and Windows Azure Tools 2.2 installed along with Visual Studio 2012 or above
- The latest version of NuGet - at least >= 2.7.2, as there is a bug in some earlier versions which can cause NuGet to miss adding a binding redirect for WindowsAzure.Storage.
You have two options for using AzureWebFarm.OctopusDeploy:
- You can use one of our pre-packaged cloud packages to avoid the need to crack open Visual Studio - this is really easy, but limits you to the standard configurations we have built
- You can install the project into a cloud project using NuGet and retain full control over how your cloud service is configured (and have the flexibility to have a non-standard configuration)
If this is something you would use (download a pre-packaged set of .cspkg and .cscfg files to upload directly to the portal rather than having your own codebase that pulls in our NuGet package) let us know so we know it's a good idea to invest time in this idea! Communicate with us via Twitter @robdmoore / @mdaviesnet or alternatively create an issue on this GitHub project.
Feel free to watch the screencast tutorial of these instructions.
The installation instructions form two parts - normal web role installation and AzureWebFarm.OctopusDeploy installation.
Creating a Web Role
- Start a new Visual Studio solution by creating a new Windows Azure Cloud Service project - be sure to select .Net Framework 4.5 and Windows Azure Tools v2.2 when creating it
- Don't add a web or worker role at this point - just create the blank cloud project
- This will henceforth be referred to as the "cloud project"
- Add a new "ASP.NET Empty Web Application" project to your solution - ensure it's .NET Framework 4.5
- This will henceforth be referred to as the "web project"
- Right-click "Roles" on the cloud project, select "Add" > "Web Role Project in solution" and select the newly added web project
- Configure RDP by right-clicking the cloud project and select "Package", tick the "Enable Remote Desktop for all roles" checkbox, select a certificate that you have uploaded to your Windows Azure cloud service and specify a username/password/expiry
- Configure the number of instances that you want to initially deploy by changing this element in
ServiceConfiguration.Cloud.cscfg
:<Instances count="1" />
- use at least 2 instances to meet the 99.95% SLA - Add in a diagnostics connection string to the
ServiceConfiguration.Cloud.cscfg
file by changing this element:<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="AccountName={ACCOUNTNAME};AccountKey={ACCOUNTKEY};DefaultEndpointsProtocol=https" />
- make sure there is NOT a trailing;
or it will fail when you deploy - Select and enter your vmsize into the
vmsize
attribute of theWebRole
element in theServiceDefinition.csdef
file - I generally recommend (see the screencast for more informaton and explaination):ExtraSmall
for test/dev farms (unless your application(s) chews up all the memory)Small
for small to medium load websitesMedium
for medium to high load websites
- Consider adding a HTTPS web role endpoint and certificate (ensure the certificate is uploaded to your Cloud Service in Azure though)
- If you want to do a test deployment at this stage to make sure everything is configured correctly first check that
osFamily
is set to3
inServiceConfiguration.Cloud.cscfg
- we check this setting automatically later, but you'll need to check it yourself to successfully deploy at this stage. You may also want to check yourWeb.config
andApp.config
files to make sure there is a binding redirect there forWindowsAzure.Storage
. Deploy your cloud package to Azure - your instances should reach the "Running" state. To publish your package you can use:- Visual Studio
- The Windows Azure portal
- A PowerShell script e.g. from a CI server
Adding AzureWebFarm.OctopusDeploy to your Web Role
- Execute the following in the Package Manager Console (or use the GUI):
Install-Package AzureWebFarm.OctopusDeploy
- Make sure it installs into the web project
- When prompted that a file has been modified click "Reload"
- If prompted that a file already exists ie
WebRole.cs
, you should allow NuGet to override it with the file from our package
- (optional) Debug locally
- Ensure that the
ServiceConfiguration.Cloud.cscfg
file has correct values for theOctopusServer
,OctopusApiKey
,TentacleEnvironment
andTentacleRole
variables - Deploy to Azure as per step 9 above
It is a good idea to debug the farm locally to make sure your configuration is correct and your OctopusDeploy server is configured correctly:
- Ensure that there is only one instance locally by checking the
ServiceConfiguration.Local.cscfg
file has<Instances count="1" />
- Ensure that the
ServiceConfiguration.Local.cscfg
file has correct values for theOctopusServer
,OctopusApiKey
,TentacleEnvironment
andTentacleRole
variables - Set the cloud project as the default project
- (optional) If you have already downloaded the tentacle installer and don't want to wait for the emulator to download it as part of startup then place the file at
c:\Octopus.Tentacle.msi
and it will automatically be used - Hit F5 to start the Azure emulator
- If all goes well you should see your computer registered with your Octopus server and any current releases deployed to your local IIS server
- If you need to debug the startup script then uncomment the relevant REM'd out lines in Startup\startup.cmd (but remember to recomment them before dpeloying to Azure or your Azure deployment WILL fail
- If you need to debug the RoleEntryPoint code then set up your Visual Studio to debug using Symbol Source and you should be able to step into the AzureWebFarm.OctopusDeploy code
The following should be able to help you debug what is happening:
- RDP into the server:
- Look at Event Viewer for application exceptions
- Look at C:\Resources\Temp\RoleTemp{GUID}\StartupLog.txt to see the output of
Startup\startup.cmd
- Look at the
LogEntity
table in table storage of the storage account you configured for Diagnostics to see the log output of the RoleEntryPoint
What if I want to use Web Roles, but don't want to pay for another VM / don't want to use OctopusDeploy?
Check out our AzureWebFarm project, which is a similar concept except the farm contains everything you need to deploy within it - you simply MsDeploy your application to it and it will sync the new code across the whole farm for you.
Apart from adding the dependencies of the package and the dll the following actions are performed:
- To your web project:
Startup\startup.cmd
is added and set as "Copy always"Startup\startup.ps1
is added and set as "Copy always"WebRole.cs
is added- Binding redirects are added to the
Web.config
file - The binding redirects in the
Web.config
file are copied into a newApp.config
file that is used by the RoleEntryPoint code (since it doesn't run under IIS it can't useWeb.config
)
- To your cloud project:
- The
{CloudProject}.ccproj
file is modified to add an MSBuild target that copies theApp.config
file from the web project tobin\{WebProject}.dll.config
in the cloud package when it's built - The
ServiceDefinition.csdef
file is changed to add:- Elevated privileges for the RoleEntryPoint code
- Startup\startup.cmd as an elevated privileges startup task that has selected environment variables
- A 1GB
Install
local resource directory (where the tentacle is installed) and a 19GBDeployments
local resource directory (where deployments are stored) - if you aren't using ExtraSmall instances then you can increase the 19GB to a larger value - Four configuration settings variables are added:
OctopusServer
,OctopusApiKey
,TentacleEnvironment
andTentacleRole
- All
ServiceConfiguration.*.cscfg
files are changed to add the four configuration settings variables:OctopusServer
,OctopusApiKey
,TentacleEnvironment
andTentacleRole
- The
To see how we perform all of this "magic" checkout the install.ps1 file.
While .NET projects will work out of the box, IIS has the capability of running almost any programming language that you want - Python, PHP, Java, NodeJS, etc. If you are using a custom install of AzureWebFarm.OctopusDeploy then you have full flexibility to add extra startup tasks to configure IIS to enable these different languages. You can then add NuGet packages to OctopusDeploy to be deployed that don't contain a .NET application.
If you are using OctopusDeploy for your deployments and you want to migrate your application to the cloud then this project provides you a really easy pathway to continue using OctopusDeploy for your deployments, while having the hard work of setting up the infrastructure done for you.
At the same time you benefit from the infinite scalability of Azure Web Roles (see next section for more information) and the App Initialisation Module configuration that we have enabled to improve startup performance of your applications.
Why are Web Roles sometimes necessary - everyone is using Azure Web Sites these days right?
Windows Azure Web Roles give you a range of advantages over Windows Azure Web Sites that, depending on your application, might mean you aren't able to use Web Sites. The particularly important advantages are:
- You can scale to hundreds or even thousands of nodes (note: most subscriptions start with a limit of 20 cores, but you can talk to support to get more enabled; we've seen an example here in Australia with 500 cores for instance)
- You can connect Web Roles to Windows Azure Virtual Network (VPN) to enable hybrid cloud scenarios
- You can use SSL for free (it costs extra for Web Sites)
- You can open up non-standard TCP ports (i.e. anything other than 80 for HTTP and 443 for HTTPS)
- You have full control to configure IIS how you see fit
- You can run/install arbitrary software applications on role startup and if necessary with elevated privileges
- You can mount NTFS volumes from blob storage
- You can perform complex auto-scaling
- You aren't restricted in what parts of .NET you can use - e.g. GDI+ is disabled in Azure Web Sites
- You can RDP into the roles, which can sometimes make debugging easier
- You can configure complex diagnostics collection rules across the whole farm using Windows Azure Diagnostics
- You have more choice of VM size/specification and (currently at least) deployment location
If your application fits within the bounds of what's possible with Azure Web Sites then we generally recommend that you use it since it provides a seamless development, deployment, debugging and support experience out-of-the-box across a number of software languages and in particular the deployment experience is quick and comprehensive.
Fair enough, so why use Web Roles over Virtual Machines - VMs are way more flexible right?
If for one of the reasons above or perhaps one of the other possible reasons you can't use Web Sites then you are left with a choice of Windows Azure Web Roles or Windows Azure Virtual Machines. There are a number of advantages and disadvantages to both, but we would generally recommend Web Roles over Virtual Machines where possible because:
- The infrastructure for Web Roles is managed for you - you automatically get Windows Updates and OS upgrades (assuming you have at least 2 roles, which is necessary for the 99.95% SLA)
- Scaling Virtual Machines is very difficult and it's impractical to scale more than 10s of nodes (without a lot of automation work and even then the storage costs would start adding up)
- Similarly, if you want to do auto-scaling beyond the basic CPU/memory scaling available in the portal then you need to implement it yourself
OK, so what are the main disadvantages with Web Roles then - it can't be a silver bullet right?
It must be said that Web Roles aren't perfect; there are three main disadvantages that we see with Web Roles:
- The out-of-the-box deployment experience leaves a lot to be desired - it's slow and error-prone
- To clarify: What is happening is amazing - within 8-15 minutes a number of customised, RDP-accessible, Virtual Machines are being provisioned for you on a static IP address and those machines can be scaled up or down at any time and they have health monitoring and diagnostics capabilities built-in as well as a powerful load balancer!
- The problem lies when you tie that deployment process to the deployment of a software application (like most of the Web Roles tutorials you will read suggest you do) - waiting 8-15 minutes for a VM to be provisioned is amazing; waiting 8-15 minutes for the latest version of your software application to be deployed is unacceptably slow
- The way we see it - you should treat a Web Role as infrastructure rather than an application and you should deploy your applications to a farm of Web Roles that have been previously set up
- This leads us to the second disadvantage of Web Roles...
- If you change state in a role dynamically (e.g. change IIS settings, install a program, deploy some files to IIS, etc.) then as soon as the role is restarted/recycled (e.g. a Windows Update is applied or you change a configuration setting that requires a recycle) you lose that state
- It should be noted that this is also the main advantage of Web Roles in that it's what allows them to be so scalable - each role is treated homogenously with the others and so can be shutdown and spun up as needed - it just requires you to specify everything that is needed for that role in the package (.cspkg) file for the operation and lifetime of that role
- The fact that you can run arbitrary code at startup and shutdown of the role means that you can do anything you want though; you just need to work within the bounds of the platform (it is afterall PaaS, not IaaS) - that's what we've taken advantage of to enable this project to be possible
- Tying your application code to your Web Role:
- Increases your solution complexity - you have another project in your solution and on top of that your deployment is more complex because rather than packaging/deploying the site you are packaging/deploying the site inside of a Web Role package
- Often leads to developers tying the application to the Web Role's development model even though sites should be agnostic of that and leave you with flexibility to deploy it anywhere (e.g. on-premise, AWS, Azure Web Sites, etc.)
How does AzureWebFarm.OctopusDeploy allow me to use Web Roles without any of the disadvantages?
- The first disadvantage above is simply taken care of by how awesome the deployment experience is with OctopusDeploy
- We've worked with the development model that Windows Azure Web Roles gives you so that the roles don't need to be changed dynamically to function as an OctopusDeploy-powered web farm; they will automatically:
- Install an OctopusDeploy tentacle
- Register the tentacle with an OctopusDeploy server in an environment and with a role all specified by you
- Deploy the latest version of all relevant applications to the role before it's registered with the load balancer on startup - when it registers with the load balancer it's good-to-go
- Configure the IIS App Initialisation Module for all sites and app pools to improve performance of your applications
- De-register the tentacle from the OctopusDeploy server on shutdown or recycle - thus your OctopusDeploy server will always show the current state of affairs
- By deploying a web farm separate to your applications and then using OctopusDeploy to deploy your applications to the farm you can develop your applications completely agnostically of the fact you are deploying them to Azure
If you would like to contribute to this project then feel free to communicate with us via Twitter @robdmoore / @mdaviesnet or alternatively send a pull request / issue to this GitHub project.
Follow the MRCollective twitter account.