BEMAロゴ

エンジニアの
成長を支援する
技術メディア

AnalysisRunとは?Argo RolloutsでCDNキャッシュ削除を自動化し、リリースの「トイル」を解消する実践例

リンクをコピー
リンクをコピーしました
Xでシェアするfacebookでシェアする

はじめに

こんにちは、株式会社メンバーズ DevOpsLeadカンパニーOpen in new tabの安藤です。

普段はAWS環境の構築・運用改善に携わっており、その中でKubernetes上のワークロードをArgo RolloutsでBlue/Greenデプロイする構成を扱っています。

Argo Rolloutsの AnalysisRun は、メトリクスを評価したりE2Eテストを実行したりする機能として紹介されることが多いと思います。今回はそれとは少し違う使い方として、AnalysisRunを 動作確認の前処理 に使ってみました。具体的には、Preview面のテストを始める前にCDNのキャッシュを削除しています。

結果として、リリースのたびに人がAWSコンソールを開いていた作業がなくなりました。

本記事では、「そもそもAnalysisRunとは何か?」という基礎から、今回の活用例、そして導入して得られたメリットまでを解説していきます。

Argo Rolloutsとは

Argo RolloutsOpen in new tabは、Kubernetes上でBlue/GreenデプロイやCanaryデプロイを宣言的に実現するためのツールです。

Deploymentなどの標準のワークロードリソースでは、新旧のPodを少しずつ入れ替えるローリングアップデートしか選べません。Argo Rolloutsは Rollout というカスタムリソースを提供し、より細かい切り替え制御ができるようにしてくれます。

Blue/Greenデプロイでは、Serviceを2つ用意します。

  • Active: 本番トラフィックが向いているService

  • Preview: 新バージョンの動作確認用Service

デプロイすると、新しいPodはまずPreview側に立ち上がります。この時点で本番トラフィックは旧Podに向いたままなので、ユーザーへ影響を出さずに新バージョンを確認できます。確認が済んだらActiveの向き先を新Podに切り替えます。この切り替えを promote(昇格) と呼びます。各段階の細かい挙動は公式ドキュメントのBlue/Green Deployment StrategyOpen in new tabにまとまっています。

なお、Argo Rolloutsは名前が似ているArgo CDOpen in new tabとは別のツールです。Argo CDはGitのマニフェストをクラスタに反映し続ける役割(GitOps)を担い、Argo Rolloutsは反映された Rollout をどう切り替えるかを担います。

AnalysisRunとは

