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?

本記事について

本記事ではAzure Monitor Pipeline (AMP)の構築の流れと構築時のハマりどころを紹介します。
AMP自体の機能紹介やユースケースは別記事にまとめていますので、よろしければこちらもご参照ください。
Azure Monitor Pipelineを使ったオンプレ機器の監視を考える

また、細かい構築手順までは紹介していませんので、ドキュメントと合わせて参照ください。
MS Learn | Azure Monitor パイプラインを構成する

前提条件

まずは構築の前提ですが、AMPが実行できるのはArc-enabled k8sになります。
そのため、k8s環境からAzureへのアウトバウンド通信が必要です。
ネットワークはAzure Arc Gatewayを利用して宛先FQDNを絞ったり、プロキシを利用したり、ExpressRoute等を介してプライベートエンドポイント経由でおこなうこともできます。

さらにk8sのディストリビューションとバージョンについてもサポート構成が定義されています。
2026年6月現在サポートされるディストリビューションはAKS Arc (Azure Local上のAKS)、VMware Tanzu Kubernetes Grid (TKG)、k3sの3つです。
現時点ではパッチバージョンまで指定されており、参考までにAKS Arcでは1.32.7のみがサポートバージョンと記載されています。
ただし、現時点で既にAKS Arcの最新バージョンは1.33がリリースされており、本記事での検証も1.32.9で動作確認していますので、ドキュメントの更新遅れな部分もあるかもしれません。

最新のサポートバージョンと対応リージョンはこちらをご確認ください。(2026年6月現在東日本リージョンはサポート、西日本は未サポート)
MS Learn | サポートされている構成

なお、AMPはcert-manager拡張機能に依存しているため、cert-manager拡張機能のサポートバージョンもチェックしておきましょう。(こちらは記事執筆時点でAKS Arcの1.33.5や1.32.9が動作確認済みになっています)
MS Learn | Azure Arc対応Kubernetesのcert-managerとは

また、知らないと見落としがちなポイントとして以下も記載しておきます。
前者はk8sに慣れている方なら一般的かもしれませんが、クラウド環境と違いオンプレでは自動でAzure Load Balancer等が用意されるわけではないので気をつけましょう。

  • k8sがk8sクラスター外 (インターネットからではなく、オンプレ内のSyslog/OTLPを送信する機器)からの通信を受信できるようにロードバランサーを構成しておく。(例: MetalLB等)
  • CEF形式のSyslogをCommonSecurityLogテーブルに保存する場合 (CommonSecurityLogテーブルを使いたい場合)はLog AnalyticsワークスペースでSentinelを有効化しておく。

構築の流れ (AKS Arc)

構築の流れは冒頭紹介のドキュメントにセットアップフローとして記載されていますが、少し噛み砕きつつ記載すると以下になります。
なお、AKS Arc (Azure Local上)を前提に記載していますのでTKGやk3sの場合では事前にArc-enabled k8s化する作業など、一部手順が異なります。

細かい手順の説明はおこないませんが、私が検証した際のコマンドは参考までに後半に記載しています。

  1. Azureの事前準備
    1. リソースプロバイダーの登録
    2. Log Analyticsワークスペース構築
    3. (任意)Sentinelの有効化 ※CEF形式のログをCommonSecurityLogテーブルに保存したい場合
    4. (任意)Log Analyticsワークスペースでカスタムログテーブルを作成 ※既定のSyslog/CommonSecurityLogテーブルに取り込めない形式を使う場合
  2. k8sの事前準備
    1. (任意)k8sをArc-enabled k8sとしてAzureに接続 ※AKS Arcの場合は不要
    2. k8sにcert-managerをインストール
    3. k8sクラスター外からの通信経路準備 (MetalLBのデプロイ等)
  3. k8sにパイプライン拡拡張機をインストール
  4. カスタムロケーションの作成
  5. データ収集エンドポイント (DCE)の作成
  6. データ収集ルール (DCR)の作成
  7. k8sのパイプライン拡張機能にDCRへのロールを付与
  8. AMPの作成
  9. Traefikゲートウェイをデプロイ

ハマりどころ

Azureポータルからのデプロイの前提の見落としに注意!

