🤖

TerraFormでAmazon MQ(RabbitMQ)環境作成

2021/10/14に公開

はじめに

メディアエンジン株式会社のナバロです!

弊社では、たくさんのデータを活用して、メディア運営を行っております。
そのため、たくさんのデータを取得する基盤システムが有り、分散処理を行っております。

分散処理の基盤は Go 言語なのですが、今回新たに、機械学習システムを導入することになり、
Python で実装されていたので、言語を超えたシステムのやりとりに AMazonMQ(RabbitMQ) というメッセージキューイング処理をしてくれるシステムを導入しました。

弊社は、システム全般 TerraForm で管理してるのですが、RabbitMQ を立ち上げる際に
日本語で解説されている記事が少なかったので、書いてみることにしました!

システムイメージ

ここに来ている方は、RabbitMQ を知っている方がほとんどかと思いますが、
知らない方のために、どのように活用しているのかイメージ図を作成しました。

RabbitMQ を Go と Python の間に挟むことで、別言語間、別サーバ間でのデータのやり取りが高パフォーマンスで実現できます。

※Amazon SQS というシンプルで使い勝手のいいサービスもあるのですが、配信したジョブの監視などをしたい場合、自前実装が必要になるので、
そこのあたりがすでに実装されていた Amazon MQ(RabbitMQ)を選定しました。

TerraForm ソースコード解説

今回はこちらを参考に設定してみました
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/mq_broker

resource "aws_mq_broker" "main" {
  broker_name = "main"

  engine_type        = "RabbitMQ"
  engine_version     = "3.8.22"
  host_instance_type = "mq.t3.micro" # 本番は値段が跳ね上がるが mq.m5.large を使うしかなさそう。
  subnet_ids         = [aws_subnet.private_mq.id]
  security_groups    = [aws_security_group.rabbitmq.id]
  # publicly_accessible = true # 基本は同一VPCからのアクセスしか受け付けないので、テストなどで、ローカル環境からアクセスしたいときなどは true にしておく

  user {
    username = "admin"
    password = random_password.rabbitmq_password.result # パスワードはランダム生成
  }
}

resource "aws_security_group" "rabbitmq" {
  name   = "rabbitmq"
  vpc_id = aws_vpc.main.id
  ingress {
    from_port   = 5671 # rabbitmqの基本ポート
    to_port     = 5671
    protocol    = "tcp"
    cidr_blocks = ["10.0.1.0/24", "10.0.2.0/24"] # 特定のサブネットのみ許可。Goサーバーとpythonのサーバーの置いてあるサブネットを許可
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["10.0.1.0/24", "10.0.2.0/24"] # 特定のサブネットのみ許可。Goサーバーとpythonのサーバーの置いてあるサブネットを許可
  }

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

resource "random_password" "rabbitmq_password" {
  length           = 16
  special          = true
  override_special = "_@/'"
  lifecycle {
    ignore_changes = all
  }
}

メインのリソースの準備はこれぐらいです。

パラメーターストアにエンドポイントなどを保存

自分の場合は更に AWS のパラメーターストアを使って、認証情報やエンドポイントを保存するようにしています。
※パラメーターストアに値を保存しておくと、ECS などのコンテナに値を注入できて便利です。

resource "aws_ssm_parameter" "mq_password" {
  name  = "/mq/mq_password"
  type  = "SecureString"
  value = random_password.rabbitmq_password.result
}

# rabbitmqのエンドポイント
resource "aws_ssm_parameter" "mq_url" {
  name  = "/mq/mq_url"
  type  = "SecureString"
  # 実は aws_mq_broker.main.instances.0.endpoints でも取得できるが、事前に認証情報を組み込んだほうが使いやすかったのでこうしています。
  value = "amqps://admin:${aws_ssm_parameter.mq_password.value}@${aws_mq_broker.main.id}.mq.ap-northeast-1.amazonaws.com:5671"
}

# rabbitmqの管理GUI画面のエンドポイント
resource "aws_ssm_parameter" "mq_admin_url" {
  name  = "/mq/mq_admin_url"
  type  = "SecureString"
  # これも実は aws_mq_broker.main.instances.0.console_url でも取得できるが、事前に認証情報を組み込んだほうが使いやすかったのでこうしています。
  value = "https://admin:${aws_ssm_parameter.mq_password.value}@${aws_mq_broker.main.id}.mq.ap-northeast-1.amazonaws.com"
}

おわりに

RabbitMQ を使うことで高パフォーマンスのメッセージキューイングシステムを構築できました!

少し宣伝入りますが・・・!
弊社は少人数のエンジニアチームながら、日々大量のデータと格闘しています。
ビッグデータの活用に興味ある人、機械学習興味ある人など
話を聞いてみたい人などいればぜひご連絡ください!

弊社チームの紹介ページがあるのでぜひ、見に来てください!
https://mediaengine.notion.site/ba128c5708fc480198f5d8c9440a7062

Discussion