5

When using AWS, it seems a nice way to deploy an application to a newly created instance is via AWS CodeDeploy. This works as follows:

  1. Set up an auto-scaling group for the application
  2. Write a user-data bash script for the auto-scaling group which pulls the CodeDeploy agent from S3, installs it and starts it
  3. Set up a CodeDeploy deployment group which deploys to the auto-scaling group

Now, when an application bundle (e.g. jar or debian package) is deployed to the deployment group, it will be deployed automatically to new instances launched in the auto-scaling group.

My question is: how can this deployment strategy fit with a CI tool like Travis CI?

Specifically:

  • How can CodeDeploy pick up a package built by a CI tool like Travis CI? Does the build job need to upload the package to S3?
  • How can CodeDeploy be used to deploy the application gradually (e.g. one instance at a time)?
  • Does this deployment strategy require each running instance to be shut down and replaced, or is the new version of the application deployed on the existing instances? If it is the former, machine IP addresses would change during deployment, so how can other services discover the newly deployed application (i.e. without hardcoded IP addresses)?
Josh
  • 697
  • 6
  • 21

2 Answers2

4

tl;dr version:

  • The build job needs to upload the package to S3.
  • Use the one at a time deployment config.
  • The new version of the application is deployed on the existing instances.

Ok, here's the long version:

I recommend you try the Deployment Walkthrough or take a looks at Concepts in the documentation. It should help you get familiar with CodeDeploy faster.

You don't have to use an AutoScaling group with CodeDeploy if you don't want to. CodeDeploy with AutoScaling integration allows you to manage fleets that need to change in size dynamically separately from the code that is deployed to them, but that is not a requirement to use CodeDeploy. You can also launch some EC2 instances manually, install the host agent, and then tag them into a deployment group - but they won't get deployed to automatically on launch like the AutoScaling instances would. In either case, you can always create fleet wide deployments.

You'll have to do some work to integrate it with your CI tool. CodeDeploy doesn't directly manage your build artifacts, so your build process will need to do that. To have automatic deployments, your will need to:

  1. Create a archive bundle with an appspec.yml, any scripts you need to handle the install/upgrade, and your build artifacts.
  2. Upload the bundle to S3.
  3. Create a deployment in CodeDeploy.

You might want to look at CodePipeline as an example of a continuous delivery system that's integrated with CodeDeploy.

CodeDeploy uses deployment configs to control how aggressively it deploys to the instances in your fleet. (This config gets ignored for automatic deployments, since each instance is handled separately.) CodeDeploy will fail your deployment and stop deploying to new instances if it cannot potentially fail another instance without violating the constraints in the deployment config.

There are three built in deployment configs, and you can create your own via the CLI or API if you need a different one. To deploy to only one instance at a time, you can use the CodeDeployDefault.OneAtATime deployment config, which allows at most one unhealthy host at any given time.

Jonathan Turpie
  • 1,343
  • 10
  • 16
  • Thanks for the detailed answer - I have been trying out CodeDeploy properly over the past week and it seems a nice tool. I have a question about deploying a new version of an API. Say we have an API which is load balanced across 5 EC2 instances and we never want to be in an inconsistent state where instances are running a different version of the API. In this scenario we probably need to deploy to 5 new instances and switch the ELB over once complete. How should CodeDeploy be used to do this? Would you create 5 new instances and a new deployment group for every release? – Josh Sep 25 '15 at 20:32
  • 1
    What you describe would work. As general best practice goes, you should always assume you are going to be running in mixed mode sometimes and your rollouts should be designed to work along side the previous version. This does make schema migrations more painful (two deployments instead of three) but your going to be much safer. – Jonathan Turpie Sep 25 '15 at 21:13
0

For anyone else (like me) looking for an example on how to actually integrate Travis-CI with CodeDeploy:

  • Configure the Application, DeploymentGroups and instances, as explained in the CodeDeploy walkthrough.
  • Use aws-cli commands to deploy your first revision successfully to the CodeDeploy target instance.
  • After you have the application deployed and running, configure Travis to trigger the deployments.
  • The CodeDeploy appspec.yml file and any scripts used for the deployment should be packaged inside your application bundle (latest.zip in the below example).

The following .travis.yml config worked for me:

script: npm run build
before_deploy:
  - zip -r latest dist/*
  - mkdir -p dpl_cd_upload
  - mv latest.zip dpl_cd_upload/latest.zip
deploy:
  - provider: s3
    access_key_id: "XXXX"
    secret_access_key: "YYYYY"
    bucket: "deployments-bucket-name"
    local_dir: dpl_cd_upload
    skip_cleanup: true
  - provider: codedeploy
    access_key_id: "ZZZZZ"
    secret_access_key: "WWWW"
    bucket: "deployments-bucket-name"
    key: latest.zip
    bundle_type: zip
    application: CodeDeployAppName
    deployment_group: CodeDeployDeploymentGroupName

This examples were really useful: https://github.com/travis-ci/cat-party/blob/master/.travis.yml

SebaGra
  • 2,801
  • 2
  • 33
  • 43