从 Kubernetes 上的 Windows 容器中摄取 IIS 日志

29 阅读6分钟

作者:来自 Elastic Muhammad Sulaman Sarwar

在 Kubernetes 中监控 Windows 工作负载面临独特的挑战:IIS 访问日志在进入 Elasticsearch 时被包裹在容器元数据中,导致无法搜索。由于缺少结构化字段,要排查 500 错误激增或响应时间变慢的问题,就只能在数 GB 的非结构化文本中用 grep 查找。业务影响是什么?更长的 MTTR、沮丧的工程师,以及对应用性能的可见性受限。

解决方案不需要新的 agent 或日志传输程序。它是一个 ingest pipeline —— Elasticsearch 在索引过程中转换数据的方式 —— 能检测流中的 IIS 日志,去除包裹层,并将其路由到结构化解析中。

简而言之:使用 ingest pipeline 通过站点标识符(W3SVC1、W3SVC2)检测 IIS 日志,移除 Kubernetes 元数据,并将其路由到 IIS 集成中,以实现自动 ECS 字段映射。结果:可查询的仪表板、更快的故障排查、无需基础设施更改。

问题

在 Kubernetes 上运行 IIS 的 Windows 容器会将 W3C 访问日志输出到 stdout。Kubernetes 集成会摄取这些日志,但它们会被容器元数据包裹。

`2025-01-15T10:23:45.123Z stdout F 2025-01-15 10:23:45 W3SVC1 WEBSERVER01 10.0.1.5 GET /api/users - 443 - 192.168.1.100 HTTP/1.1 - - 200 0 0 125` AI写代码

IIS 日志数据位于 stdout F 之后。如果不进行解析,你无法根据状态码、URI、响应时间或其他结构化字段进行查询。

前提条件

你需要 Elasticsearch 9.x+、用于收集容器日志的 Kubernetes 集成,以及已安装的 IIS 集成。IIS 集成提供 logs-iis.access@custom pipeline,用于处理 W3C 解析和 ECS 字段映射。

验证 IIS 集成是否已安装:

`GET _ingest/pipeline/logs-iis.access@custom` AI写代码

如果出现 404,通过 Kibana → Management → Integrations → IIS 安装 IIS 集成。

确认 Kubernetes 日志正在流入:

`1.  GET logs-kubernetes.*/_search
2.  {
3.    "size": 5,
4.    "sort": [{ "@timestamp": "desc" }]
5.  }` AI写代码

检查 IIS 日志是否出现在 Kubernetes 流中:

`1.  GET logs-kubernetes.*/_search
2.  {
3.    "query": { "match": { "message": "W3SVC" }},
4.    "size": 5
5.  }` AI写代码

如果没有返回结果,说明你的 IIS 容器没有将日志输出到 stdout,或者日志没有到达 Elasticsearch。使用 kubectl logs 检查容器日志。

创建路由 pipeline

此 pipeline 通过匹配站点标识符(W3SVC1、W3SVC2 等)检测 IIS 访问日志,移除 Kubernetes 包裹层,并将其路由到 IIS 数据流:

