国立競技場リレーマラソンでサブスリー達成した話

こんにちは!

マラソン完走で書類選考免除!42.195km採用 の企画に携わっている高田です。

カヤックのエンジニアにはランニングを楽しむ人が多く、SREの藤原や、サブスリーの記録を持つ荒賀、最近記録を伸ばしている千葉などが代表的なランナーです。

社内にはランナーたちが集まるSlackチャンネル「#club-running」があり、日々のランニング活動を共有しあっています。 (#club-runningの活動はこちらの記事をご覧ください

そんなエンジニアたちを中心にチームを組んで「国立競技場 Enjoyリレーマラソン」に出場してきたので、その様子をご紹介します。

完走後の記念撮影。国立競技場は広いですね!

国立競技場Enjoyリレーマラソンの様子

今回はカヤックから3チーム、グループ会社の株式会社カヤックボンドから1チームの合計4チームがエントリーしました。

私たちが参加したのは「フルリレー 会社の部」です。全部で120チームが参加したそうです。

当日の天気は快晴!ランニング日和でした!

今回のコースは1周が1.4km。国立競技場のトラックと施設内の通路を駆け抜けます。

1周ずつ交代で走りながらタスキをつなぎます。チーム全員で合計30周して、フルマラソンの距離である42.195kmの完走を目指します。

タスキを受け渡す様子

自分の番が回ってくるまで待機するメンバー

1周の距離が短めなので、スピード勝負のレースでした。全力疾走した後はへとへとです。

お疲れ様!ナイスラン!

なんと最後はアンカーに合流して、みんなで一緒にゴールできます。運営さんの粋な計らいですね!

アンカーの千葉が速すぎて、追いつくのに必死な他のメンバー

国立競技場Enjoyリレーマラソンの結果

今回出場した4チームの中で一番速かったのはCチーム。結果は2時間58分9秒で、サブスリーを達成することができました!

立派な賞状をいただきました!

サブスリーを1人で達成してしまう人がいると思うと、本当にすごいことだなと思います。もしサブスリーに挑戦したい人がいたら、ぜひ「エンジニアがすごく頑張ってサブスリーしたよって話」の記事を参考にしてみてください。

お疲れ様でした

打ち上げ参加者で記念撮影

大会終了後は馬肉を食べに行きました。こうやってランニングを楽しむ仲間が大勢いるのは素敵だな〜と思います。

というわけで、カヤックではランニング好きのエンジニアを募集しております!!

今なら マラソン完走で書類選考免除!42.195km採用 やってます!

一緒に走りましょう!

Fargate Spotを本番運用するための監視の実践

SREチームの橋本です。SRE連載の3月号となります。

Amazon ECSのコスト最適化においてはFargate Spotが有効な手段となりますが、いつ中断されるか分からない性質上、その監視も併せて実施していく必要があります。今回はそのFargate Spotを本番環境で運用しているプロジェクトにおける取り組みを紹介します。

背景

Fargate (Amazon ECS on AWS Fargate) を用いると負荷に合わせた容易なスケーリングが可能になる一方、このときCPU使用率の安全マージンや予測のブレなどにより、リソースがやや過剰になってしまうこともあります。

Fargate Spotの代表的なユースケースと言えばユーザーに露出しない開発環境ではないかと思いますが、このような場合にコストを考えると、タスクの中断をある程度許容しての本番環境でのFargate Spot運用も可能な選択肢となってくるでしょう。

そこでリスク管理の手掛かりとして重要になってくるのが各種メトリクスであり、特にどのくらいSpotのタスクが動いているのか、中断率がどのくらいなのかを見つつ調整していく必要があります。 今回Fargate Spotを導入しSpotの比率を考える際にも、これらのメトリクスの情報が不可欠でした。

On-demand/Spotのタスク数の監視

使用状況メトリクスとしてアカウント全体でのSpot使用は確認できますが、負荷の掛かり方の違いもありECSサービスごとの使用量を見たいという状況でした。

私の参加しているプロジェクトで監視はMackerelを用いています。MackerelではAWSインテグレーションによりメトリックの自動取得ができますが、そもそもAWSにないメトリックでは仕方がありません。 ただ当該プロジェクトではmaprobeが稼働しており、任意のコマンドで取得したメトリックをMackerelに送信することができたため、今回もこれを利用しました。

例えば以下のようなシェルスクリプトにより、On-demandとSpotのタスク数を集計することができます。

#!/bin/sh

