DataflowのSplunkテンプレートを用いてSplunk CloudにログをPUSHしてみた
概要
SplunkにGoogle Cloudのログを連携する方法は現在以下の2パターンがGoogle Cloudのリファレンスで紹介されています。
| 方式 | 概要 |
|---|---|
| PUSH方式 | Splunk側でHEC(Http Event Controller)を構築して、Google CloudからDataflowなどを用いてログをPUSHする方法。Google CloudからDataflowを用いる方法(テンプレート)が提供されている。サービスアカウントキーは不要。HECトークンをGoogle Cloud側で用いてログをPUSHする |
| PULL方式 | Splunk側でアドオンをインスタンスにインストールしてPub/SubトピックからPULLする方式。サービスアカウントキーが必要。Splunkにサービスアカウントキーをアップロードする。 |
PUSH方式のイメージ

PULL方式のイメージ

上記2つの方法のうち、Google Cloudが推奨しているのはPUSH方式です。
今回はGoogle Cloudが推奨しているPUSH方式を、Dataflowのテンプレートを用いて実現してみます。
Google CloudからPub/Subを用いたDataflowテンプレートが公開されているのでそれを使用します。
※PULL方式は実際に試してみて以前記事にしています
やってみる
前提
- HECトークンは作成済みであること
- Splunk Cloudに対してログ送信
構成と流れ
構成は以下のイメージです。

以下のリソースを作成します。
| リソース | 概要・役割 |
|---|---|
| Pub/Sub | PULL型サブスクリプション。シンクの向き先をこのトピックにする。DataflowがPULLしてSplunkへ送信(PUSH) |
| ログシンク | ログをPub/Subへ流すことでDataflowがPULLできるようにする。作成したPub/Subトピックへ向ける。今回は検証なので送信ログはフィルターしてテスト用だけ送る |
| Dataflow | Splunkテンプレートベースで作成。Pub/SubからメッセージをPULLしてSplunkへ送信する |
| VPC Firewall Rule | dataflowタグのついたトラフィックをIngress/Egressで許可。※必要に応じて |
手順としては以下となります。
- Pub/Subトピックとサブスクリプションを作成
- ログシンクを作成
- VPC Firewall Ruleを作成
- Dataflowのジョブを作成
- Splunkにログが送信されているか検証
それでは順番にやってみます。
1. Pub/Subトピックとサブスクリプション作成
コマンドで片付けます。実行するとPULL型のサブスクリプションが作成されます。
# トピック、サブスクリプションを作成
gcloud pubsub topics create splunk-logs
gcloud pubsub subscriptions create --topic splunk-logs logs-to-splunk
サブスクリプション作成時にPUSHするエンドポイントを指定しない場合はPULL型で作成されます。
Creates one or more Cloud Pub/Sub subscriptions for a given topic. The new subscription defaults to a PULL subscription unless a push endpoint is specified.
2. ログシンクを作成
続いて、作成したトピックにログをシンクするようにログシンクをコマンドで設定します。
# ログシンクを作成
gcloud logging sinks create my-logs pubsub.googleapis.com/projects/プロジェクト名/topics/splunk-logs \
--log-filter='logName:"projects/プロジェクト名/" NOT (resource.type = "dataflow_step" AND resource.labels.job_name = "Dataflowジョブ名") AND (resource.type = "cloud_run_revision" AND resource.labels.service_name = "Cloud Run関数名" AND resource.labels.location = "asia-northeast1" AND severity>=ERROR)'
検証用なので全てのログを連携するのではなく、--log-filterでフィルタをしています。Dataflowジョブ名を指定して動作させているDataflowジョブのログが流れないようにもしています。
そして、以下の記述で指定したCloud Run関数のエラーログだけを連携するようにしています。
resource.type = "cloud_run_revision" AND resource.labels.service_name = "Cloud Run関数名" AND resource.labels.location = "asia-northeast1" AND severity>=ERROR
コマンドの中で以下の項目は作成するDataflowジョブ・Cloud Run関数名に置き換えます。
| 設定項目 | 設定値 |
|---|---|
| resource.labels.job_name | Dataflowジョブ名 |
| resource.labels.service_name | Cloud Run関数名 |
他のログを設定したい場合などは以下をご参照ください。
3. VPC Firewall Ruleを作成
今回の検証ではEgressでタグdataflowを全て許可しています。こちらに関してはDataflow・VPC・Splunkの設定によって異なる箇所なのでご注意ください。実行する際はワークロードへの影響を十分事前にご検討ください。
以下のコマンドを実行するとdefaultVPCにEgressルールが設定されます。
# Egressの許可
gcloud compute firewall-rules create allow-dataflow-egress \
--direction=EGRESS \
--priority=1000 \
--network=default \
--action=ALLOW \
--rules=all \
--destination-ranges=0.0.0.0/0 \
--target-tags=dataflow
Egressを許可しないと、DataflowのワーカーからSplunk Cloudへのログ送信ができません。IP範囲に関してはSplunk Cloud、AWS・Google Cloudに構築した場合などで異なるのでより詳細に絞る場合は環境に応じた設定が必要です。
4. Dataflowのジョブを作成
Dataflowのコンソールのジョブを選択して、テンプレートからジョブを作成を押下します。

