1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

夜間対応を減らすために Ansible + GitHub Actions でGUIベースのミドルウェア更新を作った

1
Posted at

1. はじめに

こんにちは、天パです。👨🏻‍🦱
ミドルウェア更新も、放っておくと髪の毛みたいに絡まります。

Apache のようなミドルウェア更新は、
作業だけ見ればそこまで複雑ではありません。

  • 更新候補を確認する
  • 検証環境で試す
  • 本番環境へ反映する
  • 問題があれば切り戻す

ただ、実務で本番環境が単一サーバ構成だと話が変わります。
更新中にサービス停止が発生しやすいため、
利用者影響を避ける目的で夜間対応になりがちです。

夜間に人が待機し、手順書を見ながら更新し、
失敗したらその場で切り戻す。
この運用は、担当者にも組織にも負荷が大きいです。

そこで個人環境で、
「冗長構成にしてローリング更新を組めば、
ダウンタイムなしでミドルウェア更新できるのか」
「夜間対応をやめる方向に寄せられるのか」
を実装まで試してみました。

リポジトリはこちらです。

https://github.com/tenpa7188/zero-downtime-update-orchestrator

2. 作ったもの

Apache の更新を題材に、
LB 配下の Web サーバを 1 台ずつ切り離しながら更新する構成を作りました。

流れは次のようなイメージです。

バージョンアップ候補を検知(cron)
  -> GitHub Issue の自動作成 / Slack 通知
  -> dev dry-run
  -> dev rolling update
  -> prod dry-run
  -> production 承認
  -> prod rolling update
  -> 必要なら rollback

構成図は次のようになります。
実務では VM 環境を触ることが多いため、
検証は VM、
本番相当環境は AWS(学習のため)
という特殊な環境になっています。

構成図

技術スタックは次の通りです。

領域 技術 用途
構成管理 Ansible Apache 更新、LB 制御、ヘルスチェック、切り戻し
ローカル検証 Vagrant + VirtualBox lb01web01web02 の疑似マルチホスト環境
本番相当環境 Terraform + AWS VPC、EC2、ALB、IAM、S3 などの IaC 管理
CI/CD GitHub Actions dry-run、deploy、承認、rollback
LB Nginx / AWS ALB dev は Nginx、prod は ALB
本番相当接続 AWS SSM SSH ポートを開けずに Ansible を実行

dev は Vagrant VM と Nginx LB、
prod 相当は AWS EC2 と ALB です。
環境は違いますが、更新の中核になる Ansible playbook は共通にしています。

3. ローリング更新の考え方

単一サーバ構成では、
ミドルウェア更新は「この 1 台を止めるかどうか」の話になりがちです。

一方で、冗長構成にできるなら、
サービス全体を止めるのではなく、
対象サーバだけを LB から外して更新できます。

今回の Ansible playbook では、更新の流れを次のように固定しました。

1. 対象 Web サーバを LB から切り離す
2. Apache を指定バージョンへ更新する
3. systemd と HTTP でヘルスチェックする
4. 対象 Web サーバを LB に戻す
5. 次の Web サーバへ進む

中核になるのは serial: 1any_errors_fatal: true です。

該当コード
- name: ローリング更新
  hosts: web
  serial: 1
  any_errors_fatal: true

  pre_tasks:
    - name: LB からサーバを切り離す
      ansible.builtin.include_role:
        name: lb_control
      vars:
        lb_control_action: drain

  roles:
    - apache

  post_tasks:
    - name: 動作確認
      ansible.builtin.include_role:
        name: healthcheck

    - name: LB にサーバを組み込む
      ansible.builtin.include_role:
        name: lb_control
      vars:
        lb_control_action: restore

serial: 1 で 1 台ずつ更新し、
any_errors_fatal: true で失敗時に後続の更新を止めます。

1 台目でヘルスチェックに失敗しているのに、
2 台目、3 台目へ進むのは避けたいので、
ここはかなり大事なガードです。

4. GUI だけで更新作業を進められるようにした

今回、Ansible による自動化と GitHub Actions の CI/CD を組んだことで、
基本的なバージョンアップ対応は GitHub の画面操作だけで進められる形になりました。

サーバに SSH して手順書どおりにコマンドを打つのではなく、
GitHub Actions の Deploy workflow を画面から実行します。

実行手順としては、次のようになります。

4.1 バージョンアップ候補を検知する

