Ingress NGINX Controller 镜像体系全解析:images 目录职责划分、构建流程与实战用法
【免费下载链接】ingress-nginxIngress NGINX Controller for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/in/ingress-nginx
导读:
images/是 Ingress NGINX Controller 仓库中全部容器镜像的源代码根目录,既有用于正式发布的 NGINX 基础镜像,也有用于演示 Ingress 功能特性、支撑端到端(e2e)测试的辅助镜像。阅读本文后,你将完整掌握该目录下每个镜像的用途定位、源码结构与构建方式,并能基于custom-error-pages等官方参考实现,在自己的集群中落地自定义错误页、gRPC 代理等真实场景。
images 目录总览:谁发布、谁辅助
仓库根目录下的 images/README.md 用一句话明确了整个镜像目录的核心规则:
Only the nginx image is meant to be published(只有 nginx 镜像是用于发布的),其余镜像要么是 Ingress Controller 某项功能的示例实现,要么是用于运行 e2e 测试的辅助镜像。
这意味着当你梳理镜像供应链时,真正需要作为"正式发布件"看待的只有nginx一个;其他镜像面向的是开发与验证场景,它们在 CI、示例文档和 e2e 测试中被引用,但不会作为产品镜像对外发布。images/Makefile中通过NAME变量动态指定要构建的子目录,也为这种"一个 Makefile 管理多个镜像"的组织方式提供了统一的入口(详见后文)。
镜像目录一览
原文档以表格形式列出了 7 个镜像目录及其用途,完整继承如下:
| 目录 | 用途 |
|---|---|
cfssl | 用于执行 cfssl 命令的镜像 |
custom-error-pages | Ingress-Nginx Controller 自定义错误页的示例实现 |
fastcgi-helloserver | 供 e2e 测试使用的 FastCGI 应用 |
go-grpc-greeter-server | 用于 nginx-ingress grpc 示例的 grpc server 应用 |
httpbun | 一个简单的 HTTP 请求与响应服务,用于 e2e 测试 |
nginx | 基于 Alpine Linux 的 NGINX 基础镜像 |
test-runner | 用于运行 e2e 测试的镜像 |
需要补充说明的是,从当前仓库的目录结构看,images/下还实际存在着表格未列出的e2e-test-echo(e2e 回显服务)、ext-auth-example-authsvc(外部认证示例服务)和kube-webhook-certgen(准入 Webhook 证书生成器)等目录,它们同样遵循"示例/测试辅助"的定位,将在下文相关小节一并介绍。
nginx:唯一用于发布的基础镜像
images/nginx是整个镜像体系的基石,Ingress Controller 的最终运行镜像基于它构建。该目录下的 Dockerfile 与 build.sh 是其核心实现。
多阶段构建与运行时裁剪
Dockerfile 采用标准的多阶段构建:
- builder 阶段:基于
alpine:3.23.3,执行/build.sh完成 OpenResty/NGINX 源码的下载、打补丁与编译; - 运行时阶段:同样基于
alpine:3.23.3,仅从 builder 阶段拷贝/usr/local、OpenTelemetry 相关库(/usr/local/lib/libopentelemetry*)、/opt与/etc/nginx等必要产物。
运行时镜像随后安装bash、openssl、pcre、zlib、libmaxminddb、yaml-cpp、dumb-init、tzdata、grpc-cpp、libprotobuf等运行依赖,并创建www-data用户(UID 101)以及/var/log/nginx、/var/lib/nginx/{body,fastcgi,proxy,scgi,uwsgi}等可写目录,最后以nginx -g "daemon off;"前台方式启动。整个镜像暴露80与443端口,体现了"尽量裁剪、非 root 运行"的镜像设计原则。
编译特性与 HTTP/3 支持(实验性)
在 build.sh 的编译配置中可以看到一长串--with-*特性开关,其中包括:
--with-http_ssl_module、--with-http_v2_module--with-http_v3_module(HTTP/3/QUIC 支持,当前为实验特性)--with-stream及--with-stream_ssl_module、--with-stream_ssl_preread_module(TCP/UDP 四层代理与 SNI 预读)--with-pcre-jit、--with-threads、--with-http_realip_module、--with-http_auth_request_module等
编译前还会遍历/patches目录依次应用 patches 下的补丁文件。
关于 HTTP/3,images/nginx/README.md 给出了非常明确的现状说明:HTTP/3 支持目前是实验性的、处于开发之中。虽然 NGINX 1.25.0 起就支持通过--with-http_v3_module编译参数启用 QUIC 和 HTTP/3,仓库也已经加入了该编译参数,但要在 ingress-nginx 中真正可用仍需后续工作:
- 等待 OpenSSL 3.4 提供服务端 QUIC 支持:当前使用的 OpenSSL(3.x)对 TLS 1.3 的
early_data(0-RTT)机制支持不完整,文档明确指出 OpenSSL 的兼容层不支持 early data,且 QUIC 目前仅有客户端侧支持,因此 HTTP/3 缺少重要的安全与性能特性; - 在 ConfigMap 中增加 HTTP/3 与 quic 相关参数(如
enableHTTP3、enableHTTP/0.9、maxCurrentStream等); - 在 NGINX 配置模板中添加
listen 443 quic及add_header Alt-Svc 'h3=":8443"; ma=86400';等指令; - 在容器中为 QUIC 打开 HTTPS 端口的 UDP 通道;
- 补充相应测试。
也就是说,虽然基础镜像已经具备 HTTP/3 编译能力,但当前版本中 HTTP/3 尚未达到生产可用状态,读者不应将其视为开箱即用的特性。
版本追踪机制
镜像版本不是散落在构建脚本中的硬编码,而是通过仓库根目录与子目录中的文件统一管理:
- images/nginx/TAG 记录当前 nginx 镜像版本号(本仓库中为
v2.2.9); - 仓库根目录 NGINX_BASE 记录 NGINX 基础镜像的完整引用(
registry.k8s.io/ingress-nginx/nginx:v2.2.8@sha256:...),供test-runner、e2e-test-echo等依赖 NGINX 的镜像作为BASE_IMAGE构建参数使用; - 仓库根目录 GOLANG_VERSION 记录 Go 工具链版本(本仓库中为
1.26.1),被custom-error-pages、fastcgi-helloserver、go-grpc-greeter-server、httpbun等 Go 应用的 Dockerfile 通过ARG GOLANG_VERSION注入。
custom-error-pages:自定义错误页后端的官方参考实现
images/custom-error-pages是原文档标注为"自定义错误页示例"的镜像,也是整个目录中除 nginx 外最值得深入研究的实现,因为它对应着 Ingress NGINX Controller 的custom-http-errors核心配置项。
在错误处理链路中的角色
当 ConfigMap 中的custom-http-errors配置项启用时,Ingress Controller 会配置 NGINX,使其在出错时将若干 HTTP 头传递给default-backend。官方文档 docs/user-guide/custom-errors.md 中列出了完整的头部清单:
| Header | 含义 |
|---|---|
X-Code | 请求返回的 HTTP 状态码 |
X-Format | 客户端发送的Accept头值 |
X-Original-URI | 导致错误的原始 URI |
X-Namespace | 后端 Service 所在的命名空间 |
X-Ingress-Name | 定义该后端的 Ingress 名称 |
X-Service-Name | 支撑该后端的 Service 名称 |
X-Service-Port | 支撑该后端的 Service 端口号 |
X-Request-ID | 标识该请求的唯一 ID(与后端服务收到的相同) |
自定义错误后端可以据此返回最合适的错误页表现形态:例如当客户端Accept为application/json时,返回 JSON 格式的错误载荷而非 HTML。
这里有一个关键的行为约定需要特别注意:自定义后端必须返回正确的 HTTP 状态码而不是200,因为 NGINX 不会修改来自自定义 default-backend 的响应状态码。
源码实现原理
custom-error-pages镜像由 Go 编写,核心实现位于 images/custom-error-pages/rootfs/main.go。其工作流程如下:
- 头部定义:源码中以常量形式定义了与上表一一对应的请求头名称,例如
FormatHeader = "X-Format"、CodeHeader = "X-Code"、RequestId = "X-Request-ID"等; - 格式协商:
errorHandler读取X-Format头确定客户端期望的 MIME 类型,通过 Go 标准库的mime.ExtensionsByType将 MIME 类型映射为文件扩展名(如application/json→.json、text/html→.html);若Accept头缺失,则回退到默认格式text/html;若Accept携带多个格式,取第一个逗号前的值; - 文件定位:按
{错误码}{扩展名}拼接文件名,例如/www/404.html;若精确文件不存在,则回退到{错误码首字符}xx{扩展名}形式的通配文件,如/www/4xx.html; - 响应输出:设置
Content-Type为协商出的格式,并以X-Code指定的状态码返回文件内容;若X-Code无法解析为整数,则默认使用404。
该后端还内置了两个 HTTP 端点:
/healthz:健康检查;/metrics:Prometheus 指标端点,由 metrics.go 定义,暴露default_http_backend_http_request_count_total(按协议计数)与default_http_backend_http_request_duration_milliseconds(直方图)两类指标。
此外,源码支持通过环境变量进行行为定制:
ERROR_FILES_PATH:错误页面文件所在目录(默认/www);DEFAULT_RESPONSE_FORMAT:默认错误响应 MIME 类型(默认text/html);DEBUG:设置后,后端会把收到的全部错误头(X-Code、X-Format、X-Original-URI、X-Namespace等)原样写回客户端响应头,便于排查问题。
镜像内置的错误页位于 images/custom-error-pages/rootfs/www,提供404.html、404.json、4xx.html、4xx.json、500.html、500.json、5xx.html、5xx.json共 8 个文件,即对 4xx/5xx 大类分别提供 HTML 与 JSON 两种表现形态。其 Dockerfile 采用golang构建、gcr.io/distroless/static:nonroot运行时的方式,最终以非 root 用户运行nginx-errors二进制(当前 TAG 为v1.2.9)。
部署示例与验证
仓库在 docs/examples/customization/custom-errors/README.md 中给出了完整的落地步骤,核心清单包括:
- custom-default-backend.yaml:创建名为
nginx-errors的 Deployment 与 Service,Deployment 引用registry.k8s.io/ingress-nginx/custom-error-pages:v1.2.9镜像,容器监听8080端口,Service 暴露80端口并转发到8080; - custom-default-backend-error_pages.configMap.yaml:通过 ConfigMap 定义自定义 404/503 页面内容,可挂载到容器的
/www目录以覆盖默认错误页。
Controller 侧的配置步骤为:
- 编辑
ingress-nginx-controllerDeployment,将--default-backend-service参数指向新建的错误后端(如ingress-nginx/nginx-errors); - 编辑
ingress-nginx-controllerConfigMap,增加键custom-http-errors,值为逗号分隔的状态码列表,例如404,503; - 获取 Controller Service 的访问地址,用
curl验证。
验证效果示例:
# 不带 Accept 头时返回 HTML 错误页(HTTP 404) $ curl -D- http://10.0.0.13/ HTTP/1.1 404 Not Found Content-Type: */* ... <span>The page you're looking for could not be found.</span> # 携带 Accept: application/json 时返回 JSON 错误载荷 $ curl -D- -H 'Accept: application/json' http://10.0.0.13/ HTTP/1.1 404 Not Found Content-Type: application/json ... { "message": "The page you're looking for could not be found" }文档还演示了一个进阶玩法——全集群维护页:启用 503 自定义错误页后,将--watch-namespace-selector指向一个不存在的命名空间(如nonexistent-namespace)以停止读取任何 Ingress,再通过location-snippet设置为return 503;,即可让所有请求统一返回维护页面。
特性示例镜像:gRPC 与外部认证
go-grpc-greeter-server
images/go-grpc-greeter-server是 gRPC 示例中的服务端应用,用于演示 Ingress NGINX Controller 对 gRPC 流量的代理能力。其 Dockerfile 使用golang:${GOLANG_VERSION}-alpine3.23构建,最终产物拷贝进scratch空镜像,暴露50051端口(gRPC 默认端口),是一个极简的镜像示例。配合 docs/examples/grpc/README.md 中的部署清单,可以验证基于 HTTP/2 的 gRPC 流量经由 Ingress 路由到后端 gRPC 服务的完整链路。
ext-auth-example-authsvc
images/ext-auth-example-authsvc虽未列入原文档表格,但同样是"功能示例"定位的重要镜像:它对应 Ingress 的外部认证(external-auth)注解功能。其 Dockerfile 将authsvc.go编译为静态二进制,运行在gcr.io/distroless/base-debian11之上,暴露8080端口。该服务可作为nginx.ingress.kubernetes.io/auth-url注解指向的外部鉴权端点,配合 docs/examples/auth/external-auth/README.md 使用。
e2e 测试辅助镜像
fastcgi-helloserver
images/fastcgi-helloserver是一个 FastCGI 应用,专为 e2e 测试而生。其 Dockerfile 同样是"Go 构建 + distroless 运行"的范式,运行时不暴露 HTTP 端口,而是监听 FastCGI 端口9000。它在 e2e 测试中的实际用法可以从测试代码中得到印证:
- test/e2e/framework/fastcgi_helloserver.go 中的
NewFastCGIHelloServerDeployment会创建一个单副本 Deployment 与 Service,镜像为registry.k8s.io/ingress-nginx/fastcgi-helloserver:v1.2.9,容器端口与服务端口均为9000; - test/e2e/annotations/fastcgi.go 中的测试用例通过
nginx.ingress.kubernetes.io/backend-protocol: FCGI注解,断言生成的 NGINX 配置中包含include /etc/nginx/fastcgi_params;、fastcgi_pass以及fastcgi_index "index.php";等指令。
也就是说,这个镜像承担着验证 Controllerbackend-protocol: FCGI注解(以及fastcgi-*系列注解)正确性的任务。
httpbun
images/httpbun是一个"HTTP 请求与响应服务",用于在 e2e 测试中充当任意 HTTP 行为(如重定向、JSON 回显、延迟响应等)的后端。其 Dockerfile 固定了上游 httpbun 的一个具体 commit(a6b387c...)进行构建,镜像基于scratch,通过HTTPBUN_BIND=0.0.0.0:80监听 80 端口。测试框架 test/e2e/framework/deployment.go 中定义了HTTPBunService常量,并支持通过环境变量HTTPBUN_IMAGE指定要部署的 httpbun 镜像,供测试动态注入。
e2e-test-echo 与 test-runner
images/e2e-test-echo:一个基于 NGINX 的 echo 服务,通过 Lua(lua-resty-template)把请求信息原样回显,是 e2e 测试中验证路由、重写、header 透传等行为最常用的后端。测试框架中的EchoImage常量指向registry.k8s.io/ingress-nginx/e2e-test-echo:v1.2.9;images/test-runner:运行 e2e 测试套件的"全能"镜像,其 Dockerfile 以BASE_IMAGE(即上文提到的 NGINX 基础镜像)为基底,一次性装入 Go 工具链、etcd(用于本地拉起 kube-apiserver 进行单测)、ginkgo/golint、resty-cli、luarocks(并安装busted、luacheck)、kubectl、kube-apiserver、chart-testing、helm、yamllint、Yamale 等一整套测试与静态检查工具,对应着 test/e2e/run-e2e-suite.sh 等脚本的执行环境。
cfssl:证书工具镜像
images/cfssl用于在构建与测试流程中执行 cfssl 命令。它的 Dockerfile 基于alpine:3.23.3,从 Alpine 的 testing 源安装cfssl与bash,并暴露8888端口(cfssl 服务默认监听端口)。由于 Ingress Controller 的 HTTPS 与 Webhook 场景涉及证书签发,这类"开箱即用的证书工具"在调试自签 TLS、测试 mTLS 等场景中很有价值。
仓库中另一个证书相关工具是images/kube-webhook-certgen(源于 jet/kube-webhook-certgen 的分叉),它用于生成长期有效的 CA 与叶子证书,并自动把caBundle写入 Kubernetes Admission Webhook 配置,同时可选的--patch-failure-policy参数可同步修改 hook 的失败策略——这套流程与 Helm Chart 中 admission webhooks 的 pre-install/post-install 钩子配合紧密,相关内容见 images/kube-webhook-certgen/README.md。
镜像构建与发布:Makefile 详解
images/Makefile 是整个镜像目录的统一构建入口,其关键变量与目标如下:
NAME ?= # 指定要构建的镜像子目录(如 nginx) BUILDER ?= ingress-nginx # docker buildx 构建器名称 PLATFORMS ?= linux/amd64,linux/arm,linux/arm64 # 默认多平台 REGISTRY ?= us-central1-docker.pkg.dev/k8s-staging-images/ingress-nginx IMAGE ?= $(REGISTRY)/$(NAME) TAG ?= $(shell cat $(NAME)/TAG) # 版本号取自子目录 TAG 文件常用目标:
| 目标 | 行为 |
|---|---|
make build NAME=xxx | 创建并检查 buildx 构建器后,按PLATFORMS多平台构建镜像,注入BASE_IMAGE、GOLANG_VERSION等构建参数(来自仓库根目录的 NGINX_BASE 与 GOLANG_VERSION),并打上 OCI 标签与TAG版本号 |
make push NAME=xxx | 在 build 基础上附加--push,推送镜像到REGISTRY |
make test NAME=xxx | 进入对应rootfs目录执行go test ./... |
make test-e2e NAME=xxx | 执行子目录中的 e2e 脚本(如hack/e2e.sh) |
make clean | 删除 buildx 构建器 |
从源码结构看,每个镜像的构建单元统一约定为$(NAME)/rootfs目录,$(NAME)/TAG文件提供版本号,个别镜像还通过$(NAME)/EXTRAARGS注入额外--build-arg(例如e2e-test-echo通过 EXTRAARGS 传入LUAROCKS_VERSION与LUAROCKS_SHA并做 sha256 校验)。这种"子目录自描述 + 根 Makefile 统一驱动"的模式,让新增或维护一个镜像的成本非常低。
小结
回到 images/README.md 的核心论断:只有nginx镜像用于发布。这条规则贯穿了整个镜像体系的组织方式——nginx提供运行时底座并承载 HTTP/3 等前沿能力(当前为实验状态),custom-error-pages、go-grpc-greeter-server等镜像回答"Ingress 功能怎么用",fastcgi-helloserver、httpbun、e2e-test-echo、test-runner等镜像回答"功能怎么测"。理解这套镜像分工,无论是对生产环境的镜像选型,还是对深入阅读 Controller 源码与 e2e 测试,都能提供一个清晰的全局视图。
【免费下载链接】ingress-nginxIngress NGINX Controller for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/in/ingress-nginx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考