「KUBERNETES-INGRESS-CONTROLLER」- NGINX Ingress Controller

认识

官网:https://kubernetes.github.io/ingress-nginx/
文档:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/
仓库:https://github.com/kubernetes/ingress-nginx

Nginx Ingress Controller 是个基于 Nginx 的开源项目,用于在 Kubernetes 集群中管理和暴露应用程序的路由。它充当一个负载均衡器,将外部流量引导到 Kubernetes 集群内部的服务。简而言之,Nginx Ingress Controller 是个强大而灵活的工具,可以帮助您管理和控制 Kubernetes 集群中的流量路由,提供可靠的应用程序访问方式。

⚠️,注意事项,Ingress NGINX Retirement: What You Need to Know https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/

组成

Nginx Ingress Controller 通过在 Kubernetes 中读取 Ingress 资源来定义路由规则,并根据这些规则将流量转发到相应的服务。

[Sol.] Nginx Ingress Controller 是否会自动加载 TLS 证书?

Cert Manager 负责 Certificate 的续期,在续期成功后,Certificate 关联的 Secret 也将被更新;

我们的疑问是 Nginx Ingress 是否会自动加载新的 Secret 以使 TLS 更新,还需需要手动 reload 配置?

我们猜测 Nginx Ingress Controller 能够自动加载新的 Secret 内容,原因是:如果 Cert Manager 更新完 Secret,还需要 Reload Ingress 的话,那么 Cert Manager 需要适配各种 Ingress Controller 实现,来完成 reload 动作。如果不是这样的话,那么 Kubernetes 就要提供一种机制,让来通知 Ingress Controller 需要 reload 配置;

然后,根据 https://github.com/cert-manager/cert-manager/issues/1816#issuecomment-506509695 的只言片语,我们更加认为 Ingress Controller 应该自动检测 Secret 的变化;

命令程序 and 配置文件

Command line arguments | https://kubernetes.github.io/ingress-nginx/user-guide/cli-arguments/

ingress-nginx | kubeclt plugin

现在 2025-11-25

性质

它支持多种负载均衡算法、SSL/TLS 终止、基于路径和主机的路由,以及各种自定义配置选项。

使用 Nginx Ingress Controller 能够轻松地将 HTTP 和 HTTPS 流量引导到不同的后端服务,实现高可用性和水平扩展。

它还提供了一些高级功能,如访问控制、请求限速、基于规则的重定向等,可以根据具体需求进行配置;

注解 Annotations

https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md

nginx.ingress.kubernetes.io/ssl-redirect: “true” // SSL 重定向

nginx.ingress.kubernetes.io/auth-snippet
nginx.ingress.kubernetes.io/configuration-snippet // add additional configuration to the location.
nginx.ingress.kubernetes.io/server-snippet // add custom configuration in the server configuration block.
nginx.ingress.kubernetes.io/stream-snippet
nginx.ingress.kubernetes.io/modsecurity-snippet

Annotations Risks

… admission webhook “validate.nginx.ingress.kubernetes.io” denied the request: annotation group ServerSnippet contains risky annotation based on ingress configuration …

https://github.com/kubernetes/ingress-nginx/issues/12648

Annotations Scope and Risk | https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations-risk/

annotations-risk-level: High # default: High

Accepted values are Critical, High, Medium and Low.

GeoIP and GeoIP2

  • Since 0.27.0 and due to a change in the MaxMind databases a license is required to have access to the databases. For this reason, it is required to define a new flag –maxmind-license-key in the ingress controller deployment to download the databases needed during the initialization of the ingress controller.
  • Alternatively, it is possible to use a volume to mount the files /etc/ingress-controller/geoip/GeoLite2-City.mmdb and /etc/ingress-controller/geoip/GeoLite2-ASN.mmdb, avoiding the overhead of the download.

https://github.com/kubernetes/ingress-nginx/blob/main/internal/nginx/maxmind.go
maxmindURL = “https://download.maxmind.com/app/geoip_download?license_key=%v&edition_id=%v&suffix=tar.gz”
geoIPPath = “/etc/ingress-controller/geoip”

# 08/03/2025 国内 Wget 请求 MaxMind 下载数据库文件时,会提示 451 Unavailable For Legal Reasons 错误,所以 GeoIP2 无法正常使用:



E0803 07:52:51.672816 7 maxmind.go:74] GeoLite2-City.mmdb not found

W0803 07:52:51.672822 7 store.go:1214] The GeoIP2 feature is enabled but the databases are missing. Disabling

如果一定要使用 GeoIP2 功能,则需要想方法下载数据库文件,然后将其保存到
/etc/ingress-controller/geoip/ 中,再进行后续操作。

请求限速,流量控制,……

nginx.ingress.kubernetes.io/limit-req-rate: “5r/s” # 每个用户 5 请求 / 秒
nginx.ingress.kubernetes.io/limit-req-burst: “10” # 突发 10 请求
nginx.ingress.kubernetes.io/limit-req-key: “$http_x_user_id” # 按 X-User-ID 限速