バージョンアップ候補を検知すると、
GitHub Issue を自動作成し、Slack に通知します。

Slack 通知

Slack 通知から対象の Issue を開く導線を想定しています。
Issue ではチェックボックスで進行状況を見える化し、
GitHub Actions workflow のリンクから手動実行画面へ遷移する想定です。

GitHub Issue

4.2 GitHub Actions から手動実行する

手動実行時は、対象環境と Apache のバージョンを入力します。

environment: dev / prod
apache_version: 更新したい Apache バージョン

GitHub Actions の手動実行画面

その後の流れは GitHub Actions 側で進みます。

dry-run
  -> prod の場合は production 承認
  -> deploy
  -> inventory の apache_version を同期

切り戻しも Rollback workflow から実行できます。
切り戻し先の Apache バージョンを入力すると、
通常のローリング更新と同じ流れで戻します。

これにより、作業者が直接サーバ上でコマンドを打つ場面を減らし、
実行ログも GitHub Actions に残せるようになりました。

完全自動にしないのも意識した点です。
特に prod は dry-run 後に production environment の承認を挟み、
人間が確認してから反映する形にしています。

5. バージョンアップ検知は起点作りに止める

scripts/check_vulnerability.sh では、
代表 Web サーバ上で対象パッケージの現行バージョンと最新バージョンを比較します。
デフォルトの対象は apache2 です。

更新候補がある場合は、GitHub Issue を作成し、
Slack に通知します。

ただし、この時点で deploy workflow は起動しません。

更新候補を検知する
  -> Issue / Slack で知らせる
  -> 内容を確認する
  -> GitHub Actions の GUI から dry-run / deploy を進める

脆弱性対応は急ぎたい一方で、
検知した瞬間に更新まで走らせるのはまだ怖いです。
今は、検知は作業の起点作りにとどめています。

6. 今回の構成で意識したこと

このリポジトリでやりたかったのは、
単に Ansible で Apache を更新することではありません。

夜間対応が必要になりがちな運用を、
構成と自動化でどこまで変えられるかを試すことでした。

そのため、次の点を意識しています。

  • 単一サーバ構成で発生しやすい停止前提の運用課題を出発点にする
  • 冗長構成とローリング更新で、夜間対応を減らせるかを実装で確かめる
  • dry-run と production 承認を挟み、本番反映を段階化する
  • 失敗時に後続サーバへ進まないようにする
  • 切り戻しも通常更新と同じ仕組みに載せる
  • GUI 操作で進められるようにし、作業ログを GitHub Actions に残す

インフラ運用では、
「コマンドを知っている」だけでは足りない場面が多いです。

どの構成なら止めずに更新できるのか。
どこまで自動化し、どこに人間の承認を残すのか。
失敗したときにどう止め、どう戻すのか。

その判断を、できるだけリポジトリ上に残すようにしました。

7. 現時点の未対応と今後の課題

まだ最小構成なので、未対応のことも多いです。

  • 更新対象は Apache のみ
  • 現時点ではバージョンアップ候補の検知のみで、脆弱性自体の検出はできていない
  • CVE 情報や深刻度とパッケージ更新候補を突き合わせる処理は未対応
  • 複数ミドルウェアが対象になった場合の処理順序や承認フローは未対応
  • 監視、メトリクス、アプリケーション疎通確認は今後の拡張余地がある
  • 実際の単一サーバ本番環境を冗長化する場合は、セッション管理なども別途考慮が必要

特に次に考えたいのは、
「更新候補がある」ではなく
「どの脆弱性に対して、どの更新が必要なのか」まで見えるようにすることです。

また、Apache 以外のミドルウェアも対象にするなら、
ミドルウェアごとの更新手順、依存関係、切り戻し方法を整理する必要があります。
ここは今後の課題です。

8. まとめ

単一サーバ構成では、
ミドルウェア更新が夜間対応になりがちです。
ただ、それをずっと人の頑張りだけで支えるのはつらいです。

今回は個人環境で、
冗長構成とローリング更新を組めば、
夜間停止を前提にしない運用へ寄せられるのかを試しました。

Ansible で LB 切り離し、Apache 更新、ヘルスチェック、復帰を自動化し、
GitHub Actions から dry-run、承認、deploy、rollback を実行できるようにしています。

まだ完成形ではありませんが、
ミドルウェア更新を「夜間に手作業で頑張るもの」から、
「構成と CI/CD で制御するもの」へ寄せるための土台は作れたと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?