写在最前
1. 前置条件
2. 部署流程
2.1 下载安装
我的版本比较低是1.21.x,要注意你的kubernetes版本是否对应上否则会安装失败,ingress-nginx镜像源下载不了我换成国内的了 my-ingress-nginx-v1.3.1.yaml
https://github.com/kubernetes/ingress-nginx
# 下载
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.1/deploy/static/provider/cloud/deploy.yaml
# 将 externalTrafficPolicy: Local 改成 Cluster 允许所有节点都能访问
346 externalTrafficPolicy: Local
# 留意是不是LoadBalancer,因为要搭配metallb或openELB来使用
365 type: LoadBalancer
可以看到metalLB或者openELB提供的IP已经被ingress-nginx识别到了
2.2 配置优化
3. 维护页面
如需临时进入维护状态只需要将~/hello中的hello给删掉即可维护完毕再加回hello,即可在不影响原服务容器运行的前提下,阻止外部流量访问前端服务,同时向用户展示维护提示页。
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: xxxxxxx
namespace: xxxxxxx
annotations:
kubernetes.io/ingress.class: nginx
kubesphere.io/creator: tanqidi
nginx.ingress.kubernetes.io/server-snippet: >-
location ~/hello { default_type text/html; return 200 '<!DOCTYPE html><html
lang="zh-CN"><head><meta charset="UTF-8"/><meta name="viewport"
content="width=device-width,initial-scale=1"/><title>系统维护中</title><style>body{margin:0;background:#f0f4f8;color:#2c3e50;font-family:"Helvetica
Neue",Helvetica,Arial,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;text-align:center;}svg{width:72px;height:72px;margin-bottom:24px;stroke:url(#grad);stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round;}h1{font-weight:700;font-size:2.8rem;margin:0
0 12px;}p{margin:0 0
28px;font-size:1.2rem;line-height:1.5;color:#34495e;}a{color:#2980b9;font-weight:600;text-decoration:none;box-shadow:inset
0 -2px 0 #2980b9;transition:box-shadow 0.3s,color
0.3s;}a:hover{box-shadow:none;color:#1c5980;}</style></head><body><svg
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24
24"><defs><linearGradient id="grad" x1="0" y1="0" x2="1" y2="1"><stop
offset="0%" stop-color="#3498db"/><stop offset="100%"
stop-color="#2980b9"/></linearGradient></defs><circle cx="12" cy="12"
r="9"/><path d="M12 8v4l3
3"/></svg><h1>系统维护中</h1><p>我们正在努力升级服务,请稍后再访问。感谢您的理解与支持!</p><a href="#"
onclick="location.reload()">刷新页面</a></body></html>'; }
4. 功能变更
4.1 启用server-snippet
https://github.com/kubernetes/ingress-nginx/issues/13003?utm_source=chatgpt.com
编辑configmap加入如下配置
kind: ConfigMap
apiVersion: v1
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.13.0
data:
allow-snippet-annotations: 'true'
annotations-risk-level: Critical
同时ingress-nginx-controller启动参数加入--enable-annotation-validation=false
为什么 ingress-nginx
默认禁止 snippet 注解,但很多实际业务场景又确实离不开它。
🔒 为什么默认禁止 snippet 注解?
安全风险太大
configuration-snippet
、server-snippet
、location-snippet
允许你把 任意 NGINX 配置片段 注入到 Ingress Controller 的 NGINX 配置里。这意味着开发人员或者业务方只要能创建 Ingress,就能在 NGINX 里写出任意指令,甚至可能影响整个集群的其他应用。
举例:一个人加一段
location /hack { proxy_pass http://malicious-service; }
就可能绕过认证或数据隔离。
CVE 漏洞历史
社区里出现过多次漏洞(比如 2024、2025 年的 CVE-2025-1974),核心点就是通过 snippet 插入危险配置,从而绕过 Admission 校验。
为了防御这些“风险注解”,从 1.12.0 开始 Admission Webhook 默认拦截,要求管理员显式放行。
多租户场景尤其危险
在很多 K8s 集群里,一个团队一个 namespace。
如果默认允许 snippet,等于把 NGINX 控制权交给了租户,这对运维是不可接受的。
🏗️ 为什么实际业务确实需要?
标准 annotation 覆盖不了所有需求
nginx.ingress.kubernetes.io/*
提供了几十种常见功能(rewrite、timeout、auth 等),但远远不够。业务方经常需要用到一些 小众但关键的 NGINX 功能,比如:
自定义 header
特殊 rewrite 规则
缓存 / 限流 / Lua 脚本
这些功能官方 annotation 没有覆盖,snippet 就成了唯一出口。
迁移历史遗留配置
很多团队早期在 VM 或裸机里直接写了 NGINX 配置。
上 K8s 后,最简单的方式就是直接贴进 snippet,而不是花很久改造成 annotation。
调试 / 应急手段
出现紧急问题时,直接在 snippet 里写几行配置,比等 upstream 提供新的 annotation 快多了。
✅ 社区给的折中方案
默认禁用:保证安全。
集群管理员决定是否启用:通过
allow-snippet-annotations: "true" annotations-risk-level: "Critical"
或者关闭 Admission 校验。
未来方向:社区建议把常用的 snippet 功能,逐步收敛为官方 annotation,这样既安全又可控。
📌 总结:
默认禁止 👉 为了安全(防止越权 / 漏洞)。
实际需要 👉 因为 annotation 功能有限,业务确实要灵活性。
折中做法 👉 管理员显式开启,并通过 risk-level 控制,确保只有“知道后果的人”能用。
评论