ドキュメントの記載から分かりづらいのですが、AzureポータルでのAMPデプロイ前にはカスタムロケーションの作成が必須です。そして、カスタムロケーションの作成にはk8sにパイプライン拡張機能のインストールが必要になります。
この点がAzureポータルからのデプロイ手順のドキュメントからは読み取りづらいので注意しましょう。私はここで一度詰まってCLIからの手順に切り替えました。

一方で、CLIの手順を見ていただくと、上記フローの通りにパイプライン拡張機能をk8sにインストールし、その拡張機能のリソースIDをカスタムロケーションのデプロイ時に指定するという作業が示されています。
Azureポータルからのデプロイでもここまでの準備は必要になりまして、構築フローの4番までは済ませた上で、ポータルからパイプラインのデプロイをおこなうことで5~8をまとめて実行してくれるという流れになっています。

個人的にはAzureリソースとk8s内のポッドやサービスの対応を理解しながら進められますのでCLIからのデプロイをおすすめします。

collectorコンテナ、Traefikゲートウェイコンテナでポート514 (ウェルノウンポート)が開放できないため内部利用するポート番号の変更が必要!

ココが一番の詰まりどころだったのですが、ドキュメントの例に従ってAMPをデプロイするとAMP内のreceiverにおけるcollectorコンテナでポート514を開放できずSyslogが受信できません。
先にAMPの構成を補足すると、AMPのパイプラインはOpenTelemetryコレクターをベースにしているため、receiver、processor、exporterの3つのコンポーネントから構成されています。
OpenTelemetryコレクターのアーキテクチャはこちらが参考になります。
OpenTelemetyr | アーキテクチャ

名前の通りreceiverがSyslog/OTLPを受信し、processorがSyslog/CEFフォーマットの自動パースやクラウド送信前の自動変換&フィルタリング、exporterがDCE経由でのLog Analyticsへのデータ送信を担います。
この中で、receiverを構成するコンテナの1つであるcollectorコンテナに問題があるように見受けられました。
どうもcollectorコンテナの元になっているイメージ自体の問題で、私が動作確認した際のイメージazuremonitor/otel-arrow-internal:0.2.14では、以下のように特権がないためにエラーが出ています。
port-binding-error.png

同じくTraefikコンテナも同様にポート514が開放できていませんでした。
こちらはAMPの問題では無いため、やりようはあると思われますが、collectorコンテナのポート変更が必要なことも踏まえて、Traefikがクラスター外部に公開するポートのみ514として、Traefikおよびcollectorコンテナは1514等の非ウェルノウンポートに変更することで私は回避しています。
設定箇所は以下になります。

  • AMPのSyslog受信ポート (GUIからも変更可)
    • AMPのreceiverの定義におけるendpointの指定箇所
  • TraefikのIngressRouteTCP (UDP)における宛先collectorのポート指定
    • Traefikのルーティング設定におけるspec.rooutes.services.portの指定箇所
  • Traefikデプロイ時に指定するポート指定
    • helm install時のports.tcp-syslog.port (ports.udp-syslog.port)の指定箇所

SyslogにおけるPRIの有無に注意!

Syslogには先頭にPriorityやSeverityを示すPRIというフィールドが設定されていますが、機器ごとのログフォーマットによってPRIの有無が異なります。
AMPではDCR内で収集するログ定義を設定できますが、ここでPRIの有無を指定することとなります。
このPRIの有無を正しく設定しておかないとパイプラインが正しく動作せずログが取り込まれない状況になりますので、自分が取り込みたいログの形式を把握しておくことが重要です。
これはログを組み込みのSyslogテーブルやCommonSecurityLogテーブルに取り込むときだけではなく、カスタムログテーブルへの取り込みでもチェックされます。
pri-header-settings.png

もし環境中にPRIありとPRIなしのSyslogを送信する機器が混在し、機器側の設定で統一できない場合はパイプラインは2つ用意する必要が出てくるため要注意です。

構築後の動作確認の際はまず以下のようなコマンドでログフォーマットをいじりながらテストしてあげるとよいでしょう。

# PRIなし, UDP/514ポートあて
echo -n "$(date '+%b %e %H:%M:%S') $(hostname) testapp: This is a test syslog message" | nc -u -w1 <AMPのIPアドレス> 514

# PRIあり, UDP/514ポートあて
echo -n "<13>$(date '+%b %e %H:%M:%S') $(hostname) testapp: This is a test syslog message" | nc -u -w1 <AMPのIPアドレス> 514

