継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

redash のコンテナログを CloudWatch Logs に出力する

タダです.

redash を EC2 上のコンテナで動かしているのですが,ログを外出ししていなかったので何かあったらいちいちサーバーの中に入る必要がありました.そこで,CloudWatch Logs に出して見えた方がいいと思い,検証したのでこの記事でまとめていきます.なお,redash のバージョンは8.0.0.b32245の環境で確認しています.

事前準備

事前準備として EC2 の IAM ロールの権限に CloudWatch Logs へのアクセス権限をつけていきます.ドキュメント に沿って次のポリシーをつけました.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

次に,ログを保管する CloudWatch Logs のロググループを作っておきます.今回は /var/lib/docker/redash/logs というのを作りました.以上で事前準備が完了です.

redash の設定

続いてコンテナ側の CloudWatch Logs 設定を定義していきます.コンテナのログは/var/lib/docker/containars/[コンテナ ID]/配下にでており,EC2 のログとは異なりコンテナのログは awslogsロギングドライバを使って出力されているログを格納するので CloudWatch Agent の導入は不要です.redash のコンテナはdocker-compose.ymlで管理されているので,ドキュメントに沿って定義を追加します.今回は4つのコンテナのログを CloudWatch Logs に出力します.

  • redash_server_1
  • redash_scheduled_worker_1
  • redash_scheduler_1
  • redash_adhoc_worker_1

servicesセクション以下で,loggingセクションを追加し,CloudWatch Logs 設定を記載します.awslogs-region でリージョン,awslogs-groupでロググループ名,tagでログストリーム名を指定しています.tagでの注意点として CloudWatch Logs APIがストリーム名に:をサポートしていないため,Docker イメージがalpine:latestな場合 {{ .ImageName }}tagで指定するとエラーになります.今回のtagではredash/redash_8.0.0.b32245-コンテナ名-コンテナ IDというログストリーム名になるよう指定しています.

version: "2"
x-redash-service: &redash-service
  image: redash/redash:8.0.0.b32245
  depends_on:
    - postgres
    - redis
  env_file: /opt/redash/env
  restart: always
services:
  server:
    <<: *redash-service
    command: server
    ports:
      - "5000:5000"
    environment:
      REDASH_WEB_WORKERS: 4
      GUNICORN_CMD_ARGS: "--timeout 90"
    logging:
      driver: awslogs
      options:
        awslogs-region: ap-northeast-1
        awslogs-group: /var/lib/docker/redash/logs
        tag: '{{ with split .ImageName ":" }}{{join . "_"}}{{end}}-{{.Name}}-{{.ID}}'
  scheduler:
    <<: *redash-service
    command: scheduler
    environment:
      QUEUES: "celery"
      WORKERS_COUNT: 1
    logging:
      driver: awslogs
      options:
        awslogs-region: ap-northeast-1
        awslogs-group: /var/lib/docker/redash/logs
        tag: '{{ with split .ImageName ":" }}{{join . "_"}}{{end}}-{{.Name}}-{{.ID}}'
  scheduled_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "scheduled_queries,schemas"
      WORKERS_COUNT: 1
    logging:
      driver: awslogs
      options:
        awslogs-region: ap-northeast-1
        awslogs-group: /var/lib/docker/redash/logs
        tag: '{{ with split .ImageName ":" }}{{join . "_"}}{{end}}-{{.Name}}-{{.ID}}'
  adhoc_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "queries"
      WORKERS_COUNT: 2
    logging:
      driver: awslogs
      options:
        awslogs-region: ap-northeast-1
        awslogs-group: /var/lib/docker/redash/logs
        tag: '{{ with split .ImageName ":" }}{{join . "_"}}{{end}}-{{.Name}}-{{.ID}}'
  redis:
    image: redis:5.0-alpine
    restart: always
  postgres:
    image: postgres:9.6-alpine
    env_file: /opt/redash/env
    volumes:
      - /opt/redash/postgres-data:/var/lib/postgresql/data
    restart: always
  nginx:
    image: redash/nginx:latest
    ports:
      - "80:80"
    depends_on:
      - server
    links:
      - server:redash
    restart: always

docker-compose up -d で再起動します.CloudWatch Logs の画面を確認すると4つのログストリームができているので意図通りです.

