Link and Motivation Developers' Blog

リンクアンドモチベーションの開発者ブログです

ミドルウェアアップデートの自動化によってトイルを年間180時間削減しました

こんにちは、リンクアンドモチベーション SREグループの久原です。今回は、SREチーム内の生産性・信頼性向上のために取り組んだミドルウェアアップデートの自動化施策について紹介いたします。

背景

なぜミドルウェアアップデートの自動化に取り組んだのか?それは現在SREチームで注力している 「トイルの削減」に対して大きく貢献するため です。インフラ民主化の記事でも取り上げたように、トイルの対応時間のトップ3を見ると、かなりの割合をミドルウェアアップデートが占めていることが分かります。

トイル 対応時間 / 月
環境のミドルウェアアップデート 18h
開発者からの依頼 16h
開発者への環境の払い出し 10h

この時間を削減をすることで、改善活動に割り当てられる時間を増やすことが可能です。

自動化の成果

手順の簡略化

大きく6つのステップを踏む必要があったところから、2ステップまで削減することができました。 これにより、作業ミスのリスクが大幅に削減されました。

before

after

対応時間の削減

手順の簡略化により、月あたり15時間、年間で 180時間工数削減に成功しました。

対応時間 / 月
before 18h
after 3h

上記2つの成果によって、 SREチーム内の生産性と信頼性の向上 に寄与することができました。

やったこと

自動化の内容についてお話する前に、我々のチームで元々行っていたミドルウェアアップデートの手順をご説明します。

ミドルウェアアップデートの手順

大まかな流れは以下のようになっています。

いきなり本番のEC2, ECRイメージのアップデートを行ってしまうと、ミドルウェアアップデート起因で不具合が生じる可能性があるため、必ずテスト用環境を構築してE2Eテストを間に挟むことで安全なミドルウェアアップデート作業を実現しています。 E2Eテストは既にAutifyで自動化を行なっており、詳細については以前私が書いた記事をご覧いただけると幸いです。

上記の手順において、私が着手する前の自動化の状況を以下に記載します。

項目 自動 or 手動
EC2イメージのアップデート 自動
テスト用ECRイメージのアップデート 手動
テスト用環境の構築 自動
E2Eテスト 自動
本番ECRイメージのアップデート 手動
本番環境へデプロイ 自動

ECRのイメージアップデートの箇所は完全に手作業で行っていました。また、各項目の開始は手作業なので、全体を通してみると手作業で行わなければならない箇所は多く存在していました。

自動化の方針

上記に対し、私は以下の2つ方針で自動化を実行しました。

①各項目ごとに手動の部分をCodeBuildを使って自動化する

②項目間の移行はCodePipelineを使って一気に実施できるようにする

それぞれについて、以下で詳しく説明をしていきます。

①各項目ごとに手動の部分はCodeBuildを使って自動化する

before

以下の作業をローカルから手動で実施

### docker ログイン
$ aws ecr get-login-password --region xxxxx | docker login --username xxxxx --password-stdin xxxxx
 
### テスト用環境作成時
$ docker pull amazonlinux:2
$ docker tag amazonlinux:2 {テスト用のECRイメージ}
$ docker push {テスト用のECRイメージ}

### 本番適用時
$ docker pull {テスト用のECRイメージ}
$ docker tag {テスト用のECRイメージ} {本番用のECRイメージ}
$ docker push {本番用のECRイメージ}

Docker Hubのamazonlinux:2を直接ECRイメージとして利用してしまうと意図しないタイミングでアップデートされて不具合が生じる可能性があるため、一度テスト用, 本番用のECRにpushしています。

after

CodeBuildで以下のyamlファイルを実行する

version: 0.2

phases:
  pre_build:
    commands:
      - echo "${UPDATED_IMAGE}のDockerイメージの作成を開始します。"
  build:
    commands:
      - aws ecr get-login-password --region xxxxx | docker login --username xxxxx --password-stdin xxxxx
      - docker pull ${SOURCE_IMAGE}
      - docker tag ${SOURCE_IMAGE} ${UPDATED_IMAGE}
      - docker push ${UPDATED_IMAGE}
  post_build:
    commands:
      - echo "Dockerイメージ作成が終了しました。"
環境変数 内容
SOURCE_IMAGE アップデートの元となるイメージ
UPDATED_IMAGE アップデートしたいイメージ

上記のように、CodeBuildからSOURCE_IMAGEUPDATED_IMAGE環境変数を指定することで以下2つのフェーズに1つのCodeBuildで対応することができます。

  • テスト用ECRイメージのアップデート
  • 本番ECRイメージのアップデート

②項目間の移行はCodePipelineを使って一気に実施できるようにする

EC2イメージのアップデート〜E2Eテストまでの流れをボタン1つで実施できるよう、以下の各項目のCodeBuildをCodePipelineで結合しました。

  1. テスト用ECRイメージのアップデート
  2. テスト用環境をcdkで構築
  3. テスト用環境に最新のブランチをデプロイ
  4. E2Eテスト用にデータを初期化
  5. Autify(E2Eテスト)の実行

4のテストデータの初期化については以前の記事のテストデータで具体的な記載をしています。 5のAutifyの実行について、今まではAutifyにログインしてブラウザからテストを開始していました。しかし、AutifyはAPIを提供しているので、CodeBuildを介してAutifyを実行しています。

version: 0.2
phases:
  build:
    commands:
      - echo "running testplan ${test_plan_id}"
      - res=$(curl -s -XPOST -H "Authorization:Bearer ${AUTIFY_ACCESS_TOKEN}" https://app.autify.com/api/v1/schedules/${test_plan_id})
      - result_id=$(echo $res | jq -r .data.id)
      - if [ -z "${result_id}" ] || [ "${result_id}" == "null" ]; then echo "[ERROR] running test failed" && exit 1;fi
      - echo "check progress of the test result from below"
      - echo "https://app.autify.com/projects/${PROJECT_ID}/results/${result_id}"

AUTIFY_ACCESS_TOKENを取得すれば比較的簡単にcurlで呼び出すことができます。

今後の展望

トイルの削減という足元課題を潰しつつ、サーバーレス導入などにより、細かな運用作業自体をなくせるようなチャレンジをしていこうと考えています。