ジョブ名は適当な値を、リージョンエンドポイントはasia-northeast1を設定してDataflowテンプレートでPub/Sub to Splunkを選択します。

テンプレートを選択すると、設定項目がたくさん出てくるので最低限必要な項目だけ設定します。
| 設定項目名 | 設定値 | 役割 |
|---|---|---|
| Pub/Sub input subscription | (1.)で作成したPub/Subサブスクリプション | DataflowがPULLしてメッセージを取得 |
| Splunk HEC URL | SplunkのHEC URL | 注意点として、/services/collectorは記載してはいけません※。またSplunk Cloudの場合は8088のポート記載も不要です。AWSやGoogle CloudのEC2、GCEに自身でインストールしている場合はポート番号は必要となります |
| 一時的な場所 | Cloud Storage バケット | Dataflowの一時ファイルを書き込むためのバケット名とパス |
| Output deadletter Pub/Sub topic | (1.)で作成したPub/Subトピックまたは任意のトピック | デットレターを受け取る |
| ストリーミングモード | 正確に1回 | イベントの重複を排除 |
| HEC Authentication token | HECトークンの値 | Splunk側で発行するHECトークン |
| Disable SSL certificate validation | 任意 | SSL証明書の検証が不要な場合はチェック |
| Source of the token passed | PLAINTEXT | HECトークンをそのまま貼り付けた場合はPLAINTEXT。Secret Managerに保存している場合はSECRET_MANAGER。KMSを使用している場合はKMS |
| デフォルトのマシンタイプを使用する | 任意 | デフォルトn1-standard-1で問題なければチェック。検証なのでデフォルトのマシンタイプや低スペックのもので問題ない |
| ワーカーIPアドレスの構成 | 指定なし | 指定なしの場合、パブリック IP アドレスとプライベート IP アドレスの両方が割り当てられる。内部IP(プライベートIP)の場合はCloud NATなどVPC外との通信ができる仕組みが必要 |
| ネットワーク | デフォルト | 指定しない場合はdefaultが設定される |
上記を設定してジョブを実行を押下するとDataflowジョブが作成されます。

5. Splunkにログが送信されているか確認
Cloud Run関数のエラーログが流れるように設定しているので以下のソースでCloud Run関数を作成して実行します。
import functions_framework
@functions_framework.http
def hello_http(request):
raise ValueError("エラー発生")
return "OK"
この関数を実行すると、例外がスローされます。Cloud Functionsでは、未処理の例外がスローされると、HTTPステータスコード 500 Internal Server Errorが返されてseverity: "ERROR"のログがCloud Loggingに記録されます。よってログシンク作成時に設定したフィルタに引っかかるためSplunkへログが送信されるという寸法です。
実行した時のログ出力例は以下です。

関数を実行したらSplunk Cloudでログが連携されているかを確認します。

severity: ERRORの、logNameもGoogle Cloudのものがしっかりと記載されていました。
問題なくDataflowからSplunk CloudへログをPUSHできているのが確認できました!
Dataflowジョブの停止
一通り検証できたのでDataflowジョブは停止します。
停止を押下してキャンセルを選択してSTOP JOBを押下します。

ログシンクやPub/Subなども不要であれば削除してしまいましょう。
補足:HEC URLに関して
DataflowのテンプレートのHEC URLに/services/collectorを含めたHEC URLを設定すると以下のエラーをDataflowは吐き続けます。
Error message from worker: java.lang.RuntimeException: org.apache.beam.sdk.util.UserCodeException: java.lang.IllegalArgumentException: Invalid url format. Url format should match PROTOCOL://HOST[:PORT], where PORT is optional. Supported Protocols are http and https. eg: http://hostname:8088
このエラーが出た場合は、HEC URLに/services/collectorをつけてしまっていないかご確認ください。どうやらDataflow側で/services/collectorのパスを追加してくれているようです。
エラーメッセージにも以下の記載が出ていますので。
Url format should match PROTOCOL://HOST[:PORT]
URL 形式は PROTOCOL://HOST[:PORT] と一致する必要があります
見落としがちなのでご注意ください!
まとめ
Dataflowのテンプレートを用いることで実装することなくSplunkへログ送信することができました。PULL式では必要だったサービスアカウントキーの発行は不要でセキュリティ面ではかなり良いのですが一方でDataflowを使用しなければいけないため費用や構成の複雑さがネックにもなるなと思いました。
VPC Firewallの設定、場合によってはCloud NATも設定する必要がある、Dataflow障害発生時の切り分けや対処など、運用負荷が発生する可能性はあると思います。
PULL式、PUSH式を選定する上ではセキュリティ面以外で運用面も踏まえて考えたほうがよいと考えます。
ちなみに、私がこの検証をした時はEgressの許可やHEC URLでつまってしまいかなり時間がかかりました。私のDataflowへの理解力が低いということも一因ではありますが、そもそも使うサービスが[Pub/Sub、Dataflow、Splunk、VPC]と多岐にわたるためなかなか問題の切り分けに難儀しました・・・無事ログが連携できた時の喜びもその分大きかったですが(*´д`)
それではまた。ナマステー
参考






