OSパッチ適用（ジョブ管理システム）を、StepFunction+SystemManager（Patch Manager）でリプレイスした話

# はじめに
こんにちは、はやぴー（@HayaP）です。
日々のシステム運用、皆さんはどうされていますか？

- 過去の遺産から脱却できず、苦しんでる。
- クラウドに移行したが、オンプレミス時代の運用機能を用いている。
- クラウド移行を検討しているが、どうすればいいかわからない。

なんて人は、少なくないはずです。

そこで、今回は
オンプレミス→AWS（クラウド）に移行する際に、
システム運用を抜本的に見直した経験を記したいと思います。

## 対象読者
- AWSへの移行を検討している
- AWSに移行したが、オンプレ時代の運用を続けている。

この記事が、クライドネイティブな運用方式の参考になれればと願っています。

## 何について書くのか
今回は、数あるジョブの中から
- ＯＳセキュリティパッチ

に的を絞って話したいと思います。

## セキュリティパッチとは
セキュリティパッチとは、OSやアプリケーションの脆弱性を解決するためのプログラムです。
脆弱性（セキュリティホール）が発見されると、すぐに開発者やベンダーから配布されます。

# 概要
## 前提
- OSは、Ubuntu22.xxを想定
- 適切な権限設定(IAM Policy等)がされている

## 要件
- 毎日数回、欠落しているセキュリティパッチが無いかSCAN（検索）をする。
- 脆弱性を発見した場合は、7日以内にINSTALL（適用）を行う。
- パッチ適用時は、前後にサーバー固有のジョブ（Shell）を実行する。
- 対象サーバーは、約1000台。

## （現状）ジョブ管理システムでやっていたこと
オンプレ環境の、ジョブ管理ツール（統合システム運用管理）を利用し
パッチスキャンとパッチ適用を実施していました。

### パッチスキャン
１. 各サーバーにエージェントを導入
２. サーバーのOS毎にジョブグループを生成
３. パッチSCANジョブをジョブグループ毎に実施
４. 脆弱性を発見したら運用者にアラート通知
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478323/f8d0f193-c742-3098-89ab-6330bb77ab49.png)
### パッチ適用
５. パッチ適用のジョブを作成
６. サーバー毎に、パッチ適用時の前後ジョブを起動
７. サーバー毎に、パッチ適用
８. パッチ適用エラー時に、アラート通知
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478323/bdd62021-7d2e-a81c-e8a1-9c979d6df5ea.png)

## （あるべき姿）要望
ユーザーの要望は大きく二つでした。
1. ジョブ管理を、クラウド化したい（オンプレをやめたい）
1. 運用に係るオペレーションを省力化したい（自動化したい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478323/0ee42d7a-6256-438d-674c-c9556f42eafc.png)

## （課題）解くべき問題
世の中には、クラウド環境に最適化された
ジョブ管理系のツールも沢山あります。

しかし、納期が迫っていたこともあり
今回はAWSのサービスを利用する事になりました。

そのため、我々が解くべき問題（課題）は、
**AWSサービスだけで現状できていたことを実現できるのか？**
でした。

## （結果）どうなったのか
- AWS Systems Manager 
- AWS Step Functions

主に上記二つを用い、リプレイスすることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478323/1e9d37fa-4751-fc33-ce71-fc90eeb37568.png)

## 成果は？
オンプレのジョブ管理ツールの値段を考えると、かなり節約されました。

また、AWS上に集約し、サーバーと運用機能が近い関係にあることで
管理コストの面でも改善できたかなと思っております。


では、
これらを、どうクラウドネイティブにリプレイスしたかを説明していきます。

今回はオンプレでやっていたことリストを
そのまま引用し、説明をします。

# 詳細
## パッチスキャン
### １．各サーバーにエージェントを導入
- SSM Agentを各サーバーにインストールする。（マネージドノード化）
- AMIに含めることにより、インスタンス起動時に自動的に導入できる。

#### AWS Systems Managerとは？
AWSのインフラ管理に役立つ、お便利機能を備えたサービス群です。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/what-is-systems-manager.html

#### SSM Agentとは？
AWS Systems Managerの一部機能を利用するために、必要なエージェントです。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/prereqs-ssm-agent.html

#### カスタムAMIを作るには？
EC2 Image Builderを用いることで、簡単にカスタマイズされたAMIを作成する事ができます。

https://aws.amazon.com/jp/image-builder/

### ２．サーバーのOS毎にジョブグループを生成
- Patch Managerにて、パッチグループを作成。
- インスタンスタグに、パッチグループ情報を付与する。
    - KEY
        - "Patch Group" or "PatchGroup"
    - VALUE
        - "xxx"(パッチグループ名)

#### Patch Managerとは？
AWS Systems Managerの一部で、パッチ管理機能を有しているサービスです。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-patch.html