`1.  PUT _ingest/pipeline/k8s-iis-router
2.  {
3.    "description": "Route IIS logs from Kubernetes to IIS data stream",
4.    "processors": [
5.      {
6.        "set": {
7.          "if": "ctx.message != null && /W3SVC\\d+/.matcher(ctx.message).find()",
8.          "field": "iis_log_detected",
9.          "value": true
10.        }
11.      },
12.      {
13.        "gsub": {
14.          "if": "ctx.iis_log_detected == true",
15.          "field": "message",
16.          "pattern": "^[0-9TZ:\\.\\-]+\\s+stdout\\s+F\\s+",
17.          "replacement": ""
18.        }
19.      },
20.      {
21.        "pipeline": {
22.          "if": "ctx.iis_log_detected == true",
23.          "name": "logs-iis.access@custom"
24.        }
25.      },
26.      {
27.        "set": {
28.          "if": "ctx.iis_log_detected == true",
29.          "field": "data_stream.dataset",
30.          "value": "iis.access"
31.        }
32.      },
33.      {
34.        "set": {
35.          "if": "ctx.iis_log_detected == true",
36.          "field": "data_stream.type",
37.          "value": "logs"
38.        }
39.      },
40.      {
41.        "set": {
42.          "if": "ctx.iis_log_detected == true",
43.          "field": "data_stream.namespace",
44.          "value": "default"
45.        }
46.      },
47.      {
48.        "remove": {
49.          "if": "ctx.iis_log_detected == true",
50.          "field": ["iis_log_detected"],
51.          "ignore_missing": true
52.        }
53.      }
54.    ],
55.    "on_failure": [
56.      {
57.        "set": {
58.          "field": "error.message",
59.          "value": "IIS routing failed: {{ _ingest.on_failure_message }}"
60.        }
61.      }
62.    ]
63.  }` AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)收起代码块![](https://csdnimg.cn/release/blogv2/dist/pc/img/arrowup-line-top-White.png)

该 pipeline 通过匹配 W3SVC\d+ 检测 IIS 日志,去除 Kubernetes 时间戳和 stdout F 前缀,调用 IIS 集成 pipeline 进行 W3C 解析,并设置数据流字段,将文档路由到 logs-iis.access-default。非 IIS 日志将原样通过。

测试 Pipeline

在应用到生产前,使用 simulate API 进行测试:

`1.  POST _ingest/pipeline/k8s-iis-router/_simulate
2.  {
3.    "docs": [
4.      {
5.        "_source": {
6.          "message": "2025-01-15T10:23:45.123Z stdout F 2025-01-15 10:23:45 W3SVC1 WEBSERVER01 10.0.1.5 GET /api/users - 443 - 192.168.1.100 HTTP/1.1 - - 200 0 0 125"
7.        }
8.      }
9.    ]
10.  }` AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

响应结果应显示 data_stream.dataset: iis.access 以及已解析的字段,如 http.response.status_code、url.path 和 client.ip。

使用非 IIS 日志进行测试以确保其能正常通过:

`1.  POST _ingest/pipeline/k8s-iis-router/_simulate
2.  {
3.    "docs": [
4.      {
5.        "_source": {
6.          "message": "2025-01-15T10:23:45.123Z stdout F Some other container log"
7.        }
8.      }
9.    ]
10.  }` AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

该文档不应被路由到 IIS 数据流。

应用到 Kubernetes 日志

更新你的 Kubernetes 日志索引模板以使用路由 pipeline:

`1.  PUT _index_template/kubernetes-logs
2.  {
3.    "index_patterns": ["logs-kubernetes.*"],
4.    "priority": 250,
5.    "template": {
6.      "settings": {
7.        "index.default_pipeline": "k8s-iis-router"
8.      }
9.    }
10.  }` AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

如果使用 Fleet 管理的 Kubernetes 集成,请在集成设置中 Advanced options → Custom pipeline 下添加该 pipeline。

验证

等待 1–2 分钟以便新日志到达。该 pipeline 仅处理新文档,不会处理现有文档。

检查文档是否到达 IIS 数据流:

`GET logs-iis.access-*/_count` AI写代码

如果 count 为 0,请验证 pipeline 是否已附加:

`GET logs-kubernetes.*/_settings` AI写代码

在响应中查找 "index.default_pipeline": "k8s-iis-router"。

查看带有结构化字段的已解析日志:

`1.  GET logs-iis.access-*/_search
2.  {
3.    "size": 5,
4.    "sort": [{ "@timestamp": "desc" }]
5.  }` AI写代码

你应能看到 ECS 字段:

  • http.response.status_code(整数:200、404、500)
  • http.request.method(GET、POST、PUT、DELETE)
  • url.path(如 /api/users)
  • client.ip(客户端 IP 地址)
  • event.duration(响应时间,单位纳秒)

验证 Kubernetes 流中 IIS 日志是否减少:

`1.  GET logs-kubernetes.*/_search
2.  {
3.    "query": { "match": { "message": "W3SVC" }},
4.    "size": 5
5.  }` AI写代码

如果 IIS 日志仍出现在此处,说明未被路由。检查 pipeline 错误:

故障排查

如果日志未出现在 IIS 数据流中:确认 IIS 集成 pipeline 存在(GET _ingest/pipeline/logs-iis.access@custom)。检查 IIS 日志是否包含 W3SVC(GET logs-kubernetes.*/_search?q=W3SVC)。使用 kubectl exec -- iisreset /status 验证 IIS 容器中日志记录是否启用。

如果解析失败:IIS 集成要求默认 W3C 字段顺序:date time s-sitename s-computername s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs-version cs(Referer) cs(X-Forwarded-For) sc-status sc-substatus sc-win32-status time-taken。若你的格式不同,需要在 IIS pipeline 中自定义 grok 模式。

性能问题:正则 W3SVC\d+ 会在每个 Kubernetes 日志文档上运行。为减少开销,可将检测范围限定到特定容器:

`"if": "ctx.kubernetes?.container?.name == 'iis-app' && /W3SVC\\d+/.matcher(ctx.message).find()"` AI写代码

可选增强

在 gsub 步骤后添加此处理器,根据 Kubernetes 命名空间将日志路由到不同的数据流命名空间:

`1.  {
2.    "set": {
3.      "if": "ctx.iis_log_detected == true && ctx.kubernetes?.namespace != null",
4.      "field": "data_stream.namespace",
5.      "value": "{{ kubernetes.namespace }}"
6.    }
7.  }` AI写代码

这会创建独立的数据流,如 logs-iis.access-production 和 logs-iis.access-staging,使得按环境管理保留策略和访问控制更容易。

结果:工程团队可以按状态码查询日志,构建显示响应时间分位数的仪表板,并设置错误率警报。过去需要手动解析日志的操作现在在摄取阶段自动完成。当生产事件发生时,你搜索的是结构化数据,而非原始文本。

这种方法不仅适用于 IIS。任何在单个流中包含多种日志格式的情况——无论是应用日志与系统日志混合,还是一个容器中有多个服务——模式都是相同的:在摄取阶段检测、去除包裹层、路由到专用 pipeline。摄取层成为日志解析器,下游系统获得干净、结构化的数据。

原文:www.linkedin.com/pulse/inges…