K8s Ingress 与 Ingress API 全解析:外部访问集群的统一入口
在 Kubernetes 集群中,Pod 和 Service 的 IP 地址仅在集群内部可见,外部流量(如用户请求、第三方服务调用)无法直接访问。Ingress 作为集群的“入口网关”,解决了“外部流量如何优雅、安全地路由到集群内服务”的问题;而 Ingress API 是定义这一路由规则的标准化接口。本文将深入解析两者的核心概念、协同工作原理、实战配置及最佳实践。
一、核心概念:Ingress 与 Ingress API 的关系
1. 一句话分清:Ingress 是“功能实现”,Ingress API 是“规则定义标准”
- Ingress API:Kubernetes 内置的 API 资源(属于 `networking.k8s.io` 组),是定义路由规则的“语法规范”。它规定了如何通过 YAML 描述“外部请求(如域名、路径)如何转发到集群内的 Service”。
- Ingress:基于 Ingress API 规则运行的实际功能组件,由两部分组成:
1. Ingress 资源:用户通过 Ingress API 创建的 YAML 配置,包含具体的路由规则(如 `foo.com` → `service-foo`);
2. Ingress 控制器:监听 Ingress 资源变化的守护进程(如 Nginx Ingress Controller),负责将规则转化为实际的负载均衡配置(如 Nginx 反向代理规则),并处理外部流量转发。
简单说:Ingress API 是“规则的语言”,Ingress 控制器是“执行规则的网关”,两者协同实现外部访问集群的路由管理。
2. 为什么需要 Ingress?—— 解决 Service 的“暴露瓶颈”
K8s 中 Service 有三种暴露方式(`NodePort`、`LoadBalancer`、`ClusterIP`),但存在明显局限:
- `NodePort`:需暴露节点端口,端口管理混乱,且外部访问需携带端口(如 `http://node-ip:30080`),不友好;
- `LoadBalancer`:依赖云厂商负载均衡器,每个 Service 对应一个 LB,成本高、资源浪费;
- `ClusterIP`:仅集群内部访问,无法暴露到外部。
Ingress 则解决了这些问题:
- 统一入口:所有外部流量通过一个公共入口(Ingress 控制器的 IP/域名)进入,无需暴露多个 NodePort 或 LB;
- 灵活路由:支持按域名(如 `foo.com`、`bar.com`)、路径(如 `/api`、`/web`)、HTTP 方法(GET/POST)路由到不同 Service;
- SSL/TLS 终止:集中管理 HTTPS 证书,在 Ingress 层解密流量,无需每个 Service 单独配置;
- 负载均衡:内置负载均衡能力,分发流量到 Service 的多个 Pod。
二、Ingress API 核心规范:定义路由规则的“语法”
Ingress API 经历了多个版本演进(`v1beta1` → `v1`),目前稳定版为 `networking.k8s.io/v1`。其核心结构包括 `metadata`(元信息)和 `spec`(规则定义)两部分。
1. 核心字段解析(`spec` 部分)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress # Ingress 资源名称
namespace: default # 所属命名空间
annotations: # 附加配置(如证书、重定向、限流,依赖控制器支持)
nginx.ingress.kubernetes.io/rewrite-target: / # 路径重写(Nginx 控制器专用)
spec:
ingressClassName: nginx # 关联的 Ingress 控制器类别(需提前部署对应控制器)
tls: # HTTPS 配置(可选)
- hosts:
- foo.com # 需配置 SSL 的域名
secretName: foo-tls # 存储 SSL 证书的 Secret 名称
rules: # 核心路由规则(可配置多个)
- host: foo.com # 匹配的域名(空表示匹配所有域名)
http:
paths: # 该域名下的路径规则(可配置多个)
- path: /app # 匹配的 URL 路径(如 http://foo.com/app)
pathType: Prefix # 路径匹配类型(Prefix/Exact/ImplementationSpecific)
backend: # 路由的后端服务
service:
name: app-service # 目标 Service 名称
port:
number: 80 # 目标 Service 的端口号
- host: bar.com # 第二个域名规则
http:
paths:
- path: /api
pathType: Exact
backend:
service:
name: api-service
port:
number: 80
关键字段说明:
- `ingressClassName`:指定使用的 Ingress 控制器(如 `nginx`、`traefik`),需确保集群已部署对应控制器(否则规则不生效);
- `tls`:配置 HTTPS 证书,`secretName` 指向存储证书和私钥的 `Secret`(需提前创建,格式为 `tls.crt` 和 `tls.key`);
- `rules.host`:匹配的域名(如 `foo.com`),外部请求需通过该域名访问(需配置 DNS 解析到 Ingress 控制器的 IP);
- `paths.pathType`:路径匹配类型(核心!):
- `Prefix`:前缀匹配(如 `/app` 匹配 `/app`、`/app/xxx`);
- `Exact`:精确匹配(如 `/app` 仅匹配 `/app`,不匹配 `/app/xxx`);
- `ImplementationSpecific`:由 Ingress 控制器决定匹配规则(不推荐,兼容性差);
- `backend.service`:路由的目标 Service,Ingress 控制器会自动将流量转发到该 Service 对应的 Pod。
2. Ingress API 版本差异(v1 vs v1beta1)
K8s 1.19+ 推荐使用 `networking.k8s.io/v1`,与旧版 `v1beta1` 相比,核心变化:
- 新增 `ingressClassName` 字段,替代旧版的 `kubernetes.io/ingress.class` 注解(更规范);
- `pathType` 字段成为必填项(强制明确路径匹配规则);
- `backend` 结构简化,仅支持 `service` 类型(旧版的 `resource` 类型移至 `IngressClass` 配置);
- TLS 配置中 `hosts` 字段不再支持通配符(如 `*.foo.com` 需通过 DNS 解析或控制器配置支持)。
三、Ingress 核心组件:控制器的“执行逻辑”
Ingress 资源本身不处理流量,需依赖 **Ingress 控制器** 实现路由转发。控制器的核心工作流程:
1. 监听 Ingress 资源:通过 K8s API 监听集群中 `Ingress` 资源的创建、更新、删除事件;
2. 生成转发规则:根据 Ingress 资源的 `rules`,生成对应的负载均衡配置(如 Nginx 的 `nginx.conf`、Traefik 的动态配置);
3. 处理外部流量:控制器暴露一个公共 IP 或域名(通过 `NodePort` 或 `LoadBalancer`),外部流量进入后,根据配置的规则转发到目标 Service;
4. 动态更新:当 Ingress 资源或 Service 变化时(如 Service 后端 Pod 增减),控制器自动更新转发规则,无需手动干预。
主流 Ingress 控制器对比
| 控制器 | 核心优势 | 适用场景 | 特点 |
| Nginx Ingress | 生态成熟、配置灵活、支持丰富注解(重写、限流、缓存) | 大多数生产环境、需要复杂 HTTP 配置 | 基于 Nginx 反向代理,性能稳定,文档丰富 |
| Traefik | 云原生设计、自动发现、支持动态配置(无需重启) | K8s 原生集群、服务网格场景 | 内置服务发现,配置简洁,支持多集群 |
| HAProxy Ingress | 高性能、支持 TCP/UDP 转发、负载均衡算法丰富 | 对性能要求高的场景 | 基于 HAProxy,适合高并发服务|
| Istio Ingress | 服务网格集成、支持流量加密、灰度发布、可观测性 | 复杂微服务架构、需要高级流量控制 | 作为 Istio 服务网格的入口网关,功能强大 |
生产环境首选:Nginx Ingress(生态完善、问题排查方便)或 Traefik(云原生、维护成本低)。
四、实战:部署 Ingress 控制器 + 配置路由规则
以 Nginx Ingress Controller 为例,完整演示从部署到配置的全流程。
步骤 1:部署 Nginx Ingress Controller
推荐使用官方 Helm Chart 部署(简单高效):
1. 添加 Helm 仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
2. 部署控制器(默认命名空间 ingress-nginx):helm install nginx-ingress ingress-nginx/ingress-nginx
3. 验证部署(确保控制器 Pod 正常运行):kubectl get pods -n ingress-nginx
4. 获取 Ingress 控制器的外部 IP(云环境会自动分配 LoadBalancer IP,本地环境为 NodePort):kubectl get svc -n ingress-nginx
步骤 2:创建后端 Service 和 Pod
先部署一个简单的 Web 服务,作为 Ingress 路由的目标:
# app-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: app-service
spec:
selector:
app: web-app
ports:
- port: 80
targetPort: 80
应用配置:kubectl apply -f app-service.yaml
步骤 3:创建 Ingress 资源(路由规则)
# example-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
# 路径重写:将 /app 重写为 /(Nginx 控制器专用)
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx # 关联 Nginx 控制器
rules:
- host: app.example.com # 自定义域名(需配置 DNS 解析到控制器外部 IP)
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
应用配置:kubectl apply -f example-ingress.yaml
# 验证 Ingress 资源(确保规则生效)
kubectl get ingress
步骤 4:测试访问
1. 配置 DNS:将 `app.example.com` 解析到 Ingress 控制器的外部 IP(本地测试可修改 `/etc/hosts` 文件);
2. 访问验证:curl http://app.example.com/app
# 输出 Nginx 默认页面(说明路由成功)
五、高级功能:Ingress 的“进阶玩法”
基于 Ingress API 和控制器,可实现多种高级流量管理功能(以 Nginx Ingress 为例):
1. HTTPS 配置(TLS 终止)
1. 创建存储证书的 Secret:kubectl create secret tls app-tls --cert=path/to/tls.crt --key=path/to/tls.key
2. 在 Ingress 资源中添加 `tls` 字段(参考前文示例),重新应用后,即可通过 `https://app.example.com` 访问。
2. 路径重写与重定向
通过注解实现 URL 重写或 HTTP 到 HTTPS 重定向:
metadata:
annotations:
# HTTP 重定向到 HTTPS
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# 路径重写:/v1/api → /api
nginx.ingress.kubernetes.io/rewrite-target: /api
3. 限流与熔断
限制单个 IP 的请求速率,避免服务过载:
metadata:
annotations:
# 每秒允许 10 个请求, burst 为 20
nginx.ingress.kubernetes.io/limit-rps: "10"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "2"
4. 灰度发布(金丝雀发布)
通过 `nginx.ingress.kubernetes.io/canary` 注解实现流量切分:
# 金丝雀 Ingress 资源(与主 Ingress 同域名)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20" # 20% 流量路由到金丝雀服务
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: app-service-canary # 金丝雀服务(新版本)
port:
number: 80
六、最佳实践与避坑指南
1. 核心最佳实践
- 明确 `ingressClassName`:每个 Ingress 资源必须指定 `ingressClassName`,避免多个控制器冲突;
- 域名与 DNS 规划:为每个服务分配独立域名(如 `app.example.com`),避免路径嵌套过深(如 `/app/v1/api`);
- 证书管理:使用 `cert-manager` 自动签发和续期 Let's Encrypt 证书,避免手动维护证书过期;
- 权限控制:通过 NetworkPolicy 限制 Ingress 控制器仅能访问必要的 Service,增强安全性;
- 监控告警:监控 Ingress 控制器的请求量、错误率、响应时间(如通过 Prometheus + Grafana),及时发现异常。
2. 常见坑与解决方案
- Ingress 规则不生效:
- 检查 `ingressClassName` 是否与部署的控制器匹配;
- 检查后端 Service 是否正常运行(`kubectl get svc` 查看 `ENDPOINTS` 是否有值);
- 查看 Ingress 控制器日志(`kubectl logs -n ingress-nginx <controller-pod>`),排查配置生成错误。
- 路径匹配异常:
- 确保 `pathType` 配置正确(优先使用 `Prefix` 或 `Exact`,避免 `ImplementationSpecific`);
- Nginx 控制器的路径重写需通过 `rewrite-target` 注解,且路径配置需与重写规则匹配。
- HTTPS 访问失败:
- 检查 Secret 中的证书和私钥是否正确(`kubectl describe secret <tls-secret>`);
- 确保域名与证书的 `Common Name` 或 `Subject Alternative Name` 匹配;
- 查看控制器日志,排查证书加载错误。
总结:Ingress 与 Ingress API 的核心价值
Ingress 与 Ingress API 共同构成了 K8s 集群的“智能入口网关”,其核心价值在于:
- 统一入口管理:替代多个 NodePort/LoadBalancer,降低外部访问复杂度;
- 灵活的 HTTP/HTTPS 路由:支持域名、路径、方法级别的精细化路由;
- 扩展能力强:通过控制器和注解支持限流、熔断、灰度发布等高级功能;
- 云原生兼容:与 K8s 生态深度集成(如 Service、Secret、NetworkPolicy),适配动态扩缩容场景。