# docker-compose up -d
redash_postgres_1 is up-to-date
redash_redis_1 is up-to-date
Recreating redash_server_1           ... done
Recreating redash_scheduled_worker_1 ... done
Recreating redash_adhoc_worker_1     ... done
Recreating redash_scheduler_1        ... done
Recreating redash_nginx_1            ... done

CloudWatch Logs の画面 f:id:sadayoshi_tada:20210730065524p:plain

まとめ

EC2 上に出ていた redash のコンテナログを CloudWatch Logs に出してみました.EC2 のサーバーログを出すより簡単にログを出すことができてログを確認する時は AWS コンソールか VSCode などから確認できるので手間が減るのでありがたい機能です.

July Tech Festa 2021 に『今日から実践!継続的に自分の軌跡を残す方法』で登壇した

タダです.

7/18 開催の「July Tech Festa 2021」にて「今日から実践!継続的に自分の軌跡を残す方法」と題して自分が取り組んできた継続的アウトプットのやり方や取り組んだことで起きた変化をお話しさせていただきました.この記事で発表を振り返ってきます.

techfesta.connpass.com

発表資料

発表資料はこちらです.

発表動画

発表動画はこちらです.

www.youtube.com

当日の発表はYouTubeアーカイブされてるので他のセッションも見えてなくて残念...と思っている方は是非登録することをオススメします.

www.youtube.com

他のセッションの発表資料も connpass の資料一覧から見ることができます.

techfesta.connpass.com

発表の振り返り

JTF への登壇は今年の登壇に続いて2回目でした.オンラインの登壇も何回か経験させてもらっていたので,緊張はそこまでしてなかったような感覚だったのですが,発表では結構カミカミでしたし,早口になっていたりする部分もあって聞きづらいところあったら申し訳ないです🙇‍♂️

さて,発表の補足をしていきます.習慣化の1つ目の取り組みで続けやすい自分ルールを作るっていうので AWS 公式ブログでアップデートをサマリーするっていうのは習慣化のきっかけにはなったのですが,週1に必ず更新するっていう強い意思が欠如していた時があり,今週は更新しなくていいだろとか今週はアップデートまとめられなかったけど来週まとめよみたいなだらけていた時期もありました.この点,カックさんから教わった,記事更新のペースにおける例外を設けないというアンチパターンになっていたかなと思うのでもし発表見られてやってみたいと思う方いらしたらお気をつけください.

発表でも触れましたが,Zenn とはてなブログの使い分けが結構カミカミだったので改めて補足します.発表後の質問でもいただきましたが,Zenn は GitHub に記事をあげれば自動で公開してくれるのが体験としてよくて,検証や調査したトピックを Zenn に上げて,一通りメモを整理してはてなブログに書くのが効率も良く一度 Zenn にまとめているから記事も構成しやすくてお勧めです.

いくつか継続するためにやってきたことをお話しさせてもらったのですが,継続のモチベーションになってるのはアウトプットを楽しめるのが大事になってくるのかなと思います.ブログを良くしたくてブログのことを考える時間が増えて,考えてきたことを実践してうまくいったり,うまくいかなかったり試行錯誤しながら続けていくとブログが愛らしくなってきますw また,自分にとっての楽しさの中に人との出会いが大きくあってアウトプットを通じて出会えた方々はありがたい関係だと思うのでもっと出会い増やしたいみたいなモチベーションがあります.なので,発表でお話ししたいくつかの取り組みとは別でアウトプットすることの楽しさって自分はどこにあるっけ?を考えてみるのもいいかもしれません.

関連記事

sadayoshi-tada.hatenablog.com sadayoshi-tada.hatenablog.com

まとめ

登壇の振り返りとして補足を書いてみました.Twitter のコメントをみさせてもらったところ,ブログを書いている方が多くて嬉しかったのと発表後にメンションいただいた方で感想をくださったので励みになりました.ブログを楽しんで書く人が増えるきっかけに少しでもなれば嬉しいです!発表の機会をいただきありがとうございました!!

CodePipeline と CodeBuild で Git のタグを使ったリリースを行う

タダです.

下記の画像のような CodePipeline と CodeBuild でパイプラインを作っていた時に GitHub で登録した最新のタグでリリースを行いたいといった要望があったので試してみた内容をこの記事にまとめていきます.

