EmotionTechテックブログ

株式会社エモーションテックのProduct Teamのメンバーが、日々の取り組みや技術的なことを発信していくブログです。

GCE Container-Optimized OSでNew Relic Synthetic Monitoring - Private locationsを動かしてみた

はじめに

こんにちは。エモーションテック SREチームのおかざきです。 今回はNew RelicのSynthetic MonitoringのPrivate locationsを GCE Container-Optimized OSで稼働させてみた際の環境構成について簡単にご紹介します。

この記事はエモーションテック Advent Calendar 2022の16日目の記事です。

突然ですが、皆さんの身の回りではこんなことはないでしょうか?

  • 開発環境はインターネットからのアクセスが制限されていたりして、監視SaaSを利用している場合は外形監視を組むのがちょっと面倒である

    例えば、IP制限によるアクセス制限の場合、よくある方法として監視SaaSグローバルIPファイアウォールの許可リストに追記する形があると考えるが、グローバルIPが動的だったり稀に入れ替わりがあったりして許可リストのメンテナンスが必要になる

  • 商用環境は監視するが、開発環境はコストが気になり監視の導入を躊躇ってしまう

かといって、開発環境を監視していないと、気が付いた時には環境が壊れていて試験がやり直しになったりして、生産的でないと考えます。

今回はIP制限された開発環境を外形監視するため、New Relic の Synthetic Monitoring を使ってみました。 理由としては以下になります。

  • Private locations機能により、IP制限等で外部からアクセスできない環境も監視可能
  • New Relic は監視対象ホスト数が課金に影響しないので、コスト面での導入ハードルが低い

Synthetic Monitoringで行いたかったこと

この記事では詳細は割愛しますが、 今回、Synthetic Monitoringで行いたかったこととしてはざっくり以下の通りです。

  • 開発環境エンドポイントの外形監視。ヘルスチェック用のエンドポイントを叩いてレスポンスコード200が返ってくることを確認
  • スクリプトを用いたアプリケーションの動作監
    • 開発環境アプリケーションへのログイン試行などの簡単な機能確認。アプリケーションとデータベース等の周辺リソースとの疎通確認を兼ねる

スクリプトを用いた監視を利用すると、「ログインAPIを叩いて認証トークンを受領し、 その後ログイン後にアクセス可能なエンドポイントへPOSTする。」 というような簡単なシナリオテストを書くことができます。 これにより、例えば認証サービスの稼働監視とその他の機能を提供するサービスの稼働監視が同時に可能です。 また、データベースなどのサーバ以外のリソースを含めた疎通確認も兼ねることができるので、開発環境が稼働していることの監視を効率よく行えると考えます。

Private locations の環境構築

Private locations を利用するには New Relic からCPMsというものがDockerイメージとして提供されています。

https://docs.newrelic.com/docs/Synthetic/synthetic-onitoring/private-locations/install-containerized-private-minions-cpms

You can use New Relic's containerized private minions (CPM). These are Docker container-based private minions that accept and execute synthetic monitors against your private locations. The CPM can operate in a Docker container system environment or a Kubernetes container orchestration system environment. The CPM will auto-detect its environment to select the appropriate operating mode.

なお、本記事執筆時点で、CPMsの後継としてSynthetics job managerというものがリリースされていますが、CPMsと比較すると対応機能が少ないようなので、この記事ではCPMsの導入に焦点を当てています。 *Synthetics job managerの末尾のLimitations参照。

このCPMsのDockerコンテナを動かす環境が必要になります。 今回はGoogle Cloudの GCE Container-Optimized OS を利用してみました。

GCE Container-Optimized OSを利用した理由は以下になります。

  • 自前でサーバ管理、特にセキュリティ面の管理を省力化したいため
    • Container-Optimized OS はコンテナを動かすことに特化していて、必要最小限のパッケージのみが導入されていたり、セキュリティアップデートが自動で適用される
    • GCEはデフォルトでIAM認証と組み合わせたSSH接続ができ、外部からのSSH接続を許可するファイアウォールルールを設定する必要がない
    • TerraformでGCE起動とコンテナ設定を完結可能
  • システムの規模的に監視用途のサーバをGoogle CloudのGKE上に建てたり、AWSのEKSやFargateを組むのはToo Muchと考えたため
  • 現行プロダクトはAWSメインであったが、少しずつGoogle Cloudの活用も検討しているため。

CPMsを稼働させるGCEのTerraform moduleを以下のように作成してみました。 設定のポイントについては下記の例中にコメントで記載しています。

module "gce-container" {
  # Google 提供のcontainer稼働用GCEのTerraform moduleがあったので利用した。
  source = "terraform-google-modules/container-vm/google"
  version = "~> 2.0"

  # コンテナの各種設定はNew Relicのドキュメントを参考にして記述した。
  # https://docs.newrelic.com/docs/Synthetic/synthetic-monitoring/private-locations/install-containerized-private-minions-cpms/
  container = {
    image = var.minion_image
    env = [
      {
        name  = "MINION_PRIVATE_LOCATION_KEY"
        value = var.NR_PRIVATE_LOCATION_KEY
      },
    ]
    volumeMounts = [
      {
        name      = "host-path-0"
        mountPath = "/tmp"
        readOnly  = false
      },
      {
        name      = "host-path-1"
        mountPath = "/var/run/docker.sock"
        readOnly  = false
      }
    ]
    tty : true
  }
  volumes = [
    {
      name = "host-path-0"
      hostPath = {
        path = "/run"
      }
    },
    {
      name = "host-path-1"
      hostPath = {
        path = "/var/run/docker.sock"
      }
    }
  ]
  restart_policy = "OnFailure"
}

