blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2024.10.17 技術記事

DeNA 流 SaaS の外形監視手法

by Haruki Ido

#infrastructure #sre #saas #情シス #infra-quality

はじめに

こんにちは、IT 戦略部システム基盤グループの井戸です。

当グループは社内向けに様々なサービス(GitHub、Jira、Confluence など)を提供し、それらの運用を担当しています。最近では社内向けサービスに SaaS を活用する機会が増え、その数も増加しています。

SaaS を利用することは、従来のオンプレミスのサービスと比較していくつかのメリットがあると言われており、概ねその通りだと思います。

  1. 物理サーバーを購入する必要がないため、導入コストが低い
  2. 月額利用が一般的なため、利用開始や解約のハードルが低い
  3. ベンダーがセキュリティ対策を担当するため、ユーザーはセキュリティを意識する必要がない
  4. クラウド上でサーバーの管理が行われるため、物理的なスペースを確保する必要がない
  5. 障害時の対応はベンダーが行うため、自ら対応する必要がない

ただし、「障害時の対応はベンダーが行うため、自ら対応する必要がない」というのは一面的な見方だと考えています。SaaS 障害時の復旧作業はベンダーが担当するため、我々自身が直接対応する必要はありません。しかし障害発生時には、従業員からの問い合わせが我々サービス運用者に寄せられるため、その対応に追われることになります。

対応とは言っても復旧するまで基本的に待っているしかありません。だからと言って、障害発生に無関心でいたり、利用者である従業員から知らされるというのも良いことではないと思います。 そのため、SaaS に対しても適切な監視が欠かせません。

今回は当グループが取り組んでいる SaaS の監視についてご紹介したいと思います。

SaaS の監視方法

SaaS を監視するにはどんな方法があるか、考えてみました。

まず、各ベンダーが提供する SaaS の稼働状況を確認できるダッシュボード(例: Google Workspace ステータス ダッシュボード )があるので、ここから情報を取得する方法があります。

しかし、このダッシュボードにはいくつかの問題点があります。

  1. サービスごとに URL が異なるため、一覧性がない
  2. 全世界向けの情報である場合、日本に所属するユーザーにとって情報量が多すぎる
  3. リアルタイムでの更新が保証されていないため、障害検知に遅れる可能性がある

よって、SaaS ベンダーが提供するダッシュボードでは、私たちが求めている監視水準は得られないと判断しました。

そこで考えたのは、「あたかも人間が SaaS を利用しているかのようにアクセスを行い障害を検知する」方法です。この手法は一般的に「外形監視」と呼ばれるものです。

SaaS はその多くが Web アプリケーションの形態で提供されています。そうした Web アプリケーションの外形監視を実現するために、Selenium を採用することにしました。Selenium は Web アプリケーションの操作を自動化するツールであり、特定のシナリオを実行するのに最適です。

Selenium の詳細について興味がある方は、 selenium.dev をご覧ください。

Selenium を用いた SaaS の外形監視

それでは私たちが Selenium を使用して外形監視をどのように実現しているかを説明しましょう。

動作環境は AWS の EC2 インスタンス上です。 そのインスタンス内で、各サービスごとに Docker コンテナを用意し、それぞれのコンテナで Selenium を実行しています。
監視対象の SaaS ごとにコンテナを準備するので、新たに監視対象の SaaS が増えても、コンテナを追加するだけで Selenium による外形監視を行う環境を簡単に用意できます。

コンテナを起動する Docker Compose ファイルは以下です。

version: '3'
services:
  selenium:
    image: selenium/standalone-chrome
    container_name: 'selenium'
    volumes:
      - /dev/shm:/dev/shm
  confluence:
    restart: always
    build: ./conflu-monitoring
    container_name: 'conflu-container'
    working_dir: '/var/app'
    tty: true
    volumes:
      - ./:/var/app
    depends_on:
      - selenium
  jira:
    restart: always
    build: ./jira-monitoring
    container_name: 'jira-container'
    working_dir: '/var/app'
    tty: true
    volumes:
      - ./:/var/app
    depends_on:
      - selenium
(以下省略)

それぞれのコンテナでは以下のような cron を設定しており、Python で記述されたスクリプトを定期的に実行して、Selenium を呼び出しています。なお、cron の実行間隔はサービスの監視要件によって異なります。