构建

—— 该部分笔记将记录:在 Kubernetes Cluster 中,部署 NGINX Ingress Controller 的方法,以及相关问题。

版本选择

Supported Versions table | https://github.com/kubernetes/ingress-nginx?tab=readme-ov-file#supported-versions-table

部署方式

NGINX Ingress Controller/Installation Guide
https://kubernetes.github.io/ingress-nginx/deploy/

  • Manifest
  • Helm Chart

现在 06/03/2025 为了能够很好的进行配置管理,我们通常使用 Helm Chart 来完成应用的部署。

🛑️ on Kubernetes with Helm Chart from Bitnami

客户端真实网络地址

针对 Helm Chart 部署,在 EKS 中:

controller:
  config:
    use-proxy-protocol: "true"
    real-ip-header: "proxy_protocol"
    use-forwarded-headers: "true"
  service:
    annotations:
      service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
      service.beta.kubernetes.io/aws-load-balancer-type: "external"
      service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
      service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
      service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp

排查调试

https://github.com/kubernetes/ingress-nginx/blob/main/docs/troubleshooting.md

查看 nginx.conf 配置:kubectl exec -it ingress-nginx-controller-67956bf89d-fv58j — cat /etc/nginx/nginx.conf

# 查看生成的配置文件
kubectl exec -it -n "ingress-nginx" nginx-ingress-controller-67956bf89d-fv58j -- cat /etc/nginx/nginx.conf

# 查看当前 Nginx 版本
kubectl exec -it $POD_NAME -n $POD_NAMESPACE -- /nginx-ingress-controller --version

应用

—— 该部分笔记将记录:在 Kubernetes Cluster 中,通过 NGINX Ingress Controller 解决相关问题的方法。

针对我们的场景,我们使用 NGINX Ingress Controller 实现,这完全是基于我们具有很多 Nginx 使用经验,此外 Nginx 完全能满足我们的需要。即使日后 NGINX Ingress Controller 无法满足需求,我们亦可安装其他 Ingress Controller 实现,它们之间能够并存;

场景 | 暴露 gRPC 服务

通过 Ingress 无法访问到其后的 gRPC 服务;

未在 Ingress 资源中设置 Annotation,指定后端协议类型;
gRPC 服务只能通过 TLS 端口进行访问;

要满足两个条件:
1)在对应 Ingress 资源中,设置 Annotation: nginx.ingress.kubernetes.io/backend-protocol:”GRPC”;
2)在确认客户端发送请求时,使用的是 TLS 端口,并且将流量加密;

场景 | 开启 gzip 功能

gzip in gke with nginx-ingress
Activate gzip support #179

针对 Ingress Controller 服务,开启 gzip 特性,修改 ConfigMap 资源,增加如上配置:

kubectl edit configmap -n ingress-nginx ingress-nginx-controller

use-gzip: true;		https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-gzip
gzip-types: "*";	https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#gzip-types

针对特定 Ingress 资源,开启 gzip 特性:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: cafe-ingress
  annotations:
     kubernetes.io/ingress.class: "nginx"
     nginx.org/server-snippets: "gzip on;"
...

场景 | Request Entity Too Large | 413 | proxy-body-size

nginx.ingress.kubernetes.io/proxy-body-size: “20m”

https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#proxy-buffer-size

场景 | 关闭 http 到 https 的重定向

nginx.ingress.kubernetes.io/ssl-redirect: “false”

场景 | 跨域配置

ingress-nginx/docs/user-guide/nginx-configuration/annotations.md at main · kubernetes/ingress-nginx

Enable CORS
https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#enable-cors

nginx.ingress.kubernetes.io/enable-cors: “true”

nginx.ingress.kubernetes.io/cors-allow-headers:
cors-allow-headers does not allow wildcard · Issue #10501 · kubernetes/ingress-nginx
Accept wildcard in nginx.ingress.kubernetes.io/cors-allow-headers annotation by croemmich · Pull Request #11655

Nginx Ingress Controller, App Version 1.11.1, Chart Version 4.11.1

现在 11/11/2024 该字段无法使用 * 通配符配置,其会被解析为具体的值。

基础认证 | Basic Auth

Nginx-ingress Kubernetes routing with basic auth – Stack Overflow

注意事项,我们使用 Nginx Ingress Controller 组件,所以很多示例配置都与之相关。

第一步、创建 Secret 凭证 | 创建用于 Basic Auth 认证的 Secret 凭证:

$ htpasswd -c auth foo
New password: <bar>
New password:
Re-type new password:
Adding password for user foo

$ kubectl create secret generic basic-auth --from-file=auth
secret "basic-auth" created

$ kubectl get secret basic-auth -o yaml
apiVersion: v1
data:
  auth: Zm9vOiRhcHIxJE9GRzNYeWJwJGNrTDBGSERBa29YWUlsSDkuY3lzVDAK
kind: Secret
metadata:
  name: basic-auth
  namespace: default
type: Opaque

注意事项:该凭证必须包含名为 auth 的 Key,否则将产生 503 错误;

