Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Redmine on Fargate でサーバーレスチケット駆動開発

この記事について

「AWS & Game Advent Calendar 2020」3日目はゲーム開発に役立つコンテナ技術についてご紹介します。

image.png
大規模なゲーム開発においてはプロジェクト管理するツールとして Redmine というソフトウェアを利用される方は数多くいらっしゃいます。ゲームを開発する過程では頻繁に変更が発生するため、その作業工程を管理し、往々にして人数が膨れ上がりがちなプロジェクトメンバーに最新の状況をシェアする必要があります。

デバッグ時に発見されたバグはチケットの形で一覧化され、1つ1つを作業として割り振っていくチケット駆動開発のスタイルはアジャイル開発と相性もよく、多くのゲーム開発会社で取られている開発スタイルとなります。

ゲーム開発において身近な存在である Redmine ですが、下手をするとプロジェクト毎にサーバーが乱立しがちとなり、その構築や運用のための工数が気付かぬうちに膨れ上がるケースがあります。

このような背景から、Redmine をコンテナ化することで構築手順を減らし、運用負荷を軽減させたいと考える現場の声も多く、そんな要望に答えるべくインターネット上では様々な記事を見つけることができます。しかし、現存する多くの記事では docker-compose 等を使って、仮想サーバー上での運用方法を紹介しているものが多く、依然としてインフラエンジニアに運用の負担がかかってしまいます。

image.png

そこで、この記事では AWS Fargate を使ってサーバーレスにコンテナ化された Redmine を構築 する手順についてご紹介します。

AWS Fargate では、インスタンスの選択やクラスター容量のスケーリングなしに、適切なコンピューティング容量を割り当てることができます。そのため、サーバーのスケーリング、パッチ適用、保護、管理にまつわる運用上のオーバーヘッドは発生しません。
最小限のリソースで Redmine サーバーを運用できるため、運用コストだけでなくインフラ費用も最適化することができます。

アーキテクチャについて

アーキテクチャとコンテナイメージは次に示す構成を用います。
image.png

Dockerfile

FROM redmine:4.1-passenger

COPY config/configuration.yml config
ENV TZ=Asia/Tokyo\
    REDMINE_PLUGINS_MIGRATE=true

RUN set -eux; \
    # install plugins
    git clone --depth 1 https://github.com/akiko-pusu/redmine_banner.git plugins/redmine_banner; \
    git clone --depth 1 https://github.com/akiko-pusu/redmine_issue_templates.git  plugins/redmine_issue_templates; \ 
    \
    # install themes
    git clone -b redmine4.1 --depth 1 https://github.com/farend/redmine_theme_farend_bleuclair.git public/themes/bleuclair; \
    \
    # change owner 
    chown -R redmine:redmine plugins/ public/themes/;\
    # install gems
    bundle install;

ポイントとなる点は次の3点です。
- Docker公式の Redmine コンテナに Template と Plugin を埋め込み、コンテナ起動時に rake redmine:plugins:migrate を実行する
- 添付ファイルを EFS、データベースを RDB、ログを CloudWatchLogs に流すことで、Stateless なアプリケーションにする
- メールは SES から送信を行う(※今回の説明の範囲外)

プラグインやテーマ

Redmineはバックアップのために次のファイルをコンテナの外に保存しておく必要があります。

redmine files(/usr/src/redmine/files)
redmine plugins(/usr/src/redmine/plugins)
redmine public/themes(/usr/src/redmine/public/themes)
redmine config(/usr/src/redmine/config/configuration.yaml)

ここで、plugins と themes、config はコンテナ実行中には不変であるものとすると、外に出しておくべきファイルは添付ファイル(redmine files)だけとなります。

(Redmine on Fargate で Plugin を更新させるための補足)

ここで問題となるのは Fargate ではホストマシンに直接 SSH することは出来ない点です。
そのため、起動中のコンテナに対してrake コマンドや railsコマンドを実行しないよう意識した構成が必要となります。

今回はこの問題の解決策として、Dockerfile内で Plugin と Theme を用意(git clone)し、コンテナの環境変数にREDMINE_PLUGINS_MIGRATE = true を与えることで、rake redmine:plugins:migrate コマンドと db:migrate コマンドをコンテナ起動時に実行し、Plugins/Themes に変更があれば適宜 DB に状態を反映させています。

REDMINE_PLUGINS_MIGRATE

This variable allows you to control if rake redmine:plugins:migrate is run on container start. Just set the variable to a non-empty string like 1 or true and the migrate script will be automatically run on every container start. It will be run after db:migrate.
https://hub.docker.com/_/redmine

