资讯动态

Kubernetes Ingress 接入 F5 WAF Policy Controller(PLM):NAP v5 策略包的事件驱动编译与拉取实战

发布时间:2026/10/14 15:35:49 来源:尧图企业网站定制
API网关云原生负载均衡可观测性微服务【免费下载链接】kubernetes-ingressNGINX and NGINX Plus Ingress Controllers for Kubernetes项目地址https://gitcode.com/gh_mirrors/ku/kubernetes-ingress点击查看免费下载本篇技术文章基于仓库中的示例 examples/custom-resources/waf-plm/README.md讲解如何在 Kubernetes Ingress ControllerNICNGINX Ingress Controller中使用 NGINX Plus 与 F5 WAF for NGINXApp Protect WAF v5并让策略与日志配置的编译工作完全交给 F5 WAF Policy ControllerPLMPLM 拥有APPolicy/APLogConf的生命周期把编译产物bundle发布到 SeaweedFSNIC 则通过监听这些资源的status.bundle.state变为ready的事件按需拉取 bundle 并下发到 WAF 模块。读完本文你可以掌握 PLM 模式下完整的部署步骤、Helm 参数配置、NIC 启动参数的底层校验逻辑以及 bundle 拉取失败时的排查方法。一、PLM 模式的整体架构编译归 PLM下发归 NIC在传统 NAPApp Protect集成中NIC 直接从 URL 或 Secret 拉取策略文件并自行管理编译而在 PLM 模式下职责被清晰地切分PLMF5 WAF Policy Controller负责安装并拥有appprotect.f5.com/v1版本的 CRDAPPolicy、APLogConf、APUserSig、APSignatures运行编译器与 SeaweedFS bundle 存储把策略/日志配置编译成.tgzbundle 并发布到 S3 兼容的对象存储中NIC在启用-plm-storage-url后监听 PLM 管理的appprotect.f5.com/v1CRD当被引用的资源status.bundle.state变为ready时按 status 中记录的Location与sha256从 SeaweedFS 拉取 bundle而不是轮询。从源码结构看这一分工体现在 internal/configs/wafbundle/bundle.go 中的SourceType枚举SourceTypePLM被显式标注为“仅内部使用——不暴露在 BundleSource CRD 上”它在 NIC 解析apPolicy/apLogConf引用且-plm-storage-url已设置时被赋给请求实际的 S3 拉取则由 internal/configs/wafbundle/plm_fetcher.go 中的PLMAwareFetcher完成它把SourceTypePLM请求分派给内部S3Fetcher而端点、凭证与 TLS 配置不在请求上携带而是在拉取时从集群内的 Secret 动态解析。二、前置条件确认 PLM 已安装且 CRD 以 v1 版本提供1. 安装 F5 WAF Policy ControllerPLM 是独立组件由 PLM 负责安装并拥有appprotect.f5.com/v1CRDAPPolicy、APLogConf、APUserSig、APSignatures同时运行编译器与 SeaweedFS bundle 存储。这一步不在 NIC 仓库范围内需先完成 PLM 的安装。2. 验证 CRD 已安装并以 v1 提供kubectl describe crd appolicies.appprotect.f5.com aplogconfs.appprotect.f5.com apsignatures.appprotect.f5.com apusersigs.appprotect.f5.com确认这些 CRD 的 served version 为v1NIC 才能在 PLM 模式下正确解析资源。三、Step 1 - 创建 PLM 策略与日志配置创建APPolicy与APLogConf资源PLM 会对每个资源进行编译并把 bundle 发布到 SeaweedFSkubectl apply -f ap-dataguard-alarm-policy.yaml kubectl apply -f ap-logconf.yaml示例仓库中提供了两份完整清单ap-dataguard-alarm-policy.yaml 定义了一个名为dataguard-alarm的策略核心内容如下apiVersion: appprotect.f5.com/v1 kind: APPolicy metadata: name: dataguard-alarm spec: policy: applicationLanguage: utf-8 blocking-settings: violations: - alarm: true block: false name: VIOL_DATA_GUARD >apiVersion: appprotect.f5.com/v1 kind: APLogConf metadata: name: logconf spec: content: format: default max_message_size: 64k max_request_size: any filter: request_type: all即默认格式、单条日志上限 64k、记录所有请求类型。四、Step 2 - 确认两个 bundle 都进入 ready 状态检查 PLM 对两个资源都报告ready。NIC 在此之前不会拉取任何 bundlekubectl describe appolicy dataguard-alarm kubectl describe aplogconf logconf每个资源会在Status下报告编译产物。APPolicy的示例输出Status: Bundle: Compiler Version: 5.14.0 Location: s3://default/bundles/dataguard-alarm20260807160340-dataguard-alarm-1-1786118620559717186.tgz sha256: 47a6fdcd07b9adafaaa415fa9fd2ab2cab84b54b26a91fd518a4ff5e2dab3f8d Signatures: Attack Signatures: 2026-07-18T13:39:26Z Bot Signatures: 2026-07-16T07:35:37Z Threat Campaigns: 2026-07-13T11:56:06Z State: ready Last Good Bundle: Compiler Version: 5.14.0 Location: s3://default/bundles/dataguard-alarm20260807160340-dataguard-alarm-1-1786118620559717186.tgz sha256: 47a6fdcd07b9adafaaa415fa9fd2ab2cab84b54b26a91fd518a4ff5e2dab3f8d Signatures: Attack Signatures: 2026-07-18T13:39:26Z Bot Signatures: 2026-07-16T07:35:37Z Threat Campaigns: 2026-07-13T11:56:06Z State: ready Observed Generation: 1 Observed Policy Name: dataguard-alarm Policy Location: s3://default/policies/dataguard-alarm.json Processing: Datetime: 2026-08-07T16:03:46Z Is Compiled: trueAPLogConf的示例输出Status: Bundle: Compiler Version: 5.14.0 Location: s3://default/bundles/logconf20260807160340.tgz sha256: 0728d1cc822e32af2b880f49c433f7fe8ef28bd5fcf1761af2be4f04acace9de State: ready Observed Generation: 1 Processing: Datetime: 2026-08-07T16:03:46Z Is Compiled: true Events: none如果某个资源始终无法进入ready请先检查 PLM policy-controller 与编译器的日志再继续后续步骤。NIC 端对ready的判定比“状态为 ready”更严格。从 internal/configs/wafbundle/apstatus.go 可以看到BundleStatus.IsReady()要求三个条件同时成立state ready、Location非空、SHA256非空任一缺失例如状态机处于pending/processing或只写了 location 没写 sha256都会被视为不可拉取NIC 会将策略标记为 pending 并等待下一次 status watch 事件。五、Step 3 - 安装启用 PLM 存储的 Ingress Controller用 NGINX Plus、App Protectv5并启用 PLM 存储来部署 NIC。PLM 存储通过集群级命令行参数配置Helm chart 从controller.appprotect.plmStorage渲染参数用途-plm-storage-urlSeaweedFS S3 端点。设置后启用 PLM 集成NIC 开始监听appprotect.f5.com/v1CRD。-plm-storage-credentials-secret保存 SeaweedFS admin key 的 Secret键名为seaweedfs_admin_secret。必填。-plm-storage-ca-secret可选包含ca.crt用于 TLS 校验的 Secret。-plm-storage-client-ssl-secret可选包含tls.crt与tls.key用于 mTLS 的 Secret。-plm-storage-insecure-skip-verify禁用 TLS 校验仅限开发测试。Secret 引用统一使用namespace/name格式。以启用了 TLS 与 mTLS 的 PLM 安装为例Helm values 为controller: nginxplus: true appprotect: enable: true v5: true plmStorage: url: https://plm_release-f5-waf-seaweed-filer.plm_namespace.svc.cluster.local:9333 credentialsSecret: plm_namespace/plm_release-f5-waf-seaweedfs-auth caSecret: plm_namespace/plm_release-f5-waf-seaweedfs-ca-cert clientSSLSecret: plm_namespace/plm_release-f5-waf-seaweedfs-client-cert insecureSkipVerify: false这些 values 的定义与注释见 charts/nginx-ingress/values.yaml 中的plmStorage段渲染与校验逻辑在 charts/nginx-ingress/templates/_helpers.tpl当plmStorage.url非空时chart 会依次fail校验controller.nginxplustrue、controller.appprotect.enabletrue、controller.appprotect.v5true以及credentialsSecret必填辅助字段caSecret/clientSSLSecret不允许在url为空时被单独设置。对于未启用 TLS 的安装使用8333端口的 HTTP 端点并把caSecret与clientSSLSecret留空。端点协议必须与 PLM 的安装方式一致向 TLS 端口发送明文http://请求会失败。安装前先用kubectl apply -f deploy/crds.yaml应用 NIC 自身的 CRD并使用helm install时传入--skip-crds。另外两个易被忽略的监听范围约束若controller.watchNamespace被限制必须包含持有APPolicy与APLogConf资源的命名空间否则 NIC 无法 watch 它们的 status源码中对应resolvePLMBundleStatus检查命名空间是否被 watch并记录WAF PLM bundle: namespace %q is not watched的 pending 状态若controller.watchSecretNamespace被限制必须包含持有存储 Secret 的命名空间以便 NIC 观察到凭证轮转。启动参数在源码层的定义与交叉校验见 cmd/nginx-ingress/flags.govalidatePLMFlags以-plm-storage-url作为总开关——为空时任何辅助 PLM 参数被设置都会直接报错防止“以为开了 PLM 实际没开”的静默拼写错误启用时则强制要求-nginx-plus与-enable-app-protect同时开启、-plm-storage-credentials-secret必填并校验 URL 必须带http:///https://scheme、host 非空且不含空白字符。安装完成后把 Ingress Controller 的公网 IP 与 HTTP 端口存入 shell 变量IC_IPXXX.YYY.ZZZ.III IC_HTTP_PORTport number六、Step 4 - 部署应用与 WAF 策略创建应用 Deployment 与 Servicewebapp.yaml 部署nginxdemos/nginx-hello:plain-text并暴露 8080Servicewebapp-svc将其映射为 80 端口kubectl apply -f webapp.yaml创建接收安全日志的 syslog Service 与 Podsyslog.yaml 使用balabit/syslog-ng:4.12.0监听 514 端口kubectl apply -f syslog.yaml创建 WAF 策略waf-plm.yamlkubectl apply -f waf-plm.yaml其内容如下注意apPolicy与apLogConf均以[namespace/]name格式引用 PLM 资源apiVersion: k8s.nginx.org/v1 kind: Policy metadata: name: waf-policy spec: waf: enable: true apPolicy: dataguard-alarm securityLogs: - enable: true apLogConf: logconf logDest: syslog:serversyslog-svc.default:514PLM 源不使用url、secret、trustedCertSecret、enablePolling、pollInterval、verifyChecksum这些字段。NIC 从被引用资源的 status 中读取 bundle 位置与 SHA-256bundle 更新由 status watch 事件驱动而非轮询。源码印证了这一点internal/k8s/policy.go 中effectivePLMPolicyRef/effectivePLMLogRef只在plmEnabled且引用了apPolicy/apLogConf时返回有效引用resolvePLMBundleStatus通过 dynamic client 读取 AP 资源的.status.bundlebundleNeedsFetch用磁盘上已有 bundle 的 SHA-256 与 PLM 发布的校验值比较——只有重新编译导致 sha256 变化时才触发再次拉取因此策略重编译是事件驱动的无需轮询间隔配置。七、Step 5 - 检查策略状态当 NIC 已从 SeaweedFS 拉取到两个 bundle 后Policy 变为可用kubectl describe policy waf-policyEvents: Type Reason Message ---- ------ ------- Normal AddedOrUpdated Policy default/waf-policy was added or updated如果看到BundleFetchFailed警告事件说明 NIC 已进入拉取阶段但无法获取 bundle——请回到 Step 3 核对存储端点、凭证与 TLS 配置。源码中该事件由 internal/k8s/policy.go 通过recorder.Event(pol, api_v1.EventTypeWarning, nl.EventReasonBundleFetchFailed, msg)发出并同步写入 Policy 的 Warning status而“尚未 ready”“命名空间未被 watch”“informer 不可用”等前置问题则走recordPLMPending只记录 Warning 事件与调试日志不会让控制器崩溃需等待 status 事件驱动重试。八、Step 6 - 检查策略与日志 bundle可选可选步骤确认编译后的 bundle 已落到 Pod 文件系统kubectl exec -it -n NIC_NAMESPACE ANY_NIC_POD -c nginx-ingress -- ls -ltr /etc/app_protect/bundles-rw------- 1 nginx nginx 1901282 Aug 7 16:26 fetched_default_waf-policy_policy.tgz -rw------- 1 nginx nginx 1655 Aug 7 16:26 fetched_default_waf-policy_log_0.tgz文件名fetched_default_waf-policy_policy.tgz是确定性的从 internal/configs/wafbundle/bundle.go 的FetchedBundleFilename可见格式固定为fetched_namespace_name_suffix.tgz策略 bundle 的 suffix 为policy安全日志 bundle 依次为log_0、log_1……与示例输出完全一致。bundle 以“临时文件 rename”的方式原子写入且写入与 NGINX reload 之间有 2 秒的稳定窗口以避免 WAF v5 配置管理器因 inode 变化而短暂报 File Not Found。九、Step 7 - 配置负载均衡创建引用 Step 4 中waf-policy的 VirtualServervirtual-server.yamlkubectl apply -f virtual-server.yamlapiVersion: k8s.nginx.org/v1 kind: VirtualServer metadata: name: webapp spec: host: webapp.example.com policies: - name: waf-policy upstreams: - name: webapp service: webapp-svc port: 80 routes: - path: / action: pass: webapp十、Step 8 - 测试应用与 WAF 拦截正常请求应直接透传到后端curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP http://webapp.example.com:$IC_HTTP_PORT/Server address: 10.104.1.11:8080 Server name: webapp-d568db6b5-bx92b Date: 07/Aug/2026:16:29:39 0000 URI: / Request ID: d18679e4cb94c0f6279a5f053898d8df发送触发 data guard 违规XSS 闭合标签的请求curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP http://webapp.example.com:$IC_HTTP_PORT//script返回 WAF 拦截页htmlheadtitleRequest Rejected/title/headbodyThe requested URL was rejected. Please consult with your administrator.brbrYour support ID is: 14276123774182424059brbra hrefjavascript:history.back();[Go Back]/a/body/html%在 syslog Pod 中查看安全日志确认策略名、签名与严重级别kubectl exec -it SYSLOG_POD -- cat /var/log/messagesAug 7 16:29:57 nic-nginx-ingress-controller-f6c988865-twql8 ASM:attack_typeNon-browser Client,Abuse of Functionality,Cross Site Scripting (XSS),Other Application Activity,blocking_exception_reasonN/A,date_time2026-08-07 16:29:57,dest_port80,ip_clientsome_ip,is_truncatedfalse,methodGET,policy_namedataguard-alarm,protocolHTTP,request_statusblocked,response_code0,severityCritical,sig_cvesN/A,sig_ids200000093,sig_namesXSS script tag end (URI),sig_set_names{High Accuracy Signatures;Cross Site Scripting Signatures},src_port53923,sub_violationsN/A,support_id14276123774182424059,threat_campaign_namesN/A,unit_hostnamenic-nginx-ingress-controller-f6c988865-twql8,uri//script日志中policy_namedataguard-alarm与sig_ids200000093XSS script tag end证实 PLM 编译的策略 bundle 已在数据面生效request_statusblocked说明该违规被整体阻断模式拦截data-guard 违规本身按策略配置为 alarm-only。十一、PLM 模式 vs 传统 BundleSource 模式排查要点小结场景PLM 模式行为排查方向status.bundle.state非readyNIC 不拉取策略 pending查 PLM policy-controller / 编译器日志ready但拉取失败发出BundleFetchFailedWarning 事件与 Policy Warning status核对-plm-storage-url协议与端口8333/9333、credentials Secretseaweedfs_admin_secret键、CA/mTLS 配置策略重编译后 NIC 未更新正常情况下 status watch 事件会驱动重新拉取sha256 变化确认 NIC watch 的命名空间包含 AP 资源所在命名空间启动即报错validatePLMFlags交叉校验失败确认nginxplustrue、appprotect.enabletrue、appprotect.v5true、credentialsSecret非空且辅助参数未脱离url单独设置整体来看该示例展示了 NIC 与 PLM 之间“状态驱动”的协作契约PLM 负责编译与签名sha256NIC 只信任ready状态的 status 信息并做校验值比对两端都不需要轮询。相关实现集中在 internal/k8s/policy.go、internal/configs/wafbundle/apstatus.go、internal/configs/wafbundle/plm_fetcher.go 与 cmd/nginx-ingress/flags.go可对照本文的排查表格进一步深入。赞分享API网关云原生负载均衡可观测性微服务【免费下载链接】kubernetes-ingressNGINX and NGINX Plus Ingress Controllers for Kubernetes项目地址https://gitcode.com/gh_mirrors/ku/kubernetes-ingress点击查看免费下载相关推荐NGINX Ingress Controller 实战通过 HTTPS Bundle Source 为 F5 WAF v5 下发预编译策略NGINX Ingress Controller 实战通过 HTTPS Bundle Source 为 F5 WAF v5 下发预编译策略 导读 本指南基于API网关云原生负载均衡可观测性微服务Kubernetes Ingress 缓存策略实战基于 NGINX Ingress Controller 的 Policy CRD 配置指南Kubernetes Ingress 缓存策略实战基于 NGINX Ingress Controller 的 Policy CRD 配置指南 本指南以 exaAPI网关云原生负载均衡可观测性微服务NGINX Plus Ingress Controller 集成 App Protect WAF v5 实战从策略 Bundle 部署到 VirtualServer 防护配置NGINX Plus Ingress Controller 集成 App Protect WAF v5 实战从策略 Bundle 部署到 VirtualSerAPI网关云原生负载均衡可观测性微服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