SHELL=/bin/bash
PATH=/opt/gi/bin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
* * * * * root  cd /app && python main.py > /proc/1/fd/1 2> /proc/1/fd/2

では、Selenium のシナリオを Slack の監視を例に説明します。

Slack でのメッセージ投稿をシュミレートするために、一定の時間間隔で特定のチャンネルにメッセージを投稿し続ける Slack Bot を用意しました。

この Slack Bot のメッセージを確認するためには、認証を通過し、Bot が投稿しているチャンネルに移動した後、最新のメッセージを読むという動作が必要です。これをシナリオとして記述します。

この監視では投稿されたメッセージ文自体は重要ではなく、期待されている間隔で投稿されているかを見るために、メッセージの投稿された時刻を確認しています。

以下に、作成したシナリオのコードを示します。

# Slack のワークスペース名を入力
workspace_url = driver.find_element(
                                    By.CSS_SELECTOR,
                                    "input[data-qa='signin_domain_input']"
                                )
workspace_url.send_keys("xxxx.yyyy")

# Okta への認証画面を選択する画面へ移動
submit_button = WebDriverWait(driver, 30).until(
    EC.element_to_be_clickable((
        By.CSS_SELECTOR,
        "button[data-qa='submit_team_domain_button']"
    ))
)
submit_button.click()

# Okta の認証画面を選択
okta_signin_button = WebDriverWait(driver, 30).until(
    EC.element_to_be_clickable((
        By.ID,
        "enterprise_member_guest_account_signin_link_Okta"
        ))
)
click_element_with_retry(okta_signin_button)

# Okta の認証画面に到達したことを確認
WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.ID,"okta-sign-in")))

# ユーザー名とパスワードの入力欄へ認証情報を入力
username = driver.find_element(By.CSS_SELECTOR, "input[autocomplete='username']")
username.send_keys(okta_auth_info[0])
password = driver.find_element(By.CSS_SELECTOR, "input[type='password']")
password.send_keys(okta_auth_info[1])

# Sign In ボタンをクリック
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[data-type='save']"))).click()

# メッセージを定期投稿する Bot がいるチャンネルに移動
atlassian_monitoring_channel_button = WebDriverWait(driver, 30).until(
    EC.element_to_be_clickable((By.ID, message_post_channel)))
click_element_with_js(driver, atlassian_monitoring_channel_button)

# 全てのメッセージのタイムスタンプを取得し、
timestamps = driver.find_elements(
    By.CSS_SELECTOR,
    "div[role='listitem']"
)

# その中の最新メッセージのタイムスタンプを抽出
last_message_timestamp = timestamps[-1].get_attribute("data-item-key")
return last_message_timestamp

あとは取得したタイムスタンプを現在時刻と比較して、5 分以上の遅延がある場合は障害と判定しています。

同じような手法で、Slack の他にも、Okta、Atlassian(Jira / Confluence)などの監視を実現しています。このようにして、私たちが普段使っている様なアクセスを擬似的に行い、その結果を継続的に評価して、迅速に障害を検知できる体制を整えることができました。

DeNA サービスステータスダッシュボード

ところで、SaaS の障害が発生した場には従業員からの問い合わせに対応する必要があります。多くの場合、回答は障害の有無に関するものです。各種ベンダー提供のステータスダッシュボードは稼働状況を把握する手段の一つですが、「リアルタイムでの更新が保証されていない」などの問題があります。

そのため、当グループではベンダー提供のステータスダッシュボードを模倣して、社内の各サービスの稼働状況を一元的に把握できるステータスダッシュボードを開発・提供することにしました。

以下が実際に提供している DeNA サービスステータスダッシュボードです。

DeNA サービスステータスダッシュボード

DeNA サービスステータスダッシュボード

このダッシュボードでは、Selenium で外形監視をした結果を集約しており、各サービスに障害が起きているのかそれとも稼働中なのかを一目で把握することができます。

上記の取り組みにより、全ての従業員が DeNA で利用している各サービスの稼働状況をリアルタイムに確認できるようになり、不要な問い合わせや情報を求めて Slack を探し回るといった時間を削減できるようになりました。

今後の展望

今回は、SaaS の外形監視に焦点を当てて説明しましたが、当グループでは SaaS 以外にも VPN や Active Directory などの他のシステムも運用しています。
今後はこのような SaaS 以外に対する監視も強化していく予定です。

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。