💬

Mattermost を Amazon Lightsail Container Service に載せる (続き)

2022/08/29に公開

前回の記事はこちら。
https://zenn.dev/fehde/articles/ad386337cb02c9

これまで Slack の代替として Mattermost を利用できないか、検討を進めてきました。
構成は下記のとおり。

  • DB: postgresql
  • 本体: mattermost
  • リバースプロキシ: nginx
    前回はこれらをまとめて Lightsail Container に構成しました。
    ただ、Lightsail Container はステートレスサービスでデータを保持することができないため、このままでは再起動する度に初期化されることに・・
    これらのデータを保持するためには、データベースおよびファイルの永続化が必要となります。

今回は Amazon Lightsail のデータベースサービス、ストレージサービスを利用して、データ永続化を実現していきます。
目指す構成は下記のとおり。

  • Amazon Lightsail Database (Mattermost データ保持)
  • Amazon Lightsail Storage (Mattermost 添付ファイル保持)
  • Amazon Lightsail Container (Mattermost 本体・リバースプロキシ Nginx)
    ※この環境の場合 SSL も自動付帯してくるのでリバースプロキシは実質不要かも・・

実施した手順をざっくり記載していきます。

サービス作成

1. データベースサービスの作成

マネージドデータベースに移行するため、Lightsail のサイトでサービスを作成します。

サービスが作成されるまで少し時間が掛かります。
最小プランなら初めの 3 ヶ月無料、やったね!

サービス名は database-mm-limited-20221031 としました。
初期データベース名を指定しないとデフォルトで dbmaster データベースが作成されます。

2. ストレージサービスの作成

続けてストレージサービスを作成します。

サービス名は bucket-mm-limited-20230731 としました。
こちらも最小プランなら初めの 12 ヶ月無料、やったね!

データベースの永続化

まずは簡単そうなデータベースの永続化をしてみます。

1. 環境変数の調整

Mattermost に設定する環境変数をローカルデータベースからマネージドデータベースに振り替えます。なお、パスワードは URL Encode しています。

./.env
MM_SQLSETTINGS_DRIVERNAME=postgres
MM_SQLSETTINGS_DATASOURCE=postgres://dbmasteruser:6O%26UQ%3Ao%3Can%25A%25V%2BPgGaYaO%7Bb%7EZ3%3Fr%7C%26v@ls-7906fb576d40bdfacdbf1036c3b5c0d8ee91b3c4.cg2ey0mxhfyi.ap-northeast-1.rds.amazonaws.com:5432/dbmaster?sslmode=disable&connect_timeout=10

2. GitHub Workflow の調整

Workflow が走る際に、デプロイコマンドに環境変数を繋げられるように調整します。

./.github/workflows/deploy.yml
...
jobs:
  deploy:
    steps:
      - name: Make deploy setting
        run: |
	  ...
          | jq --arg MM_SQLSETTINGS_DATASOURCE $MM_SQLSETTINGS_DATASOURCE '.containers.mattermost.environment.MM_SQLSETTINGS_DATASOURCE=$MM_SQLSETTINGS_DATASOURCE' \
          ...

3. データベースの確認

デプロイするとマネージドデータベースにテーブルが作成されます。とてもスムーズでした!

Mattermost 設定と添付ファイルの永続化

続けてストレージサービスに Mattermost の設定ファイルを保持できるよう設定します。
Mattermost の設定ファイルのダウンロード・アップロードやデプロイ用に IAM ユーザーを作成し、それとは別に Mattermost のストレージ設定用にバケットのアクセスキーを発行します。

1. IAM ポリシーとユーザーの作成

lightsail へのアクセスポリシーを作成します。

% aws iam create-policy \
> --policy-name LightsailFullAccessPolicy \
> --policy-document \
> '{
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Action": "lightsail:*",
>             "Resource": "*"
>         }
>     ]
> }'
{
    "Policy": {
        "PolicyName": "LightsailFullAccessPolicy",
        "PolicyId": "ANPATRA4OQAQGJU4G2OLZ",
        "Arn": "arn:aws:iam::242725322784:policy/LightsailFullAccessPolicy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2022-08-22T09:19:54+00:00",
        "UpdateDate": "2022-08-22T09:19:54+00:00"
    }
}

GitHub Actions からのデプロイや、設定ファイルのダウンロード・アップロード用の IAM ユーザーを作成します。ユーザー名は mattermost としました。

% aws iam create-user --user-name mattermost
{
    "User": {
        "Path": "/",
        "UserName": "mattermost",
        "UserId": "AIDATRA4OQAQHMQYYHE6H",
        "Arn": "arn:aws:iam::242725322784:user/mattermost",
        "CreateDate": "2022-08-22T09:37:53+00:00"
    }
}

IAM ユーザーに作成したポリシー及び S3 フルアクセスポリシーを割り当てます。

% aws iam attach-user-policy --user-name mattermost --policy-arn "arn:aws:iam::242725322784:policy/LightsailFullAccessPolicy"
% aws iam attach-user-policy --user-name mattermost --policy-arn "arn:aws:iam::aws:policy/AmazonS3FullAccess"
% aws iam list-attached-user-policies --user-name mattermost
{
    "AttachedPolicies": [
        {
            "PolicyName": "AmazonS3FullAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/AmazonS3FullAccess"
        },
        {
            "PolicyName": "LightsailFullAccessPolicy",
            "PolicyArn": "arn:aws:iam::242725322784:policy/LightsailFullAccessPolicy"
        }
    ]
}

作成した IAM ユーザーのアクセスキーを作成します。