# fargate_capacity
#
# ECSサービスごとのFargateキャパシティープロバイダーの利用状況を計測する。
# 出力例:
# ecs.capacity.FARGATE.app    7   1699955130
# ecs.capacity.FARGATE_SPOT.app   1   1699955130

metric_prefix=ecs.capacity.
timestamp=$(date +%s)
cluster=""
services=""

while getopts c:s: OPT
do
    case $OPT in
        c)
            cluster=$OPTARG
            ;;
        s)
            services=$OPTARG
            ;;
    esac
done

tasks=$(aws ecs list-tasks --cluster $cluster | jq -r '.taskArns[]')
service_capacities=$(aws ecs describe-services --cluster $cluster --services $services | jq -r '.services[] | select(.capacityProviderStrategy) | .capacityProviderStrategy[].capacityProvider + "." + .serviceName')

data=""

for capacity in $service_capacities
do
    data="$data\n$capacity 0"
done

service_pattern=$(echo $services | sed -e 's/ /|/g')
task_capacities=$(aws ecs describe-tasks --cluster $cluster --tasks $tasks | jq -r ".tasks[] | select(.lastStatus == \"RUNNING\" and (.group | match(\"$service_pattern\"))) | ((.capacityProviderName // .launchType) + \".\" + (.group | split(\":\")[1]))")

for capacity in $task_capacities
do
    data="$data\n$capacity 1"
done

echo $data \
    | awk '{ arr[$1] += $2 } END { for (i in arr) { if (i != "") { print i, arr[i] } } }' \
    | awk "{ print \"$metric_prefix\" \$1 \"\t\" \$2 \"\t\" $timestamp }"

maprobeに対しては以下のように設定すると、各ECSクラスタ(Mackerel上ではECSロールが付いたホストとして扱われる)に対して、上記のスクリプトを起動しカスタムメトリックを投稿してくれます。

probes:
  - service: production
    role: ECS
    command:
      command: 'fargate_capacity -c {{ index .Host.Meta.Cloud.MetaData "cluster-name" }} -s "foo bar"'

Mackerelの実際の画面としては下図のようなグラフとなります。

On-demand/Spotのタスク数グラフ

Fargate Spotの中断の監視

EC2スポットインスタンスであれば中断率が公表されていますが、Fargate Spotにはそのような情報がないようです。よって運用に当たっては自力で中断リスクを管理する必要があります。

またFargate Spotのタスク中断は公式情報によると、流れとしては通常のタスク停止と同様にSIGTERMが送られてstopTimeoutだけ待つ、となっているようです。しかし実際にはFargate Spotの中断だと正常終了しない……というケースも存在するでしょう。こうした時には中断時の挙動を調べる必要があります。

当該プロジェクトではECSタスクの異常終了イベントをCloudWatch Logsに保存しており、これについては例えばClassmethod様のAmazon ECS タスクの停止理由 (エラー内容) を CloudWatch Logs に保存する方法とその分析をしてみた | DevelopersIOをご覧頂ければと思いますが、EventBridgeからCloudWatch Logsへ直接渡して記録できるので簡単に実現できます。

Fargate Spotの中断はstoppedReasonがYour Spot Task was interrupted.となるため、Logs Insightsを用いると以下のようなクエリで抽出することができます。

fields time, detail.group
    | filter detail.stoppedReason like 'Your Spot Task was interrupted'
    | sort @timestamp desc

下図のようにグラフも表示され、簡単に分析することができます。

CloudWatch Logs InsightsでSpot中断を分析する

なおこうして中断率を見ると、概算で1時間あたり1%弱の中断率が計測されました。上記のEC2スポットインスタンスでは1ヶ月で5%未満といったデータが多いので、Fargate Spotではかなり性質が異なるのかもしれません。

またLogs Insightsの活用については、他にも「CloudWatch Logs Insights クエリを定期的に実行して結果をS3に置く」など紹介していますので併せてご覧ください。

まとめ

今回は自社OSSやAWSの各種サービスを活用したFargate Spotの監視について紹介しました。

Fargate Spotはその大きな割引率によってコスト最低化に当たり大きな魅力を持ち、また中断のリスクもコンテナアプリケーションとしてお行儀が良ければ、つまりステートレスであれば御しやすいものと言えます。 適切な監視と共にECSのキャパシティーの一部として活用すれば、スケーリングに更なる自由度をもたらすことができるのではないかと思います。

カヤックでは、サービスの選択肢を増やす監視に興味があるエンジニアも募集しています。