Upgrade to PRO for Only $50/Yearโ€”Limited-Time Offer! ๐Ÿ”ฅ

Ansible vs CloudFormation Smackdown!

Avatar for Steven Ringo Steven Ringo
October 21, 2015

Ansible vs CloudFormationย Smackdown!

A quick comparison of Ansible and CloudFormation followed by some best practices for CloudFormation.

Accompanying code at https://github.com/stevenringo/cloudformation-ruby-ansible-examples

Avatar for Steven Ringo

Steven Ringo

October 21, 2015
Tweet

More Decks by Steven Ringo

Other Decks in Programming

Transcript

  1. What is CloudFormation? โ€œ...an easy way to create and manage

    a collection of related AWS resources, provisioning and updating them in an orderly and predictable fashion.โ€ https://aws.amazon.com/cloudformation/
  2. |--------------|---------------|----------------| | Feature | Ansible | CloudFormation | |==============|===============|================| |

    Written in | YAML | JSON | |--------------|---------------|----------------| | Grouped as | Playbook | Stack | |--------------|---------------|----------------| | State | Stateless | Keeps state | |--------------|---------------|----------------| | Deletion | Manual | Automatic | |--------------|---------------|----------------| | Dependencies | Manual | Automatic | |--------------|---------------|----------------| | Ordering | Top to bottom | Simultaneous | |--------------|---------------|----------------|
  3. |--------------------|------------------|-----------------| | Feature | Ansible | CloudFormation | |====================|==================|=================| |

    UI | CLI/Tower | CLI/AWS Console | |--------------------|------------------|-----------------| | Reusability | Roles / includes | Nested Stacks | |--------------------|------------------|-----------------| | Rollbacks | No | Yes | |--------------------|------------------|-----------------| | Existing resources | Can incorporate | No | |--------------------|------------------|-----------------| | AWS Services | Limited | Most | |--------------------|------------------|-----------------| | Ease | Easier | Harder | |--------------------|------------------|-----------------| | Triggers/Policies | No | Yes | |--------------------|------------------|-----------------|
  4. God stack โ€” Single stack for all resources โ€” Good

    for small deployments โ€” Size limits โ€” Reuse only by using a generator tool
  5. Nested stacks โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Solution โ”‚

    โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ–ผ โ–ผ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ VPC โ”‚ โ”‚ Database โ”‚ โ”‚ Servers โ”‚ โ”‚ Security Groups โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  6. Nested stacks โ€” CloudFormation invokes child templates โ€” Atomic execution

    โ€” One fails, all fail โ€” Pass parameters through "references" โ€” Need to pass parameters for child template "through" the parent
  7. Pipelined stacks Executor โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 1 โ”‚

    โ”‚ 2 โ”‚ โ”‚ 3 โ”‚ โ”‚ 4 โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ VPC โ”‚ โ”‚ Database โ”‚ โ”‚ Servers โ”‚ โ”‚ Security Groups โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  8. Pipelined stacks โ€” Execute each template manually, requires orchestration โ€”

    Non-atomic execution โ€” One fails, only that template fails โ€” Pass parameters directly โ€” Chain outputs to inputs
  9. Horizontal โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Database โ”‚

    โ”‚ Servers โ”‚ โ”‚ Security Groups โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ Application 1 โ”‚ โ”‚ Application 1 โ”‚ โ”‚ Application 1 โ”‚ โ”‚ VPC โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ Application 2 โ”‚ โ”‚ Application 2 โ”‚ โ”‚ โ”‚ โ”‚ Application 2 โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Application 3 โ”‚ โ”‚ Application 3 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  10. Vertical โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Application 1

    โ”‚ โ”‚ Application 2 โ”‚ โ”‚ Application 3 โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ Servers โ”‚ โ”‚ Servers โ”‚ โ”‚ โ”‚ โ”‚ VPC โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ Servers โ”‚ โ”‚ โ”‚ โ”‚ Database โ”‚ โ”‚ Database โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ Security Groups โ”‚ โ”‚ Security Groups โ”‚ โ”‚ Security Groups โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  11. Partitioning โ€” Keep templates simple โ€” Reuse parameters and mappings

    via a DSL โ€” Choose vertical or horizontal scaling โ€” Decide if you want to rollback the stack or not
  12. Shell โ€” Simple batch script โ€” Use aws-cli to invoke

    CloudFormation templates: aws cloudformation create-stack... โ€” Capture output variables for input variables for next stack โ€” Returns immediately, therefore must check status: aws cloudformation create-describe- stacks...
  13. Ansible - name: launch ansible cloudformation example cloudformation: stack_name: ansible-cloudformation

    state: present region: us-east-1 disable_rollback: true template: files/cloudformation-example.json template_parameters: KeyName: jmartin DiskType: ephemeral InstanceType: m1.small ClusterSize: 3 tags: Stack: ansible-cloudformation
  14. Ansible - include: key_pairs.yml tags: always - include: compile.yml tags:

    always - include: vpc.yml tags: always - include: nat.yml tags: nat - include: titan.yml tags: titan
  15. Ansible - name: delete old cloudformation templates file: path: "{{

    item }}" state: absent with_fileglob: ../cloudformation/compiled/*.json when: clean is defined and clean|bool - name: compile the cloudformation templates shell: "{{ item }} expand --nopretty" with_fileglob: ../cloudformation/dsl/*.rb register: compiled - name: write and validate templates template: src: templates/cloudformation.json dest: cloudformation/compiled/{{ item.item | basename | regex_replace('\.rb$', '.json') }} validate: aws cloudformation validate-template --region {{ region }} --template-body file://%s environment: AWS_ACCESS_KEY_ID: "{{ aws_credentials[env].access_key }}" AWS_SECRET_ACCESS_KEY: "{{ aws_credentials[env].secret_key }}" with_items: compiled.results
  16. Ansible - name: execute vpc cloudformation template cloudformation: aws_access_key: "{{

    aws_credentials[env].access_key }}" aws_secret_key: "{{ aws_credentials[env].secret_key }}" stack_name: vpc-{{ env }} region: "{{ region }}" template: ./cloudformation/compiled/vpc.json disable_rollback: true template_parameters: Environment: "{{ env }}" tags: Environment: "{{ env }}" Region: "{{ region }}" register: vpc
  17. Ansible - name: execute titan cloudformation template cloudformation: aws_access_key: "{{

    aws_credentials[env].access_key }}" aws_secret_key: "{{ aws_credentials[env].secret_key }}" stack_name: titan-{{ env }} region: "{{ region }}" template: ./cloudformation/compiled/titan.json disable_rollback: true template_parameters: Environment: "{{ env }}" CochlearLinkHostedZone: "{{ vpc.stack_outputs.HostedZone }}" CochlearLinkVpc: "{{ vpc.stack_outputs.Vpc }}" TitanSubnets: "{{ vpc.stack_outputs.TitanSubnets }}" tags: Environment: "{{ env }}" Region: "{{ region }}" register: titan
  18. { "ap-southeast-2": { "dev": { "productVersion": "3.0.0", "installationId": "eeeeeeee-f057-40c7-b365-792cc7faeccb" },

    "sit": { "productVersion": "3.1.8", "installationId": "17171717-f057-40c7-b365-792cc7faeccb" } }, "us-east-1": { "prd": { "productVersion": "2.1.0", "installationId": "e047ac6f-f057-40c7-b365-792cc7faeccb" } } }
  19. { "versions": { "3.1.8": { "ap-southeast-2": { "image": "ami-9f266aa5" },

    "eu-west-1": { "image": "ami-0914307e" } }, "3.1.2": { "ap-southeast-2": { "image": "ami-170e422d" }, "eu-west-1": { "image": "ami-5dbf9a2a" } } } }
  20. The dreaded _FAILED states โ€” Resolve manually โ€” Console will

    give you indication of which resource failed to update โ€” Delete offending resource or its dependencies manually โ€” Run delete stack again โ€” When in real shit, call support
  21. Creating the templates โ€” Use CloudFormer to instrospect your VPC.

    โ€” http://docs.aws.amazon.com/AWSCloudFormation/ latest/UserGuide/cfn-using-cloudformer.html โ€” http://aws.amazon.com/developertools/ 6460180344805680 โ€” Uses a Micro instance inside your VPC to interrogate and dumps results to S3 โ€” Parse with the ruby cloudformation-ruby-
  22. Incorporating templates โ€” Resources must be provisioned by CloudFormation โ€”

    Use a phased approach. Use Ref to refer to existing resources, passed as parameters. โ€” Usually in reverse of your pipeline โ€” machines first, VPCs last โ€” e.g. "VpcId" : { "Ref" : "VpcId" }
  23. Policies โ€” Use DependsOn and WaitConditions to control dependency creation

    โ€” Use UpdatePolicy for ASG changes. โ€” Use DeletionPolicy to ensure are not deleted by CloudFormation (instance termination protection on steroids) โ€” Note the Update requires property in the documentation
  24. Other โ€” Test deploys in a sandbox environment that mirrors

    production. Smaller resource types can help reduce costs. โ€” Parameterise everything. โ€” Use the http://docs.aws.amazon.com/ AWSCloudFormation/latest/UserGuide/template- reference.html