Showing posts with label AWSDeploy. Show all posts
Showing posts with label AWSDeploy. Show all posts

Wednesday, 12 June 2013

Deploying from SVN through Jenkins to AWS Elastic Beanstalk (Part 2): Linking Jenkins to AWS EB

Following on from Part 1 of the blog on integrating Jenkins with AWS EB, this concludes the two part series by focussing on the AWS deployment process within Jenkins. At the end we will briefly outline the limitations of AWSDeploy to EB and what you would need to look to if your needs are more complex.

So what does Jenkins look like?

Setting up Jenkins will basically require executing the following the steps:
  1. Create a 'New Job' in Jenkins 
  2. Fill in the URL of  your SVN repository
  3. Decide on Jenkins' polling frequency for SVN
  4. Fill in the batch process details, including MSBuild.exe and AWSDeploy.exe CLI, with appropriate parameters
  5. Save the job

Step 1: Create a 'New Job' in Jenkins

Nice and easy, from the main Jenkins page, click "New Job" on the left hand menu in Jenkins.

When the new job page loads, fill in the details of the job you with to create. You'll want to create a free-style software project. 

I Normally prefix the job name with 'RELEASE-' but for this demo, I am being a bit slapdash. When you are happy with it, click the OK button.

fig 1 - Creating a 'New Job' in Jenkins (click to enlarge)

Step 2: Configure the Job

Jenkins then moves to the job configuration page which allows you to set up the SCM (in this case SVN), the Build Steps and Post Build Actions.

Hence:

1. Fill in a display name under "Advanced Project Options" if you want it

2. Under "Source Code Management" select the Subversion radio button and enter your repository URL. Jenkins will poll your SCM and if you need to enter SVN credentials, a validation help link appears and you can click to enter your SVN credentials within that.
fig 2 - Links to enter your server's credentials. This server doesn't exist - just showing the link
3. Select your method of authentication. In my case, I chose Username/Password and then enter your credentials. Important note, the site runs unsecured by default. Once you have entered the credentials, click the OK button.

fig 3 - Subversion authentication in Jenkins (click to enlarge)
4. Complete the rest of Jenkins' SVN config. I always check out a fresh copy so I don't have previous builds laying around and potentially making a mess of the build. Note, you can also check out multiple URL's if you have dependent projects. This can of course, also be done through an SVN 'extern' declaration.

5. Build Triggers - This is an important feature that allows you to configure what sets off the build. For example, if you have a dependency chain of projects/solutions which are already set up as Jenkins jobs, you can choose which project(s) need to complete before this job runs. Projects are separated by commas.

Here you should select the "Poll SCM" step. This then brings up a text box where you can enter the polling frequency in a CRON like language. Jenkins polls your SCM (SVN here) and stores the latest revision that it builds. If there is a change in that revision number on a poll, it then starts a checkout and build process.  

Alternatively you can choose to build periodically, or combine the two.

6. The build steps - This is probably the key elements when it comes to deploying to AWS. For simplicity, I have put all the steps in this demo into one build step so that it completes the steps in one go. However, you would normally want to split them out into multiple steps, such as 'Build', 'Test', 'Deploy' so you can stop at any point. You can pick up the build artefacts between the steps by using the same workspace environment variables.

Putting it all together still works, as long as an errorcode is returned, but it isn't neat.

Clicking on the "Add build step" button open up a text area when you can enter a list of  Windows console commands. In my case, they are:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe "%WORKSPACE%\AProject.sln" /p:Configuration=Release /p:Platform="Any CPU" /m
cd "%WORKSPACE%\AProject"
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe /t:Package /p:Configuration=Release
"C:\Program Files (x86)\AWS Tools\Deployment Tool\awsdeploy.exe" /w /r /v /DDeploymentPackage="%WORKSPACE%\AProject\obj\Release\Package\AProject.zip" "%WORKSPACE%\AProject\AWSDeploy.txt"

You will notice the %WORKSPACE% environment variable in this series of commands. This is the Jenkins workspace that the code has been checked out to. There are a number of environment variable and they are: 

