Ingress 与 Gateway API
CKA Domain 3 — Kubernetes Ingress 控制器配置与 Gateway API 概念
概述
Ingress 是 Kubernetes 中管理外部访问集群服务的 API 对象,提供基于 HTTP/HTTPS 的路由规则。Gateway API 是新一代的 API 网关标准,旨在替代 Ingress,提供更强大的路由能力和更清晰的职责分离。
一、Ingress
Ingress 控制器 vs Ingress 资源
- Ingress 控制器:实际运行的反向代理/负载均衡器(如 nginx-ingress、traefik、HAProxy)
- Ingress 资源:定义路由规则的 YAML 声明
只有安装了 Ingress 控制器后,Ingress 资源才能生效。
安装 Ingress 控制器
# NGINX Ingress Controller (minikube)
minikube addons enable ingress
# NGINX Ingress Controller (k8s 集群)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.4/deploy/static/provider/cloud/deploy.yaml
基础 Ingress YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
spec:
ingressClassName: nginx # K8s v1.18+,指定 Ingress 控制器
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
pathType
| 类型 | 说明 |
|---|---|
Prefix | 基于 URL 前缀匹配(如 /api 匹配 /api/users) |
Exact | 精确 URL 匹配 |
ImplementationSpecific | 由 Ingress 控制器自定义匹配逻辑 |
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-type-ingress
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
# 精确匹配
- path: /exact-match
pathType: Exact
backend:
service:
name: exact-svc
port:
number: 80
# 前缀匹配
- path: /api
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 8080
多主机名路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
ingressClassName: nginx
rules:
- host: app1.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app1-svc
port:
number: 80
- host: app2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app2-svc
port:
number: 80
Ingress 注解
注解用于配置 Ingress 控制器的特定行为:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: annotated-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # URL 重写
nginx.ingress.kubernetes.io/ssl-redirect: "true" # SSL 重定向
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
nginx.ingress.kubernetes.io/limit-rps: "10" # 速率限制
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /old-path
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
常用注解列表:
| 注解 | 说明 |
|---|---|
nginx.ingress.kubernetes.io/rewrite-target | URL 重写目标 |
nginx.ingress.kubernetes.io/ssl-redirect | HTTP 自动跳转 HTTPS |
nginx.ingress.kubernetes.io/cors-enabled | 启用 CORS |
nginx.ingress.kubernetes.io/limit-rps | 每秒请求数限制 |
nginx.ingress.kubernetes.io/whitelist-source-range | IP 白名单 |
TLS/SSL 配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- secure.example.com
secretName: tls-secret # 使用 kubectl create secret tls 创建
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: secure-svc
port:
number: 443
# 创建 TLS Secret
kubectl create secret tls tls-secret --cert=path/to/tls.crt --key=path/to/tls.key
常用命令
# 创建 Ingress
kubectl create ingress my-ingress --rule="example.com/=my-service:80"
# 查看 Ingress
kubectl get ingress
kubectl get ingress -o wide
kubectl describe ingress my-ingress
# 编辑 Ingress
kubectl edit ingress my-ingress
二、Gateway API
概述
Gateway API 是 Kubernetes 的一个扩展 API,旨在大幅改进 Ingress 的功能。它引入了一种新的服务网络模型,其关键特性包括:
- 面向角色的设计:区分基础设施提供商、集群管理员和应用开发者
- 可移植性:跨不同实现的标准 API
- 表达能力更强:支持 HTTP 头匹配、权重路由、流量分割等
核心资源
GatewayClass → 集群范围的网关类定义
↓
Gateway → 网关实例(类似 Ingress 控制器实例)
↓
HTTPRoute → 路由规则(类似 Ingress 规则)
Gateway 示例
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: example-gateway-class
spec:
controllerName: example.io/gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
spec:
gatewayClassName: example-gateway-class
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-http-route
spec:
parentRefs:
- name: my-gateway
hostnames:
- example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-svc
port: 8080
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: web-svc
port: 80
Gateway API 特性
# 流量分割(Traffic Splitting / Canary)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: traffic-split
spec:
parentRefs:
- name: my-gateway
rules:
- backendRefs:
- name: stable-svc
port: 80
weight: 90
- name: canary-svc
port: 80
weight: 10
Ingress vs Gateway API 对比
| 特性 | Ingress | Gateway API |
|---|---|---|
| 标准规范 | Kubernetes 核心 API | 扩展 API (CRD) |
| 角色分离 | 单一资源 | GatewayClass / Gateway / Route 三层 |
| 协议支持 | HTTP/HTTPS | HTTP、HTTPS、TCP、UDP、TLS |
| 流量分割 | 依赖注解 | 原生支持(权重路由) |
| 头匹配 | 依赖注解 | 原生支持 |
| 跨命名空间 | 默认不支持 | 原生支持 |
| 成熟度 | GA(稳定) | Beta(v1.0+) |
🧪 完整操作实例:配置基于路径的 Ingress 路由
场景描述
创建两个 Deployment(app1 和 app2),通过 Ingress 按路径前缀(/app1 和 /app2)将流量路由到不同的后端 Service。
前置条件
- 集群已安装 NGINX Ingress Controller(或 minikube 已启用 ingress addon)
- kubectl 已配置好集群访问
- 测试机器上可修改 /etc/hosts 或使用 curl --resolve
操作步骤
Step 1: 创建 app1 Deployment 及其 Service
# 创建 app1 Deployment(模拟前端应用)
kubectl create deployment app1 --image=nginx:1.25 --replicas=2
# 预期输出:deployment.apps/app1 created
# 自定义 app1 的首页内容,便于区分
kubectl exec deployment/app1 -- sh -c 'echo "<h1>App 1</h1>" > /usr/share/nginx/html/index.html'
# 预期输出:无报错
# 暴露 app1 为 ClusterIP Service
kubectl expose deployment app1 --name=app1-svc --port=80 --target-port=80
# 预期输出:service/app1-svc exposed
Step 2: 创建 app2 Deployment 及其 Service
# 创建 app2 Deployment(模拟后端 API 服务)
kubectl create deployment app2 --image=nginx:1.25 --replicas=1
# 预期输出:deployment.apps/app2 created
# 自定义 app2 的首页内容
kubectl exec deployment/app2 -- sh -c 'echo "<h1>App 2</h1>" > /usr/share/nginx/html/index.html'
# 预期输出:无报错
# 暴露 app2 为 ClusterIP Service
kubectl expose deployment app2 --name=app2-svc --port=80 --target-port=80
# 预期输出:service/app2-svc exposed
# 确认 Service 已创建
kubectl get svc app1-svc app2-svc
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# app1-svc ClusterIP 10.96.100.1 <none> 80/TCP 1m
# app2-svc ClusterIP 10.96.100.2 <none> 80/TCP 1m
Step 3: 创建 Ingress 资源
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-based-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /app1
pathType: Prefix
backend:
service:
name: app1-svc
port:
number: 80
- path: /app2
pathType: Prefix
backend:
service:
name: app2-svc
port:
number: 80
EOF
# 预期输出:ingress.networking.k8s.io/path-based-ingress created
kubectl get ingress path-based-ingress
# NAME CLASS HOSTS ADDRESS PORTS AGE
# path-based-ingress nginx myapp.example.com localhost 80 10s
Step 4: 配置本地域名解析
# 获取 Ingress 控制器暴露的 IP
# 如果是 minikube:
minikube ip
# 假设输出:192.168.49.2
# 如果是 kind 或其他集群,获取 Ingress 控制器 Pod 所在节点 IP:
kubectl get pods -n ingress-nginx -o wide
# 添加 hosts 记录(Linux/macOS 需要 sudo):
# echo "192.168.49.2 myapp.example.com" | sudo tee -a /etc/hosts
# 对于 minikube,也可以使用 minikube tunnel(另开终端):
# minikube tunnel
# 或者使用 curl --resolve 避免修改 hosts
INGRESS_IP=$(kubectl get ingress path-based-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "Ingress IP: $INGRESS_IP"
# 如果 IP 为空,minikube 可能需要 minikube tunnel
Step 5: 验证路径路由
# 使用 curl 测试 /app1 路径
curl -H "Host: myapp.example.com" http://localhost/app1
# 或如果已有 Ingress IP:
curl --resolve myapp.example.com:80:$INGRESS_IP http://myapp.example.com/app1
# 预期输出:<h1>App 1</h1>(rewrite-target 将 /app1 重写为 /)
# 测试 /app2 路径
curl --resolve myapp.example.com:80:$INGRESS_IP http://myapp.example.com/app2
# 预期输出:<h1>App 2</h1>
# 测试根路径(应返回 404 因为未定义根路径路由)
curl --resolve myapp.example.com:80:$INGRESS_IP http://myapp.example.com/
# 预期输出:nginx 404 Not Found
Step 6: 对比 Gateway API 格式(附加)
# 查看 Gateway API 等效配置(需安装 Gateway API CRD)
cat <<EOF
# Gateway API 等效的 HTTPRoute 配置:
# apiVersion: gateway.networking.k8s.io/v1
# kind: HTTPRoute
# metadata:
# name: app-routes
# spec:
# parentRefs:
# - name: my-gateway
# hostnames:
# - "myapp.example.com"
# rules:
# - matches:
# - path:
# type: PathPrefix
# value: /app1
# backendRefs:
# - name: app1-svc
# port: 80
# - matches:
# - path:
# type: PathPrefix
# value: /app2
# backendRefs:
# - name: app2-svc
# port: 80
EOF
验证结果
# 查看 Ingress 详情
kubectl describe ingress path-based-ingress
# Rules:
# Host Path Backends
# ---- ---- --------
# myapp.example.com
# /app1 app1-svc:80 (10.244.1.5:80,10.244.2.7:80)
# /app2 app2-svc:80 (10.244.3.9:80)
# 查看 Ingress 控制器日志(确认请求路由)
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller --tail=50 | grep -i "myapp.example.com"
# 清理资源
kubectl delete ingress path-based-ingress
kubectl delete deployment app1 app2
kubectl delete svc app1-svc app2-svc
考试提示
-
rewrite-target 注解是关键:
nginx.ingress.kubernetes.io/rewrite-target: /将路径前缀重写为/,否则后端 Pod 收到的请求路径仍带前缀 -
pathType 选择:Prefix 按前缀匹配(如 /api 匹配 /api/users),Exact 精确匹配
-
Ingress 控制器必须先安装,否则 Ingress 资源创建后状态一直是
<pending> -
CKA 考试中通常使用
kubectl create ingress命令快速创建,但 YAML 方式更可控 -
访问 Ingress 前需确保网络可达(minikube:
minikube tunnel或kubectl port-forward) -
如果无法修改 /etc/hosts,使用
curl --resolve或curl -H "Host: ..."替代 -
https://kubernetes.io/docs/concepts/services-networking/ingress/
-
https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/
-
https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/
-
https://kubernetes.io/docs/concepts/services-networking/gateway/