第二步、添加 Ingress 注解

...
metadata:
  annotations:
    ...
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
...

若需要针对不同的域名进行 Basic Auth 的认证:

  • 或,创建不同的 Ingress 资源;
  • 或,通过 nginx.ingress.kubernetes.io/configuration-snippet 来增加特定的 Nginx 配置;

请求重定向

Kubernetes nginx ingress: How to redirect foo.example.org to example.org? – Server Fault
Exclude specific hosts from ssl redirect in Kubernetes Nginx Ingress – Stack Overflow

访问 example.com 重定向到 www.example.com 地址

通过 nginx.ingress.kubernetes.io/rewrite-target 实现

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: webhook-dnspod-cluster-issuer
    nginx.ingress.kubernetes.io/preserve-trailing-slash: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/rewrite-target: "https://www.example.com$request_uri"
  name: redirect-example.com
spec:
  ingressClassName: nginx-02
  rules:
  - host: example.com
  tls:
  - hosts:
    - example.com
    secretName: example-com-ingress-tls

通过 nginx.ingress.kubernetes.io/configuration-snippet 实现

nginx.ingress.kubernetes.io/configuration-snippet: |
    if ($host = 'example.com' ) {
        rewrite ^ https://www.example.com$request_uri permanent;
    }

修改默认重定向状态码(IE8 无法跳转)

Permanent redirect 308 not supported in IE11 #1825
Change default redirect to 301 to support old internet explorer versions #2002
Kubernetes Nginx Ingress HTTP to HTTPS redirect via 301 instead of 308?
NGINX Ingress Controller/ConfigMaps/http-redirect-code

在 NGINX Ingress Controller 中,开启强制 SSL 跳转之后,当访问 HTTP 时将被重定向到 HTTPS 地址。但是在 IE8 浏览器中,无法正常跳转(虽然现在基本以及忽略 IE8 浏览器),我们需要解决这个问题。

原因分析

默认 NGINX Ingress Controller 返回 308 重定向,但是 IE8 浏览器不支持 308 状态码。同时 Permanent redirect 308 not supported in IE11 #1825 指出 IE11 浏览器也不支持 308 状态码。所以导致浏览器无法正常跳转。

当使用 308 状态码时,在重定向 POST 请求时可以保留“有效载荷”(简单理解成 POST 请求的数据即可)。

解决方案

我们只能修改返回状态码,而不再使用 308 状态码。

这需要修改 Nginx 的 ConfigMap 对象,添加 http-redirect-code: "301" 配置。配置文件结构大致如下:

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  name: nginx-configuration
  namespace: ingress-nginx
data:
  http-redirect-code: "301"

地址重写 Rewrite to Root

kubernetes – Is there a best practice to implement ingress rule with rewrite to root – Stack Overflow
Removing url prefixes in nginx Kubernetes Ingress – Graphics Unplugged

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - backend:
          serviceName: http-svc
          servicePort: 80
        path: /something/(.*)
--
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: /api(/|$)(.*)
        backend:
          ...

改进

—— 常见问题处理

[Sol.] … master process died (-1): signal: illegal instruction …

process exit with code 132 #39
0.25.0 crashes at backend reload maybe due to recent OpenResty changes #4311

环境概述

  • CentOS Linux release 7.4.1708 (Core)
  • Kubernetes v1.12.1
  • Docker version 18.06.1-ce, build e68fc7a
  • Helm v3.0.0-beta.3
  • 另外,针对该版本 Nginx Ingress Controller 镜像,其使用 Openresty 程序;

在集群中部署 Nginx Ingress Controller 组件,但是在某两个节点(node3、node4)中 nginx-ingress-controller 无法启动。错误信息如下:

...
NGINX master process died (-1): signal: illegal instruction (core dumped)
-------------------------------------------------------------------------------
W1207 07:56:02.153812       8 nginx.go:39]
-------------------------------------------------------------------------------
NGINX master process died (-1): signal: illegal instruction (core dumped)
-------------------------------------------------------------------------------
W1207 07:56:02.165902       8 nginx.go:39]
...

原因分析

遇到这种问题肯定去搜索。既然有错误日志,而且还是 NGINX 输出的错误日志,这就说明这是个可预见的错误;

然后我找到下面两篇讨论:

在上述讨论中,问题已经很清楚。作者在程序中使用了新 CPU 指令集(SSE 4.2),作者也不打算支持旧 CPU 型号;

解决方案

目前,我们能够想到的解决办法有两个:

  • 将节点迁移到新服务器(选择 CPU 支持 SSE 4.2 指令集的服务器),或将 Pod 调度到新节点(如果使用 DaemonSet 部署,则仅能迁移虚拟机到新服务器)
  • 而实际上,Openresty 程序也有“No SSE 4.2”版本。(但是不知道 Nginx Ingress Controller 镜像有没有“No SSE 4.2”版本)

我们选择第一个方案,直接将节点迁移到新节点中;

参考

Basic usage – NGINX Ingress Controller