recordMapの定義

カスタムテーブルへのログのマッピングはAMPのARMテンプレートにてrecordMapの部分で定義します。
ここで変換前に指定できる項目はドキュメントのトラブルシュートに記載がありますので、確認しておきましょう。
"body", "severity_text", "time_unix_nano"の3つと"attributes.{fieldName}"の形式が指定可能です。
MS Learn | レコードのマップスキーマのマッピングを確認する

Arcゲートウェイ利用環境におけるHeartbeatテーブルのAMPからの送信元IPの不具合?

AMPが正しく構成されるとAMPからLog AnalyticsワークスペースのHeartbeatテーブルに1分毎にハートビートが送信されます。
このときの送信元IPアドレスはArcゲートウェイが無い環境であればArc-enabled serversやArc-enabled k8sのハートビートと同様にオンプレミス拠点からインターネットアクセスする際のグローバルIPアドレスが記録されます。
一方で、Arcゲートウェイありの環境ではAMPからのハートビートの送信元IPアドレスがMicrosoft所有のグローバルIPアドレスとなっており、どうもArcゲートウェイの基板側のグローバルIPアドレスが記録されているように見受けられました。
このIPアドレスは定期的に変更されて記録されていました。
Arc-enabled servers等であればArcゲートウェイありであっても、オンプレミスのグローバルIPアドレスがハートビートの送信元として記録されため、一時的な不具合かもしれません。
ログを確認する際に目的のAMPからのハートビートが届いているのかがわかりづらくなるため要注意です。
heartbeat-arcgw-ip.png

CLI構築時の参考コマンド

構築時のコマンドを参考に残しておきます。
検証環境はAKS Arcです。Azureの事前準備の一部は省略しています。

カスタムログテーブル作成

ここではカスタムログテーブルに最小限の列を定義して、SyslogメッセージをすべてBody列に取り込む想定としています。
カスタムログテーブル名は末尾に"_CL"をつける必要があります。

logWsName="<Log Analyticsワークスペースの名前>"
logRgName="<RG名>"
customTable="<カスタムログテーブル名>"
az monitor log-analytics workspace table create --workspace-name ${logWsName} --resource-group ${logRgName} --name ${customTable} --columns TimeGenerated=datetime Body=string SeverityText=string

cert managerのインストール

rgName="<RG名>"
clusterName="<AKS Arc名>"
az k8s-extension create --resource-group ${rgName} --cluster-name ${clusterName} --cluster-type connectedClusters --name "azure-cert-management" --extension-type "microsoft.certmanagement" --release-train stable --config subcharts.zdtrcontroller.enabled=true

k8s外からの受信経路 (MetalLB)の準備

# MetalLBのインストール
subId="<サブスクリプションID>"
az k8s-runtime load-balancer enable --resource-uri subscriptions/${subId}/resourceGroups/${rgName}/providers/Microsoft.Kubernetes/connectedClusters/${clusterName}

# MetalLBのデプロイ
lbName="metalLB" #任意の名前
advMode="ARP" #今回ARP選択、BGPも可
ipRange="192.168.10.213/32" #任意のIPレンジ
az k8s-runtime load-balancer create --load-balancer-name ${lbName} --resource-uri subscriptions/${subId}/resourceGroups/${rgName}/providers/Microsoft.Kubernetes/connectedClusters/${clusterName} --addresses ${ipRange} --advertise-mode ${advMode}

k8sにパイプライン拡張機能をインストール

release-namespaceでnamespaceを指定しないとkube-systemにデプロイされるため指定推奨。
2026年6月時点では"--release-train"に"Preview"を指定することとなっています。

extName="<パイプライン拡張機能の名前指定>"
nameSpaceName="<k8s上のnamespace名>"
az k8s-extension create --name ${extName} --extension-type microsoft.monitor.pipelinecontroller --scope cluster --cluster-name ${clusterName} --resource-group ${rgName} --cluster-type connectedClusters --release-train Preview --release-namespace ${nameSpaceName}

カスタムロケーション作成

AKS Arcが実行されているAzure Localのカスタムロケーションとは別で、AMP用にカスタムロケーションが必要なため注意。
指定するnamespaceはパイプライン拡張機能をインストールしたものと同一を指定すること。

