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?

エンジニア体験を守るために、社内開発環境向けの可観測基盤を OSS+Zabbix で構築した話

Last updated at Posted at 2025-12-14

社内の横断チームとして、

「エンジニアが快適に開発できる環境をつくる」

ことをミッションにしています。

その一環として、Jenkins ベースの CI / CD 基盤や GitLab などの 開発環境そのものを「社内向けサービス」 とみなし、エンジニアを「ユーザ」として扱って SLO(Service Level Objective、サービスレベル目標) を意識した可観測基盤を構築しました。

この基盤は、既にZabbixによるインフラ監視が導入されていたため、これを活用しつつ、OSSツールを組み合わせて可観測基盤を構築しました。

なお、記事中のホスト名(obsv-server / zabbix-server など)は、説明用の例です。

想定読者

  • CI / CD や GitLab を「社内向けサービス」としてちゃんと運用したい
  • OpenTelemetry / Jaeger / Loki / Grafana / Zabbix を組み合わせた構成例を知りたい
  • 「監視」はあるけど、開発者体験(DevEx)や SLO まで踏み込みたい

という SRE / プラットフォームエンジニア / 内製開発チーム向けです。

背景:開発環境も立派な「サービス」だった

横断チームで面倒を見ている主な開発環境はこんな感じです。

  • Jenkins:CI 基盤(静的解析や自動テスト)
  • Jenkins:CD 基盤(ビルドやデプロイ)
  • GitLab:ソースコード管理
  • 開発対象のアプリケーション:
    • 開発用共有環境(コンテナ構成)
    • 検証用環境(コンテナ構成)
  • 可観測基盤を構成する各種 OSS コンテナ群(Jaeger / Loki / Grafana など)
  • 監視:Zabbix(インフラ監視)

ここで困っていたのは、例えばこんな状況でした。

  • Jenkins が詰まると、各プロジェクトの開発が全部止まる
  • マルチブランチ + Git pull で、ストレージがじわじわ逼迫
  • 「最近 CI が重い」という声に対しても、メトリクスがないため、CI/CD のパフォーマンス低下を定量的なデータで説明できない

本番プロダクト側はそれなりに SLO や監視が整っている一方で、開発環境の監視には改善の余地があり、「落ちたら復旧する」「重くなったらチューニングする」レベルに留まっていました。

そこで発想を変えて、

CI / CD・Git などの開発環境も「社内向けサービス」
その利用者であるエンジニアを「ユーザ」とみなし、
SLO を意識して可観測性を整える

という方針に切り替えました。

要件整理:何を観測したかったのか?

まずは「何を知りたいのか」をざっくり言葉にしました。

観測したかったもの

  • サービスの実行状況
    • ジョブ成功率・失敗率
    • ジョブキュー待ち時間
    • 各ステージの実行時間
    • コンテナの稼働状況
       
  • リソース・ストレージ
    • ディスク使用率
    • メモリ使用率
    • リソース逼迫の状況
       
  • ログ・トレース
    • どのステージで遅くなっているか
    • 失敗時に何が起きていたか

設計ポリシー

  • できるだけ OSS を組み合わせて構成する
  • メトリクス収集は既存の Zabbix を使い、二重化しない
  • 「入口」「出口」を後から差し替えやすい構造にする
  • 「開発環境向け」なので、運用コストも現実的な範囲に収める

全体アーキテクチャ