f:id:sadayoshi_tada:20210715051202p:plain

前提

冒頭の話について今回の設定と関連する部分を補足します.CodePipelineの設定は当初下記の画像のようなデフォルト設定でGitHub(バージョン2)の接続がされている状況でした.

f:id:sadayoshi_tada:20210715051410p:plain f:id:sadayoshi_tada:20210715051427p:plain

また,CodeBuild の IAM ロールは下記のデフォルト設定が入っている状態だったとします.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:logs:ap-northeast-1:xxxxxxxxxxxx:log-group:/aws/codebuild/xxxx",
                "arn:aws:logs:ap-northeast-1:xxxxxxxxxxxx:log-group:/aws/codebuild/xxxx:*"
            ],
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::codepipeline-ap-northeast-1-*"
            ],
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "codebuild:CreateReportGroup",
                "codebuild:CreateReport",
                "codebuild:UpdateReport",
                "codebuild:BatchPutTestCases",
                "codebuild:BatchPutCodeCoverages"
            ],
            "Resource": [
                "arn:aws:codebuild:ap-northeast-1:xxxxxxxxxxxx:report-group/xxxx*"
            ]
        }
    ]
}

CodeBuild のタグリリースに関するコマンド追加

ビルドをする段階で最新のタグをチェックアウトしたいのでコマンドをbuildspec.ymlに追加します.buildフェーズにgit checkout $(git describe --tags --abbrev=0)というコマンドを追加しています.

version: 0.2
env:
  git-credential-helper: yes
~中略~
  build:
    commands:
      - git checkout $(git describe --tags --abbrev=0)
~中略~

タグとしては次のようなものが設定されていた場合,git describe --tags --abbrev=0を実行すると最新のv1.6が選ばれるのでこのコマンドの実行結果を使ってチェックアウトしています.

% git tag
v1.0
v1.1
v1.2
v1.3
v1.4
v1.5
v1.6
% git describe --tags --abbrev=0
v1.6

関連情報

docs.aws.amazon.com

CodePipeline の設定を変更

git describe --tags --abbrev=0を実行するために Git メタデータを取得する必要があり CodePipeline の設定で完全クローンを指定します.

f:id:sadayoshi_tada:20210716094545p:plain

CodePipeline で GitHub ソースアクションの完全なクローンオプションを選択できます。パイプラインビルドアクションで Git メタデータの CodeBuild コマンドを実行するには、このオプションを使用します。

CodeBuild の IAM ロール の設定変更

GitHub(バージョン2)を使っていてかつ CodePipeline の完全クローンオプションを使う時そのままリリースしたいブランチでコードをあげたところ Command did not exit successfully git checkout $(git describe --tags --abbrev=0) exit status 128というエラーがでました.

[Container] 2021/07/02 12:02:44 Command did not exit successfully git checkout $(git describe --tags --abbrev=0) exit status 128
[Container] 2021/07/02 12:02:44 Phase complete: BUILD State: FAILED
[Container] 2021/07/02 12:02:44 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: git checkout $(git describe --tags --abbrev=0). Reason: exit status 128

ドキュメント を確認したところ codestar-connections の権限がなかったので CodeBuild の IAM ロールを変更しています.

CodeBuild サービスのロールは、接続を使用するアクセス許可で更新する必要があるため、最初のパイプライン実行は失敗します。codestar-connections:UseConnectionサービスロールポリシーに対する IAM アクセス許可を追加。

IAM ロール変更後,再度パイプラインを動かしたところ意図したタグでチェックアウトができました.

[Container] 2021/07/14 00:13:19 Running command git checkout $(git describe --tags --abbrev=0)
Previous HEAD position was xxxx Merge pull request #4 from tasogare0919/xxxx
HEAD is now at xxxx v1.6

まとめ

CodePipeline と CodeBuild で最新の Git タグによるリリースを行うために行った設定をまとめていきました.タグリリースを使えるようになると万が一過去のバージョンに戻したい時に戻しやすくなるし開発方針に合えば使うのを検討したいですね.

ECS Fargate の AutoScaling 設定に関するコマンドをまとめておく

タダです.

AWS CLI で ECS Fargate の AutoScaling 設定をしているのですが,都度調べていたりしたのでよく使うコマンドをまとめておきます.

AutoScaling ポリシーを定義・更新する