customLocName="${clusterName}-loc"
clusterId=$(az connectedk8s show -n ${clusterName} -g ${rgName} --query "id" --output tsv)
clusterExtId=$(az k8s-extension list -t connectedClusters -c ${clusterName} -g ${rgName} --query "[?contains(extensionType, 'pipelinecontroller')].id" -o tsv)
az customlocation create --name ${customLocName} --resource-group ${rgName} --namespace ${nameSpaceName} --host-resource-id ${clusterId} --cluster-extension-ids ${clusterExtId}

DCE作成

dceName="${clusterName}-dce"
region="<region名>"
az monitor data-collection endpoint create --name ${dceName} --resource-group ${rgName} --location ${region} --public-network-access "Enabled"

DCR作成

DCRの定義ファイルパスを指定します。

dcrName="${clusterName}-dcr"
az monitor data-collection rule create --name ${dcrName} --location ${region} --resource-group ${rgName} --rule-file '<dcr-file-path>'
  • DCRの定義ファイル例
    DCEのリソースIDやログ取り込み先のテーブル定義を指定します。
    ここではCustom-RawLogsで定義するカスタムログテーブルへのログ取り込みルールを作成。
{
    "properties": {
        "dataCollectionEndpointId": "<DCEのリソースID>",
        "streamDeclarations": {
            "Custom-<streamの定義名>": {
                "columns": [
                    {
                        "name": "Body",
                        "type": "string"
                    },
                    {
                        "name": "TimeGenerated",
                        "type": "datetime"
                    },
                    {
                        "name": "SeverityText",
                        "type": "string"
                    }
                ]
            }
        },
        "dataSources": {},
        "destinations": {
            "logAnalytics": [
                {
                    "name": "<宛先DCRを示す名前、リソース名ではなくて任意の名称でOK>",
                    "workspaceResourceId": "<Log AnalyticsワークスペースのリソースID>"
                }
            ]
        },
        "dataFlows": [
            {
                "streams": [
                    "Custom-<streamの定義名>"
                ],
                "destinations": [
                    "<上で定義した宛先DCRを示す名前"
                ],
                "transformKql": "source",
                "outputStream": "Custom-<カスタムログテーブル名>"
            }
        ]
    }
}

k8sのパイプライン拡張機能にDCRへのロールを付与

clusterManagedId=$(az k8s-extension show --name ${extName} --cluster-name ${clusterName} --resource-group ${rgName} --cluster-type connectedClusters --query "identity.principalId" -o tsv)
dcrId=$(az monitor data-collection rule show --name ${dcrName} --resource-group ${rgName} --query "id" --output tsv)
az role assignment create --assignee ${clusterManagedId} --role "Monitoring Metrics Publisher" --scope ${dcrId}

AMPのデプロイ

ARMテンプレートに設定情報を記載してARMテンプレートでデプロイします。