添付ファイル

添付ファイルに関してはコンテナ外に出しておく必要があるため、2020年4月のUpdateであるFargateにEFSをマウントする機能を使います。
Fargate のタスク定義で、ECSコンテナのボリュームマウントからマウントされたEFSを参照させます。

ログファイル

Redmine では log/production.log に Redmine へのアクセス情報といったログがファイルに追記されていきます。コンテナを再起動すると、このログファイルも消滅してしまうため、外に出しておく必要があります。

Docker 公式の redmine コンテナでは、production.log の代わりに stdout にログ出力がされるよう変更がされているため、stdout の出力を awslogs ドライバーが拾い、CloudWatch Logs にログを送信します。
https://github.com/docker-library/redmine/pull/146

メールサーバーの設定

Redmine ではメールサーバーを使ってメールの送信を行います。Amazon SES というEメール送信のマネージドサービスを使うことで、高可用性かつ低価格なメールサーバーを使うことができます。

今回の記事では SES の設定については省略するため、下記のような記事をご参照願います。
-備忘録- AWS SES を使ってRedmineからのメールを送る
全部AWSでRedmineをサクッと構築する

ここからは、Redmine を Fargate 上で動作させるための構築手順について見ていきましょう。

1.ネットワーク、ファイルシステム、データベースの設定

1.1 VPC の作成

まずは VPC Wizard から VPC を作成します。
image.png
image.png

つぎに、パブリックサブネットを1つ追加します。後ほど ALB の作成で 2 AZ のサブネットが必要となるため、アベイラビリティーゾーンをパブリックサブネット1と違うものを選ぶよう、注意します。(今回はap-northeast-1とap-northeast-1c)
image.png
サブネット新規作成後、ルートテーブルの関連付けを編集して、インターネットゲートウェイへのルーティングが含まれるようにします。
image.png

1.2 SecurityGroup の作成

EC2 コンソールから SecurityGroup を作成します。名前とプロトコル、ソースは次のように設定します。

名前 プロトコル ソース
redmine-alb-sg TCP 80(HTTP) 0.0.0.0/0
redmine-fargate-sg TCP 3000 redmine-alb-sg
redmine-efs-sg TCP 2049(NFS) redmine-fargate-sg
redmine-db-sg TCP 3306(Aurora) redmine-fargate-sg

1.3 ALBの作成

EC2 コンソールから Application Load Balancer を作成していきます。
image.png
後ほど ECS サービスを設定するために、ALB作成完了後にリスナーを削除します。
image.png

1.4 EFS の作成

EFS コンソールから添付ファイルの保存先となるファイルシステムを作成していきます。
マウントターゲットのセキュリティグループをredmine-efs-sgとすることで、Fargate コンテナからの通信が可能となります。
image.png

1.5 RDS の作成

次の設定値に従い、MySQLのデータベースを作成していきます。

名前 設定値
DBエンジンのバージョン MySQL 5.7.31
DBインスタンスのクラス db.t2.micro
DBインスタンス識別子 fargate-db
マスターユーザーの名前 redmineuser
マスターパスワード redminepassword
VPC redmine
データベースの名前 redmine

DB 作成後、セキュリティーグループをredmine-db-sgに変更します。
また、後ほど RDS Endpoint を利用するため値を控えておきます。

2.コンテナの設定

2.1 Dockerfile の記述

次のような配置でDockerfile と configuration.yml を作成します。

フォルダ構成
├── Dockerfile
└── config
    └── configuration.yml

Dockerfile の詳細については、Dockerfile をご参照ください。
configuration.ymlの詳細についてはメールサーバーの設定をご覧下さい。(下記コードはサンプルとなります)

default:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      address: mail.example.com
      port: 25
      authentication: :login
      domain: redmine.example.com
      user_name: myaccount
      password: password

2.2 ECR レポジトリの作成

ECR コンソールからリポジトリを作成します。
image.png

作成したリポジトリのプッシュコマンドを表示し、Dockerfile と同じディレクトリで実行します。
image.png

    // docker login
    aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <account_number>.dkr.ecr.ap-northeast-1.amazonaws.com
    // build container image
    docker build -t redmine-fargate .
    // taging to image
    docker tag redmine-fargate:latest <account_number>.dkr.ecr.ap-northeast-1.amazonaws.com/redmine-fargate:latest
    // push image to ECR repository
    docker push <account_number>.dkr.ecr.ap-northeast-1.amazonaws.com/redmine-fargate:latest