AutoScaling ポリシーを定義・更新する時のコマンドとしてput-scaling-policyを使います.ECS の AutoScaling は CPU,メモリ,ターゲットグループごとのリクエスト数を追跡してスケーリングのトリガーにできます.下記のはターゲットグループごとのリクエスト数をベースにしています.そして,AutoScaling のポリシーを参照するには describe-scaling-policies を使い,誤って作ってしまったポリシーを削除するには delete-scaling-policyを使います.

※定義・更新
aws application-autoscaling put-scaling-policy \
--service-namespace ecs --scalable-dimension ecs:service:DesiredCount \
--resource-id service/クラスター名/サービス名 \
--policy-name ポリシー名 \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration file://config.json

※参照
aws application-autoscaling describe-scaling-policies --service-namespace ecs

※削除
aws application-autoscaling delete-scaling-policy --policy-name ポリシー名 --scalable-dimension ecs:service:DesiredCount --resource-id service/クラスター名/サービス名 --service-namespace ecs

なお,put-scaling-policyで指定しているconfig.jsonは次のような定義をいれます.

{
     "TargetValue": 1000.0,
     "PredefinedMetricSpecification": {
         "PredefinedMetricType": "ALBRequestCountPerTarget",
         "ResourceLabel": "app/ELB 名/xxx/targetgroup/ターゲットグループ名/xxx"
     },
     "ScaleOutCooldown": 60,
    "ScaleInCooldown": 60
}

関連情報

awscli.amazonaws.com

awscli.amazonaws.com

awscli.amazonaws.com

スケジューリングで AutoScaling のスケールアウト・スケールインを設定する

AutoScaling をスケジュール設定を入れたい場合があります.特定のイベントやメディア露出が分かっているような時に予めコンテナを増やしたいと言った要求向けの作業です.スケールアウトさせたい時間とスケールインさせたい時間でput-scheduled-actionを使ってMinCapacityの値を変更するスケジュールを登録しておく設定になっています.なお,cronで指定する時間は UTC 時間です.スケーリングの設定の参照はdescribe-scheduled-actionsを使い,削除にはdelete-scheduled-actionを使います.

※スケールアウト
aws application-autoscaling put-scheduled-action \
--service-namespace ecs \
--resource-id service/クラスター名/サービス名 \
--scheduled-action-name スケジューリングの名前 \
--schedule "cron(00 10 ? * * *)" \
--scalable-dimension ecs:service:DesiredCount \
--scalable-target-action MinCapacity=4,MaxCapacity=10

※スケールイン
aws application-autoscaling put-scheduled-action \
--service-namespace ecs \
--resource-id service/クラスター名/サービス名 \
--scheduled-action-name スケジューリングの名前 \
--schedule "cron(00 13 ? * * *)" \
--scalable-dimension ecs:service:DesiredCount \
--scalable-target-action MinCapacity=2,MaxCapacity=10

※スケジュールアクションの参照
aws application-autoscaling describe-scheduled-actions --service-namespace ecs

※削除
aws application-autoscaling delete-scheduled-action \
    --service-namespace ecs \
    --scalable-dimension ecs:service:DesiredCount \
    --resource-id service/クラスター名/サービス名 \
    --scheduled-action-name スケジューリングの名前

関連情報

awscli.amazonaws.com

awscli.amazonaws.com

awscli.amazonaws.com

まとめ

小ネタですが,ECS Fargate の AutoScaling 設定に関するコマンドについて都度調べていたのをまとめておきたくて記事にしました.

ECS Fatgate の FastAPI 関連プロセスを Mackerel で監視する

タダです.

前回の記事で Mackerel のカスタムプラグインを使った監視をやってみたんですが,EC2 の Uvicorn プロセス数の取得とプロセスの監視をしてみました.今回は前回のカスタムプラグインを使って ECS Fargate 上のプロセス監視をいれていきます.

sadayoshi-tada.hatenablog.com

監視のための準備

1, アプリケーション のコンテナ側での設定

FastAPI を動かすコンテナ側で Mackerel の監視設定とカスタムプラグインスクリプトを追加していきます.ディレクトリとして mackerelを追加してそこに設定ファイルとスクリプトを入れていきます.