AnalysisRunは、Rolloutの進行中に任意の処理を差し込める仕組みです。(Analysis & Progressive DeliveryOpen in new tab

処理の中身を定義するのが AnalysisTemplate で、それが実際に実行されたインスタンスが AnalysisRun になります。DeploymentとReplicaSetのような関係だと考えてください。

Rollout のどこに指定するかで、実行タイミングが変わります。

  • prePromotionAnalysis: promoteの直前、つまりPreview面が立ち上がった後に実行する

  • postPromotionAnalysis: promoteの直後に実行する

処理の内容はproviderで切り替えられます。よく紹介されるのは次のような使い方です。

  • Prometheusにクエリを投げてエラー率が閾値を超えていないか確認する

  • Datadogのメトリクスで新バージョンのレイテンシを評価する

  • E2Eテストを実行する

今回の課題:Preview面の確認時に古い資材が表示される

Blue/Greenデプロイの利点は、本番トラフィックを流す前にPreview面で新バージョンを確認できることです。

ところが、CDN経由でアクセスする構成だとここで問題が起きます。CloudFrontのエッジには前のバージョンのレスポンスがキャッシュされたまま残っているため、Preview面を開いても古い資材が表示されてしまうのです。

これでは確認になりません。そこで当初は、次のような手作業を行っていました。

  1. デプロイ前に、CloudFrontのTTLをコンソールで0に変更する

  2. Preview面で動作確認し、promoteする

  3. リリース後に、TTLを元の値に戻す

対象サービスが2つあったため、前後で計4ステップ、所要10分強です。これがリリースのたびに発生していました。

さらに厄介なのは、戻し忘れるとTTL 0のまま本番が動き続けるという点です。オリジンに全リクエストが流れ、負荷と転送量が静かに増えていきます。誰も気づかないまま数日経つ、というリスクを毎回抱えている状態でした。

prePromotionAnalysisでキャッシュ削除を自動化する

TTLを操作するのをやめて、キャッシュ削除そのものをデプロイの流れに組み込むことにしました。

欲しかったのは、次の順序です。

  1. Preview面のPodが起動する

  2. キャッシュ削除が完了する

  3. Preview面で動作確認する

  4. promoteする

2を1と3のあいだに挟みたい。これはまさに prePromotionAnalysis のタイミングです。

Rollout 側では、テンプレートを指定するだけです。

spec:
  strategy:
    blueGreen:
      activeService: my-app-active
      previewService: my-app-preview
      autoPromotionEnabled: false
      prePromotionAnalysis:
        templates:
        - templateName: cdn-invalidation-template

AnalysisTemplate 側で、invalidationの実行と完了待ちを行います。

apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: cdn-invalidation-template
spec:
  metrics:
  - name: cdn-invalidation
    # job providerではJobの成否がresultに入る
    successCondition: result == "Successful"
    failureCondition: result == "Failed"
    provider:
      job:
        spec:
          activeDeadlineSeconds: 300  # Jobがハングした場合の時間ガード
          backoffLimit: 1
          template:
            spec:
              restartPolicy: Never
              serviceAccountName: cdn-invalidation
              containers:
              - name: invalidation
                image: public.ecr.aws/aws-cli/aws-cli:2.35.1
                command: ["sh", "-c"]
                args:
                  - |
                    set -euo pipefail
                    ID=$(aws cloudfront create-invalidation \
                      --distribution-id "$DISTRIBUTION_ID" --paths "/*" \
                      --query 'Invalidation.Id' --output text)
                    # 完了までポーリングして待つ
                    aws cloudfront wait invalidation-completed \
                      --distribution-id "$DISTRIBUTION_ID" --id "$ID"

ポイントは wait invalidation-completed です。create-invalidation は非同期APIなので、リクエストを投げた時点では正常終了しますが、その瞬間にキャッシュが消えているとは限りません。動作確認の直前に実行する以上、完了まで待たないと意味がありません。

完了待ちを入れておくと、AnalysisRunが成功した時点でキャッシュが消えていることが保証されます。動作確認を始めてよい状態になったことが、Rolloutの進行状況から分かるわけです。

なお autoPromotionEnabled: false にしているため、promote自体は人が実行します。AnalysisRunはあくまで確認を始める前の下準備という位置づけです。

導入して得られたメリット

数十分のリリース時間を削減できた他、手動設定による設定ミス等の障害リスクを低減することができました。

SREの文脈では、こうした繰り返し発生する手作業をトイルOpen in new tabと呼びます。トイルは工数を奪うだけでなく、「やり忘れ」を常に抱え込む点が厄介です。人間が元に戻す前提の手順は、戻らなかったときに何が起きるかまで手順書に書かれていないことが多いためです。処理の順序ごと仕組みに預けられると、この不安も一緒に消えます。

運用してみて気づいたこと

良い面ばかり書いてきましたが、導入にあたって運用手順を一つ変える必要がありました。切り戻しの方法です。

もともと切り戻しには Argo CD の History and Rollback を使っていました。過去のリビジョンを選んで戻すだけなので手軽です。ところが、promote前の切り戻し、つまりActiveが旧バージョンのままPreviewに新バージョンが立っている状態から戻す場合、AnalysisRunが実行されませんでした。

理由はArgo Rolloutsの高速ロールバックです。戻し先のPodがまだ動いている場合、Argo Rolloutsは新しいPodを作らず既存のPodを再利用し、分析ステップをスキップします(RollbackOpen in new tab)。素早く戻すための挙動なのですが、キャッシュ削除もあわせてスキップされるため、切り戻した直後のPreview面には古い資材が残ってしまいます。

そこで切り戻し手順を、対象のPRをrevertして通常のリリースと同じ経路を通す形に変更しました。新しいPodが作られるのでAnalysisRunも実行されます。一周分の時間はかかりますが、キャッシュ削除まで含めて毎回同じ経路をたどるので、手順書としては単純になったと思います。

prePromotionAnalysisに処理を寄せるときは、「切り戻しの経路でもその処理が走るか」を先に確認しておくとよいと思います。デプロイ経路だけを見て組むと、切り戻しの場面で前提が崩れてしまいます。

まとめ

本記事では、AnalysisRunの基礎から、Preview面の動作確認の前処理として使うという活用例、そして導入によって得られたメリットを解説しました。

AnalysisRunは「メトリクスを評価する仕組み」「テストを実行する仕組み」として紹介されがちですが、実際には Rolloutの進行中の決まったタイミングに任意の処理を差し込むことができます。

使い分けの目安は、その処理を「動作確認を始める前に終わらせておきたいか」です。promote後でよい処理なら postPromotionAnalysis が適していますし、長時間かかる処理を prePromotionAnalysis に置くとデプロイの進行が止まってしまう点にも注意が必要です。

リリース手順書に「コンソールを開いて設定を変更する」「後で元に戻す」といった作業が残っていたら、それがデプロイのどのタイミングに紐づく操作かを一度考えてみてはいかがでしょうか。AnalysisRunを活用して自動化することができるかもしれません。

この記事が役に立ったと思ったら、
ぜひ「いいね」とシェアをお願いします!

��リンクをコピー
リンクをコピーしました
Xでシェアするfacebookでシェアする

この記事を書いた人

安藤 雄大
安藤 雄大
2023年にメンバーズに新卒で入社。DevOps Leadカンパニーでインフラ構築や運用保守に従事しています。
詳しく見る
ページトップへ戻る