"After all, the engineers only needed to refuse to fix anything, and modern industry would grind to a halt." -Michael Lewis

Enable Massive Growth

How to Create Multiple Digital Ocean Droplets and Provision Them Using Ansible

Jun 2019

In a previous post, we saw how to create a digital ocean droplet and provision it with Ansible. Creating multiple droplets is very similar, you mostly just have to pay attention to the response object that you get back, which is different in the single vs. the many case.

Creating Multiple Droplets

If you're using Ansible < 2.8, to create multiple droplets you will first have to set your digital ocean api token as an environment variable:

$ export DO_API_TOKEN=1234YourTokenHere4321

We can then structure our droplet creation playbook like so:

---
- hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - name: create two droplets
      digital_ocean:
        unique_name: yes
        region_id: ams3
        image_id: ubuntu-18-10-x64
        wait_timeout: 100
        wait: yes
        name: "{{ item }}"
        size_id: s-1vcpu-1gb
        state: present
        command: droplet
        ssh_key_ids: [ '' ] # <---- put your numeric ssh key in here
      register: created_droplets
      with_items:
        - tmp-droplet-1
        - tmp-droplet-2

    - name: add to dynamic inventory
      add_host:
        name: "{{ item.droplet.ip_address }}"
        group: do
      with_items: "{{ created_droplets.results }}"

If you're using ansible 2.8 or greater, that playbook beginning can instead look like:

---
- hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - name: create two droplets
      digital_ocean_droplet:
        unique_name: yes
        region: ams3
        image: ubuntu-18-10-x64
        wait_timeout: 100
        name: "{{ item }}"
        size_id: s-1vcpu-1gb
        state: present
        ssh_keys: [ '' ] # <---- put your numeric ssh key in here
      register: created_droplets
      with_items:
        - tmp-droplet-1
        - tmp-droplet-2

    - name: add to dynamic inventory
      add_host:
        name: "{{ item.data.ip_address }}"
        group: do
      with_items: "{{ created_droplets.results }}"

Before you run this, you'll want to make sure to include an ansible.cfg file that looks like this:

[defaults]
host_key_checking = False

This will not prompt you before connecting via SSH to your newly created droplets. In a development environment where servers are ephemeral, this is preferred, and can further aid automation so that new droplets can be created without human intervention.

To prove this out, as we did in the last post, we can provision each server with nginx and a custom index page. Create an index.html.j2 Jinja2 template in the same directory as your playbook and fill it with:

<h1> On a digital ocean droplet now </h1>

<p> The ip address where we're at is: {{ ansible_default_ipv4.address }} </p>

And round out the playbook with:

- hosts: do
  remote_user: root
  gather_facts: false

  vars:
    ansible_python_interpreter: /usr/bin/python3

  tasks:
    - name: wait for port 22 to become available
      wait_for:
        host: "{{ inventory_hostname }}"
        port: 22
      delegate_to: localhost
    
    - name: Gather Facts
      setup:

    - name: install nginx
      apt:
        name: nginx
      
    - name: modify html file
      template:
        src: ./index.html.j2
        dest: /var/www/html/index.html

You should now be able to navigate to your IP addresses and see the home page with the IP address displayed. Go get 'em, tiger.

Nick Fisher is a software engineer in the Pacific Northwest. He focuses on building highly scalable and maintainable backend systems.