Skip to content

Commit 7741533

Browse files
committed
rabitmq terraform cluster
0 parents  commit 7741533

File tree

6 files changed

+321
-0
lines changed

6 files changed

+321
-0
lines changed

.github/chart.png

122 KB
Loading

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.tfstate
2+
*.tfstate.backup
3+
*.tfvars

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Dead simple Terraform configuration for creating RabbitMQ cluster on AWS.
2+
3+
4+
## Requirements
5+
1. AWS account
6+
2. Route53 Zone (internal preferably)
7+
8+
## How to use it ?
9+
10+
Create `terraform.tfvars` file with content:
11+
```
12+
region = "<REGION-HERE>"
13+
access_key = "<YOUR-KEY-HERE>"
14+
secret_key = "<YOUR-SECRET-HERE>"
15+
ssh_key_name = "<SSH-KEY-NAME>"
16+
vpc_id = "<VPC-ID>"
17+
subnet_ids = ["<SUBNET-1-ID>", "<SUBNET-2-ID>"]
18+
route53_zone_id = "<ROUTE53-ZONE-ID>"
19+
```
20+
21+
then run `terraform plan` and `terraform apply`
22+
23+
## What it does ?
24+
25+
1. Creates `${var.count}` nodes in `${var.subnet_ids}` subnets
26+
1. Adds Route53 A record for each node in `${var.route53_zone_id}` zone (like `rabbit-0.local`, `rabbit-1.local`, ...)
27+
1. Makes sure they can talk to each other and create cluster
28+
1. Configures `/` vhost queues in High Available (Mirrored) mode with automatic synchronization (`"ha-mode":"all", "ha-sync-mode":"automatic"`)
29+
1. Creates ELB to load balance nodes and Route53 record for it (like `rabbit.local`)
30+
31+
32+
<p align="center">
33+
<img src=".github/chart.png" width="600">
34+
</p>

cloud-init.yaml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#cloud-config
2+
hostname: ${hostname}
3+
4+
write_files:
5+
- path: /root/docker-compose.yaml
6+
content: |
7+
version: "2"
8+
services:
9+
node:
10+
hostname: ${hostname}
11+
environment:
12+
- RABBITMQ_ERLANG_COOKIE=${secret_cookie}
13+
- RABBITMQ_USE_LONGNAME=true
14+
- RABBITMQ_NODENAME=rabbit@${hostname}
15+
image: "rabbitmq:3-management"
16+
ports:
17+
- '4369:4369'
18+
- "5672:5672"
19+
- "15672:15672"
20+
- '25672:25672'
21+
volumes:
22+
- ./data:/var/lib/rabbitmq
23+
- ./conf:/etc/rabbitmq
24+
- path: /root/conf/enabled_plugins
25+
content: |
26+
[rabbitmq_management].
27+
- path: /root/conf/rabbitmq.config
28+
content: |
29+
[ { rabbit, [
30+
{cluster_nodes, {[${nodes}], disc}},
31+
{ loopback_users, [ ] } ] }
32+
].
33+
34+
35+
36+
runcmd:
37+
# wait until DNS records are created
38+
- sleep 10
39+
- yum update -y
40+
- yum install -y docker
41+
- service docker start
42+
- chkconfig docker on
43+
- usermod -a -G docker ec2-user
44+
- pip install docker-compose
45+
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml up -d
46+
- sleep 2
47+
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} add_user admin ${admin_password} || true
48+
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} set_user_tags admin administrator || true
49+
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} add_user rabbit ${rabbit_password} || true
50+
51+
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} add_vhost / || true
52+
- /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
53+
54+
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} set_permissions -p / admin ".*" ".*" ".*" || true
55+
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} set_permissions -p / rabbit ".*" ".*" ".*" || true
56+
57+
- /usr/local/bin/docker-compose -f /root/docker-compose.yaml exec -T node rabbitmqctl -n rabbit@${hostname} delete_user guest || true

