Azure: Is there any way to deploy different instance sizes for test/production
Asked Answered
B

5

21

I have a Windows Azure site which is deployed to two separate hosted services. One for test, one for production. When we're ready to push to production, we spin up a staging deployment in the production service, push there, then do a VIP swap. All good.

The question is, now we want to move up from XS web instances, but it doesn't really make sense to spend the extra money on the test deployment. Is there any way to use an XS instance for test, and then say medium instances for production? I know I can change the number of instances for each service config, but I can only change the instance size for all configs.

I'm thinking of just leaving it XS in the config, and then remembering to switch it to Medium before I deploy to production. Is there any reason why I shouldn't do this? Is there a better way?

Cheers!

Boathouse answered 23/6, 2012 at 15:36 Comment(2)
May also want to check out built-in support for multiple cloud profiles: nickharris.net/2011/08/… or even more super-dynamic: blogs.msdn.com/b/philliphoff/archive/2012/07/02/…Patience
another handy article here blogs.msdn.com/b/microsoft_press/archive/2015/03/12/…Ruche
M
24

There are a few ways to do this... Simpler way is to do a little "hacking" of the CCPROJ file:

1) create a clone of the CSDEF file for every environment that matches the Configuration Name (Release/Debug/QA/UAT/etc): ServiceDefinition.Release.csdef, ServiceDefinition.Debug.csdef, etc.

2) Add those files manually to the CCPROJ file by using a notepad editor

3) Define a Pre-Build Event command that copies the ServiceDefinition.$(ConfigurationName).csdef into ServiceDefintion.csdef

voila, now your ServiceDefintion will adapt to whatever configuration you're using.

If you want to get fancier or see more details, check out this blog entry that can help you switch all sorts of settings in unison

http://www.paraleap.com/blog/post/Managing-environments-in-a-distributed-Azure-or-other-cloud-based-NET-solution.aspx

Edit: Here is a config that works. Notice that other files are included as type "None" instead of ServiceDefinition to avoid the multiple definitions error.

  <ItemGroup>
    <ServiceConfiguration Include="ServiceConfiguration.Local.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.Development 1.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.Development 2.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.Local Dev 1.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.Local Dev 2.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.QA 1.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.QA 2.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.Pre-Production 1.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.Production.cscfg" />
    <ServiceDefinition Include="ServiceDefinition.csdef" />
    <None Include="ServiceDefinition.Local.csdef" />
    <None Include="ServiceDefinition.Development 1.csdef" />
    <None Include="ServiceDefinition.Development 2.csdef" />
    <None Include="ServiceDefinition.Local Dev 1.csdef" />
    <None Include="ServiceDefinition.Local Dev 2.csdef" />
    <None Include="ServiceDefinition.QA 1.csdef" />
    <None Include="ServiceDefinition.QA 2.csdef" />
    <None Include="ServiceDefinition.Pre-Production 1.csdef" />
    <None Include="ServiceDefinition.Production.csdef" />
  </ItemGroup>
Makassar answered 23/6, 2012 at 16:23 Comment(3)
Thanks much. Only issue I had was the Azure project would not build with multiple .csdef files in it. Just omit step #2 in your solution, though, and all seems to work. Error was "Microsoft.WindowsAzure.targets(845,5): error : WAT020 : Only one service definition can be active."Boathouse
@Igorek: Your blog post is missing the images. Can that be fixed? I was also interested in the solution.Sylvie
@Sid: images have been restored. Thanks for patienceMakassar
C
15

You can use the Web Publishing TransformXml MSBuild task to transform only the parts of the ServiceDefinition you want (like you can do now with Web.Config).

  • Create a ServiceDefinition.[BuildConfigName].csdef file next to the ServiceDefinition.csdef file (you'll probably need to do this in File Explorer)
  • Create the transform file like you'd created a Web.config transform. I explicitly set the root namespace, just in case, so my root element is:
  <ServiceDefinition name="Cloud.JobsWorker" 
          xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" 
          xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"
          schemaVersion="2013-10.2.2">
  • Manually add it to your ccproj using:
  <ServiceDefinition Include="ServiceDefinition.csdef" />
  <None Include="ServiceDefinition.Release.csdef" />
  • At the bottom of your project include:
  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <PropertyGroup>
    <ServiceDefinitionTransform>ServiceDefinition.$(Configuration).csdef</ServiceDefinitionTransform>
  </PropertyGroup>
  <Target Name="TransformServiceDefinition" BeforeTargets="ResolveServiceDefinition" Condition="exists('$(ServiceDefinitionTransform)')">
    <!-- Generate transformed service config in the intermediate directory -->
    <TransformXml Source="@(ServiceDefinition)" Destination="$(IntermediateOutputPath)%(Filename)%(Extension)" Transform="$(ServiceDefinitionTransform)" />
    <!--Force build process to use the transformed configuration file from now on.-->
    <ItemGroup>
      <ServiceDefinition Remove="ServiceDefinition.csdef" />
      <ServiceDefinition Include="$(IntermediateOutputPath)ServiceDefinition.csdef" />
    </ItemGroup>
  </Target>

When you package or publish your cloud app, your csdef should be transformed depending on the build config you're using.

This is adapted from here: http://blogs.staykov.net/2011/06/windows-azure-configuration-settings.html

Covin answered 3/4, 2014 at 16:56 Comment(5)
Slightly more work to set up than the accepted answer, but I prefer this one for a few reasons: it's an opt-in solution, it minimizes duplication and maintenance effort (you don't end up having tons of csdef files to change when adding or removing a Setting, for instance), and it doesn't play around too much with files as copying using Pre-Build steps would. Still, both answers are great!Intimacy
This works fine for ServiceDefinition but ServiceConfiguration is not working as it still using the default oneThreedecker
When you say "At the bottom of your project include" is this in the ServiceDefinition file or a separate file?Hospitaler
The bottom of your project file that the ServiceDefinition file is in.Covin
Good solution. See my answer for few comments.Transmigrant
M
2

Using transformation as David Faivre suggested is much cleaner and without the overhead to update all files after adding single property.

This is the transformation xml for changing vm size:

<?xml version="1.0"?>
<ServiceDefinition name="CloudServiceName" 
                   xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2015-04.2.6" 
                   xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <WorkerRole name="WorkerRoleName.Role" vmsize="Medium" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</ServiceDefinition>
Mathildamathilde answered 19/10, 2015 at 14:24 Comment(0)
W
1

VM size is handled in the ServiceDefinition.csdef file, which is something you can't edit at run or deploy time. You would need to change the setting in the .csdef, repackage your solution, and then redeploy.

One solution may be to have multiple Windows Azure deployment projects set up. One project would be your "test" project that has the .csdef configured to use a XS. Another project would be the "production" project that uses a larger instance. This would allow you to use the standard Windows Azure / Visual Studio tools to manage the project - which may be nice depending on your process.

Wasting answered 23/6, 2012 at 15:47 Comment(0)
T
1

David Faivre proposed a good solution. Few comments from me:

  1. If your ServiceDefinition file contains links to some directories (e.g. section), than there will be an error caused by the fact that transformed file is in intermediate directory. For my use I solved this problem by placing transformed file alongside original ServiceDefinition.csdef (don't forget to add *.transformed into .gitignore):

<TransformXml Source="@(ServiceDefinition)" Destination="ServiceDefinition.csdef.transformed" Transform="$(ServiceDefinitionTransform)" />

  1. $(Configuration) variable corresponds to Build configuration (Debug, Release etc.). If you want to have profile specific transformation (corresponding to ServiceConfiguration..cscfg), you need to use $(TargetProfile) variable:

<ServiceDefinitionTransform>ServiceDefinition.$(TargetProfile).csdef</ServiceDefinitionTransform>

Transmigrant answered 27/4, 2017 at 8:58 Comment(1)
Thanks for the additional info. Using "TargetProfile" and not "Configuration" saved me a lot of time.Acth

© 2022 - 2024 — McMap. All rights reserved.