Skip to content

Commit

Permalink
rabitmq terraform cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
krotkiewicz committed Jul 14, 2017
0 parents commit 7741533
Show file tree
Hide file tree
Showing 6 changed files with 321 additions and 0 deletions.
Binary file added .github/chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.tfstate
*.tfstate.backup
*.tfvars
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Dead simple Terraform configuration for creating RabbitMQ cluster on AWS.


## Requirements
1. AWS account
2. Route53 Zone (internal preferably)

## How to use it ?

Create `terraform.tfvars` file with content:
```
region = "<REGION-HERE>"
access_key = "<YOUR-KEY-HERE>"
secret_key = "<YOUR-SECRET-HERE>"
ssh_key_name = "<SSH-KEY-NAME>"
vpc_id = "<VPC-ID>"
subnet_ids = ["<SUBNET-1-ID>", "<SUBNET-2-ID>"]
route53_zone_id = "<ROUTE53-ZONE-ID>"
```

then run `terraform plan` and `terraform apply`

## What it does ?

1. Creates `${var.count}` nodes in `${var.subnet_ids}` subnets
1. Adds Route53 A record for each node in `${var.route53_zone_id}` zone (like `rabbit-0.local`, `rabbit-1.local`, ...)
1. Makes sure they can talk to each other and create cluster
1. Configures `/` vhost queues in High Available (Mirrored) mode with automatic synchronization (`"ha-mode":"all", "ha-sync-mode":"automatic"`)
1. Creates ELB to load balance nodes and Route53 record for it (like `rabbit.local`)


<p align="center">
<img src=".github/chart.png" width="600">
</p>
57 changes: 57 additions & 0 deletions cloud-init.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#cloud-config
hostname: ${hostname}

write_files:
- path: /root/docker-compose.yaml
content: |
version: "2"
services:
node:
hostname: ${hostname}
environment:
- RABBITMQ_ERLANG_COOKIE=${secret_cookie}
- RABBITMQ_USE_LONGNAME=true
- RABBITMQ_NODENAME=rabbit@${hostname}
image: "rabbitmq:3-management"
ports:
- '4369:4369'
- "5672:5672"
- "15672:15672"
- '25672:25672'
volumes:
- ./data:/var/lib/rabbitmq
- ./conf:/etc/rabbitmq
- path: /root/conf/enabled_plugins
content: |
[rabbitmq_management].
- path: /root/conf/rabbitmq.config
content: |
[ { rabbit, [
{cluster_nodes, {[${nodes}], disc}},
{ loopback_users, [ ] } ] }
].
runcmd:
# wait until DNS records are created
- sleep 10
- yum update -y
- yum install -y docker
- service docker start
- chkconfig docker on
- usermod -a -G docker ec2-user
- pip install docker-compose
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml up -d
- sleep 2
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} add_user admin ${admin_password} || true
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} set_user_tags admin administrator || true
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} add_user rabbit ${rabbit_password} || true

- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} add_vhost / || true
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} set_policy -p / ha-all_ttl_expiry "^" '{"ha-mode":"exactly", "ha-params":${majority}, "ha-sync-mode":"automatic", "message-ttl":${message_timeout}, "expires":${message_timeout}}' || true

- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} set_permissions -p / admin ".*" ".*" ".*" || true
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} set_permissions -p / rabbit ".*" ".*" ".*" || true

- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} delete_user guest || true
193 changes: 193 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
provider "aws" {
region = "${var.region}"
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
}

data "aws_vpc" "vpc" {
id = "${var.vpc_id}"
}

data "aws_route53_zone" "selected" {
zone_id = "${var.route53_zone_id}"
}

data "aws_ami_ids" "ami" {
owners = ["amazon"]

filter {
name = "name"
values = ["amzn-ami-hvm-2017*-gp2"]
}
}

data "null_data_source" "nodes" {
count = "${var.count}"
inputs = {
name = "rabbit-${count.index}"
domain = "rabbit-${count.index}.${substr(data.aws_route53_zone.selected.name, 0, length(data.aws_route53_zone.selected.name) - 1)}"
node_name = "rabbit@rabbit-${count.index}.${substr(data.aws_route53_zone.selected.name, 0, length(data.aws_route53_zone.selected.name) - 1)}"
}
}