main.tf

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
provider "aws" {
2+
region = "${var.region}"
3+
access_key = "${var.access_key}"
4+
secret_key = "${var.secret_key}"
5+
}
6+
7+
data "aws_vpc" "vpc" {
8+
id = "${var.vpc_id}"
9+
}
10+
11+
data "aws_route53_zone" "selected" {
12+
zone_id = "${var.route53_zone_id}"
13+
}
14+
15+
data "aws_ami_ids" "ami" {
16+
owners = ["amazon"]
17+
18+
filter {
19+
name = "name"
20+
values = ["amzn-ami-hvm-2017*-gp2"]
21+
}
22+
}
23+
24+
data "null_data_source" "nodes" {
25+
count = "${var.count}"
26+
inputs = {
27+
name = "rabbit-${count.index}"
28+
domain = "rabbit-${count.index}.${substr(data.aws_route53_zone.selected.name, 0, length(data.aws_route53_zone.selected.name) - 1)}"
29+
node_name = "rabbit@rabbit-${count.index}.${substr(data.aws_route53_zone.selected.name, 0, length(data.aws_route53_zone.selected.name) - 1)}"
30+
}
31+
}
32+
33+
resource "aws_security_group" "rabbitmq_elb" {
34+
name = "rabbitmq_elb"
35+
vpc_id = "${var.vpc_id}"
36+
description = "Security Group for the rabbitmq elb"
37+
38+
ingress {
39+
protocol = "tcp"
40+
from_port = 5672
41+
to_port = 5672
42+
security_groups = ["${var.security_group_ids}"]
43+
}
44+
45+
ingress {
46+
protocol = "tcp"
47+
from_port = 80
48+
to_port = 80
49+
security_groups = ["${var.security_group_ids}"]
50+
}
51+
52+
egress {
53+
protocol = "-1"
54+
from_port = 0
55+
to_port = 0
56+
cidr_blocks = [
57+
"0.0.0.0/0"
58+
]
59+
}
60+
61+
tags {
62+
Name = "rabbitmq elb"
63+
}
64+
}
65+
66+
resource "aws_security_group" "rabbitmq_nodes" {
67+
name = "rabbitmq-nodes"
68+
vpc_id = "${var.vpc_id}"
69+
description = "Security Group for the rabbitmq nodes"
70+
71+
ingress {
72+
protocol = -1
73+
from_port = 0
74+
to_port = 0
75+
self = true
76+
}
77+
78+
ingress {
79+
protocol = "tcp"
80+
from_port = 5672
81+
to_port = 5672
82+
security_groups = ["${aws_security_group.rabbitmq_elb.id}"]
83+
}
84+
85+
ingress {
86+
protocol = "tcp"
87+
from_port = 15672
88+
to_port = 15672
89+
security_groups = ["${aws_security_group.rabbitmq_elb.id}"]
90+
}
91+
92+
ingress {
93+
protocol = "tcp"
94+
from_port = 22
95+
to_port = 22
96+
security_groups = ["${var.security_group_ids}"]
97+
}
98+
99+
egress {
100+
protocol = "-1"
101+
from_port = 0
102+
to_port = 0
103+
cidr_blocks = [
104+
"0.0.0.0/0"
105+
]
106+
}
107+
108+
tags {
109+
Name = "rabbitmq nodes"
110+
}
111+
}
112+
113+
data "template_file" "cloud-init" {
114+
count = "${var.count}"
115+
template = "${file("${path.module}/cloud-init.yaml")}"
116+
117+
vars {
118+
majority = "${floor(var.count / 2) + 1}"
119+
nodes = "${join(", ", formatlist("'%s'", data.null_data_source.nodes.*.inputs.node_name))}"
120+
hostname = "${element(data.null_data_source.nodes.*.inputs.domain, count.index)}"
121+
secret_cookie = "${var.rabbitmq_secret_cookie}"
122+
admin_password = "${var.admin_password}"
123+
rabbit_password = "${var.rabbit_password}"
124+
message_timeout = "${3 * 24 * 60 * 60 * 1000}" # 3 days
125+
}
126+
}
127+
128+
resource "aws_instance" "rabbitmq" {
129+
count = "${var.count}"
130+
subnet_id = "${element(var.subnet_ids, count.index)}"
131+
ami = "${data.aws_ami_ids.ami.ids[0]}"
132+
instance_type = "${var.instance_type}"
133+
key_name = "${var.ssh_key_name}"
134+
vpc_security_group_ids = ["${aws_security_group.rabbitmq_nodes.id}"]
135+
associate_public_ip_address = false
136+
user_data = "${element(data.template_file.cloud-init.*.rendered, count.index)}"
137+
tags {
138+
Name = "rabbitmq-${count.index}"
139+
}
140+
}
141+
142+
resource "aws_route53_record" "rabbit" {
143+
count = "${var.count}"
144+
zone_id = "${var.route53_zone_id}"
145+
name = "rabbit-${count.index}"
146+
type = "A"
147+
ttl = "300"
148+
records = ["${element(aws_instance.rabbitmq.*.private_ip, count.index)}"]
149+
}
150+
151+
resource "aws_elb" "elb" {
152+
name = "rabbit-elb"
153+
154+
listener {
155+
instance_port = 5672
156+
instance_protocol = "tcp"
157+
lb_port = 5672
158+
lb_protocol = "tcp"
159+
}
160+
161+
listener {
162+
instance_port = 15672
163+
instance_protocol = "http"
164+
lb_port = 80
165+
lb_protocol = "http"
166+
}
167+
168+
health_check {
169+
healthy_threshold = 2
170+
unhealthy_threshold = 2
171+
timeout = 3
172+
target = "TCP:5672"
173+
interval = 30
174+
}
175+
176+
instances = ["${aws_instance.rabbitmq.*.id}"]
177+
subnets = ["${var.subnet_ids}"]
178+
idle_timeout = 3600
179+
internal = true
180+
security_groups = ["${aws_security_group.rabbitmq_elb.id}"]
181+
182+
tags {
183+
Name = "rabbitmq"
184+
}
185+
}
186+
187+
resource "aws_route53_record" "elb" {
188+
zone_id = "${var.route53_zone_id}"
189+
name = "rabbit"
190+
type = "CNAME"
191+
ttl = "300"
192+
records = ["${aws_elb.elb.dns_name}"]
193+
}

variables.tf

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
variable "access_key" {}
2+
variable "secret_key" {}
3+
variable "region" {}
4+
variable "vpc_id" {}
5+
variable "ssh_key_name" {}
6+
variable "count" {
7+
description = "Number of RabbitMQ nodes"
8+
default = 2
9+
}
10+
variable "subnet_ids" {
11+
description = "Subnets for RabbitMQ nodes"
12+
type = "list"
13+
}
14+
variable "security_group_ids" {
15+
description = "Security groups which should have access to ELB (amqp + http ports) and nodes (ssh port)"
16+
type = "list"
17+
}
18+
variable "route53_zone_id" {
19+
description = "Route53 internal zone"
20+
}
21+
variable "admin_password" {
22+
description = "Password for 'admin' user"
23+
default = "password"
24+
}
25+
variable "rabbit_password" {
26+
description = "Password for 'rabbit' user"
27+
default = "password"
28+
}
29+
variable "rabbitmq_secret_cookie" {
30+
default = "supersecretcookie"
31+
}
32+
variable "instance_type" {
33+
default = "t2.small"
34+
}

0 commit comments

Comments
 (0)