NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

注目のタグ

    SSMって20種類あんねん 〜Run Commandで定期バッチを起動する〜

    どうも。小林です。
    みなさん、自動化してますか?

    私の課では特定の顧客のシステムを多数運用しています。
    かなり多くのシステムがあり、顧客側の担当者も異なるため、弊社側でも複数のチームを組んで手分けしてシステムを担当しています。

    チームも顧客担当者も異なるとなれば、当然運用のやり方はシステムごとに変わってきます。その一方で統一できる部分は統一しておかないと全体の統制は効きづらくなってしまいます。
    そこで「標準化チーム」を発足し、チーム間で共用するシステムのアカウント管理やその申請ルール、顧客報告やメンバーの勤怠管理といったものの標準化を進めています。

    標準化の恩恵のひとつとして、「作業が単純化できて自動化しやすくなる」という点が挙げられます。
    例えばアカウント発行の申請フォーマットを統一すると、「フォーマットにしたがって記載されたテキストをバッチに読み込ませてアカウントを自動的に発行する」ということができます。

    当初は手作業が多かったのですが、こういった活動を通して多くの作業を自動化することができてきました。

    ここまで来るとバッチ実行すら勝手にやってほしいですよね?

    さて、ではどこでバッチを動かしましょうか?
    そもそも「標準化チーム」は特定のシステム担当ではないので自由に使えるサーバというものを持っていません。

    どこで動かそうか…?

    サーバ…サーバ…

     ・
     ・
     ・

    あ、ありました。
    以前作った踏み台サーバです。

    tech.nri-net.com
    tech.nri-net.com

    ここにバッチスクリプトを置いて、cronで自動実行を設定して…
    動いた!

    となったところで気付きました。
    これ、個人ユーザでcronを動かしたら他の人が管理できなくない?

    そうです。我々は標準化"チーム"なのです。チームメンバーみんなで運用していかねばならないのです。

    少し考えて思い出しました。踏み台に使ったSSMを。
    SSMの機能のひとつに「Run Command」というサーバのコマンドを実行する機能があることを。

    やってみた

    前置きが長くなりましたがやってみます。

    構成のイメージはこうです。

    この形にすればEventBridgeコンソールで実行スケジュールの管理ができ、SSMコンソールで実行結果の確認ができるはず。

    今回はテストも兼ねて新しく作った勤怠管理報告用Redmineチケットの自動作成バッチを動かしてみます。

    Run Commandで呼び出すコマンド

    対象のバッチスクリプトはRubyで書かれており、実行環境としてgemの事前インストールが必要です。
    bundlerを利用しているのですが、bundle installが完了している環境をコンテナイメージとして用意し、Run Commandからはそのコンテナを呼び出すことにしました。

    こういうDockerfileを書いてビルドし、Dockerイメージを作ります。

    FROM ruby:3.1.4-bullseye
    
    WORKDIR /app
    COPY Gemfile /app/Gemfile
    COPY Gemfile.lock /app/Gemfile.lock
    COPY *.rb /app/
    RUN bundle install
    
    ENTRYPOINT ["bundle","exec","ruby"]
    CMD ["--version"]

    するとこんなコマンドで特定のRubyスクリプトを実行できます。

    docker run --rm <Dockerイメージ名> xxxxx.rb

    SSMコンソールからRun Commandのコマンドの実行画面を開き、コマンドドキュメントの「AWS-RunShellScript」を選択します。

    ここにコマンドを書いてっと…

    「ちょっと待てぃ!!」

    はい。ダメですね。APIキーを直接書いちゃ。
    SSMの機能のひとつ、Parameter Storeに格納して変数として与えましょう。
    (本来は機密情報はKMSを利用したSecureStringにする方が良いですが、ここでは一旦この形で説明します。)

    動かしてみるとこんな感じでログも出ます。ログはS3やCloudWatch Logsに書き出すことも可能です。

    ちょっとわかりにくいポイントなのですが、ログをS3およびCloudWatch Logsに出力するときはコマンドを実行するEC2インスタンスロールに出力先のサービスへの書き込み権限が必要となりますのでご注意ください。

    EventBridgeから呼び出す

    さて、これをEventBridgeから呼び出してみましょう。

    EvendBridgeコンソールからスケジュールを作成します。
    cron形式で指定できるのですがこのように動く日を明示してくれるのは便利ですね。

    ターゲットはSendCommandを選択します。(「Run Command」は無いので要注意)
    どうやらSSMの機能名が「Run Command」、API名が「SendCommand」や「CancelCommand」のようです。 docs.aws.amazon.com

    入力はこう指定します。

    {
      "DocumentName": "AWS-RunShellScript",
      "DocumentVersion": "1",
      "InstanceIds": [ "<インスタンスID>" ],
      "MaxConcurrency": "50",
      "MaxErrors": "0",
      "Parameters": { 
        "workingDirectory":[""],
        "executionTimeout":["3600"],
        "commands":["docker run --rm <Dockerイメージ名> xxxxx.rb"] 
      },
      "TimeoutSeconds": 600
    }

    指定時間後にRun Commandの履歴を見るとちゃんと動いてました!
    (時間変更して動かしたので↑の画像とは時刻が違いますが)

    これでチームメンバーにEventBridgeの操作権限とSSMの参照権限を与えれば起動設定とログのチェックがチーム全員でできますね。

    まとめ

    ということで、無事にやりたかったことが追加のコストをかけずに実現できました。
    (DockerイメージをECRに格納する。KMSを使ってParameter Storeの格納文字列を暗号化する。などコストを掛けることで可用性やセキュリティレベルを上げることもできます。)

    SSMってほんと多機能で便利ですね。
    今ざっと数えると20ぐらいの機能がありました。

    そして現在使っているのはこれ。

    • 踏み台へのアクセスに利用している「Session Manager」
    • Windows踏み台のOSパッチ適用に使っている「State Manager」
    • 今回使ったコマンド実行のための「Run Command」
    • 今回使ったパラメータ格納のための「Parameter Store」
    • 今回使ったシェルコマンド実行方法を定義する「Documents」

    まだまだ使い尽くせてはいないですね…

    以前はわた推しサービスとしてDynamoDBを挙げましたが、今はSSMが最有力かなと思っています。

    執筆者小林恭平

    2021-2024 APN ALL AWS Certifications Engineers
    2021-2023 AWS Top Engineer
    IPA13冠、AWS12冠(どちらも全区分)
    大阪で主にインフラのお仕事してます。
    技術書もいくつか書いてます。

    Twitter:@kobakoba09

    Amazon 著者ページ:小林 恭平:作品一覧、著者略歴 - Amazon.co.jp