% aws iam create-access-key --user-name mattermost
{
    "AccessKey": {
        "UserName": "mattermost",
        "AccessKeyId": "AKIATRA4OQAQA5KSOOG6",
        "Status": "Active",
        "SecretAccessKey": "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",
        "CreateDate": "2022-08-22T09:40:35+00:00"
    }
}

2. Bucket アクセスキーの作成

Mattermost に設定する添付ファイル操作用のバケットアクセスキーを作成します。

% aws lightsail create-bucket-access-key --region ap-northeast-1 --bucket-name bucket-mm-limited-20230731
{
    "accessKey": {
        "accessKeyId": "AKIA4N7DYQ46NAYM45UX",
        "secretAccessKey": "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",
        "status": "Active",
        "createdAt": "2022-08-18T12:57:58+09:00"
    },
    "operations": [
        {
            "id": "9a740493-91d0-4f2c-8802-fb7bbd5b6e7e",
            "resourceName": "bucket-mm-limited-20230731",
            "resourceType": "Bucket",
            "createdAt": "2022-08-18T12:57:58.917000+09:00",
            "location": {
                "availabilityZone": "all",
                "regionName": "ap-northeast-1"
            },
            "isTerminal": true,
            "operationDetails": "CreateBucketAccessKey",
            "operationType": "CreateBucketAccessKey",
            "status": "Succeeded",
            "statusChangedAt": "2022-08-18T12:57:58.917000+09:00",
            "errorCode": "",
            "errorDetails": ""
        }
    ]
}

3. アクセスキーの設定

IAM ユーザーとバケットのアクセスキーを Git Actions の環境変数に設定します。

AWS_ACCESS_KEY_ID=AKIATRA4OQAQA5KSOOG6
AWS_SECRET_ACCESS_KEY=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
MM_FILESETTINGS_AMAZONS3ACCESSKEYID=AKIA4N7DYQ46NAYM45UX
MM_FILESETTINGS_AMAZONS3SECRETACCESSKEY=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

Workflow が走る際に、デプロイコマンドに環境変数を繋げられるように調整します。

./.github/workflows/deploy.yml
...
jobs:
  deploy:
    steps:
      - name: Make deploy setting
        run: |
	  ...
          | jq --arg AWS_ACCESS_KEY_ID ${{secrets.BUCKET_ACCESS_KEY}} '.containers.mattermost.environment.AWS_ACCESS_KEY_ID = $AWS_ACCESS_KEY_ID' \
          | jq --arg AWS_SECRET_ACCESS_KEY ${{secrets.BUCKET_SECRET_KEY}} '.containers.mattermost.environment.AWS_SECRET_ACCESS_KEY = $AWS_SECRET_ACCESS_KEY' \
          | jq --arg AWS_ACCESS_KEY_ID ${{secrets.BUCKET_ACCESS_KEY}} '.containers.mattermost.environment.MM_FILESETTINGS_AMAZONS3ACCESSKEYID = $AWS_ACCESS_KEY_ID' \
          | jq --arg AWS_SECRET_ACCESS_KEY ${{secrets.BUCKET_SECRET_KEY}} '.containers.mattermost.environment.MM_FILESETTINGS_AMAZONS3SECRETACCESSKEY = $AWS_SECRET_ACCESS_KEY' \
          ...

4. Mattermost 設定ファイルの保持

Mattermost の設定テンプレートファイルに S3 の設定を記載します。

./mattermost/config.template.json
{
    "FileSettings": {
        "DriverName": "amazons3",
        "AmazonS3AccessKeyId": "",
        "AmazonS3SecretAccessKey": "",
        "AmazonS3Bucket": "bucket-mm-limited-20230731",
        "AmazonS3PathPrefix": "",
        "AmazonS3Region": "ap-northeast-1",
        "AmazonS3Endpoint": "s3.ap-northeast-1.amazonaws.com",
        "AmazonS3SSL": true,
        "AmazonS3SignV2": false,
        "AmazonS3SSE": false,
        "AmazonS3Trace": false
    },
}

Docker 起動時に設定ファイルを Storage からダウンロードするコマンドを組み込みます。

./mattermost/entrypoint.sh
% aws s3api get-object --bucket ${AWS_S3_BUCKET:xxx} --key mm_config /mattermost/config/config.json

Mattermost のシステムコンソールから設定を変更すると設定ファイル ./config/config.json に変更が適用されるため、Docker 内で定期的に設定ファイルをアップロードするよう cron を設定します。supervisord を用いてコンテナ内で mattermostcron を同時に起動するようにしました。

corontab
25-55/30 * * * * aws s3api put-object --bucket $AWS_S3_BUCKET --key mm_config --body /mattermost/config/config.json --acl bucket-owner-full-control

以上で設定は完了とします。(最後端折りました・・)

まとめ

今回の設定で、データベースは Emergency Restore 機能で 5 分毎にスナップショットが作成されます。高可用性のためマルチ AZ プランもありますが、筆者の用途ではそこまでは不要です。
ストレージは設定ファイル保存と添付ファイル用とし、コンテナ環境でも Mattermost のデータ永続化を実現することができました。

Lightsail Container ではアウトバウンドポートは一つしか持てないため RTC 等は利用できないですが、Slack ライクのチャットソフトとしてのみであれば、これで最低限運用は出来るのではないでしょうか。
コンテナ環境なのでセキュリティ的にも少し気楽に運用できます。

今後はインスタンスサービスにも載せて検討を進めたいと思いますが、続きを書くかは不明。
(まずこの記事をもっと充実させろと言われそうですし)
それではまた!

Discussion