Contents
hide
概述
什么是 Ingress?
Ingress 是 Kubernetes 中用于管理外部访问集群内服务的 API 对象。它提供了 HTTP 和 HTTPS 路由、负载均衡、SSL/TLS 终止等功能。
核心概念
- Ingress Controller:实际处理流量的组件,负责实现 Ingress 规范
- Ingress 资源:定义路由规则的 Kubernetes 资源对象
- IngressClass:用于指定使用哪个 Ingress Controller
为什么需要 Ingress?
- 统一入口管理:避免为每个 Service 使用 NodePort 或 LoadBalancer
- 成本优化:一个 LoadBalancer 可以服务多个应用
- 灵活路由:基于域名、路径的路由规则
- SSL/TLS 管理:集中管理证书
架构设计原则
1. 集中式 Controller + 分布式 Ingress 资源
核心思想:
- 集群级部署一个或多个 Ingress Controller(高可用)
- 各业务命名空间独立管理自己的 Ingress 资源
- Controller 统一处理所有命名空间的 Ingress
2. IngressClass 作用域
集群作用域(Cluster-scoped)
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
spec:
controller: k8s.io/ingress-nginx
特点:
- 集群内所有命名空间可用
- 适合共享的 Ingress Controller
- 生产环境推荐使用
命名空间作用域(Namespace-scoped)
特点:
- 仅在该命名空间内可用
- 适合多租户或特殊隔离场景
- 一般不建议使用
Ingress Controller 选型
主流 Controller 对比
| Controller | 维护者 | 特点 | 适用场景 |
|---|---|---|---|
| Ingress-NGINX | Kubernetes 社区 | 最流行,基于 Nginx,功能丰富 | 通用场景,推荐 |
| Traefik | Traefik Labs | 配置简单,自动证书 | 微服务架构 |
| Istio Gateway | Istio 社区 | 服务网格集成 | 服务网格环境 |
| Kong | Kong Inc. | API 网关功能 | API 管理场景 |
推荐:Ingress-NGINX
优势:
- Kubernetes 官方维护,社区活跃
- 功能完善,文档齐全
- 性能优秀,生产验证
- 支持丰富的注解(annotations)
企业级架构方案
标准架构图
┌─────────────────────────────────────────────────────────┐
│ 外部流量入口 │
│ (LoadBalancer / NodePort) │
└──────────────────────┬──────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────┐
│ Ingress Controller (集群级) │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Namespace: ingress-nginx │ │
│ │ - Deployment: ingress-nginx-controller (3副本) │ │
│ │ - Service: LoadBalancer │ │
│ │ - IngressClass: nginx (集群作用域) │ │
│ └──────────────────────────────────────────────────┘ │
└──────────────────────┬──────────────────────────────────┘
│ 监听所有命名空间
┌──────────────┼──────────────┐
│ │ │
┌───────▼──────┐ ┌─────▼──────┐ ┌─────▼──────┐
│ a-api │ │ b-api │ │ c-api │
│ namespace │ │ namespace │ │ namespace │
│ │ │ │ │ │
│ Ingress │ │ Ingress │ │ Ingress │
│ Service │ │ Service │ │ Service │
│ Deployment │ │ Deployment│ │ Deployment│
└──────────────┘ └────────────┘ └────────────┘
高可用部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
replicas: 3 <em># 多副本高可用</em>
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- ingress-nginx
topologyKey: kubernetes.io/hostname
多 Controller 场景(可选)
如果需要内外网隔离:
- ingress-nginx-internal (内网,IngressClass: nginx-internal)
- ingress-nginx-external (外网,IngressClass: nginx-external)
Ingress-NGINX 工作原理
1. 核心架构组件
┌─────────────────────────────────────────┐
│ Ingress Controller Pod │
│ ┌───────────────────────────────────┐ │
│ │ Ingress Controller (Go程序) │ │
│ │ - 监听 Kubernetes API Server │ │
│ │ - 生成 Nginx 配置 │ │
│ │ - 管理 Nginx 进程 │ │
│ └───────────────────────────────────┘ │
│ ┌───────────────────────────────────┐ │
│ │ Nginx (C程序) │ │
│ │ - 实际处理 HTTP/HTTPS 流量 │ │
│ │ - 读取生成的配置文件 │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
2. 工作流程
阶段 1:Controller 启动和初始化
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
template:
spec:
containers:
- name: controller
args:
- /nginx-ingress-controller
- --watch-ingress-without-class=true <em># 监听所有 Ingress</em>
- --ingress-class=nginx <em># 只处理指定 class 的 Ingress</em>
- --configmap=ingress-nginx-controller <em># 全局配置</em>
启动步骤:
- 连接 Kubernetes API Server
- 创建必要的 RBAC 权限(ClusterRole/ClusterRoleBinding)
- 初始化 Informer 监听机制
阶段 2:监听机制(Informer Pattern)
Controller 使用 Kubernetes 的 Informer 机制实现事件驱动监听:
关键特性:
- 集群级权限:通过 ClusterRole 读取所有命名空间的资源
- 事件驱动:资源变化时立即触发,无需轮询
- 本地缓存:减少 API Server 压力
监听资源类型:
- Ingress 资源(所有命名空间)
- Service 资源(相关命名空间)
- Endpoints 资源(相关命名空间)
- Secret 资源(TLS 证书)
阶段 3:Ingress 资源发现和过滤
当在任何命名空间创建 Ingress 时:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: a-api-ingress
namespace: a-api
spec:
ingressClassName: nginx <em># 关键:指定使用 nginx IngressClass</em>
rules:
- host: a-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: a-api-service
port:
number: 80
Controller 处理逻辑:
- IngressClass 匹配检查
- 检查
spec.ingressClassName是否匹配 - 如果不匹配,忽略该 Ingress
- 检查
- 资源验证
- 验证 Ingress 规则的有效性
- 检查引用的 Service 是否存在
- 规则解析
- 解析 host、path 规则
- 获取后端 Service 信息
- 缓存更新
- 更新内部 Ingress 缓存
- 触发配置重新生成
阶段 4:Nginx 配置生成
Controller 将 Ingress 规则转换为 Nginx 配置:
生成的配置示例:
<em># /etc/nginx/nginx.conf</em>
<em># 从 a-api 命名空间</em>
upstream upstream_balancer_a {
least_conn;
server 10.244.1.5:8080 max_fails=0 fail_timeout=0;
server 10.244.1.6:8080 max_fails=0 fail_timeout=0;
}
server {
listen 80;
server_name a-api.example.com;
location / {
proxy_pass http://upstream_balancer_a;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
<em># 从 b-api 命名空间</em>
upstream upstream_balancer_b {
least_conn;
server 10.244.2.3:8080 max_fails=0 fail_timeout=0;
}
server {
listen 80;
server_name b-api.example.com;
location / {
proxy_pass http://upstream_balancer_b;
}
}
配置生成过程:
- 遍历所有匹配的 Ingress 资源
- 解析每个 Ingress 的规则(host、path)
- 获取对应的 Service 和 Endpoints
- 生成 upstream 配置(负载均衡)
- 生成 server 块(路由规则)
- 写入配置文件
- 验证配置语法
- 重载 Nginx(
nginx -s reload)
阶段 5:Service 和 Endpoints 发现
Controller 同时监听 Service 和 Endpoints 变化:
Endpoints 更新流程:
- Pod 启动/停止 → Endpoints 变化
- Controller 监听到变化
- 更新对应的 upstream 配置
- 重载 Nginx
关键点:
- Endpoints 变化时自动更新负载均衡配置
- 无需手动干预,实现自动服务发现
3. 跨命名空间访问原理
RBAC 配置
<em># ClusterRole - 集群级权限</em>
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ingress-nginx
rules:
- apiGroups: [""]
resources: ["services", "endpoints", "secrets", "nodes", "pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses/status"]
verbs: ["update"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingressclasses"]
verbs: ["get", "list", "watch"]
---
<em># ClusterRoleBinding - 绑定到所有命名空间</em>
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
权限说明:
ClusterRole提供集群级权限,可访问所有命名空间ClusterRoleBinding将权限绑定到 Controller 的 ServiceAccount- Controller 因此可以读取所有命名空间的 Ingress、Service、Endpoints
4. IngressClass 匹配机制
IngressClass 定义
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
spec:
controller: k8s.io/ingress-nginx
匹配逻辑
Controller 启动时指定要处理的 IngressClass:
--ingress-class=nginx
匹配规则:
- Ingress 明确指定
ingressClassName: nginx→ 匹配 - Ingress 未指定,但 nginx 是默认 IngressClass → 匹配
- 其他情况 → 不匹配,忽略
5. 完整数据流
用户创建 Ingress (a-api 命名空间)
↓
Kubernetes API Server
↓
Ingress Controller Informer 监听到事件
↓
Controller 验证 IngressClass 匹配
↓
Controller 读取对应的 Service (a-api 命名空间)
↓
Controller 读取 Service 的 Endpoints
↓
Controller 生成 Nginx 配置(包含 upstream)
↓
Controller 写入 /etc/nginx/nginx.conf
↓
Controller 执行 nginx -s reload
↓
Nginx 开始处理流量
↓
流量 → Nginx → Service → Pod
实施步骤
步骤 1:部署 Ingress Controller
使用 Helm 部署(推荐)
<em># 添加 Helm 仓库</em>
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
<em># 安装 Ingress Controller</em>
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.replicaCount=3 \
--set controller.service.type=LoadBalancer
使用官方 YAML 部署
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml
验证部署
<em># 检查 Controller 状态</em>
kubectl get pods -n ingress-nginx
<em># 检查 IngressClass</em>
kubectl get ingressclass
<em># 检查 Service</em>
kubectl get svc -n ingress-nginx
步骤 2:创建 IngressClass(如未自动创建)
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
spec:
controller: k8s.io/ingress-nginx
步骤 3:在各命名空间创建 Ingress 资源
a-api 命名空间示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: a-api-ingress
namespace: a-api
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- a-api.example.com
secretName: a-api-tls
rules:
- host: a-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: a-api-service
port:
number: 80
b-api 命名空间示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: b-api-ingress
namespace: b-api
spec:
ingressClassName: nginx
rules:
- host: b-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: b-api-service
port:
number: 80
步骤 4:配置 TLS 证书(可选)
<em># 创建 TLS Secret</em>
apiVersion: v1
kind: Secret
metadata:
name: a-api-tls
namespace: a-api
type: kubernetes.io/tls
data:
tls.crt: <base64-encoded-cert>
tls.key: <base64-encoded-key>
步骤 5:验证配置
<em># 检查 Ingress 状态</em>
kubectl get ingress -A
<em># 查看 Ingress 详情</em>
kubectl describe ingress a-api-ingress -n a-api
<em># 测试访问</em>
curl -H "Host: a-api.example.com" http://<ingress-ip>/
最佳实践
✅ 推荐做法
1. 单一 Ingress Controller
- 一个集群部署一个 Ingress Controller(多副本高可用)
- 所有命名空间共享同一个 Controller
- 节省资源,便于管理
2. IngressClass 集群作用域
- 使用集群作用域的 IngressClass
- 所有命名空间可以引用
- 统一管理,避免混乱
3. 命名空间隔离
- 每个业务命名空间管理自己的 Ingress 资源
- 通过 RBAC 限制权限
- 实现职责分离
4. 域名规划
方案 A:子域名
a-api.example.com
b-api.example.com
c-api.example.com
方案 B:路径路由
example.com/a-api
example.com/b-api
example.com/c-api
5. RBAC 控制
<em># 限制命名空间只能管理自己的 Ingress</em>
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ingress-manager
namespace: a-api
rules:
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ingress-manager
namespace: a-api
subjects:
- kind: ServiceAccount
name: app-deployer
namespace: a-api
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-manager
6. 监控告警
- 监控 Ingress Controller 的 Pod 状态
- 监控 Nginx 错误日志
- 监控 Ingress 资源状态
- 设置告警规则
7. 资源限制
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
spec:
template:
spec:
containers:
- name: controller
resources:
requests:
cpu: 100m
memory: 90Mi
limits:
cpu: 1000m
memory: 512Mi
8. 配置优化
<em># ConfigMap 配置</em>
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
<em># 工作进程数</em>
worker-processes: "4"
<em># 最大连接数</em>
max-worker-connections: "16384"
<em># 启用 gzip</em>
enable-gzip: "true"
<em># 日志格式</em>
log-format-upstream: |
$remote_addr - $remote_user [$time_local] "$request"
$status $body_bytes_sent "$http_referer"
"$http_user_agent" $request_length $request_time
[$proxy_upstream_name] [$proxy_alternative_upstream_name]
$upstream_addr $upstream_response_length
$upstream_response_time $upstream_status
$req_id
❌ 不推荐做法
- 每个命名空间部署独立的 Controller
- 资源浪费
- 管理复杂
- 成本增加
- 使用命名空间作用域的 IngressClass
- 除非有特殊隔离需求
- 一般场景不推荐
- 在 Ingress 中硬编码 IP
- 使用 Service 名称
- 利用服务发现
- 忽略 TLS 配置
- 生产环境必须启用 HTTPS
- 使用 Let’s Encrypt 自动证书
常见问题与解决方案
Q1: Controller 无法发现其他命名空间的 Ingress?
原因:
- RBAC 权限不足
- IngressClass 不匹配
解决方案:
<em># 检查 RBAC</em>
kubectl get clusterrole ingress-nginx -o yaml
kubectl get clusterrolebinding ingress-nginx -o yaml
<em># 检查 IngressClass</em>
kubectl get ingressclass
kubectl describe ingress <ingress-name> -n <namespace>
Q2: 如何实现蓝绿部署?
使用 Ingress 注解:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10" <em># 10% 流量</em>
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service-v2 <em># 新版本</em>
port:
number: 80
Q3: 如何配置限流?
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/limit-rps: "100"
nginx.ingress.kubernetes.io/limit-connections: "10"
spec:
ingressClassName: nginx
<em># ...</em>
Q4: 如何实现跨命名空间服务访问?
Ingress 可以引用其他命名空间的 Service(需要特殊配置):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cross-ns-ingress
namespace: a-api
annotations:
nginx.ingress.kubernetes.io/upstream-vhost: "b-api-service.b-api.svc.cluster.local"
spec:
ingressClassName: nginx
rules:
- host: a-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: b-api-service
namespace: b-api <em># 跨命名空间</em>
port:
number: 80
注意:需要 Controller 有跨命名空间访问权限。
Q5: 如何查看 Nginx 配置?
<em># 进入 Controller Pod</em>
kubectl exec -it -n ingress-nginx <controller-pod> -- /bin/sh
<em># 查看生成的配置</em>
cat /etc/nginx/nginx.conf
<em># 查看特定 upstream</em>
grep -A 10 "upstream_balancer" /etc/nginx/nginx.conf
GitOps 集成
目录结构
ic2-deploy-config/
├── ingress-controller/ # Ingress Controller 配置
│ ├── base/
│ │ ├── ingressclass.yaml
│ │ ├── deployment.yaml
│ │ └── kustomization.yaml
│ └── overlays/
│ ├── production/
│ └── staging/
├── apps/
│ ├── backend/
│ │ ├── a-api/
│ │ │ ├── base/
│ │ │ │ └── ingress.yaml # 业务 Ingress
│ │ │ └── overlays/
│ │ └── b-api/
│ └── ...
└── argocd-bootstrap/
└── ingress-controller/
└── application.yaml
ArgoCD Application 示例
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ingress-controller
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/ic2-deploy-config
targetRevision: main
path: ingress-controller/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: ingress-nginx
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
业务 Ingress 管理
每个业务应用在自己的目录下管理 Ingress:
<em># apps/backend/a-api/base/ingress.yaml</em>
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: a-api-ingress
namespace: a-api
spec:
ingressClassName: nginx
rules:
- host: a-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: a-api-service
port:
number: 80
环境差异化配置
<em># apps/backend/a-api/overlays/production/ingress-patch.yaml</em>
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: a-api-ingress
namespace: a-api
spec:
rules:
- host: a-api.prod.example.com <em># 生产环境域名</em>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: a-api-service
port:
number: 80
总结
核心要点
- 一个集群级 Ingress Controller 处理所有命名空间的 Ingress
- 通过 ClusterRole 获得集群级权限
- 使用 Informer 监听所有命名空间
- IngressClass 过滤匹配的 Ingress
- IngressClass 使用集群作用域
- 所有命名空间共享
- 统一管理,避免混乱
- 各命名空间独立管理 Ingress 资源
- 职责分离
- 通过 RBAC 控制权限
- GitOps 实践
- Controller 配置放在基础设施仓库
- 业务 Ingress 随应用代码管理
- 使用 ArgoCD/Flux 自动化部署
架构优势
- ✅ 资源高效:一个 Controller 服务所有应用
- ✅ 管理简单:统一入口,集中管理
- ✅ 成本优化:减少 LoadBalancer 数量
- ✅ 灵活扩展:支持多 Controller 场景
- ✅ 生产就绪:高可用、监控、告警