#### 注意点
パッチグループを作成せずに、instanceID等をターゲットにパッチ適用を実施できますが、
ベストプラクティスでは、タグを用いてパッチグループを指定する事が推奨されています。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-patch-group-tagging.html

### ３．パッチSCANジョブをジョブグループ毎に実施
- AWS Systems Managerの一部であるMaintenance Windowsを使用
- パッチグループ毎に、ウィンドウを登録
- ターゲットに、パッチグループを指定
- タスクに、RunCommandタスクを登録する
    - コマンドドキュメントを、"AWS-RunPatchBaseline"とする。

#### Maintenance Windowsとは？
AWS Systems Manager等の、様々なアクションを実行するスケジュールを定義できるサービス。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-maintenance.html

#### パッチベースラインとは？
パッチSCANやINSTALLの条件を、指定したものである。パッチグループと紐づけることができる。

#### RunCommandとは？
OS上で、コマンドを実行できる機能。
(SSM)ドキュメントと呼ばれる、コマンドの集まりを作成し、実行できる。
（Amazon所有という予め用意されている(SSM)ドキュメントもあるが、自分で作成する事もできる）

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/execute-remote-commands.html

#### AWS-RunPatchBaselinとは？
Amazon所有の(SSM)ドキュメントである。RunCommandで実行する事ができる。
マネージドノードにパッチ関連のオペレーションを実行できる。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/about-patch-baselines.html

### ４．脆弱性を発見したら運用者にアラート通知
Security Hubと連携させることで、楽にアラートを発出させることができます。
AWS-RunPatchBaselineを実行する事で、調査結果が生成、その後Security Hubに連係されます。
Security Hub上で、Amazon SNSへの通知を実装する事が出来ます。

#### Security Hubとは？
AWS のセキュリティ状態を包括的に把握することが可能で、
セキュリティ業界標準およびベストプラクティスに照らした環境チェックを行う事が出来るサービス。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/patch-manager-security-hub-integration.html

#### Amazon SNS
メッセージ配信ができる、マネージドサービス。
https://docs.aws.amazon.com/ja_jp/sns/latest/dg/welcome.html

## パッチ適用
### ５． パッチ適用のジョブを作成
ここからが、特に重要です。

- AWS Step Functionsを作成
- Step Functions内で、RunCommand（"AWS-RunPatchBaseline"）の定義を作成
- Maintenance Windowsを用い、起動スケジュールを作成（サービスに影響が少ない時間帯を設定）
- パッチグループ毎に、ウィンドウを登録
- タスクに、オートメーションタスクを登録する
    - オートメーションドキュメントを、"aws:executeStateMachine"とする。

上記で、パッチグループ毎にAWS Step Functionsを実行するウィンドウを作成しました。

ここで、「Maintenance Windowsのタスクで、RunCommand（"AWS-RunPatchBaseline")すれば
よいのではないか？」と疑問に持った読者の方も多いと思います。

AWS Step Functionsを使う理由は、
この後に設定する、前後ジョブが失敗した場合、
パッチ適用外にしたいからです。

### ６．サーバー毎に、パッチ適用時の前後ジョブの作成
- 事前/事後ジョブ（Shell）を作成
    - 各サーバーの特定ディレクトリに、.shファイルとして作成する
- （５．で作成した）AWS Step Functionsを編集
- パッチ適用タスクの前後に、Runcommand（"AWS-RunShellScript"）を定義
    - 各サーバーの特定ディレクトリのShellファイルを実行する
- 事前ジョブ失敗時、パッチ適用を行わず終了させるエラーハンドリングを作成

前後ジョブに関しては新たなルールを作り、
Shellファイルを特定のディレクトリに配置するルールに変更しました。

そうすることで、サーバー毎にジョブを作成しなくとも
共通的なStep Functionで実現することができます。

オンプレ時は、
サーバー毎に、前後ジョブを作成していました。

つまり、
約1000台のサーバーが存在するならば、
1000通りのジョブを作成、管理する必要がありました。

それをやめる事で、大幅に運用工数を下げる事ができました。

### ７．サーバー毎にパッチ適用
- （５．で作成した）AWS Step Functions内の、RunCommand（"AWS-RunPatchBaseline"）によってパッチが適用されます。

### ８．パッチ適用エラー時に、アラート通知
- （５．で作成した）AWS Step Functionsを編集
- 事前/事後ジョブ失敗時、アラート通知を行うAmazon SNS通知 APIを定義

最後に、6.で作成したエラーハンドリングに、アラート通知機能を実装します。

# まとめ
いかがでしたでしょうか。

責任共有モデル（開発者の責任を減らす）を意識し、マネージドサービスを多く使う事で
運用工数をかなり下げることができます。

是非、クラウド移行の際に参考にして頂ければと思います。