resource "aws_security_group" "rabbitmq_elb" {
name = "rabbitmq_elb"
vpc_id = "${var.vpc_id}"
description = "Security Group for the rabbitmq elb"

ingress {
protocol = "tcp"
from_port = 5672
to_port = 5672
security_groups = ["${var.security_group_ids}"]
}

ingress {
protocol = "tcp"
from_port = 80
to_port = 80
security_groups = ["${var.security_group_ids}"]
}

egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = [
"0.0.0.0/0"
]
}

tags {
Name = "rabbitmq elb"
}
}

resource "aws_security_group" "rabbitmq_nodes" {
name = "rabbitmq-nodes"
vpc_id = "${var.vpc_id}"
description = "Security Group for the rabbitmq nodes"

ingress {
protocol = -1
from_port = 0
to_port = 0
self = true
}

ingress {
protocol = "tcp"
from_port = 5672
to_port = 5672
security_groups = ["${aws_security_group.rabbitmq_elb.id}"]
}

ingress {
protocol = "tcp"
from_port = 15672
to_port = 15672
security_groups = ["${aws_security_group.rabbitmq_elb.id}"]
}

ingress {
protocol = "tcp"
from_port = 22
to_port = 22
security_groups = ["${var.security_group_ids}"]
}

egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = [
"0.0.0.0/0"
]
}

tags {
Name = "rabbitmq nodes"
}
}

data "template_file" "cloud-init" {
count = "${var.count}"
template = "${file("${path.module}/cloud-init.yaml")}"

vars {
majority = "${floor(var.count / 2) + 1}"
nodes = "${join(", ", formatlist("'%s'", data.null_data_source.nodes.*.inputs.node_name))}"
hostname = "${element(data.null_data_source.nodes.*.inputs.domain, count.index)}"
secret_cookie = "${var.rabbitmq_secret_cookie}"
admin_password = "${var.admin_password}"
rabbit_password = "${var.rabbit_password}"
message_timeout = "${3 * 24 * 60 * 60 * 1000}" # 3 days
}
}

resource "aws_instance" "rabbitmq" {
count = "${var.count}"
subnet_id = "${element(var.subnet_ids, count.index)}"
ami = "${data.aws_ami_ids.ami.ids[0]}"
instance_type = "${var.instance_type}"
key_name = "${var.ssh_key_name}"
vpc_security_group_ids = ["${aws_security_group.rabbitmq_nodes.id}"]
associate_public_ip_address = false
user_data = "${element(data.template_file.cloud-init.*.rendered, count.index)}"
tags {
Name = "rabbitmq-${count.index}"
}
}

resource "aws_route53_record" "rabbit" {
count = "${var.count}"
zone_id = "${var.route53_zone_id}"
name = "rabbit-${count.index}"
type = "A"
ttl = "300"
records = ["${element(aws_instance.rabbitmq.*.private_ip, count.index)}"]
}

resource "aws_elb" "elb" {
name = "rabbit-elb"

listener {
instance_port = 5672
instance_protocol = "tcp"
lb_port = 5672
lb_protocol = "tcp"
}

listener {
instance_port = 15672
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}

health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "TCP:5672"
interval = 30
}

instances = ["${aws_instance.rabbitmq.*.id}"]
subnets = ["${var.subnet_ids}"]
idle_timeout = 3600
internal = true
security_groups = ["${aws_security_group.rabbitmq_elb.id}"]

tags {
Name = "rabbitmq"
}
}

resource "aws_route53_record" "elb" {
zone_id = "${var.route53_zone_id}"
name = "rabbit"
type = "CNAME"
ttl = "300"
records = ["${aws_elb.elb.dns_name}"]
}
34 changes: 34 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
variable "access_key" {}
variable "secret_key" {}
variable "region" {}
variable "vpc_id" {}
variable "ssh_key_name" {}
variable "count" {
description = "Number of RabbitMQ nodes"
default = 2
}
variable "subnet_ids" {
description = "Subnets for RabbitMQ nodes"
type = "list"
}
variable "security_group_ids" {
description = "Security groups which should have access to ELB (amqp + http ports) and nodes (ssh port)"
type = "list"
}
variable "route53_zone_id" {
description = "Route53 internal zone"
}
variable "admin_password" {
description = "Password for 'admin' user"
default = "password"
}
variable "rabbit_password" {
description = "Password for 'rabbit' user"
default = "password"
}
variable "rabbitmq_secret_cookie" {
default = "supersecretcookie"
}
variable "instance_type" {
default = "t2.small"
}

0 comments on commit 7741533

Please sign in to comment.