# ARMテンプレートに必要なDCRのImmutable IDとDCEのインジェストエンドポイントのFQDNを取得
dcrImmutableId=$(az monitor data-collection rule show --name ${dcrName} --resource-group ${rgName} --query "immutableId" --output tsv)
dceIngestionEp=$(az monitor data-collection endpoint show --name ${dceName} --resource-group ${rgName} --query "logsIngestion.endpoint" --output tsv)
  • ARMテンプレートの例
    この例ではUDPで送られてくるPRIヘッダーなしのSyslogメッセージをそのままカスタムログテーブルのBody列に取り込む設定。
    前述の問題から内部で利用するポート番号は1514を指定しています。
    ポイントはreceiverやprocessor、exporterの名前はそれぞれの定義とpipelinesの定義で一致させるようにします。
{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "metadata": {
        "description": "This template deploys an edge pipeline for azure monitor."
    },
    "resources": [
        {
            "type": "Microsoft.monitor/pipelineGroups",
            "location": "<リージョン名>",
            "apiVersion": "2026-04-01",
            "extendedLocation": {
                "name": "<カスタムロケーションのリソースID>",
                "type": "CustomLocation"
            },
            "name": "<AMP名>",
            "properties": {
                "receivers": [
                    {
                        "type": "Syslog",
                        "name": "syslog-receiver",
                        "syslog": {
                            "endpoint": "0.0.0.0:1514",
                            "allowSkipPriHeader": true,
                            "allowedFormats": [
                                "all"
                            ],
                            "transportProtocol": "udp"
                        }
                    }
                ],
                "processors": [
                    {
                        "type": "Batch",
                        "name": "batch-processor",
                        "batch": {
                            "timeout": 60000
                        }
                    },
                    {
                        "type": "TransformLanguage",
                        "name": "my-transform",
                        "transformLanguage": {
                            "transformStatement": "source"
                        }
                    }
                ],
                "exporters": [
                    {
                        "type": "AzureMonitorWorkspaceLogs",
                        "name": "rawlogs-exporter",
                        "azureMonitorWorkspaceLogs": {
                            "api": {
                                "dataCollectionEndpointUrl": "<DCEのインジェストエンドポイント>",
                                "dataCollectionRule": "<DCRのImmutable ID>",
                                "stream": "Custom-RawLogs",
                                "schema": {
                                    "recordMap": [
                                        {
                                            "from": "body",
                                            "to": "Body"
                                        },
                                        {
                                            "from": "time_unix_nano",
                                            "to": "TimeGenerated"
                                        },
                                        {
                                            "from": "severity_text",
                                            "to": "SeverityText"
                                        }
                                    ]
                                }
                            }
                        }
                    }
                ],
                "tlsConfigurations": [
                    {
                        "name": "disabled-tls",
                        "mode": "disabled"
                    }
                ],
                "service": {
                    "pipelines": [
                        {
                            "name": "rawlogs-pipeline",
                            "receivers": [
                                "syslog-receiver"
                            ],
                            "processors": [
                                "batch-processor",
                                "my-transform"
                            ],
                            "exporters": [
                                "rawlogs-exporter"
                            ],
                            "type": "Logs"
                        }
                    ]
                }
            }
        }
    ]
}

Traefikゲートウェイのデプロイ

まずはじめにTraefikのルーティング設定ファイルを作成し、そちらに合わせた内容でhelm installを実行します。
MicrosoftのドキュメントではTLS暗号化ありとTCPの場合の例が載っています。
MS Learn | Kubernetesゲートウェイを構成する

ここではUDPの場合のルーティング設定とhelm installの設定を示します。

# namespaceへのラベル付け
nameSpaceName="<namespaceの名前>"
kubectl label namespace ${nameSpaceName} arc-amp-trust-bundle=true --kubeconfig <path>

# Traefikのカスタムリソース定義(CRD)をインストール
helm repo add traefik https://traefik.github.io/charts 2>/dev/null || true
helm repo update traefik
helm show crds traefik/traefik | kubectl apply -f - --kubeconfig <path>

# Traefikルーティングの構成
kubectl apply -f <path> --kubeconfig <path>

# 外部公開のポートは514、内部のポートは1514を指定
# AMPの名前を指定
helm install traefik-<AMPの名前> traefik/traefik \
    --namespace azmon-pipeline \
    --set deployment.replicas=1 \
    --set providers.kubernetesIngress.enabled=false \
    --set providers.kubernetesCRD.enabled=true \
    --set "providers.kubernetesCRD.labelSelector=traefik-instance=<AMPの名前>-gateway" \
    --set ports.udp-syslog.port=1514 \
    --set ports.udp-syslog.expose.default=true \
    --set ports.udp-syslog.exposedPort=514 \
    --set ports.udp-syslog.protocol=UDP \
    --set ports.web.expose.default=false \
    --set ports.websecure.expose.default=false \
    --set service.type=LoadBalancer \
    --kubeconfig <path> \
    --wait

IngressRouteUDPの例です。
ここで指定するportはAMPのcollectorのポートです。

# routing.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRouteUDP
metadata:
  name: <AMPの名前>-udp-syslog-route
  namespace: <namaspaceの名前>
  labels:
    traefik-instance: <AMPの名前>-gateway
spec:
  entryPoints:
    - udp-syslog
  routes:
    - services:
      - name: <AMPの名前>-service
        port: 1514

まとめ

Azureリソースとk8sのnamespaceやコンテナの対応を理解しながらデプロイすることが重要と感じました。
手軽な検証環境としてはk3sへのデプロイになり少し異なるかもしれませんが、抑えるべきポイントは同じはずです。
今回の検証では永続ボリュームやTLSの設定は試せていませんので、別途そちらも確認しておきたいところです。

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?