.
├── app ・・・アプリケーション のコードが格納されているディレクトリ 
├── mackerel ・・・Mackerel の設定及びカスタムプラグインのスクリプトが格納されているディレクトリ 
├── ecs_setting・・・タスク定義が格納されているディレクトリ 

まず設定ファイルとしてmackerel.yamlを作ります.この中でカスタムプラグインのどのスクリプト がメトリックの取得をし,プロセス監視をするのかを設定していきます.

apikey: "YOUR_MACKEREL_APIKEY"
plugin:
  metrics:
    uvicorn:
      command: sh /xxx/mackerel/uvicorn-ps-count.sh ・・・メトリック監視
  checks:
    check_uvicorn:
      command: sh /xxx/mackerel/uvicorn-ps-check.sh・・・プロセス監視
ignoreContainer: '\Amackerel-container-agent\z'

mackerel.io

次にスクリプトの配置ですが,次のスクリプト を配置し,実行権限を与えています.

uvicorn-ps-count.sh

#!/bin/sh
metric_name='uvicorn.process.counts'
metric=`ps aux |grep uvicorn | grep -v grep | wc -l`
date=`date +%s`

echo "${metric_name}\t${metric}\t${date}"

uvicorn-ps-check.sh

#!/bin/sh
count=`ps aux |grep uvicorn | grep -v grep | wc -l`
counts=`printf "%d\n" $count`
if [ $counts -ge (正常なプロセスの数) ]; then
  exit 0
else
  exit 2
fi

最後にアプリケーションコンテナの Dockerfile とタスク定義に追加の設定を行います.Dockerfile では Mackerel のサイドカーコンテナから設定ファイルやスクリプトにアクセスできるようにVOLUMEの設定をし,タスク定義には設定ファイルのパスとマウント設定を記載していきます.

Dockerfile の該当箇所抜粋

WORKDIR /xxx/
COPY . .
VOLUME /xxx/mackerel

タスク定義の該当箇所抜粋

    {
      "name": "mackerel-container-agent",
      "volumesFrom": [
        {
          "sourceContainer": "アプリケーションコンテナ名"
        }
      ],
      "environment": [
        {
          "value": "fargate",
          "name": "MACKEREL_CONTAINER_PLATFORM"
        },
        {
          "value": "/xxx/mackerel/mackerel.yaml",
          "name": "MACKEREL_AGENT_CONFIG"
        }
      ],
    }

関連記事

sadayoshi-tada.hatenablog.com

2, mackerel-container-agent のカスタム設定

今回で,mackerel-container-agentのコンテナから監視のシェルを叩いてもps: not foundが表示されていたため,ps コマンドをいれていきます.

2021/07/05 11:28:03 INFO <main> starting mackerel-container-agent (version:0.5.0, revision:e1a219c)
2021/07/05 11:28:03 INFO <agent> wait for the platform status to be running
2021/07/05 11:28:07 INFO <agent> start the agent: host id = xxxx, host name = xxxx
2021/07/05 11:28:07 INFO <metric> plugin fastapi (sh /xxx/mackerel/uvicorn-ps-count.sh): "/xxx/mackerel/uvicorn-ps-count.sh: 1: /xxx/mackerel/uvicorn-ps-count.sh: ps: not found\n"

mackerel-container-agent では公開されているコンテナイメージを使ったカスタマイズが可能です.mackerel-container-agentDebian ベースのため ps コマンド実行に必要な処理を Dockerfile に記述し,ECR に格納していきます.

hub.docker.com

Dockerfile は次の定義をして ECR に格納しました.

FROM mackerel/mackerel-container-agent:plugins
RUN apt update && apt install -y procps

コンテナ起動後の動作確認

コンテナを起動して意図したプロセス数の収集とプロセス監視ができているかを確認します.両方の設定が画面から確認できたのとプロセス監視はアラートが飛ぶことも確認できました.

プロセス数収集

f:id:sadayoshi_tada:20210707133143p:plain

プロセス監視

f:id:sadayoshi_tada:20210707134136p:plain f:id:sadayoshi_tada:20210707133405p:plain

まとめ

ECS Fargate でmackerel-container-agentにないプロセス監視をやってみました.今回の設定を確認していくにあたって Mackerel サポートの方に助けていただきました.ありがとうございました!同じように ECS Fargate 環境でのカスタムプラグインによる監視をされたい方の参考になれば嬉しいです!