最終的に、ざっくり以下の構成に落ち着きました。

  • Jenkins(CI / CD)
    • OpenTelemetry プラグインでトレース・ログを送信
  • OpenTelemetry Collector(以下、OTel Collector
    • Jenkins から OTLP(トレース/ログ)を受信
    • Jaeger(トレース)と Loki(ログ)に転送
  • Jaeger + Cassandra
    • トレースデータの永続化
  • Grafana Loki
    • ログの保存・検索
  • Grafana
    • Jaeger / Loki / Zabbix をデータソースとして統合ダッシュボード化
    • アラート設定 + Slack 通知
  • Zabbix(既存監視)
    • 各サーバの CPU / メモリ / ストレージなどのメトリクス取得
    • Grafana からデータソースとして参照

役割分担を一言でいうと:

メトリクス:Zabbix
ログ:Loki
トレース:Jaeger
ダッシュボード:Grafana

という構図です。

可観測基盤forQiita.png

OTel Collector の構成

OTel Collector には、「トレースとログのハブ」という役割に専念させています。
メトリクスはあえて扱わず、Zabbix に完全に任せる構成です。

config.yaml のイメージ

/etc/otelcol-contrib/config.yaml は、ざっくりこんな構成です。

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4320"
      http:
        endpoint: "0.0.0.0:4330"

exporters:
  otlp:
    endpoint: obsv-server:4317
    tls:
      insecure: true
  loki:
    endpoint: obsv-server:3100/loki/api/v1/push
  debug:
    verbosity: detailed

processors:
  batch:
    send_batch_size: 1024
    timeout: 5s

extensions:
  zpages:
    endpoint: 0.0.0.0:7777
  health_check: {}

service:
  extensions: [zpages, health_check]
  pipelines:
    traces:
      receivers: [otlp]
      processors: []
      exporters: [otlp, debug]
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [debug, loki]

  telemetry:
    logs:
      level: "debug"
    metrics:
      level: detailed
      address: ":8888"

ポイント:

  • receivers.otlp

    • gRPC: 4320
    • HTTP: 4330
  • pipelinestraceslogs のみ(メトリクスは扱わない)

  • exporters

    • Jaeger(OTLP gRPC)へトレース送信
    • Loki の HTTP API へログをプッシュ

OTel Collector の役割は一言で言うと、

Jenkins →(OTLP)→ OTel Collector → Jaeger / Loki

の「真ん中の中継+フォーマット変換」です。

Jenkins:OpenTelemetry プラグインでトレース・ログ送信

Jenkins 側では、次のプラグインを利用しています。

  • OpenTelemetry
  • Remoting monitoring with OpenTelemetry

設定例(System 設定):

  • OTLP Endpoint
    http://obsv-server:4330

    • OTel Collector の OTLP/HTTP ポート(4330) に合わせています
  • Authentication:なし(社内ネットワーク内で完結)

OTel Collector 側の設定では、

  • gRPC: 0.0.0.0:4320
  • HTTP: 0.0.0.0:4330

としているので、今回は Jenkins → OTLP/HTTP → OTel Collector という構成です。
(gRPC を使いたい場合は、Jenkins 側の設定を gRPC にして obsv-server:4320 を指定する想定)

これにより:

  • ジョブ単位のトレースが取れる
  • 各ステージの所要時間・エラーがトレースに紐づく
  • ジョブ履歴画面から OpenTelemetry アイコン経由でトレースを辿れる

といった形で、Jenkins が可観測基盤の入口になります。

Jaeger + Cassandra:トレースの永続化

トレーシングのバックエンドには Jaeger を採用しました。

  • Jaeger all-in-one コンテナを obsv-server 上に起動

  • ストレージには Cassandra を利用

    • Jaeger 用の Keyspace を作成
    • Jaeger 公式スキーマを実行してテーブル作成

Jaeger の UI から直接トレースを見ることもできますが、運用上は

Grafana から Jaeger をデータソースとして参照

する使い方に寄せています。

理由:

  • ダッシュボード上で「メトリクス → トレース → ログ」と辿りたい
  • ツールを行き来するより、Grafana に寄せた方が運用しやすい

Loki:ログストア(ログだけ見る、トレースは Jaeger に任せる)

ログは Grafana Loki に集約しています。

  • Jenkins のコンソールログ
  • OTel Collector 経由で送られてくるアプリケーションログ(必要に応じて)

ここで重要なのは:

  • Loki はログ(Log)を扱うツール
  • トレース(Trace)を扱うのは Jaeger

という役割分担です。

OTel Collector はクライアントから OTLP(トレース/ログ) を受け取り、Loki Exporter が Loki の HTTP API に対してログをプッシュする構成になっています。

ラベル設計は最初から作り込みすぎず、例えば:

  • job="jenkins"
  • Jenkins ジョブ名
  • ビルド番号

くらいから始めて、運用の中で「欲しい切り口」が見えてきたところから増やしていきました。

Grafana:ダッシュボードとアラートのハブ

Grafana は、

  • Jaeger(トレース)
  • Loki(ログ)
  • Zabbix(メトリクス)

をまとめて扱うハブとして使っています。

データソース構成

  • Jaeger

    • URL:http://obsv-server:16686/
    • 「Trace to logs」を設定し、トレースから Loki のログにジャンプできるようにする
  • Loki

    • URL:http://obsv-server:3100/
  • Zabbix

    • URL:http://zabbix-server/api_jsonrpc.php(例)

代表的なダッシュボード

  • メモリ / ディスク使用率(Zabbix)
    メモリディスク使用率.png

  • 実行時間分布(Jaeger)
    パイプラインの実行時間分布.png

  • ジョブの詳細(Jaeger)
    ジョブの詳細(Jaeger).png

Alerting(Slack 連携)

  • 閾値を超えたら Slack の特定チャンネルへ通知

  • Contact point(通知先)とメッセージテンプレートを定義しておく

  • 例:

    • Jenkins ノードのメモリ使用率が 70% 超:Warning(Slack 通知)

    • Jenkins ノードのディスク使用率が 70% 超:Warning(Slack 通知)

      アラート設定.png

  • アラートは Zabbix のデータ送信間隔、および稼働時間を踏まえて設定し、
    「まだメトリクスが届いていないだけで No Data 判定になる」パターンを避けています。
    • Zabbix のデータ送信間隔を踏まえ、閾値超過の状態が 5 分間続いた場合にアラートが発火するよう設定
      Pending period.png

    • Zabbix が稼働している時間帯以外にはアラートが発信されないよう、ミュートタイミング(mute timing)を設定
      mute timing.png

Zabbix:メトリクスの収集

メトリクスの収集はすべて Zabbix に任せています。

  • 各サーバに Zabbix エージェントを導入
  • CPU / メモリ / ディスク / ネットワークなどを計測
  • Zabbix 本体でもアラートを設定できるが、
    今回は 可視化と通知は Grafana に寄せる 方針

こうすることで:

  • エージェントの運用は既存の監視チームのフローに乗せられる
  • 新たにメトリクス収集スタックを増やさなくて済む
  • 可視化とアラートのルールを Grafana 側で統一管理できる

というメリットがありました。

「エンジニアをユーザとみなした」SLO の考え方

ガチガチな数値 SLO というよりは、まずは「エンジニアの体感」に近いラインを決めています。

例:

  • ジョブの実行状況

    • 平日日中のジョブ成功率:99% 以上
       
  • メモリ、および、ストレージの使用率:

    • 70% 超:Warning
    • 90% 超:Critical

これらを可観測基盤でモニタしつつ、
超えたら Slack にアラート、という運用にしています。

イメージとしては、

「エンジニアがイライラし始めるライン」をSLO の目安として可視化する

感じです。

実際に効いたところ

1. ストレージ逼迫を「兆候」で捉えられるようになった

マルチブランチの CD 基盤では、ブランチ数や実行回数に比例して、

  • Jenkins ワークスペース
  • アーティファクト
  • Git クローン

などがストレージを消費します。

導入前は、

  • メトリクスがないため、パフォーマンス低下を定量的データで把握できていなかった
    → 「最近パイプラインが重い気がする」と感じてから確認に行くと、ストレージ使用率 95% 超え
    → 慌てて古いジョブやアーティファクトを削除

といった、従来の事後対応中心の運用から脱却する必要がありました。

導入後は、

  • Zabbix → Grafana でストレージ使用率のトレンドを可視化

  • 余裕を持って

    • ローテーション設定見直し
    • クリーンアップジョブの追加
    • ストレージ増強を検討

といった 事前の一手 を打てるようになりました。

2. Jenkins の「なんとなく遅い」をデータで説明できるようになった

「最近 Jenkins 重くない?」という声に対しても、

  • トレース(Jaeger)
    どのステージで時間がかかっているか

  • ログ(Loki)
    そのタイミングでエラー・リトライが発生していないか

  • メトリクス(Zabbix)
    その時間帯の ストレージ / メモリ の状況はどうか

を一緒に見ることで、

  • 特定時間帯にジョブが集中しすぎている
  • 一部ジョブのステップが無駄に重い
  • ストレージの余裕がなくなりそう

といったことを 定量的に説明 できるようになりました。

3. チーム内に「サービスとしての開発環境」という意識が根付いた

一番効いたのは、横断チーム側のマインドセットかもしれません。

  • CI / CD / Git / 可観測基盤を「社内向けプロダクト」として扱う
  • 社内エンジニアを「そのプロダクトのユーザ」とみなす
  • ユーザ体験を守るために SLO と可観測性を整える

という視点で会話できるようになり、

「とりあえず動いていれば OK」
から
「サービスとしてどんなレベルを維持するか」

という運用にシフトしてきています。

まとめ

  • Jenkins / GitLab / 各種開発サーバといった 社内開発環境を「社内向けサービス」 と捉え直し、エンジニアをユーザとみなして SLO を意識した可観測基盤を構築しました
  • メトリクスは既存の Zabbix をメインに据えつつ、トレースとログを OpenTelemetry+Jaeger+Loki で扱い、Grafana で統合しています
  • その結果、ストレージ逼迫やジョブ遅延を“兆候”で捉えられるようになり開発者、開発者体験に直結する SLO を意識した運用に一歩近づけました

同じように「開発環境をちゃんとしたサービスとして運用したい」と考えている方のヒントになればうれしいです。

補足:Cassandra は開発環境向けの 1 ノード構成

ここで使っている Cassandra は、「開発環境の可観測基盤」という位置づけのため 1 ノード構成 で運用しています。

本番用途で Jaeger + Cassandra を採用する場合は、レプリカ数や障害時の自動復旧を考えると 3 ノード以上のクラスタ構成が推奨 されます。
一方で、今回の構成では次のような割り切りをしています。

  • 対象は開発環境のトレースであり、一部トレースの欠損は許容する
  • 保存期間も比較的短めにし、ストレージ要件を抑える
  • 追加のサーバを増やさず、既存の仮想基盤上のリソースで収める

つまり、「まずは開発者が困っている CI/CD の見えにくさを解消する」ことを優先し、 可用性やスケール要件は本番プロダクトほどは求めていない、というバランスになっています。

本番環境で同様の構成を検討する場合は、この 1 ノード構成をそのまま真似するのではなく、 Cassandra のクラスタ構成やストレージ設計を自分たちの SLO・障害許容度に合わせて見直すことをおすすめします。

補足:Jenkins 単体+プラグインとしなかった理由

よくある疑問として、

「Jenkins のプラグインを入れれば、監視やメトリクスはだいたい見えるのでは?」

というものがあります。実際、Jenkins 単体でもジョブの実行時間や成功率、ノード負荷、ビルドログの閲覧などはある程度カバーできます。

しかし、今回対象にしているのは CD 用 Jenkins だけでなく、CI 用 Jenkins、GitLab、コンテナ上の SaaS アプリ(開発者用/UI 単体テスト用)、さらにそれらを支えるインフラや可観測基盤のコンテナ群まで含めた「開発者が日常的に触る一連の環境」です。

Jenkins 単体+プラグインだけで観測しようとすると、次のような限界がありました。

  • 視点が Jenkins に閉じてしまい、GitLab や SaaS アプリ、インフラの状態を含めた「エンドツーエンドのサービスレベル」として捉えにくい
  • Zabbix のメトリクス/アプリログ/トレースを 1 つのダッシュボードで突き合わせて「この時間帯に何が起きていたか」を追うことが難しい
  • 可観測性の仕組みを Jenkins プラグイン前提にすると、将来 CI/CD ツールや構成を変えたときに監視基盤ごと作り直すリスクがある
  • 監視系プラグインを積みすぎると Jenkins 自身の負荷・安定性にも影響しやすい

そこで、Jenkins は「ジョブを実行してトレース/ログを出力するだけ」とし、OTel Collector / Jaeger / Loki / Grafanaを組み合わせて、開発環境全体を可視化できる構成としています。

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?