The following variables are available to shell scripts

BUILD_NUMBER
The current build number, such as "153"

BUILD_ID
The current build id, such as "2005-08-22_23-59-59" (YYYY-MM-DD_hh-mm-ss)

BUILD_DISPLAY_NAME
The display name of the current build, which is something like "#153" by default.

JOB_NAME
Name of the project of this build, such as "foo" or "foo/bar"

BUILD_TAG
String of "jenkins-${JOB_NAME}-${BUILD_NUMBER}". Convenient to put into a resource file, a jar file, etc for easier identification.

EXECUTOR_NUMBER
The unique number that identifies the current executor (among executors of the same machine) that's carrying out this build. This is the number you see in the "build executor status", except that the number starts from 0, not 1.

NODE_NAME
Name of the slave if the build is on a slave, or "master" if run on master

NODE_LABELS
Whitespace-separated list of labels that the node is assigned.

WORKSPACE
The absolute path of the directory assigned to the build as a workspace.

JENKINS_HOME
The absolute path of the directory assigned on the master node for Jenkins to store data.

JENKINS_URL
Full URL of Jenkins, like http://server:port/jenkins/

BUILD_URL
Full URL of this build, like http://server:port/jenkins/job/foo/15/

JOB_URL
Full URL of this job, like http://server:port/jenkins/job/foo/

SVN_REVISION
Subversion revision number that's currently checked out to the workspace, such as "12345"

SVN_URL
Subversion URL that's currently checked out to the workspace.

The batch commands perform the following functions.

The 1st command builds the solution containing the project, using the release configuration. In a normal project I at least use the web.Debug.config and web.Release.config files with the MS Build match and replace mark-up into the main web.config file. A tutorial blog can be found here.

The 2nd command enters into the directory of the built project. This is just so we can run the package verb for MSBuild.

The 3rd builds a standard deployment package out of the project.

The 4th line is the AWS Deployment line. This actually carries out the deployment of the package created in batch step 3 previously using the AWSDeploy.txt file we created from within Visual Studio.

Post-build actions
A post build action in Jenkins is an event that takes place after the build steps. They occur regardless of whether or not the build has completed successfully and encompass one or more of the steps shown in the screengrab below.

fig 4 - The Jenkins post-build actions (click to enlarge).
In email post-build steps, Jenkins allows users to be sent emails for unstable builds (it builds but tests fail), build failures and send separate emails to the people who broke the build.

You'll notice form the screenshot that there is the option of publishing JUnit tests. Obviously, MSTest results are not exactly in the same format. However, you can run a build step to convert MSTest's TRX to HTML files using tools such as the MS Test Report Generator. There is a similar process for NUnit results.

Recommendations:
Don't forget to set up e-mail alerts within Jenkins for job events as a "Post-build action". You can also tie events to an RSS feed. In either case, you have the option of using them for failed builds and all builds. Plus the email benefits identified above. Note though, Jenkins doesn't automatically set up an (or your) email server. You have to have a mail service/daemon running to send emails.

Also, I definitely recommend post-build steps to publish your test results. This may include a step to post to your build monitor if you have one. Maybe naming and shaming the individual breaking the build... not that you want a harassment suit on your company's hands of course ;-)

Step 3: Run the darn thing!

When you check in some code, at the intervals specified for the Jenkins cron, Jenkins will poll SVN, clean checkout the code, build, test and deploy the code. Any failure will cause the build history to include the usual red light.

