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,但它并不直接暴露在公网上。它依赖一个类型为 NodePortLoadBalancerService 来接收外部流量。

场景 A:使用 NodePort 方式

kubectl get svc -n ingress-nginx
NAME                                 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 端口时,内核中的 iptablesIPVS 规则拦截请求
  • 规则由 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: Ingress

4.2 完整 YAML 结构

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  namespace: default
  annotations:                      # 关键!通过注解控制 Controller 行为
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/proxy-body-size: 50m
spec:
  ingressClassName: nginx           # v1.35 推荐方式,指定 Controller
  defaultBackend:                   # 可选:所有规则不匹配时的默认后端
    service:
      name: default-backend
      port:
        number: 80
  rules:                            # 核心路由规则列表
    - host: www.example.com         # 可选:不写则匹配所有域名
      http:
        paths:
          - path: /api
            pathType: Prefix        # 路径匹配类型:Exact / Prefix / ImplementationSpecific
            backend:
              service:
                name: api-service
                port:
                  number: 8080
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-service
                port:
                  number: 80
  tls:                              # 配置 HTTPS
    - hosts:
        - www.example.com
      secretName: example-tls-secret

4.3 关键字段深度解析

pathType 路径匹配类型
类型行为示例
Exact严格区分大小写,完全匹配 URL 路径/foo 匹配 /foo,不匹配 /foo//foobar
Prefix基于 / 分隔的前缀匹配/foo 匹配 /foo/foo//foobar
ImplementationSpecific由具体 Ingress Controller 自行决定可移植性差,不推荐
ingressClassName(v1.35 推荐方式)

当集群中有多个 Ingress Controller 时,通过此字段精确指定:

# 查看集群中的 IngressClass
kubectl get ingressclass

# 输出示例
NAME    CONTROLLER                    PARAMETERS   AGE
nginx   k8s.io/ingress-nginx          <none>       10d
traefik traefik.io/ingress-controller <none>       5d
backend 后端服务定义

在 v1.35 中,backend 必须指向具体的 Service 对象,支持两种写法:

  • Service(最常见)
  • Resource(指向自定义资源,极少用)

第五章:实战场景配置

5.1 场景一:基于路径的路由(微服务拆分)

