diff --git a/terraform/openstack/README.org b/terraform/openstack/README.org new file mode 100644 index 000000000..a1e7c7b74 --- /dev/null +++ b/terraform/openstack/README.org @@ -0,0 +1,30 @@ +#+AUTHOR: parasitid@yahoo.fr +#+TITLE: Terraforming consul on Openstack + +* 1. Pre-requisites + - Populates all variables in your terraform.tfvars + #+BEGIN_SRC terraform + username = "..." + password = "..." + tenant_name = "..." + auth_url = "https://myopenstackprovider.com/identity/v2.0" + public_key = "ssh-rsa AAAAB..." + key_file_path = "..." + #+END_SRC + - Change regions, networks, flavor and image ids in the variables.tf + according to your openstack settings + - Use an "upstart" compatible image for your consul nodes + +* 2. Terraform for test + + : terraform apply + +* 3. Terraform as a module + + You should now be able to use openstack as a provider for the consul module. + #+BEGIN_SRC terraform + module "consul" { + source = "github.com/hashicorp/consul/terraform/openstack" + servers = 3 + } + #+END_SRC diff --git a/terraform/openstack/consul.tf b/terraform/openstack/consul.tf new file mode 100644 index 000000000..8c4cd67d8 --- /dev/null +++ b/terraform/openstack/consul.tf @@ -0,0 +1,60 @@ +provider "openstack" { + user_name = "${var.username}" + tenant_name = "${var.tenant_name}" + password = "${var.password}" + auth_url = "${var.auth_url}" +} + +resource "openstack_compute_keypair_v2" "consul_keypair" { + name = "consul-keypair" + region = "${var.region}" + public_key = "${var.public_key}" +} + +resource "openstack_compute_floatingip_v2" "consul_ip" { + region = "${var.region}" + pool = "${lookup(var.pub_net_id, var.region)}" + count = "${var.servers}" +} + +resource "openstack_compute_instance_v2" "consul_node" { + name = "consul-node-${count.index}" + region = "${var.region}" + image_id = "${lookup(var.image, var.region)}" + flavor_id = "${lookup(var.flavor, var.region)}" + floating_ip = "${element(openstack_compute_floatingip_v2.consul_ip.*.address,count.index)}" + key_pair = "consul-keypair" + count = "${var.servers}" + + connection { + user = "${var.user_login}" + key_file = "${var.key_file_path}" + timeout = "1m" + } + + provisioner "file" { + source = "${path.module}/scripts/upstart.conf" + destination = "/tmp/upstart.conf" + } + + provisioner "file" { + source = "${path.module}/scripts/upstart-join.conf" + destination = "/tmp/upstart-join.conf" + } + + provisioner "remote-exec" { + inline = [ + "echo ${var.servers} > /tmp/consul-server-count", + "echo ${count.index} > /tmp/consul-server-index", + "echo ${openstack_compute_instance_v2.consul_node.0.network.0.fixed_ip_v4} > /tmp/consul-server-addr", + ] + } + + provisioner "remote-exec" { + scripts = [ + "${path.module}/scripts/install.sh", + "${path.module}/scripts/server.sh", + "${path.module}/scripts/service.sh", + ] + } +} diff --git a/terraform/openstack/outputs.tf b/terraform/openstack/outputs.tf new file mode 100644 index 000000000..363702ba5 --- /dev/null +++ b/terraform/openstack/outputs.tf @@ -0,0 +1,3 @@ +output "nodes_floating_ips" { + value = "${join(\",\", openstack_compute_instance_v2.consul_node.*.floating_ip)}" +} diff --git a/terraform/openstack/scripts/install.sh b/terraform/openstack/scripts/install.sh new file mode 100644 index 000000000..6dd99c6df --- /dev/null +++ b/terraform/openstack/scripts/install.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -e + +# Read the address to join from the file we provisioned +JOIN_ADDRS=$(cat /tmp/consul-server-addr | tr -d '\n') + +sudo sh -c 'echo "127.0.0.1 consul-node-'$(cat /tmp/consul-server-index)'" >> /etc/hosts' + +echo "Installing dependencies..." +sudo apt-get update -y +sudo apt-get install -y unzip + +echo "Fetching Consul..." +cd /tmp +wget https://dl.bintray.com/mitchellh/consul/0.5.0_linux_amd64.zip -O consul.zip + +echo "Installing Consul..." +unzip consul.zip >/dev/null +sudo chmod +x consul +sudo mv consul /usr/local/bin/consul +sudo mkdir -p /etc/consul.d +sudo mkdir -p /mnt/consul +sudo mkdir -p /etc/service + +# Setup the join address +cat >/tmp/consul-join << EOF +export CONSUL_JOIN="${JOIN_ADDRS}" +EOF +sudo mv /tmp/consul-join /etc/service/consul-join +chmod 0644 /etc/service/consul-join + +echo "Installing Upstart service..." +sudo mv /tmp/upstart.conf /etc/init/consul.conf +sudo mv /tmp/upstart-join.conf /etc/init/consul-join.conf diff --git a/terraform/openstack/scripts/server.sh b/terraform/openstack/scripts/server.sh new file mode 100755 index 000000000..779114e28 --- /dev/null +++ b/terraform/openstack/scripts/server.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +# Read from the file we created +SERVER_COUNT=$(cat /tmp/consul-server-count | tr -d '\n') + +# Write the flags to a temporary file +cat >/tmp/consul_flags << EOF +export CONSUL_FLAGS="-server -bootstrap-expect=${SERVER_COUNT} -data-dir=/mnt/consul" +EOF + +# Write it to the full service file +sudo mv /tmp/consul_flags /etc/service/consul +chmod 0644 /etc/service/consul diff --git a/terraform/openstack/scripts/service.sh b/terraform/openstack/scripts/service.sh new file mode 100755 index 000000000..7c186e97a --- /dev/null +++ b/terraform/openstack/scripts/service.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +echo "Starting Consul..." +sudo start consul diff --git a/terraform/openstack/scripts/upstart-join.conf b/terraform/openstack/scripts/upstart-join.conf new file mode 100644 index 000000000..16343d875 --- /dev/null +++ b/terraform/openstack/scripts/upstart-join.conf @@ -0,0 +1,25 @@ +description "Join the consul cluster" + +start on started consul +stop on stopped consul + +task + +script + if [ -f "/etc/service/consul-join" ]; then + . /etc/service/consul-join + fi + + # Keep trying to join until it succeeds + set +e + while :; do + logger -t "consul-join" "Attempting join: ${CONSUL_JOIN}" + /usr/local/bin/consul join \ + ${CONSUL_JOIN} \ + >>/var/log/consul-join.log 2>&1 + [ $? -eq 0 ] && break + sleep 5 + done + + logger -t "consul-join" "Join success!" +end script diff --git a/terraform/openstack/scripts/upstart.conf b/terraform/openstack/scripts/upstart.conf new file mode 100644 index 000000000..af8260a7b --- /dev/null +++ b/terraform/openstack/scripts/upstart.conf @@ -0,0 +1,24 @@ +description "Consul agent" + +start on runlevel [2345] +stop on runlevel [!2345] + +respawn + +script + if [ -f "/etc/service/consul" ]; then + . /etc/service/consul + fi + + # Make sure to use all our CPUs, because Consul can block a scheduler thread + export GOMAXPROCS=`nproc` + + # Get the public IP + BIND=`ifconfig eth0 | grep "inet addr" | awk '{ print substr($2,6) }'` + + exec /usr/local/bin/consul agent \ + -config-dir="/etc/consul.d" \ + -bind=$BIND \ + ${CONSUL_FLAGS} \ + >>/var/log/consul.log 2>&1 +end script diff --git a/terraform/openstack/variables.tf b/terraform/openstack/variables.tf new file mode 100644 index 000000000..59fe1076d --- /dev/null +++ b/terraform/openstack/variables.tf @@ -0,0 +1,44 @@ +variable "username" {} +variable "password" {} +variable "tenant_name" {} +variable "auth_url" {} +variable "public_key" {} +variable "user_login" { + default = "stack" +} +variable "key_file_path" {} + +variable "nb_of_nodes" { + default = "4" +} + +variable "pub_net_id" { + default = { + tr2="PublicNetwork-01" + tr2-1 = "" + } +} + +variable "region" { + default = "tr2" + description = "The region of openstack, for image/flavor/network lookups." +} + +variable "image" { + default = { + tr2 = "eee08821-c95a-448f-9292-73908c794661" + tr2-1 = "" + } +} + +variable "flavor" { + default = { + tr2 = "100" + tr2-1 = "" + } +} + +variable "servers" { + default = "3" + description = "The number of Consul servers to launch." +}