fig 5 - Build history, including failures 
You can of course, run the build using the "Build Now" menu link in the top left menu to kick it off manually. In either case, there is a significant increased delay over any local process, but that is to be expected since the deployment is going over the wire and EB is incrementally building the environment (it would be longer first time out. I've had to wait over 10 minutes sometimes. However, )

The following is the example deployed to AWS using the above process. As well as using AWS Elastic Beanstalk, for my own work, I have a route 53 entry to the domain name and a back end DB.

fig 6 - Deployed EB example site (click to enlarge)

Conclusion

Jenkins has always been a really easy to use system for CI. I've found it easier to use than ThoughtWorks Go. However, both Go and TFS give you more customisation options out of the box. You can certainly expand Jenkins using custom plugins. Obviously, there is quite a bit more to do to set up a CI system from the above. But it gives you a framework to modify and work with. 

Also, the use of the AWSDeploy.exe makes it really easy to deploy fairly simple environments. 

Limitations
When you get up to the level of having to manage large, custom architectures and deployments, where detailed configuration and set-up of multiple AWS resources are requires with EC2, ELB, SQS, S3, SWF, RedShift and big data instances for example, a basic AWSDeploy text file won't cut it any more. 

At that point, you would need to consider moving from just using an EB setup to using CloudFormation to set up a more complex cloud architecture. As it happens, EB does basically generate a JSON Chef  Cookbook which is used as the CloudFomation template. You can see this if you go to the ClouseFormation stacks page in the AWS Console. I suspect there will be times when you'll need to roll your own.

Thursday, 23 May 2013

Deploying from SVN through Jenkins to AWS Elastic Beanstalk (Part 1)

Following on from the AWS Summit last month, I figured I'd do a technical one this time round. This will fall into two parts as they are fairly detailed. But I am not going to go through to much .NET stuff and shall assume that if you follow my blog, that you can already write .NET web apps. 

Part 1: AWS Toolkit and Deploying to the Cloud

Whilst working on my current project which is going to be deployed on AWS, it became the time to look to build the release deployment process to send it to AWS. I had a choice of deployment mechanisms, including AWS CloudFormation, but for the simplicity of this environment, I plumped for deploying direct to EB.

I am running the following setup:
  • VS2010 SP1
  • Visual SVN (with Tortoise SVN client)
  • Jenkins 1.514

Having had a little bit of experience using Go, Jenkins and TFS, I chose Jenkins for the deployment and decided to deploy to AWS Elastic Beanstalk (EB). I will assume you know how to set up and use Jenkins and have an AWS account.

What's this Beanstalk?

Elastic Beanstalk is an autoscaling platform to deploy applications into the AWS cloud. It is built on top of the EC2 PaaS setup and allows you to deploy your software, without the headache of maintaining your own Elastic Load Balancer (ELB), EC2 servers and Relational Data Services (RDS) servers etc.

How many cows do I need to sell for the magic beans to use it with Visual Studio?

None, the AWS toolkit is free. If you use the t1.micro environments for everything, you also have 750 hours of AWS use per month for the EC2 and RDS instances run by EB for free. 750 hours is almost enough to run for an entire month for nothing. Note, the minimum charging unit is per hour. Details of the free usage tier are here:


This lot is way above what Microsoft Azure offers customers. Not surprising given how much more mature Amazon's platform is compared to other platforms.

One thing I would advise is you consider how your account will actually use this. If you start on the free usage tier and then it kicks up a second instance, you may end up paying for the computing time of that other instance (or use your monthly free usage up faster). There are solutions around this, such as the use of reserved instances for servers that are running continuously; or setting the ELB to not scale past 1 system etc. but I won't be covering them here.

Installing the AWS for MSFT VS toolkit

In order to use the AWS platform with Visual Studio, you have to download and install the AWS Toolkit for Visual Studio. The installation will provide a combination of Visual Studio Add-ins and Command Line Interface (CLI), including the AWS Explorer shown below.

fig 1 - AWS Explorer in VS2010
It also installs context menus to build the deployment package. However, as part of the Jenkins CI process, we will be deploying partly through the CLI.

Security and Using AWS Access Keys

In order to deploy to AWS, there are a number of security steps you have to use to get passed the security of the AWS cloud.
  1. Sign up for an AWS account (I shall assume you've done that)
  2. Using the web based account management portion of the site, obtain the secret key and Access Key ID for the platform (in this case EB uses REST/Query API) - You will need these for the automated deployment.
  3. Sign in to the AWS Management Console and set up your server as authorised to deploy to the website to AWS.
The secret key and access key are used to permit the uploading of packages to the cloud. So yes, that means you need to create a package :-) But here is where the AWS tool-kit's CLI tools actually comes in. 

fig 2 - Secret and Access Key IDs

What does AWS Explorer in VS have to do with this?

The AWS Explorer allows you to deploy applications straight from VS2010/12. It also contains the project templates which you need to use to deploy different types of project on the AWS platform. For this demo, I used the "AWS Web Project" selection, which is pretty much like a normal MS Web Project, but contains the AWSSDK.dll file. 

In the image below, you can see 5 sub-items and these are almost all sample applications to help you learn how to use AWS, or to use as a template for AWS development of your own versions of these class of project. 

fig 3 - AWS Toolkit installs new project types
So select the AWS Web Project option and build a web project like you normally would any other .NET application. In my experience, there is nothing an ASP.NET/WCF app has been able to do that it hasn't.  

Let's assume I've done that, what next?

Your easiest (maybe best) bet is to first deploy the application you have created straight from VS2010. This fulfils a number of functions:
  • Allows you to create a deployment file which AWSDeploy.exe uses to deploy your application to EB
  • Tests your CI server (or even PC) can connect to the AWS environment
  • Makes sure your access keys are correct
fig 4 - Items added to the project context menu after AWS Toolkit is installed
After installing the AWS toolkit, you'll note that unlike VS2010, the context menu elements to deploy a project are only available at the project level, not the solution level. That means you can really only deploy one project at a time from here. I've highlighted the differences in the image above. Republishing is the just publishing step without having to enter the publishing settings again.

Publishing to the cloud eh?

Configuring the publishing process from inside VS2010 is actually pretty simple. It is a matter of using the following dialog box.

fig 5 - VS2010's AWS Deploy dialog box
The steps are pretty straightforward.

  • Click the 'Add [another] account' icon next to the accounts dropdown, or select an existing  account to use for deployment. In the popup that appears, this is where the Secret Key and and Access Key ID are used from previous stages. When you have completed this box click OK.
    fig 6 - Creating a new AWS account record (your existing AWS account)
  • Selecting the region to deploy to. In this case, I am using the EU West region which is based in Ireland.
  • For new deployments, select the "AWS Elastic Beanstalk" item form the list box. It is far too easy to attempt to click on 'Next' without doing this step, especially when it appears to be lit. So make sure it is selected. Click next and you are taken to the Application details screen.
fig 7 - Application details screen
  • What this screen does is allow you to specify the name of the application you wish to deploy to EB. Take a note of the bottom checkbox. This shows that the AWS toolkit set up a local Git repository to then push changes to AWS with. 
  • Clicking 'Next' then takes you to the Environment details screen. Here you should create the name of the entire EB environment. 
fig 8 - EB environment details



Important Note:  
This EB environment name is not the same as the names of any EC2 instance, any RDS instance or anything else within that EB environment. The EB environment automatically creates the names of the internal EC2, S3. RDS etc. instances whe it creates the environment. For example, the EB environment could be called AProjectSample1234 and within that, we may have an EC2 instance which it names axjkljehyhsdsds-1 and an RDS instance which it names abbdhjwiukskjkmn-1. Remember, you are deploying to an IaaS environment which is designed to autoscale. You will have automatically been assigned an ELB and at least one EC2 instance, which can scale if your processing needs scale. Hence, the underlying PaaS mechanism is transparent to you, though you can examine the instances from the usual AWS Management Console of the AWS Explorer in VS.


  • Select a URL to use as the main environment. Note, this URL sub-domain is linked to your ELB not your EC2 instance, which is what you configure on the next screen in the Wizard.
  • The AWS Options screen is where you configure your Amazon Machine Image (AMI). A container is the image that you use to contain your application. In this case, a web app. Given it is Windows, you have the choice of 64-bit Win2012 or 2008 R2 OS platforms, with IIS8 or 7.5 respectively. The free tier is the Micro tier (which corresponds to the t1.micro tier in AWS). If you have configured an AMI if your own in Amazon's cloud, you can select it here too. 

fig 9 - Selecting the EC2 config
  • The next screen after that is the Application Options screen. This is where you can configure the .NET Framework version the app pool uses; a health-check page (think heartbeat monitor in IIS for ASP.NET) as well as the security credentials to log in with (I definitely recommend you get some :-)
fig 10 - Setting up the type of container.
  • If you have an RDS instance associated with your project, the screen in fig 11 allows you to configure the security groups associated with your RDS instance. Note that to communicate between the EC2 and RDS instances, they both have to exist in the same security group. This is to save you having to deal with Windows Authentication, especially if the servers are going to scale and the load balanced, since the same authentication accounts would not necessarily be available. If you have no RDS servers, then the checkboxes can be left alone and you can click 'Next'. You can always change this later and add an RDS instance from the AWS Management console > EB or AWS Explorer in VS.
fig 11 - Security group config for RDS
  • As far as we are concerned for this blog post, all those steps were really to get to the following review screen. The review screen has a critical checkbox at the bottom with the label "Generate AWSDeploy configuration". For the Jenkins deployment, this is the key screen. You need to check the box and enter the location of where you want to save your AWS configuration file. I definitely recommend you generate it in your SVN workspace, since you will have to commit it to SVN, for Jenkins to then check out into its workspace and subsequently run AWS with this configuration. 
fig 12 - AWS configuration options highlighted in the review wizard panel

When you're done, hit the 'deploy' button. The wizard will then attempt to deploy your application to AWS EB, using the supplied account credentials and .NET framework onto the elasticbeanstalk.com sub-domain you specified.  This takes some time, but with any luck, you should find it deploys successfully. If you go to the sub-domain you selected in a few minutes (for example http://AProjectSample1234.elasticbeanstalk.com), you should have your site at that address. You can monitor the site through the AWS management console or through the AWS Explorer in Visual Studio.

What's in the AWS Deploy configuration  file?

When the file has been created, opening it shows us the following structure (yes I have changed my keys, you don't think I am showing you that do you? :-)

# For detailed explanation of how these config files should be used and created please see the developer guide here:
# http://docs.amazonwebservices.com/AWSToolkitVS/latest/UserGuide/tkv-deployment-tool.html

# Edit the parameter line below to set the path to the deployment archive or use
# /DDeploymentPackage=value
# on the awsdeploy.exe command line for more flexibility.
# DeploymentPackage = <-- path to web deployment archive -->

# Instead of embedding the AWSAccessKey and AWSSecretKey to be used to deploy
# artifacts we recommend that you consider using the /DAWSAccessKey and
# /DAWSSecretKey command line parameter overrides.

AWSAccessKey = XXXXXXXXXX11223XXXXX
AWSSecretKey = alkHd1PO3lakjsdka/asdlas/1+djasdjl/zu/lkjaslkdas
Region = eu-west-1
SolutionStack = 64bit Windows Server 2008 R2 running IIS 7.5
Template = ElasticBeanstalk

aws:elasticbeanstalk:application:environment.AWS_ACCESS_KEY_ID = XXXXXXXXXX11223XXXXX
aws:elasticbeanstalk:application:environment.AWS_SECRET_KEY = alkHd1PO3lakjsdka/asdlas/1+djasdjl/zu/lkjaslkdas

Application.Description = Sandbox
Application.Name = AProject

Container.Enable32BitApplications = False
Container.InstanceType = t1.micro
Container.TargetRuntime = 4.0

Environment.CNAME = AProject
Environment.Description = Sandbox environment
Environment.Name = AProject

All the details you specified in the wizard are stored here. This file is passed to AWSDeploy.exe on the command line or in our case, through Jenkins. The comments give you some very useful tips. Decisions on the keys will be especially important. If you are deploying to different environments or platforms on client's private clouds for example (over VPC for example), you wouldn't want to use your dev keys to do that. So you would pass them in on the command line, but always take care to store them appropriately (including thinking about an encryption step in the build process).

What next?

The next blog will show you how how to link this to Jenkins and built and deployed the project to AWS. This will focus on configuring the Jenkins job to use MSBuild to build the package and AWSDeploy to deploy it to the elastic beanstalk URL we've already specified here.