# restart_policyは、GCPコンソール上で確認すると、OnFailure, Always, Noneのいずれかしか選択できないようだった。

# GCEのグローバルIPを固定する。このIPを開発環境のIP制限を行なっているファイアウォール等のAllow Listに設定する。
resource "google_compute_address" "external" {
  name   = "monitoring-gce"
  region = "asia-northeast1"
}

resource "google_compute_instance" "this" {
  name         = "monitoring-gce"
  machine_type = var.machine_type
  zone         = "asia-northeast1-a"
  boot_disk {
    initialize_params {
      image = module.gce-container.source_image
      size  = var.disk_size
    }
  }
  network_interface {
    subnetwork = var.sub_network_name

    access_config {
      nat_ip = google_compute_address.external.address
    }
  }

  # GCEのログ収集、メトリクス収集を有効化する。
  metadata = {
    gce-container-declaration = module.gce-container.metadata_value
    google-logging-enabled    = "true"
    google-monitoring-enabled = "true"
  }

}

resource "google_compute_firewall" "firewall_iap_rule" {
  name        = "monitoring-gce-default-nw-allow-iap-segment-rule"
  network     = "default"
  description = "IAP接続のために必要なNWサブネット(Cloud IAP バックエンド)からの通信を許可する"
  allow {
    protocol = "tcp"
    ports    = ["22"]
  }
  # Cloud IAPバックエンドIPアドレス
  # See: https://cloud.google.com/iap/docs/using-tcp-forwarding?hl=ja#preparing_your_project_for_tcp_forwarding
  source_ranges = ["35.235.240.0/20"]
}

variable "sub_network_name" {
  description = "GCEを接続するサブネット名"
  type        = string
  default     = "default"
}

variable "machine_type" {
  description = "GCEのマシンタイプ"
  type        = string
}

variable "disk_size" {
  description = "GCEのディスク容量"
  type        = number
}

variable "NR_PRIVATE_LOCATION_KEY" {
  description = "New Relic Private Location監視用のキー"
  type        = string
}

variable "minion_image" {
  description = "New Relicから提供されているPrivate Location監視用のDockerイメージのパスとタグ"
  type        = string
}

module呼び出しの記述例は以下の通りです。

module "newrelic_private_monitoring_server" {
  source           = "../modules/gcp_monitoring_server/"
  machine_type     = "e2-medium"
  disk_size        = 20

  # gcloud compute images list でマシンイメージ名を探せる
  machine_image           = "debian-cloud/debian-11"
  NR_PRIVATE_LOCATION_KEY = var.NR_PRIVATE_LOCATION_KEY

  # See: https://docs.newrelic.com/docs/synthetics/synthetic-monitoring/private-locations/install-containerized-private-minions-cpms#private-location-key
  minion_image = "quay.io/newrelic/synthetics-minion:latest"
}

所感

GCE Container-Optimized OSを利用するのは初めてでしたが、この検討を通じて制約事項を知ることができました。 例えば、Container-Optimized OSではコンテナを同時に一つまでしか起動できないようです。 可能ならDockerのNew Relic Infrastructure agentのDocker版も一緒に導入してGCE自体の監視をしたかったのですが、少々難しいようです。

*インターネット上の事例を調べるとdocker-composeを入れたコンテナを稼働させ、その中で複数のコンテナを動かすということをやっている事例も見かけますが...

今回は、GCE自体のメトリクスや死活監視を厳密に行うのではなく、Private Monitoring Jobのキューの滞留が起きていたらアラートを発報し、Google CloudコンソールからGCEのログやメトリクスを見たり、GCEに接続して状態を把握できれば良いと考え、 Infrastructure agentの導入は妥協しました。 なお、GCEはIAMで必要な権限を指定すればSSHで簡単に接続でき、かつIAP構成にすればSSH許可するファイアウォールルールを適用する必要が無い点も良いと思いました。

GCE Container-Optimized OSはコンテナをカジュアルに起動し、かつ最小限の設定で動かしたり運用を省力化したい場合に利用するのが良いと思いました。 より複雑なユースケースを想定する場合はGKEだったりAWS ECS、EKSの利用を考える方が良いかもしれません。

まとめ

今回はIP制限された環境をNew Relicを用いて簡単に動作監視するための環境を構築してみました。 仕組み自体は難しいものではないですが、一つ作っておけば開発環境が壊れたことに気が付かず無駄な稼働をかけてしまうようなことが防げて有用かなと思っています。

また、個人的には、Google Cloud にはコンテナ稼働させる環境として今回紹介した GCE Container-Optimized OS の他にGKEやCloud Run等もある中で、GCE Container-Optimized OS については今ひとつユースケースを思い浮かべられていなかったので、今回試してみることができたのは良かったと思います。

エモーションテックでは顧客体験、従業員体験の改善をサポートし、世の中の体験を変えるプロダクトを開発しています。 ぜひこの記事や他の記事を見て少しでも弊社に興味をもっていただけましたら、カジュアル面談も行っていますのでご応募お待ちしております。

hrmos.co

hrmos.co

hrmos.co