# Kubernetes Ingress 完全指南(适用于 Kubernetes v1.35)
Kubernetes Ingress 完全指南(适用于 Kubernetes v1.35)
文档说明
- 适用版本:Kubernetes v1.35.4(
networking.k8s.io/v1) - 前置知识:了解 Pod、Service 的基本概念
- 目标:从零掌握 Ingress 的原理、配置、部署与流量路径
第一章:为什么需要 Ingress?
在 Kubernetes 中,Service 是 Pod 的稳定访问入口,但 Service 类型存在明显局限:
| Service 类型 | 局限 |
|---|---|
| ClusterIP | 仅集群内部可访问,无法对外提供服务 |
| NodePort | 端口范围固定(30000-32767),不易记忆;Node IP 变更频繁;无法支持域名和路径路由 |
| LoadBalancer | 每个 Service 需独立公网 IP,成本高昂;不支持 L7(HTTP/HTTPS)层面的高级路由 |
Ingress 解决了什么问题?
Ingress 是 Kubernetes 中管理集群外部访问集群内服务的 API 对象,它通过定义 HTTP/HTTPS 路由规则,将外部流量从集群边界路由到集群内的 Service。
一句话总结:Ingress 让你用一个公网 IP/域名,对外暴露多个内部服务,并支持基于域名、路径的精细化路由。
第二章:核心概念(务必分清)
很多初学者混淆这三者,实际上它们分工明确:
| 概念 | 作用 | 通俗类比 |
|---|---|---|
| Ingress Controller | 实际的程序(Pod),负责处理流量并执行路由转发(如 Nginx、Traefik、Envoy)。 | 真正的“保安”,站在门口拦截和指引访客 |
| Ingress 资源 | 你写的 YAML 配置文件,定义了“哪个域名指向哪个服务”的规则。 | 给保安的“工作手册”,告诉他遇到谁该带去哪个房间 |
| IngressClass | 标识集群中安装了多个 Controller 时,该 Ingress 资源由哪个 Controller 处理。 | 标识“这是保安 A 负责的片区”还是“保安 B 负责的片区” |
⚠️ 重要提示:仅创建 Ingress 资源(YAML)不会生效!你必须在集群中安装并运行一个 Ingress Controller(如 Nginx Ingress Controller),否则 Kubernetes 只会忽略它。
第三章:流量全链路解析(请求是如何到达 Pod 的?)
理解了概念之后,你需要明白一件事:一条外部请求是如何最终进入你的容器里的?
本章从请求进入集群的那一刻开始,拆解完整路径。
3.1 整体路径概览(默认模式:hostNetwork: false)
互联网用户 │ ▼ 访问 http://example.com/api ┌─────────────────────────────────────────────────────────────┐ │ Kubernetes 集群边界 │ │ │ │ 第1步:请求到达宿主机 NodePort(如 30080) │ │ └─ 由 Ingress Controller 的 Service(NodePort 类型)暴露│ │ │ │ 第2步:kube-proxy 拦截并转发 │ │ └─ iptables/IPVS 规则将流量转发到 Controller Pod IP │ │ │ │ 第3步:Ingress Controller Pod(Nginx 容器)接收请求 │ │ └─ 根据 Ingress 规则(Host/Path)匹配后端 Service │ │ │ │ 第4步:Nginx 通过 Service 的 ClusterIP 转发请求 │ │ └─ 再次经过 kube-proxy,负载均衡到后端 Pod │ │ │ │ 第5步:目标 Pod 接收请求,处理并返回响应 │ └─────────────────────────────────────────────────────────────┘ │ ▼ 返回响应(原路返回)3.2 各步骤详解
第 1 步:外部流量如何进入集群?
Ingress Controller 本身是一个 Deployment 或 DaemonSet,但它并不直接暴露在公网上。它依赖一个类型为NodePort或LoadBalancer的Service来接收外部流量。
场景 A:使用 NodePort 方式
kubectl get svc-ningress-nginxNAME TYPE CLUSTER-IP PORT(S) AGE ingress-nginx-controller NodePort 10.96.0.1 80:30080/TCP,443:30443/TCP 10d- Service 将容器的80 端口映射到宿主机的30080 端口
- 外部用户访问
http://<任意节点IP>:30080,请求进入集群
场景 B:使用 LoadBalancer 方式(云环境)
设置 Service 为LoadBalancer类型,云厂商自动分配公网 IP,将流量直接转发到 Controller Pod。
第 2 步:kube-proxy 如何把流量交给 Controller Pod?
kube-proxy运行在每个节点上,维护网络规则:
- 请求到达节点的
30080端口时,内核中的iptables或IPVS规则拦截请求 - 规则由
kube-proxy根据 Service 的 Endpoints 动态生成 - 将请求随机或轮询地转发到其中一个 Ingress Controller Pod 的 IP 上
此时,请求已经从“宿主机网卡”进入了“容器网络”。
第 3 步:Controller(Nginx)内部做了什么?
请求进入 Ingress Controller Pod 内部的Nginx 容器:
- Nginx 监听容器内部的 80/443 端口
- Nginx 配置文件动态生成,由 Ingress Controller 进程根据 Ingress 资源实时更新
- 匹配
server_name(域名)和location(路径),决定转发目标
自动生成的 Nginx 配置片段示例:
server { listen 80; server_name example.com; location /api { proxy_pass http://backend-api-service.default.svc.cluster.local:8080; } location / { proxy_pass http://frontend-service.default.svc.cluster.local:80; } }关键点:Nginx 转发时使用的是Service 的 DNS 域名(ClusterIP),利用 Kubernetes 内置的服务发现能力。
第 4 步:从 Controller 到后端 Service
- Nginx 将请求发往
backend-api-service.default.svc.cluster.local:8080 - 解析到Service 的 ClusterIP(如
10.96.0.100) - 再次被
kube-proxy拦截,根据 Endpoints 负载均衡到其中一个 Pod
第 5 步:Pod 处理并返回响应
- 业务应用处理请求,生成响应
- 响应沿完全相同路径原路返回:Pod → kube-proxy → Ingress Controller Pod → kube-proxy → 宿主机 → 用户
第四章:Ingress YAML 核心字段详解
4.1 API 版本(Kubernetes v1.35)
apiVersion:networking.k8s.io/v1# 唯一的稳定版本,v1.22+ 唯一支持kind:Ingress4.2 完整 YAML 结构
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:my-app-ingressnamespace:defaultannotations:# 关键!通过注解控制 Controller 行为nginx.ingress.kubernetes.io/rewrite-target:/nginx.ingress.kubernetes.io/proxy-body-size:50mspec:ingressClassName:nginx# v1.35 推荐方式,指定 ControllerdefaultBackend:# 可选:所有规则不匹配时的默认后端service:name:default-backendport:number:80rules:# 核心路由规则列表-host:www.example.com# 可选:不写则匹配所有域名http:paths:-path:/apipathType:Prefix# 路径匹配类型:Exact / Prefix / ImplementationSpecificbackend:service:name:api-serviceport:number:8080-path:/pathType:Prefixbackend:service:name:web-serviceport:number:80tls:# 配置 HTTPS-hosts:-www.example.comsecretName:example-tls-secret4.3 关键字段深度解析
pathType路径匹配类型
| 类型 | 行为 | 示例 |
|---|---|---|
Exact | 严格区分大小写,完全匹配 URL 路径 | /foo匹配/foo,不匹配/foo/或/foobar |
Prefix | 基于/分隔的前缀匹配 | /foo匹配/foo、/foo/、/foobar |
ImplementationSpecific | 由具体 Ingress Controller 自行决定 | 可移植性差,不推荐 |
ingressClassName(v1.35 推荐方式)
当集群中有多个 Ingress Controller 时,通过此字段精确指定:
# 查看集群中的 IngressClasskubectl get ingressclass# 输出示例NAME CONTROLLER PARAMETERS AGE nginx k8s.io/ingress-nginx<none>10d traefik traefik.io/ingress-controller<none>5dbackend后端服务定义
在 v1.35 中,backend必须指向具体的 Service 对象,支持两种写法:
- Service(最常见)
- Resource(指向自定义资源,极少用)
第五章:实战场景配置
5.1 场景一:基于路径的路由(微服务拆分)
需求:example.com/api/*→ API 服务,example.com/*→ Web 服务。
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:path-routingannotations:nginx.ingress.kubernetes.io/rewrite-target:/$2spec:ingressClassName:nginxrules:-host:example.comhttp:paths:-path:/api(/|$)(.*)pathType:Prefixbackend:service:name:backend-apiport:number:8080-path:/pathType:Prefixbackend:service:name:frontend-webport:number:80注解说明:
rewrite-target: /$2将/api/v1/users重写为/v1/users发送给后端。
5.2 场景二:基于域名的虚拟主机(多租户)
需求:blog.example.com→ Blog 服务,shop.example.com→ Shop 服务。
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:virtual-host-routingspec:ingressClassName:nginxrules:-host:blog.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:blog-serviceport:number:80-host:shop.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:shop-serviceport:number:805.3 场景三:配置 HTTPS(TLS 终止)
Step 1:创建 TLS Secret
# Secret 必须与 Ingress 在同一 Namespacekubectl create secret tls example-tls\--key=./tls.key\--cert=./tls.crtStep 2:在 Ingress 中引用
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:tls-ingressspec:ingressClassName:nginxtls:-hosts:-example.comsecretName:example-tlsrules:-host:example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:web-serviceport:number:80效果:访问
https://example.com时,流量到达 Controller 后被解密,再转发给后端。
5.4 场景四:默认后端(自定义 404)
访问的域名或路径不在任何规则中时,流量进入defaultBackend。
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:with-default-backendspec:ingressClassName:nginxdefaultBackend:service:name:custom-404-serviceport:number:80rules:-host:valid.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:main-appport:number:80第六章:常用 Ingress Controller 注解速查表(Nginx)
Ingress 本身功能有限,强大的流量治理能力完全依赖Annotations(注解)。
| 分类 | 注解 | 示例值 | 用途 |
|---|---|---|---|
| 路径重写 | nginx.ingress.kubernetes.io/rewrite-target | /$2 | 重写 URL 路径后再转发 |
| Session 保持 | nginx.ingress.kubernetes.io/affinity | cookie | 开启会话粘滞 |
| Session 保持 | nginx.ingress.kubernetes.io/session-cookie-name | route | 自定义 Cookie 名 |
| 超时设置 | nginx.ingress.kubernetes.io/proxy-connect-timeout | 30 | 连接后端超时(秒) |
| 超时设置 | nginx.ingress.kubernetes.io/proxy-read-timeout | 180 | 读取响应超时(秒) |
| 速率限制 | nginx.ingress.kubernetes.io/limit-rps | 10 | 每秒请求数限制 |
| 速率限制 | nginx.ingress.kubernetes.io/limit-whitelist | 192.168.1.0/24 | 白名单 IP 不限制 |
| CORS | nginx.ingress.kubernetes.io/enable-cors | true | 开启跨域支持 |
| 认证 | nginx.ingress.kubernetes.io/auth-type | basic | 基础认证 |
| 认证 | nginx.ingress.kubernetes.io/auth-secret | my-secret | 存储用户名密码的 Secret |
| Body 大小 | nginx.ingress.kubernetes.io/proxy-body-size | 50m | 上传文件大小限制 |
第七章:高级配置——hostNetwork: true
7.1 什么是hostNetwork: true?
当你在 Ingress Controller 的 Deployment 中设置hostNetwork: true时,Pod不再拥有独立的容器网络命名空间,而是直接共享宿主机的网络栈。Pod 里的 Nginx 监听的 80 端口,就等于直接绑定了宿主机的 80 端口。
7.2 开启前后的流量路径对比
默认模式(hostNetwork: false):
用户 → 宿主机IP:30080(NodePort) → kube-proxy(iptables) → CNI网络跨越节点 → Ingress Controller Pod IP(如 10.244.1.5:80) → Nginx 处理路由 → 再次经过 kube-proxy → 业务 Pod(10.244.2.6:8080)开启 hostNetwork: true:
用户 → 宿主机IP:80 (直接请求) → 宿主机网络协议栈 → 直接命中 Nginx 进程(因为共享内核) → Nginx 根据规则转发 → (可能经过或不经过 kube-proxy) → 业务 Pod7.3 关键变化
| 对比项 | 默认模式 | hostNetwork: true |
|---|---|---|
| 用户访问目标 | 宿主机IP:30080 | 宿主机IP:80(标准端口) |
| 是否支持标准 80/443 端口 | ❌ (需端口映射) | ✅ (直接监听) |
| 是否经过 kube-proxy 第一跳 | ✅ 必须经过 | ❌ 直接绕过 |
| 性能 | 中等(有 NAT 损耗) | 极佳(无损耗) |
7.4 优缺点分析
优点:
- 极致性能:去除了 CNI 网络的 overlay 封装和 kube-proxy 的第一层 NAT,延迟更低
- 获取真实客户端 IP:Nginx 直接看到
$remote_addr的真实用户 IP - 使用标准端口:可以直接使用 80/443,无需 NodePort 的 30000+ 端口
缺点:
- 端口冲突:同一台宿主机只能运行一个监听 80 端口的 Controller Pod
- 宿主机网络依赖:Pod 不受
NetworkPolicy限制,防火墙规则需自行维护 - 可移植性降低:对宿主机网络有强依赖
7.5 YAML 配置示例
apiVersion:apps/v1kind:Deploymentmetadata:name:ingress-nginx-controllernamespace:ingress-nginxspec:template:spec:hostNetwork:true# 关键!开启宿主机网络模式dnsPolicy:ClusterFirstWithHostNet# 重要!确保 DNS 解析走集群内部containers:-name:controllerimage:registry.k8s.io/ingress-nginx/controller:v1.11.07.6 适用场景
- DaemonSet 部署:每个节点运行一个 Controller 副本,避免端口冲突
- 高性能网关场景:对延迟极度敏感,需要极致性能
- 边缘节点部署:将 Controller 部署在特定边缘节点,作为集群的统一流量入口
第八章:安装 Ingress Controller
正如前面强调的,YAML 写完后必须安装 Controller。以Nginx Ingress Controller为例:
8.1 使用 Helm 安装(推荐)
# 注意创建ingress controller 有最低配置需求,如果测试环境遇到配置低,需要多加配置# 添加 Helm 仓库helm repoaddingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update# 安装(默认 NodePort 模式)helminstallingress-nginx ingress-nginx/ingress-nginx\--setcontroller.service.type=NodePort# 或安装为 DaemonSet + hostNetwork 模式(高性能)helminstallingress-nginx ingress-nginx/ingress-nginx\--setcontroller.kind=DaemonSet\--setcontroller.hostNetwork=true\--setdnsPolicy=ClusterFirstWithHostNet# 或者安装阿里的higresshelm repoaddhigress.io https://higress.io/helm-charts helminstallhigress higress.io/higress-nhigress-system --create-namespace8.2 验证安装
# 查看 Controller Podkubectl get pods-ningress-nginx# 查看 Servicekubectl get svc-ningress-nginx# 查看 IngressClasskubectl get ingressclass第九章:故障排查三板斧
创建 Ingress 后发现无法访问,按此顺序排查:
9.1 检查 Ingress 资源状态
kubectl describe ingress<ingress-name>查看Events字段是否有Succeeded或报错信息。
9.2 检查 Ingress Controller 状态
# 查看 Controller Pod 状态kubectl get pods-ningress-nginx# 查看 Controller 日志kubectl logs-fdeployment/ingress-nginx-controller-ningress-nginx9.3 检查 Service Endpoints
kubectl get endpoints<service-name>如果ENDPOINTS列为空,说明 Service 的 Label Selector 没有匹配到任何 Pod。
9.4 从 Controller Pod 内测试连通性
# 进入 Controller 容器kubectlexec-it<controller-pod>-ningress-nginx -- /bin/bash# 测试能否访问后端 Servicecurl-vhttp://<backend-service-ip>第十章:最佳实践总结
- 始终指定
ingressClassName:明确指定 Ingress Controller,避免多 Controller 环境下的歧义 - 使用 TLS/HTTPS:生产环境务必开启 TLS,证书存放为 Secret
- 善用默认后端:配置自定义 404 页面,避免暴露 Nginx 默认错误页
- 谨慎使用正则表达式:过度使用正则可能降低路由性能
- 设置资源请求与限制:为 Ingress Controller Pod 设置 CPU/内存限制
- 根据场景选择部署模式:
- 一般场景:Deployment + NodePort/LoadBalancer
- 高性能场景:DaemonSet + hostNetwork: true
附录:快速索引
| 需求 | 命令/配置 |
|---|---|
| 查看 Ingress 列表 | kubectl get ingress -A |
| 查看 Ingress 详情 | kubectl describe ingress <name> |
| 查看 IngressClass | kubectl get ingressclass |
| 查看 Controller 日志 | kubectl logs -f deployment/ingress-nginx-controller -n ingress-nginx |
| 检查 Service Endpoints | kubectl get endpoints <service-name> |
| 开启 hostNetwork | hostNetwork: true+dnsPolicy: ClusterFirstWithHostNet |
| 路径重写 | nginx.ingress.kubernetes.io/rewrite-target: /$2 |
| 开启 HTTPS | tls.secretName引用包含证书的 Secret |
文档版本:v1.0(整合完整版)
适用环境:Kubernetes v1.35+ / networking.k8s.io/v1
推荐 Controller:Nginx Ingress Controller(v1.11+)
