Kubernetes Ingress-NGINX终极指南:从入门到实战
目录
模块1:ingress-nginx 基础认知
Kubernetes 中,Ingress 是用于管理集群内服务对外访问的资源对象。通过 Ingress,可以在单一 IP/域名下对不同 Service 的 HTTP/HTTPS 请求进行路由。例如,可以根据请求的 Host 和 Path 将流量转发到不同的后端 Service 的 Pod。与之相比,没有 Ingress 时,服务对外暴露通常使用 NodePort 或 LoadBalancer:
-
NodePort: 将 Service 暴露在每个节点的指定端口(30000-32767)。缺点在于“每个端口只能对应一个服务,端口范围受限”,且要管理多节点 IP 地址,对于端口管理混乱。
-
LoadBalancer: 在云环境下可创建外部负载均衡器,为每个 Service 分配一个外部 IP。虽可无侵入式支持多协议,但缺点是“每个 Service 需要独立的负载均衡器和 IP 地址,成本高昂”。
Ingress 能力弥补了上述短板:它充当第7层(HTTP/HTTPS)负载均衡器,通过统一的入口域名/IP 支持多 Service 的路径和域名路由,可集中管理 TLS 证书、应用多种策略。正如 F5 官方文档所述:“Ingress 可能是暴露服务的最强大方式……你只需要为一个负载均衡器付费,并且由于 Ingress 是‘智能’的,还可以获得 SSL、认证、路由等开箱即用特性”。
Ingress-NGINX 是 Kubernetes 常用的 Ingress Controller 实现。它使用 NGINX 作为反向代理和负载均衡器。Ingress-NGINX Controller 作为一个 Pod(通常运行在 ingress-nginx 命名空间),持续监听 Kubernetes API 中的 Ingress/Service/Endpoints/Secret 等资源,当规则变更时,自动生成新的 NGINX 配置并重载 NGINX。这种架构类似于住宅小区的大门岗亭,根据访客(请求)的域名/路径指引到目标楼栋(Service)和房间(Pod)。
Ingress Controller 持续 Watch Ingress、Service、Endpoints 等资源的变化,生成 Nginx 配置并热重载,当客户端请求到达时根据 Host/Path 规则将流量转发到相应 Service 后端的 Pod。
1.1 Ingress-NGINX 的核心架构
-
Controller Pod: Ingress-NGINX 运行时会部署一个 Deployment(Controller),Pod 内运行 NGINX 及一个 Go 语言控制器进程。该进程通过 Kubernetes Informer 监听 Ingress、Service、Endpoints、Secret、ConfigMap 等资源。每当规则或后端 Pod 变更时,Controller 会动态生成新的
nginx.conf并执行nginx -s reload,从而更新负载均衡策略help.aliyun.com。该 Controller 通常使用一个 ServiceAccount 运行,并绑定相应的 RBAC 权限(见下)。 -
ConfigMap: Ingress-NGINX 的行为(如连接超时、日志格式、worker 数量等)通过 ConfigMap 配置中心定义kubernetes.github.io。ConfigMap 存储键值对,以覆盖 Controller 的默认设置kubernetes.github.io;例如可以设置
map-hash-bucket-size、worker-processes、ssl-protocols等。这意味着无需更改容器镜像即可调整控制器运行时配置。修改 ConfigMap 后,Controller 会自动检测并重新加载新的 NGINX 配置。 -
RBAC 权限: Ingress-NGINX 在集群中需要丰富权限来读写资源。通常会创建一个
ingress-nginxServiceAccount,并为其绑定 ClusterRole(集群级权限)和 Role(命名空间级权限)kubernetes.github.iokubernetes.github.io。示例中,ClusterRole 赋予对configmaps、endpoints、pods、secrets列表/监视权限,以及对services、ingresses、ingressclasses等资源的读写权限kubernetes.github.io;而命名空间级 Role 赋予对同名命名空间内 configmaps、pods、secrets、endpoints 的只读权限kubernetes.github.io。这样,Ingress Controller 才能实时获取 Ingress 规则、Service/Endpoint 变化并更新配置。 -
后端关联逻辑: 当 Ingress 配置包含某个 Service 作为后端时,Controller 会查询该 Service 对应的 Endpoints(或 EndpointSlice)来获取后端 Pod 的 IP 列表alibabacloud.comalibabacloud.com。例如,在图 1 中,Service 是后端真实服务的抽象,一个 Service 可以对应多个相同后端的 Podalibabacloud.com。Ingress Controller 解析 Ingress 规则后,将请求发送到匹配的 Service,再由 Service 将流量分发到其后端 Pod。这意味着后端 Pod 的弹性扩容/缩减、IP 变更都会被 Controller 感知并即时反映到 Nginx upstream 中。
1.2 Ingress-NGINX 的核心功能
-
HTTP/HTTPS 路由: 支持基于域名和路径的请求路由。Ingress 规则可指定
host和http.paths,Controller 根据 Host/Path 匹配转发到对应 Service。这实现了同一 IP(或域名)下对多服务的区分路由。如阿里云文档所述:“Nginx Ingress 是反向代理规则,用来规定 HTTP/HTTPS 请求应该被转发到哪个 Service 所对应的 Pod 上。例如根据请求中不同的 Host 和 URL 路径,让请求落到不同的 Service 所对应的 Pod 上”alibabacloud.com。典型场景:前端域名frontend.example.com转发至前端服务,API 子域api.example.com转发至后端 API 服务,实现路径级别的业务隔离。 -
路径重写(Rewrite): 在某些场景下,希望去掉请求中的基础路径。Ingress-NGINX 提供
nginx.ingress.kubernetes.io/rewrite-target注解,对请求路径进行重写。例如将外部/api/v1/xxx重写为内部/v1/xxx。这一功能常用于微服务版本升级或统一路由格式。使用时通常结合正则匹配注解(use-regex: "true")将匹配路径的部分替换到后端。例如,可以设置:
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2 # 重写目标
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: example.com
http:
- path: /api/v1(/|$)(.*) # 正则路径匹配
pathType: ImplementationSpecific
backend:
service:
name: api-svc
port:
number: 80
这样,访问 example.com/api/v1/foo 会被重写为 /foo 转发到 api-svc。
-
负载均衡: NGINX 默认采用 轮询(Round Robin) 分发到后端。Ingress-NGINX 允许通过 ConfigMap 全局配置
load-balance参数来改变算法(例如可选ewma峰值加权平均),默认为轮询kubernetes.github.io。也可在 Ingress 上使用注解实现不同策略:如通过nginx.ingress.kubernetes.io/upstream-hash-by启用基于客户端 IP 或其它变量的一致性哈希,或者通过nginx.ingress.kubernetes.io/affinity: cookie启用基于会话 Cookie 的会话粘滞(Session Affinity)kubernetes.github.iokubernetes.github.io。会话粘滞常见于需要保持用户会话状态的场景(如电商购物车)。注解affinity: cookie会在首次访问时设置一个粘滞 Cookie(默认名INGRESSCOOKIE),后续来自同一用户的请求将被固定路由到同一后端 Podkubernetes.github.io。 -
SSL/TLS 证书管理: Ingress 支持 TLS 终止,可在 Ingress 规则中配置
tls字段和 Secret,统一管理证书。Ingress-NGINX 支持 SNI,可在同一 Controller 上同时终止多个域名的 HTTPS。在企业环境中,常用 cert-manager 等组件配合自动签发证书。通过为 Ingress 添加cert-manager.io/cluster-issuer注解,cert-manager 会自动为对应域名申请证书并存储在指定 Secret 中cert-manager.io。企业可利用此方式集中管理数百个域名的 HTTPS 证书,降低手工维护成本。例如,在 Ingress 上加注cert-manager.io/cluster-issuer: letsencrypt,Ingress Controller 会自动调用 ClusterIssuer 发起证书颁发,并更新 Secret,Nginx 随即加载新证书cert-manager.io。 -
跨域配置(CORS): 当前后端分离部署时,不同域名/端口下的资源访问需要 CORS。Ingress-NGINX 提供注解方式配置 CORS HTTP 头。开启方式为在 Ingress 上添加
nginx.ingress.kubernetes.io/enable-cors: "true"kubernetes.github.io,并可通过如cors-allow-origin、cors-allow-methods、cors-allow-headers等注解设定Access-Control-Allow-*的值kubernetes.github.iokubernetes.github.io。例如当前端应用部署在https://frontend.example.com,后端服务部署在https://api.example.com时,需要在后端对应的 Ingress 上配置 CORSalibabacloud.com,如设置cors-allow-origin: "https://frontend.example.com",以允许前端跨域调用。 -
其他功能: 还包括会话保持、HTTP/2 支持、灰度发布(Canary)、全局自定义 Header、限流等。例如可以在 Ingress 上使用
nginx.ingress.kubernetes.io/limit-rps: "10"为某一后端服务设置 QPS 限制,通过 nginx 的limit_req模块防止超高请求流量造成后端过载。
模块2:ingress-nginx 安装部署
安装前准备: 推荐使用 Kubernetes 1.28.x 版本,已知 ingress-nginx v1.10.1 与 K8s 1.28 完全兼容github.com。集群节点建议配置至少 2 核 CPU、4GB 内存;生产环境中建议多节点冗余。网络层无需特别要求,Calico、Flannel 等主流 CNI 均可正常使用。部署前需具备集群管理员权限(可创建 ClusterRole 等资源),以便应用 RBAC 相关配置。
2.1 Minikube 环境快速安装(测试/开发)
Minikube 提供了内置的 Ingress 插件,可快速启用。
# 启用 ingress 插件
$ minikube addons enable ingress
ingress addon is enabled
# 查看 ingress-nginx 控制器 Pod 运行情况
$ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-5cbcdd65b4-2kjh7 1/1 Running 0 30s
# 验证 NGINX 版本
$ kubectl exec -it ingress-nginx-controller-5cbcdd65b4-2kjh7 -n ingress-nginx -- nginx -v
nginx version: nginx/1.25.3
以上演示了在 Minikube 中启用 Ingress 插件后,会自动部署 ingress-nginx 控制器。通过 kubectl get pods 可见 ingress-nginx-controller Pod 正常运行,使用 nginx -v 验证其内置的 NGINX 版本(v1.25.3,见版本表github.com)。
2.2. Helm 3 安装(生产推荐)
在企业级生产环境中,通常使用 Helm Chart 安装 ingress-nginx,以便更灵活地定制配置。以下示例基于 ingress-nginx v1.10.1 Helm Chart:
# 添加 helm 仓库并更新
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
$ helm repo update
接着编写 values.yaml 自定义配置(以下为示例片段):
controller:
replicaCount: 2 # 控制器副本数,用于高可用
resources: # 资源限制,生产环境应合理配置
requests:
cpu: "200m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
nodeSelector: # 指定节点亲和(如只调度到标记为 ingress 节点)
ingress-node: "true"
tolerations: # 如果存在污点,可添加容忍策略
affinity:
podAntiAffinity: # 避免 Pod 部署在同一节点
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 50
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
topologyKey: "kubernetes.io/hostname"
config:
name: "nginx-configuration"
enable-access-log: "true"
access-log-format: "$remote_addr - $remote_user [$time_local] \"$request\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\" $request_length $request_time"
service:
annotations: # 公共负载均衡器注解
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "tcp"
关键配置说明:
-
replicaCount:Ingress Controller 副本数,生产一般设为 >=3 用于高可用。 -
resources:根据服务规模设置 CPU/内存请求和限制,以防止过度抢占节点资源。 -
nodeSelector/affinity:可将 Ingress Controller 调度到专门的节点上,并通过亲和性避免多个副本调度到同一节点。 -
config:用于初始化 ConfigMap 的键值,可调整 Nginx 行为(如日志格式、连接超时等)。 -
service:如果使用 LoadBalancer 类型,可在此添加云平台相关注解(上例为 AWS)。
然后执行 Helm 安装:
# 创建命名空间并安装 ingress-nginx
$ helm install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx --create-namespace -f values.yaml
# 查看安装结果
$ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-5cbcdd65b4-abc12 1/1 Running 0 2m
ingress-nginx-controller-5cbcdd65b4-def34 1/1 Running 0 2m
# 验证服务
$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.0.0.15 <pending> 80:31553/TCP,443:32607/TCP 2m
安装后,可通过访问 Controller Service 的外部 IP 或节点端口测试默认欢迎页(如果已开启访问日志可查看日志)。以上步骤展示了添加 Helm 仓库、撰写 values.yaml 以及使用 helm install 安装过程。
2.3. 手动 YAML 安装(深度自定义)
手动方式适合对每个组件细节有严格控制的场景。下面给出完整资源清单示例,并对关键字段添加注释。实际使用时请根据环境修改。
apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx # 创建独立的命名空间隔离 Ingress 组件
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: ingress-nginx # 为 Ingress Controller 创建专用 ServiceAccount
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ingress-nginx # ClusterRole 定义 Controller 在集群层面的权限
rules:
- apiGroups: [""] # 核心 API 组
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources:
- services
verbs: ["get", "list", "watch"]
- apiGroups: ["networking.k8s.io"] # Ingress API 组
resources:
- ingresses
- ingressclasses
- ingressstatus
verbs: ["get", "list", "watch", "update"]
- apiGroups: [""] # 事件与租约
resources:
- events
- leases
verbs: ["create", "patch", "get", "update", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ingress-nginx # 绑定 ClusterRole 到 ServiceAccount
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configuration # 存放 NGINX 全局配置的 ConfigMap
namespace: ingress-nginx
data:
# 在此处添加对应的配置选项,如:
worker-processes: "2" # Nginx 工作进程数
keep-alive: "75" # 连接保持时间
ssl-protocols: "TLSv1.2 TLSv1.3" # 支持的 TLS 版本
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller # Ingress Controller 的 Deployment
namespace: ingress-nginx
spec:
replicas: 2 # 控制器副本数
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
spec:
serviceAccountName: ingress-nginx
containers:
- name: controller
image: k8s.gcr.io/ingress-nginx/controller:v1.10.1 # 指定 ingress-nginx 版本
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration # 指定使用的 ConfigMap
ports:
- containerPort: 80 # 暴露 HTTP
- containerPort: 443 # 暴露 HTTPS
---
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller # Ingress Controller 暴露 Service
namespace: ingress-nginx
spec:
type: NodePort # 节点端口模式(也可用 LoadBalancer)
selector:
app.kubernetes.io/name: ingress-nginx
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30080 # 指定外部访问端口(30080)
- name: https
port: 443
targetPort: 443
nodePort: 30443 # HTTPS 的节点端口(30443)
保存上述 YAML 为 ingress-nginx.yaml 后应用:
$ kubectl apply -f ingress-nginx.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
configmap/nginx-configuration created
deployment.apps/ingress-nginx-controller created
service/ingress-nginx-controller created
# 查看 Pod 状态
$ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-abcdef123-ghijk 1/1 Running 0 10s
ingress-nginx-controller-abcdef123-lmnop 1/1 Running 0 10s
如果 Pod 启动失败,可使用 kubectl logs -n ingress-nginx <pod-name> 查看详细日志,如出现 “permission denied” 错误,则可能是 RBAC 配置缺失或权限不足。此时应确保 ServiceAccount 和 Role/Binding 已正确创建并关联后再重试。
安装后基础配置: 安装完成后,可通过修改 ConfigMap 来调整 NGINX 行为。例如,调整连接超时时间或工作进程数:
$ kubectl edit configmap nginx-configuration -n ingress-nginx
# 修改完成后保存,Ingress Controller Pod 会自动检测到 ConfigMap 变更并重载 Nginx
编辑后可在 Controller Pod 日志中看到 “Configuration changes detected, reloading Nginx” 的日志确认生效。
模块3:ingress-nginx 实操使用
3.1 HTTP 路由配置示例
场景:部署两个服务——前端 frontend-svc:80 和 API api-svc:8080。希望通过不同域名访问:frontend.example.com 指向前端,api.example.com 指向 API。可定义如下 Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-http
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx" # 指定使用 nginx Ingress Controller
spec:
rules:
- host: frontend.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc # 前端服务名称
port:
number: 80
- host: api.example.com
http:
paths:
- path: /v1/health
pathType: Prefix
backend:
service:
name: api-svc # API 服务名称
port:
number: 8080
应用该 Ingress:
$ kubectl apply -f ingress-http.yaml
ingress.networking.k8s.io/example-http created
# 验证 Ingress 规则是否生效
# (假设在本地 /etc/hosts 里将域名指向集群节点IP或 LoadBalancer IP)
$ curl -I http://frontend.example.com
HTTP/1.1 200 OK
...
$ curl -I http://api.example.com/v1/health
HTTP/1.1 200 OK
...
以上 curl 测试返回 HTTP 200,表明请求被正确路由到对应服务的 Pod。这样即实现了基于域名和路径的分流路由。
3.2 HTTPS 配置示例
场景1:自签名证书测试
创建一个自签名证书,并在 Ingress 中使用:
# 生成自签名证书
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=*.example.com"
# 在 default 命名空间创建 TLS Secret
$ kubectl create secret tls example-tls -n default --cert=tls.crt --key=tls.key
secret/example-tls created
将上一步 Secret 加到 Ingress 的 tls 字段:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-https
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- frontend.example.com
secretName: example-tls # 关联 TLS Secret
rules:
- host: frontend.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
应用并测试:
$ kubectl apply -f ingress-https.yaml
ingress.networking.k8s.io/example-https created
# 忽略证书警告测试 HTTPS
$ curl -vk https://frontend.example.com
* Trying 10.0.0.1...
* Connected to frontend.example.com (10.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* SSL connected...
> GET / HTTP/1.1
> Host: frontend.example.com
>
< HTTP/1.1 200 OK
...
使用 -k (或 -vk) 参数可忽略自签名证书警告,返回结果正常,表明 HTTPS 路由生效。浏览器访问时会提示“证书无效”,但可用于测试。
场景2:Let’s Encrypt 免费证书
安装 cert-manager 并使用 Let’s Encrypt 自动签发真实证书:
# 安装 cert-manager(示例使用 Helm)
$ helm repo add jetstack https://charts.jetstack.io
$ helm repo update
$ helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace \
--set installCRDs=true
# 部署 ClusterIssuer 配置
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-key
solvers:
- http01:
ingress:
class: nginx
EOF
在上面,我们创建了名为 letsencrypt 的 ClusterIssuer,配置了 HTTP-01 验证方式。然后在 Ingress 加注解触发证书签发:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-letsencrypt
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt" # 使用上面创建的 ClusterIssuer
spec:
tls:
- hosts:
- frontend.example.com
secretName: frontend-https-secret # cert-manager 会将证书保存到此 Secret
rules:
- host: frontend.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
EOF
应用后,cert-manager 的 ingress-shim 子组件会检测到带有 cert-manager.io/cluster-issuer 注解的 Ingress,自动创建对应的 Certificate 并完成证书签发cert-manager.io。签发完成后,查看证书状态并使用 curl 测试:
# 等待证书签发
$ kubectl wait certificate frontend-https-secret -n default --for=condition=Ready --timeout=120s
# 验证访问(无需忽略证书)
$ curl -I https://frontend.example.com
HTTP/2 200
...
此时返回正常,且不再需要 -k。浏览器访问也会显示有效的 Let’s Encrypt 证书。通过这种方式,可为企业中成百上千的域名自动化管理 HTTPS 证书cert-manager.io。
3.3 进阶功能使用
路径重写: 如需将外部路径 /api/v1/xxx 转换为后端的 /v1/xxx,可在 Ingress 添加 nginx.ingress.kubernetes.io/rewrite-target: /$2 注解,并使用正则匹配路径:
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: "/$2"
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: example.com
http:
- path: /api/v1(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-svc
port:
number: 80
-
保存并
curl -I http://example.com/api/v1/test,可看到后端收到的是/test,实现了路径重写。 -
负载均衡策略: 默认使用轮询,可通过 ConfigMap 或注解切换算法。示例:通过
nginx.ingress.kubernetes.io/upstream-hash-by强制基于 URI 做一致性哈希。
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"
此时不同 URI 的请求将路由到固定后端,提高缓存命中。
- IP 哈希/会话粘滞: 使用
nginx.ingress.kubernetes.io/affinity: cookie开启基于 Cookie 的粘滞会话kubernetes.github.iokubernetes.github.io。例如:
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/affinity: "cookie"
spec:
rules:
- host: app.example.com
http:
- path: /
pathType: Prefix
backend:
service:
name: app-svc
port:
number: 80
客户端首次请求后会收到名为 INGRESSCOOKIE 的粘滞 Cookie,此后的请求将自动路由到同一后端 Pod。
- 跨域配置: Ingress-NGINX 通过注解简化 CORS 设置。启用方式为:
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://frontend.example.com"
spec:
...
如上,为后端 API 的 Ingress 添加上述注解,表示允许来自 https://frontend.example.com 的跨域访问kubernetes.github.iokubernetes.github.io。使用 curl -I 可查看响应头中是否出现 Access-Control-Allow-Origin。
- 限流配置: 通过注解设置 QPS 限流。例如限制
/order接口每秒最大请求数:
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/limit-rps: "10"
spec:
rules:
- host: api.example.com
http:
- path: /order
pathType: Prefix
backend:
service:
name: order-svc
port:
number: 80
配置后可以使用压力测试工具(如 ab)验证:
$ ab -n 50 -c 5 http://api.example.com/order
Requests per second: 10.02 [#/sec] (mean)
QPS 超过 10 后会触发 503 错误,证明限流生效。
模块4:企业真实案例
4.1:微服务架构下的多应用路由
场景描述: 某企业部署了三个微服务:前端 Web 服务、用户 API 服务、订单 API 服务。需求:通过域名 web.example.com 访问前端,通过 api.example.com/user 和 api.example.com/order 访问后端。其中订单接口要求 HTTPS 访问并启用限流。
架构流程: 外部流量经过 Ingress-NGINX Controller,根据域名和路径转发:前端域名全流量转发到前端 Service,/user 路径转发到用户 API,/order 路径转发到订单 API。订单路径启用 TLS 和限流。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: enterprise-app
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/limit-rps: "5" # 对该 Ingress 全部路径生效的限流
spec:
tls:
- hosts:
- api.example.com
secretName: api-tls-secret # 订单API的TLS证书Secret
rules:
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-svc # 前端服务
port:
number: 80
- host: api.example.com
http:
paths:
- path: /user
pathType: Prefix
backend:
service:
name: user-svc # 用户API服务
port:
number: 80
- path: /order
pathType: Prefix
backend:
service:
name: order-svc # 订单API服务
port:
number: 80
部署步骤:首先创建上述 Ingress 资源和对应的 Service、Secret,然后使用域名访问。
$ kubectl apply -f ingress-enterprise.yaml
ingress.networking.k8s.io/enterprise-app created
验证:在本地 /etc/hosts 文件中将 10.0.0.1 web.example.com api.example.com,然后执行:
$ curl -I http://web.example.com
HTTP/1.1 200 OK
$ curl -I http://api.example.com/user
HTTP/1.1 200 OK
$ curl -I https://api.example.com/order # 注意使用 https
HTTP/2 200
/order 路径默认返回正常,但为了测试限流,我们可使用压测工具:
$ ab -n 20 -c 10 http://api.example.com/order
Requests per second: 5.01 [#/sec] (mean)
从结果可见平均约 5 QPS,超过设定值后出现503(Too Many Requests),证明限流生效。
企业优化点:
-
IngressClass 指定: 可在 Ingress 对象中增加
ingressClassName: nginx明确使用 ingress-nginx 控制器。 -
监控指标: 建议将 Controller 指标暴露给 Prometheus 并导入官方 Grafana 仪表盘(官方提供 Nginx Ingress Dashboard),实时监控流量、响应时间等。
-
资源监控: 对 Controller 的 CPU/内存使用率设置告警,必要时自动扩容。
-
证书管理: 应用 Let’s Encrypt + cert-manager 实现证书自动续签。
-
日志收集: 将 Controller 的访问日志和 NGINX 错误日志推送到 ELK/EFK 集群,方便问题定位和统计分析。
4.2:ingress-nginx 高可用部署
场景描述: 核心业务要求 Ingress 无单点故障。需部署多副本的 Ingress-NGINX,利用节点亲和性和外部负载均衡实现 HA。
部署方案: 使用 Helm Chart 安装并设置:
controller:
replicaCount: 3 # 部署 3 个副本
affinity:
podAntiAffinity: # 确保三副本不调度到同一节点
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
topologyKey: "kubernetes.io/hostname"
service:
type: LoadBalancer
externalTrafficPolicy: Local # 保持客户端源 IP(需要支持)
同时在云平台(如阿里云 SLB)配置健康检查,确保只向健康节点转发。
故障演练:
-
Pod 容量故障:
# 观察 ingress-nginx 控制器的 Pod
$ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-abc123-xyz 1/1 Running 0 10m
ingress-nginx-controller-def456-xyz 1/1 Running 0 10m
ingress-nginx-controller-ghi789-xyz 1/1 Running 0 10m
# 模拟删除一个 Pod(集群应自动重建)
$ kubectl delete pod ingress-nginx-controller-def456-xyz -n ingress-nginx
pod "ingress-nginx-controller-def456-xyz" deleted
# 观察新 Pod 启动
$ kubectl get pods -n ingress-nginx -w
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-abc123-xyz 1/1 Running 0 11m
ingress-nginx-controller-ghi789-xyz 1/1 Running 0 11m
ingress-nginx-controller-jkl012-xyz 1/1 Running 0 0s
-
日志显示新 Pod 很快被调度并正常运行,Ingress 不间断。
-
节点故障:
如果单个节点不可用,SLB 会自动转移流量到其它节点上的 Controller。可测试:
# 将某节点标记为不可调度(模拟故障)
$ kubectl cordon worker-node1
# 停止 worker-node1 网络或杀死 nginx-controller(视环境而定)
# 此时流量将自动切换到其他节点,业务不受影响
企业运维实践:
-
日志收集: 推荐将 ingress-nginx 的访问日志发送至集中日志平台(如 ELK/EFK),用于业务分析和错误排查。也可开启 NGINX 日志格式自定义,以记录请求 ID、延迟等信息。
-
监控告警: 使用 Prometheus + Grafana 监控 Ingress Controller 的关键指标(如请求量、延迟、5xx 错误率等)。Ingress-NGINX 官方提供了 Grafana 仪表盘模板,可直接导入使用。
-
备份策略: 定期使用
kubectl get ingress,configmap,secret -o yaml导出关键配置;对于基于 Helm 的安装,定期备份 Helm Release 状态。
模块5:易错提醒与问题排查
5.1 常见安装错误
-
错误1:Controller 启动失败,提示“permission denied”
现象: Ingress Controller Pod 一直 CrashLoop 或日志中反复出现 “permission denied” 或 “failed to list” 之类的错误。
原因: 通常是 RBAC 配置不完整导致 Controller 无权访问 K8s API。可能是忘记创建 ClusterRole/Role 或 ClusterRoleBinding/RoleBinding。
解决方案: 检查并重新应用 RBAC 资源。确保 ServiceAccount 已绑定对应的 ClusterRole 和 Role(如上述 YAML 示例),然后重启 Controller Pod。
$ kubectl apply -f rbac.yaml # 重新应用缺失的 RBAC 配置
$ kubectl delete pod -l app.kubernetes.io/name=ingress-nginx -n ingress-nginx
$ kubectl logs -n ingress-nginx ingress-nginx-controller-abc123-xyz
完成后,日志中不应再出现权限相关错误。
错误2:Ingress 创建后无路由效果,kubectl describe ingress 提示“IngressClass not found”
现象: 新建的 Ingress 资源状态一直显示 Pending,访问无响应。描述该 Ingress 时看到事件 “IngressClass not found”。
原因: 没有指定或错误指定 IngressClass 名称。Ingress-NGINX 默认的类名通常为 nginx,或通过注解 kubernetes.io/ingress.class: nginx。如果 IngressClass 未创建或名称不匹配,就无法绑定到 Controller。
解决方案: 在 Ingress 资源中添加 ingressClassName: nginx(或相应的 Controller 名称)字段。例如:
spec:
ingressClassName: nginx
rules: ...
或在 metadata 中添加 kubernetes.io/ingress.class: nginx 注解。应用后,使用 kubectl get ingress -o wide 可在 CLASS 列看到值,确保与部署的 Controller 一致。
5.2 常见功能踩坑点
-
踩坑1:路径匹配规则错误
例如,配置了 Path/api,发现访问/api会成功,但访问/api/xxx失败(或反之)。原因通常是 NGINX 默认将路径视为前缀匹配,或路径末尾斜杠问题。
解决方案: 若需精确或正则匹配,可使用注解nginx.ingress.kubernetes.io/use-regex: "true"并在 path 字段使用正则表达式,如/api(/|$)(.*)kubernetes.github.io。或者确保定义的路径类型(Prefix/Exact)符合预期。 -
踩坑2:HTTPS 证书不生效
浏览器访问时提示“证书无效”。常见原因是 TLS Secret 与 Ingress 不在同一个命名空间或名称不匹配。
解决方案:-
确认 Secret 生成后存在:
kubectl get secret example-tls -n default(以命名空间为例)。 -
检查 Ingress
spec.tls.secretName是否和实际 Secret 名称一致,且 Ingress 与 Secret 位于同一命名空间alibabacloud.com。 -
若使用 cert-manager,检查 Certificate 和 Secret 是否已经就绪:
kubectl describe certificate。
-
排查工具与命令总结
-
日志排查: 使用
kubectl logs查看 Ingress Controller 日志。常用命令:
$ kubectl logs -n ingress-nginx <controller-pod-name> # 查看主容器日志(转发日志)
$ kubectl logs -n ingress-nginx <controller-pod-name> -c nginx # 查看 Nginx 进程原生日志
-
日志中可看到 Nginx 请求转发记录、错误信息等。使用
-f参数可以实时跟踪日志。 -
资源状态检查
kubectl describe ingress <ingress-name>:查看 Ingress 事件,监测是否有错误事件或 IngressClass 问题。
kubectl get svc ingress-nginx-controller -n ingress-nginx:查看 Controller Service 的类型和外部地址/端口,用于验证流量入口。
-
配置验证:
-
查看 NGINX 配置:通过
kubectl exec进入 Controller Pod:
-
-
$ kubectl exec -it <controller-pod> -n ingress-nginx -- cat /etc/nginx/nginx.conf -
-
可检查生成的 Nginx 路由配置,验证 Ingress 规则是否正确渲染到配置文件中。
-
测试服务连通性:在 Controller Pod 中使用
curl或wget测试从 Controller 到后端 Service 的网络连通性,确认是否为网络问题。
-
通过上述排查步骤,通常可以定位绝大多数 Ingress-NGINX 的常见问题并解决。本模块提供的命令和思路,可作为运维日常检查与故障排除的参考。
参考文献: Ingress 官方文档kubernetes.ioalibabacloud.comhelp.aliyun.com、Ingress-NGINX 官方文档github.comkubernetes.github.iokubernetes.github.iokubernetes.github.iokubernetes.github.iocert-manager.io等。上述内容基于 ingress-nginx v1.10.1 和 Kubernetes v1.28.x 实践验证。
更多推荐


所有评论(0)