需求example.com/api/* → API 服务,example.com/* → Web 服务。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-routing
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: backend-api
            port:
              number: 8080
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-web
            port:
              number: 80

注解说明rewrite-target: /$2/api/v1/users 重写为 /v1/users 发送给后端。

5.2 场景二:基于域名的虚拟主机(多租户)

需求blog.example.com → Blog 服务,shop.example.com → Shop 服务。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: virtual-host-routing
spec:
  ingressClassName: nginx
  rules:
  - host: blog.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: blog-service
            port:
              number: 80
  - host: shop.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: shop-service
            port:
              number: 80

5.3 场景三:配置 HTTPS(TLS 终止)

Step 1:创建 TLS Secret

# Secret 必须与 Ingress 在同一 Namespace
kubectl create secret tls example-tls \
  --key=./tls.key \
  --cert=./tls.crt

Step 2:在 Ingress 中引用

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    secretName: example-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

效果:访问 https://example.com 时,流量到达 Controller 后被解密,再转发给后端。

5.4 场景四:默认后端(自定义 404)

访问的域名或路径不在任何规则中时,流量进入 defaultBackend

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: with-default-backend
spec:
  ingressClassName: nginx
  defaultBackend:
    service:
      name: custom-404-service
      port:
        number: 80
  rules:
  - host: valid.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: main-app
            port:
              number: 80

第六章:常用 Ingress Controller 注解速查表(Nginx)

Ingress 本身功能有限,强大的流量治理能力完全依赖 Annotations(注解)

分类注解示例值用途
路径重写nginx.ingress.kubernetes.io/rewrite-target/$2重写 URL 路径后再转发
Session 保持nginx.ingress.kubernetes.io/affinitycookie开启会话粘滞
Session 保持nginx.ingress.kubernetes.io/session-cookie-nameroute自定义 Cookie 名
超时设置nginx.ingress.kubernetes.io/proxy-connect-timeout30连接后端超时(秒)
超时设置nginx.ingress.kubernetes.io/proxy-read-timeout180读取响应超时(秒)
速率限制nginx.ingress.kubernetes.io/limit-rps10每秒请求数限制
速率限制nginx.ingress.kubernetes.io/limit-whitelist192.168.1.0/24白名单 IP 不限制
CORSnginx.ingress.kubernetes.io/enable-corstrue开启跨域支持
认证nginx.ingress.kubernetes.io/auth-typebasic基础认证
认证nginx.ingress.kubernetes.io/auth-secretmy-secret存储用户名密码的 Secret
Body 大小nginx.ingress.kubernetes.io/proxy-body-size50m上传文件大小限制

第七章:高级配置——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)
    → 业务 Pod

7.3 关键变化

对比项默认模式hostNetwork: true
用户访问目标宿主机IP:30080宿主机IP:80(标准端口)
是否支持标准 80/443 端口❌ (需端口映射)✅ (直接监听)
是否经过 kube-proxy 第一跳✅ 必须经过❌ 直接绕过
性能中等(有 NAT 损耗)极佳(无损耗)

7.4 优缺点分析

优点:

  1. 极致性能:去除了 CNI 网络的 overlay 封装和 kube-proxy 的第一层 NAT,延迟更低
  2. 获取真实客户端 IP:Nginx 直接看到 $remote_addr 的真实用户 IP
  3. 使用标准端口:可以直接使用 80/443,无需 NodePort 的 30000+ 端口

缺点:

  1. 端口冲突:同一台宿主机只能运行一个监听 80 端口的 Controller Pod
  2. 宿主机网络依赖:Pod 不受 NetworkPolicy 限制,防火墙规则需自行维护
  3. 可移植性降低:对宿主机网络有强依赖

7.5 YAML 配置示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  template:
    spec:
      hostNetwork: true      # 关键!开启宿主机网络模式
      dnsPolicy: ClusterFirstWithHostNet  # 重要!确保 DNS 解析走集群内部
      containers:
      - name: controller
        image: registry.k8s.io/ingress-nginx/controller:v1.11.0

7.6 适用场景

  • DaemonSet 部署:每个节点运行一个 Controller 副本,避免端口冲突
  • 高性能网关场景:对延迟极度敏感,需要极致性能
  • 边缘节点部署:将 Controller 部署在特定边缘节点,作为集群的统一流量入口

第八章:安装 Ingress Controller

正如前面强调的,YAML 写完后必须安装 Controller。以 Nginx Ingress Controller 为例:

8.1 使用 Helm 安装(推荐)

# 注意创建ingress controller 有最低配置需求,如果测试环境遇到配置低,需要多加配置
# 添加 Helm 仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# 安装(默认 NodePort 模式)
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --set controller.service.type=NodePort

# 或安装为 DaemonSet + hostNetwork 模式(高性能)
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --set controller.kind=DaemonSet \
  --set controller.hostNetwork=true \
  --set dnsPolicy=ClusterFirstWithHostNet
 
# 或者安装阿里的higress
helm repo add higress.io https://higress.io/helm-charts
helm install higress higress.io/higress -n higress-system --create-namespace

8.2 验证安装

# 查看 Controller Pod
kubectl get pods -n ingress-nginx

# 查看 Service
kubectl get svc -n ingress-nginx

# 查看 IngressClass
kubectl get ingressclass

第九章:故障排查三板斧

创建 Ingress 后发现无法访问,按此顺序排查:

9.1 检查 Ingress 资源状态

kubectl describe ingress <ingress-name>

查看 Events 字段是否有 Succeeded 或报错信息。

9.2 检查 Ingress Controller 状态

# 查看 Controller Pod 状态
kubectl get pods -n ingress-nginx

# 查看 Controller 日志
kubectl logs -f deployment/ingress-nginx-controller -n ingress-nginx

9.3 检查 Service Endpoints

kubectl get endpoints <service-name>

如果 ENDPOINTS 列为空,说明 Service 的 Label Selector 没有匹配到任何 Pod。

9.4 从 Controller Pod 内测试连通性

# 进入 Controller 容器
kubectl exec -it <controller-pod> -n ingress-nginx -- /bin/bash

# 测试能否访问后端 Service
curl -v http://<backend-service-ip>

第十章:最佳实践总结

  1. 始终指定 ingressClassName:明确指定 Ingress Controller,避免多 Controller 环境下的歧义
  2. 使用 TLS/HTTPS:生产环境务必开启 TLS,证书存放为 Secret
  3. 善用默认后端:配置自定义 404 页面,避免暴露 Nginx 默认错误页
  4. 谨慎使用正则表达式:过度使用正则可能降低路由性能
  5. 设置资源请求与限制:为 Ingress Controller Pod 设置 CPU/内存限制
  6. 根据场景选择部署模式
    • 一般场景:Deployment + NodePort/LoadBalancer
    • 高性能场景:DaemonSet + hostNetwork: true

附录:快速索引

需求命令/配置
查看 Ingress 列表kubectl get ingress -A
查看 Ingress 详情kubectl describe ingress <name>
查看 IngressClasskubectl get ingressclass
查看 Controller 日志kubectl logs -f deployment/ingress-nginx-controller -n ingress-nginx
检查 Service Endpointskubectl get endpoints <service-name>
开启 hostNetworkhostNetwork: true + dnsPolicy: ClusterFirstWithHostNet
路径重写nginx.ingress.kubernetes.io/rewrite-target: /$2
开启 HTTPStls.secretName 引用包含证书的 Secret

文档版本:v1.0(整合完整版)
适用环境:Kubernetes v1.35+ / networking.k8s.io/v1
推荐 Controller:Nginx Ingress Controller(v1.11+)

更多推荐