Skip to content

Instantly share code, notes, and snippets.

@millerjs
Created February 27, 2020 17:29
Show Gist options
  • Save millerjs/d9e0397c564a6a8934315a8d45f88fcd to your computer and use it in GitHub Desktop.
Save millerjs/d9e0397c564a6a8934315a8d45f88fcd to your computer and use it in GitHub Desktop.
Terraform + Ansible Redis Orchestration

Redis configuration with terraform & ansible

Terraform + Ansible = Terrible?

  • terraform is great at creating the actual servers
  • ansible is greate at making sure things are installed and running

Creating the servers

# redis01 - instance (sanjsoe)

resource "ibm_compute_vm_instance" "redis01" {
  hostname          = "redis01.${terraform.workspace}"
  domain            = "benchprep.com"
  ssh_key_ids       = ["${ibm_compute_ssh_key.ibm_redis_compute_key.id}"]
  os_reference_code = "${local.redis_os_reference_code}"
  datacenter        = "${local.sanjose-zone}"
  network_speed     = "${local.redis_network_speed}"
  cores             = "${local.redis_cores}"
  memory            = "${local.redis_memory}"
  ...
}

The above specifies that the server should exist.

It also allows us to reference the actual state of the declaration. Specifically, we can access the ip address that got assigned:

ibm_compute_vm_instance.redis01.ipv4_address_private

Configuring Redis

  • Use the output of the ibm server declaration
  • Use terraform to call ansible (so we can do the above)
  • Use null_resource to create a custom declaration
  • Use external data to generate the ansible command for the null_resource
data "external" "redis01-server-command" {
  program = ["./bin/ansible-playbook-command"]

  query {
    playbook           = "terraform/ibmcloud/redis-resources/playbook-redis-master.yml"
    ssh_host           = "${ibm_compute_vm_instance.redis01.ipv4_address}"
    ssh_user           = "root"
    ssh_key            = "${local.ibm_compute_ssh_key}"

    var_bind_host      = "${ibm_compute_vm_instance.redis01.ipv4_address_private} localhost"
    var_redis_port     = "${local.redis_port}"
    var_redis_password = "${local.redis_password}"
    var_license_key    = "${var.nria_license_key}"
  }
}

resource "null_resource" "redis01-server-service" {
  triggers {
    playbook = "${md5(file("terraform/ibmcloud/redis-resources/playbook-redis-master.yml"))}"
    config   = "${md5(file("terraform/ibmcloud/redis-resources/redis-master.conf.j2"))}"
    command  = "${md5(data.external.redis01-server-command.result["command"])}"
  }

  provisioner "local-exec" {
    command = "${data.external.redis01-server-command.result["command"]}"
  }
}

Ansible playbook 'meta' command

Input

{
  "playbook": "./playbook.yml",
  "ssh_host": "127.0.0.1",
  "ssh_key": "./ssh_key",
  "ssh_user": "root",
  "var_bind_host": "localhost"
}

Output

{
  "command": "chmod 600 ./ssh_key; echo waiting for valid ssh connection...; while ! ssh -o 'StrictHostKeyChecking=no' -i ./ssh_key root@127.0.0.1 'true'; do sleep 1; done; ANSIBLE_NOCOWS=1 ansible-playbook -i127.0.0.1, -uroot --ssh-extra-args=\"-i ./ssh_key\" ./playbook.yml --extra-vars=\"{\\\"bind_host\\\":\\\"localhost\\\"}\""
}

tl;dr:

ansible-playbook -i127.0.0.1,            \
  -uroot                                 \
  --ssh-extra-args="-i ./ssh_key"        \
  ./playbook.yml                         \
  --extra-vars={"bind_host":"localhost"}

Redis playbook

---
- name: Redis Configuration
  hosts: all
  vars:
    redis_databases: 16
  tasks:
    - name: Ensure epel-release is installed
      yum:
        name: epel-release
        state: latest

    - name: Ensure Redis is present
      yum:
        name: redis
        state: latest

    - name: Ensure Redis Configuration
      template: src=redis-master.conf.j2 dest=/etc/redis.conf owner=root group=root mode=0644
      become: yes
      notify: Redis Restart

    - name: Ensure Redis is started
      service: name=redis state=started enabled=yes
      become: yes

  handlers:
    - name: Redis Restart
      service: name=redis state=restarted enabled=yes
      become: true

- import_playbook: playbook-new-relic-infra.yml
  vars:
    license_key: "{{ license_key }}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment