0
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?

More than 1 year has passed since last update.

Elastic Stack (Elasticsearch) Advent Calendar 2023Advent Calendar 2023

Day 4

AzureのログをさくっとElastic Cloudに送る方法

Last updated at Posted at 2023-12-04

この記事について

AzureのログをElastic Stackに送りたいけど、具体的にどうすればいいのか? 
基本的にはElastic Agentを使うことになりますが、どちらかというとログの転送のためのAzure側の設定が大変なので、そこをTerraformでさくっと作ってみます。

他のクラウド版の記事と含め最終的にはこのように3つのクラウドからログを集めることができます。
image.png

何のログを今回Elastic Cloudに送るか?

今回は以下の2つについてElastic Stackに転送してみます。

監査ログ (アクティビティログ)
アプリケーションログ (Azure Spring Appsのログ)

アーキテクチャー概要

今回のアーキテクチャーはこうです。

P                     P               T                  T
┌────────────────┐   ┌───────────┐   ┌──────────────┐   ┌────────────────┐                    
│Azure Spring App│   │Diagnostic │   │Log Analytics │   │   app logs     │                    
│  <<service>>   │──▶│settings   │──▶│data export   │──▶│ <<event hub>>  │──┐   M              
└────────────────┘   └───────────┘   └──────────────┘   └────────────────┘  │   ┌────────────┐
                                                                            │   │  Elastic   │
 P                    M                  T                                  ├──▶│   Agent    │
┌────────────────┐   ┌──────────────┐   ┌────────────────┐                  │   └────────────┘
│ Azure Monitor  │   │  Diagnostic  │   │  activitylogs  │                  │                 
│  <<service>>   ├──▶│   settings   │──▶│ <<event hub>>  │----------------──┘                 
└────────────────┘   └──────────────┘   └────────────────┘                              

P ... 事前に設定してある前提
G ... マニュアルで構成 (Azure MonitorのアクティビティログをエクスポートするCLI/Terraformは現在まだない模様)
T ... この記事のTerraformスクリプトで構成

元ネタは以下の公式ページにある図とのアーキテクチャーですが、今回はAzure Log Analyticsからデータを取るという形もやってみました。Log AnalyticsのData Exportというのを使うと、Event Hubにエクスポートできます。
https://docs.elastic.co/en/integrations/azure

手順

Step1. 以下のTerraformスクリプトを作ります。

main.tf
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>3.0"
    }
  }
}

variable namespace {}
variable location {}
variable table_names { type = list }
variable log-analytics-workspace-resource-id {}
variable log-analytics-resource-group-name {}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "azure-log-to-elastic" {
  name     = "${var.namespace}elastic"
  location = var.location
}

resource "azurerm_storage_account" "azure-log-to-elastic" {
  name                     = "${var.namespace}elastic"
  resource_group_name      = azurerm_resource_group.azure-log-to-elastic.name
  location                 = azurerm_resource_group.azure-log-to-elastic.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

output "azurerm_storage_account-name" {
  value = azurerm_storage_account.azure-log-to-elastic.name
}

resource "azurerm_eventhub_namespace" "azure-log-to-elastic" {
  name                = "${var.namespace}elastic"
  location            = azurerm_resource_group.azure-log-to-elastic.location
  resource_group_name = azurerm_resource_group.azure-log-to-elastic.name
  sku                 = "Standard"
  capacity            = 1
}

output "event_hub_connection_string_azure_to_elastic" {
  value = azurerm_eventhub_namespace.azure-log-to-elastic.default_primary_connection_string
  sensitive = true
}

resource "azurerm_eventhub" "activity-logs" {
  name                = "${var.namespace}_activity_logs"
  namespace_name      = azurerm_eventhub_namespace.azure-log-to-elastic.name
  resource_group_name = azurerm_resource_group.azure-log-to-elastic.name
  partition_count     = 2
  message_retention   = 1
}

output "azurerm_eventhub-activity-logs" {
  value = azurerm_eventhub.activity-logs.name
}

# =========== Log Analytics to Elastic ==============

resource "azurerm_eventhub" "springapplog" {
  name                = "${var.namespace}-springapplog"
  namespace_name      = azurerm_eventhub_namespace.azure-log-to-elastic.name
  resource_group_name = azurerm_resource_group.azure-log-to-elastic.name
  partition_count     = 2
  message_retention   = 1
}

output "azurerm_eventhub-springapplog" {
  value = azurerm_eventhub.springapplog.name
}

resource "azurerm_log_analytics_data_export_rule" "springapplog-to-elastic" {
  name                    = "${var.namespace}-springapplog-to-elastic"
  resource_group_name     = var.log-analytics-resource-group-name
  workspace_resource_id   = var.log-analytics-workspace-resource-id
  destination_resource_id = azurerm_eventhub.springapplog.id
  table_names             = var.table_names
  enabled                 = true
}

Step2. 以下の変数ファイルを作成します。値は例なので、適宜変えてください。

terraform.tfvars
namespace="test1204"
location="Japan East"
table_names = ["AppPlatformIngressLogs"]
log-analytics-resource-group-name="nobu-test_group"
log-analytics-workspace-resource-id="/subscriptions/xxx 省略 xxxx/resourceGroups/nobu-test_group/providers/Microsoft.OperationalInsights/workspaces/defaultworkspace-1cf2751a-e85c-4e4a-af37-cf8d9f00b985-lpqjiw7n"

Step3. terraform applyで反映します。その際以下のoutput値が出力されるので、これを後ほどのElastic Agentの設定で使います。(値は今回における例です)

azurerm_eventhub-springapplog = "test1204_activity_logs"
azurerm_eventhub-activity-logs = "test1204-springapplog"
azurerm_storage_account-name = "test1204elastic"
event_hub_connection_string_azure_to_elastic = "Endpoint=sb://test1204elastic.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxx 省略 xxx"

Step4. AzureモニターのアクティビティログをEvent Hubにエクスポートする設定

Azureモニターのアクティビティログのエクスポートを選択
image.png

診断設定を作成し、転送するログカテゴリを選び、イベントハブは上のTerraformで作成したものを選びます。
image.png

Step5. Azure Log AnalyticsからEvent Hubにエクスポートする設定

既に構成されてログを受け取っているLog Analyticsワークスペースを開き、データエクスポートを選択し、ルールを作成します。
image.png

今回はテーブルは1つ、Springアプリケーションへのアクセスログ(AppPlatformIngressLogs)を転送に指定します。
image.png

とここまで書いて気づきましたが、このStep5はTerraformに含まれていたので、手動でやる必要はありません。


ここまでで、Event HubにアクティビティログとSpringのアプリケーションログが送られている状態となっています。


Step6. Elastic AgentのVirtual Machinesへのインストール
この手順は詳しくは書きませんが、普通にVMにElastic AgentをインストールしてElastic Cloudに接続してください。Agentは1台だけでいいです。

Step7. Azure Log integrationの設定

さきほどのElastic Agentに割り当ててあるAgent Policyに対して以下の2つのIntegrationを作ります。
image.png

Springアプリケーションのログは、Collect events from Event Hubを指定します。
image.png

アクティビティログはCollect Azure Activity Logs from Event Hubを指定します。
image.png

結果

アクティビティログ

image.png

上記と同じ情報をElasticで確認できました
image.png

ES|QL
from logs-* 
| where event.dataset == "azure.activitylogs"
| keep azure.activitylogs.operation_name, azure.activitylogs.result_type, azure.activitylogs.event_category, @timestamp, 
azure.subscription_id, azure.activitylogs.identity.claims_initiated_by_user.name, azure.resource.provider, azure.resource.id
| sort @timestamp desc
| limit 100

アプリケーションログ (Spring アクセスログ)

image.png

アプリケーションログのような汎用的なログはElastic側はそのスキーマについて知らないので、デフォルトだとこのようにmessageフィールドに情報が全部入ってました。
image.png

ES|QLを使い、ログを見る時にGROKを使うとパースすることができます。(全部のGROK文かくのが大変なので、今回は2列だけ)
image.png

ES|QL
from logs-* 
| where event.dataset == "azure.eventhub"
| grok message "\\{%{GREEDYDATA:head}\"Host\":\"%{DATA:Host}\"%{GREEDYDATA:middle}\"TimeLocal\":\"%{DATA:TimeLocal}\"%{GREEDYDATA:tail}\\}"
| keep TimeLocal, Host
| sort TimeLocal desc
| limit 100

その他、Ingest Pipelineを作り、データをインデックスする過程で、messageのJSON文字列をフィールドに分割させることができます(こちらの方がES|QLで都度パースするより読み込み負荷が低く、推奨です)
Ingest Pipelineの名前をlogs-(指定したネームスペース).eventhub@customとすると、自動的にそれがインデックス時の処理に使われる仕組みになっています。
image.png

そうすれば、Pipeline追加以降のデータに関してはこのようにGROKを検索時にやらなくても表示できます。
image.png

おわり

続編として、Elastic AgentのところもTerraform化したいですね。

0
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
0
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?