3.ECS Fargate の設定

3.1 ECS Cluster の作成

ECS コンソールから AWS Fargate(ネットワーキングのみ) のクラスターを作成します。
image.png

3.2 ECS タスク定義の作成

Fargate のタスク定義を作成します。

名前 設定値
タスク定義名 redmine-fargate-taskdef
タスク実行ロール ecsTaskExecutionRole
タスクメモリ 1GB
タスク CPU 0.25vCPU

3.3 ボリュームの追加

タスク定義に EFS ボリュームを追加します。
image.png

3.4 コンテナの追加

ECR に Push したコンテナを指定していきます。

名前 設定値
コンテナ名 redmine-fargate-container
イメージ <account_number>.dkr.ecr.ap-northeast-1.amazonaws.com/redmine-fargate:latest
ポートマッピング 3000
マウントポイント redmine-efs
コンテナパス /usr/src/redmine/files

そして、環境変数として DB の接続情報を記入していきます。
※本番環境では AWS SecretsManager の利用をご検討ください

キー
REDMINE_DB_DATABASE redmine
REDMINE_DB_ENCODING utf8mb4
REDMINE_DB_MYSQL <RDS Endpoint>
REDMINE_DB_USERNAME redmineuser
REDMINE_DB_PASSWORD redminepass

3.5 ECS サービスの作成

ECS コンソールから ECS サービスを作成します。
今回は EFS を利用するため、プラットフォームバージョンを 1.4.0 にする必要があります。

名前 設定値
起動タイプ FARGATE
タスク定義 redmine-fargate-taskdef
プラットフォームのバージョン 1.4.0
クラスター redmine-fargate
サービス名 redmine-fargate-service
タスクの数 2

VPCやロードバランサーの設定も進めていきます。

名前 設定値
クラスターVPC redmine
サブネット パブリックサブネット1、パブリックサブネット2
セキュリティグループ redmine-fargate-sg
ヘルスチェックの猶予期間 30
ロードバランサーの種類 Application Load Balancer
ロードバランサー名 fargate-alb
プロダクションリスナーポート 80
プロダクションリスナーポート 80

image.png

ECS サービス作成後、Task がヘルスチェックに失敗して落とされ続ける場合は、EC2 コンソールから ECS サービスに紐づく TargateGroup のヘルスチェックを変更してみてください。
image.png

ここまでの作業で Redmin onFargate 構築は終わりです。
最後に動作確認をしていきます。

4.動作確認

早速、作成した Redmine を実際に触ってみます。
ALB のドメイン名にアクセスすると、Redmine の TOP 画面を開くことができます。
ログインを選び、ID:admin、パスワード:admin を入力します。ログイン後はパスワードの変更を求められます。
image.png

まずは Theme をデフォルトから変更してみましょう。
トップナビゲーションから管理→設定→表示→テーマから、Dockefile で記述した Bleuclair を選択してみます。
image.png

無事に変更することができました。テーマを追加する場合は Dockerfile に記述し、コンテナを Build&Pushし、ECS Service を更新します。
image.png

次にプラグインを確認してみます。まずは 管理→プラグイン を表示して、Redmine Banner Plugin がインストールされていることを確認します。
image.png

管理→バナーからプラグインを有効化してみます。
image.png

無事に画面上部にバナーが表示されるようになりました!
image.png

他にも、添付ファイルをアップロードしてみたり、ECS Task をあえて停止させてみる、ALB+ACM を使って HTTPS 化を行うなど今回作った環境をご自由にお試し頂けますと幸いです。

おわりに

ゲーム開発に必要なシステムをサーバーレスにコンテナ化して運用する方法についてご紹介いたしました。
Redmine 以外にも Fargate 上でアプリケーションを動かす際の参考となりましたら幸いです。

それでは、残りの年末もよいコンテナ×サーバーレスライフをお過ごし下さい!

(免責) 本記事の内容はあくまでも個人の意見であり、所属する企業や団体とは関係がございません。

参考資料

Redmine.JP https://redmine.jp/
最新の Redmine 4 を Docker 公式イメージで運用する https://qiita.com/bezeklik/items/b9d75ee74e0ae4c6d42c
コンテナでRedmineの環境構築をやってみた https://qiita.com/asubee/items/db6985549d83334d0a46
Redmine(Docker)環境構築メモ https://qiita.com/KWS68810828/items/962ff0db367d8ea2473a

cataiiwai
4つ繋がると消えるネコ
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away