User guide
18 分钟阅读
版本信息
以下配置说明均基于官方版本 1.31 做说明。
Support Versions table
Ingress-NGINX version | k8s supported version | Alpine Version | Nginx Version |
---|---|---|---|
v1.3.1 | 1.24, 1.23, 1.22, 1.21, 1.20 | 3.16.2 | 1.19.10† |
v1.3.0 | 1.24, 1.23, 1.22, 1.21, 1.20 | 3.16.0 | 1.19.10† |
v1.1.1 | 1.23, 1.22, 1.21, 1.20, 1.19 | 3.14.2 | 1.19.9† |
v1.0.0 | 1.22, 1.21, 1.20, 1.19 | 3.13.5 | 1.20.1 |
安装部署
配置示例
参数解析
可用的Annotations
这里仅记录个人认为有比较有用处的几个注解,全部列表可以参考官方文档说明。
在ingress上annotation的键值对只能是字符串类型,数字或布尔类型需通过引号包含,如:“100”, “false”。默认键前缀是"nginx.ingress.kubernetes.io",由参数"–annotations-prefix"控制。
名称 | 说明 | 默认值 | 可取值 |
---|---|---|---|
nginx.ingress.kubernetes.io/app-root | 当应用请求"/“时做302重定向的目标url | - | - |
nginx.ingress.kubernetes.io/affinity | 用于保持会话连接 | - | cookie |
nginx.ingress.kubernetes.io/affinity-mode | 同上 | balanced | “balanced” or “persistent” |
nginx.ingress.kubernetes.io/affinity-canary-behavior | 同上 | sticky | “sticky” or “legacy” |
nginx.ingress.kubernetes.io/session-cookie-name | 同上 | INGRESSCOOKIE | - |
nginx.ingress.kubernetes.io/session-cookie-path | 同上 | / | - |
nginx.ingress.kubernetes.io/session-cookie-secure | 同上;只能用https协议发送给服务器 | false | true, false |
nginx.ingress.kubernetes.io/session-cookie-samesite | 同上;Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击 和用户追踪 | - | “None”, “Lax”, “Strict” |
nginx.ingress.kubernetes.io/session-cookie-conditional-samesite-none | 同上 | - | “true”, “false” |
nginx.ingress.kubernetes.io/auth-type | 认证 | - | “basic” or “digest” |
nginx.ingress.kubernetes.io/auth-secret | 同上;存放认证"secret"资源的名称 | - | - |
nginx.ingress.kubernetes.io/auth-secret-type | 同上;存放认证"secret"资源的格式 | - | “auth-file”, “auth-map” |
nginx.ingress.kubernetes.io/auth-realm | 认证 | - | - |
nginx.ingress.kubernetes.io/canary | 灰度、金丝雀发布 | - | “true” or “false” |
nginx.ingress.kubernetes.io/canary-by-header | 同上,基于HTTP请求头的流量调度,这里对于请求头名称,对应值可取"always"或"never” | - | - |
nginx.ingress.kubernetes.io/canary-by-header-value | 同上,自定义匹配请求头的值,以代替"always"与"never" | - | - |
nginx.ingress.kubernetes.io/canary-by-header-pattern | 同上 | - | - |
nginx.ingress.kubernetes.io/canary-by-cookie | 同上,基于Cookie的流量调度,这里对应cookie名称,对应值可取"always"或"never" | - | - |
nginx.ingress.kubernetes.io/canary-weight | 同上,流量调度到灰度副本的权重,填写数字如:30 | - | - |
nginx.ingress.kubernetes.io/canary-weight-total | 同上,总权重是多少,配合上面使用 | - | 100 |
[nginx.ingress.kubernetes.io/client-body-buffer-size] | TODO; HTTP请求体缓冲区大小,如果请求超过这个值会写入nginx配置的temp_path做个缓冲 | - | 8k |
[nginx.ingress.kubernetes.io/configuration-snippet] | TODO; 可自定义nginx配置,比较危险,建议关闭 | - | - |
[nginx.ingress.kubernetes.io/server-snippet] | TODO; 可自定义nginx配置,比较危险,建议关闭 | - | - |
[nginx.ingress.kubernetes.io/stream-snippet] | TODO; 可自定义nginx配置,比较危险,建议关闭 | - | - |
[nginx.ingress.kubernetes.io/custom-http-errors] | TODO; 设置 proxy-intercept-errors | - | - |
[nginx.ingress.kubernetes.io/default-backend] | TODO;访问该ingress如果后端没有活跃地址,则转发至同空间下配置的服务名, 优先级高于全局配置 | - | - |
[nginx.ingress.kubernetes.io/enable-cors] | TODO; 开启跨域 | - | - |
[nginx.ingress.kubernetes.io/force-ssl-redirect] | TODO; 如果该ingress开启ssl,是否强制跳转http,通过http状态码308 | - | - |
[nginx.ingress.kubernetes.io/ssl-redirect] | TODO; | - | - |
[nginx.ingress.kubernetes.io/from-to-www-redirect] | TODO; | - | - |
[nginx.ingress.kubernetes.io/permanent-redirect] | TODO; | - | - |
[nginx.ingress.kubernetes.io/permanent-redirect-code] | TODO; | - | - |
[nginx.ingress.kubernetes.io/temporal-redirect] | TODO; | - | - |
[nginx.ingress.kubernetes.io/preserve-trailing-slash] | TODO; | - | - |
[nginx.ingress.kubernetes.io/enable-rewrite-log] TODO; 是否开启rewrite日志,默认为关闭 | - | - | |
[nginx.ingress.kubernetes.io/rewrite-target] | TODO; | - | - |
[nginx.ingress.kubernetes.io/http2-push-preload] | TODO; HTTP2推送预加载 | - | - |
[nginx.ingress.kubernetes.io/limit-connections] | TODO; 请求限制 | - | - |
[nginx.ingress.kubernetes.io/proxy-body-size] | TODO; 代理配置 | - | - |
[nginx.ingress.kubernetes.io/upstream-hash-by] | TODO; 代理后段算法 | - | - |
[nginx.ingress.kubernetes.io/load-balance] | TODO; 代理后段算法 | - | - |
[nginx.ingress.kubernetes.io/satisfy] | TODO; 不清楚用途 | - | - |
[nginx.ingress.kubernetes.io/server-alias] | TODO; 设置别名,不能冲突 | - | - |
[nginx.ingress.kubernetes.io/ssl-passthrough] | TODO; | “false” | “true” or “false” |
[nginx.ingress.kubernetes.io/x-forwarded-prefix] | TODO; | - | - |
[nginx.ingress.kubernetes.io/upstream-vhost] | TODO; | - | - |
[nginx.ingress.kubernetes.io/enable-access-log] | TODO; | - | - |
[nginx.ingress.kubernetes.io/enable-opentracing] | TODO; | - | - |
[nginx.ingress.kubernetes.io/opentracing-trust-incoming-span] | TODO; | - | - |
[nginx.ingress.kubernetes.io/enable-influxdb] | 写入性能数据至influxdb,在k8s上使用prometheus,这个不建议开启 | “false” | “true” or “false” |
[nginx.ingress.kubernetes.io/influxdb-measurement] | 同上 | - | - |
[nginx.ingress.kubernetes.io/influxdb-port] | 同上 | - | - |
[nginx.ingress.kubernetes.io/influxdb-host] | 同上 | - | - |
[nginx.ingress.kubernetes.io/influxdb-server-name] | 同上 | - | - |
[nginx.ingress.kubernetes.io/use-regex] | TODO; | - | - |
[nginx.ingress.kubernetes.io/enable-modsecurity] | 开启modsecurity,仅在专用集群使用,业务集群不开启 | - | - | | ||
[nginx.ingress.kubernetes.io/enable-owasp-core-rules] | 同上 | - | - |
[nginx.ingress.kubernetes.io/modsecurity-transaction-id] | 同上 | - | - |
[nginx.ingress.kubernetes.io/modsecurity-snippet] | 同上 | - | - |
[nginx.ingress.kubernetes.io/mirror-request-body] | TODO;镜像 | - | - |
[nginx.ingress.kubernetes.io/mirror-target] | 同上 | - | - |
[nginx.ingress.kubernetes.io/mirror-host] | 同上 | - | - |
命令行参数
名称 | 说明 | 默认值 | 原始HELP |
---|---|---|---|
add_dir_header | TODO | TODO | If true, adds the file directory to the header of the log messages |
alsologtostderr | 错误输出终端,同时写入也文件 | - | log to standard error as well as files (no effect when -logtostderr=true) |
annotations-prefix | ingress使用注解的标签前缀 | nginx.ingress.kubernetes.io | Prefix of the Ingress annotations specific to the NGINX controller. (default “nginx.ingress.kubernetes.io”) |
apiserver-host | 连接的api server地址 | kubernetes.default.svc | Takes the form “protocol://address:port”. If not specified, it is assumed the program runs inside a Kubernetes cluster and local discovery is attempted. |
certificate-authority | ca证书,验证api server的https | - | Path to a cert file for the certificate authority. This certificate is used only when the flag –apiserver-host is specified. |
configmap | 用于控制器全局的ConfigMap配置名 | nginx-configuration | Name of the ConfigMap containing custom global configurations for the controller. |
controller-class | TODO | k8s.io/ingress-nginx | Ingress Class Controller value this Ingress satisfies. The class of an Ingress object is set using the field IngressClassName in Kubernetes clusters version v1.19.0 or higher. The .spec.controller value of the IngressClass referenced in an Ingress Object should be the same value specified here to make this object be watched. |
deep-inspect | TODO | true | Enables ingress object security deep inspector (default true) |
default-backend-service | 处理查询到的主机,流量转发的后段服务 | $(POD_NAMESPACE)/ingress-nginx-defaultbackend | Service used to serve HTTP requests not matching any known server name (catch-all). Takes the form “namespace/name”. The controller configures NGINX to forward requests to the first port of this Service. |
default-server-port | TODO | 8181 | Port to use for exposing the default server (catch-all). |
default-ssl-certificate | TODO | - | Secret containing a SSL certificate to be used by the default HTTPS server |
disable-catch-all | TODO | - | Disable support for catch-all Ingresses |
disable-full-test | TODO;默认开启 | - | Disable full test of all merged ingresses at the admission stage and tests the template of the ingress being created or updated |
disable-svc-external-name | TODO | - | Disable support for Services of type ExternalName |
dynamic-configuration-retries | TODO | 15 | Number of times to retry failed dynamic configuration before failing to sync an ingress. |
election-id | 解决多副本同时更新状态,使用的选举id锁 | ingress-controller-leader | Election id to use for Ingress status updates. |
enable-metrics | 开启nginx的prometheus类型性能指标,影响性能,高并发下可以考虑关闭 | true | Enables the collection of NGINX metrics |
enable-ssl-chain-completion | TODO | - | Autocomplete SSL certificate chains with missing intermediate CA certificates. Certificates uploaded to Kubernetes must have the “Authority Information Access” X.509 v3 extension for this to succeed. |
enable-ssl-passthrough | TODO | - | Enable SSL Passthrough. |
health-check-path | 健康检测的url地址 | /healthz | URL path of the health check endpoint. Configured inside the NGINX status server. All requests received on the port defined by the healthz-port parameter are forwarded internally to this path. |
health-check-timeout | 健康检测超时时间,秒 | 10 | Time limit, in seconds, for a probe to health-check-path to succeed. |
healthz-host | 健康检测主机地址 | - | Address to bind the healthz endpoint. |
healthz-port | 健康检测端口 | 10254 | Port to use for the healthz endpoint. |
http-port | 接收http协议流量的端口 | 80 | Port to use for servicing HTTP traffic. |
https-port | 接收https协议流量的端口 | 80 | Port to use for servicing HTTPS traffic. |
ingress-class | 已被废弃;TODO | - | Name of the ingress class this controller satisfies. The class of an Ingress object is set using the annotation “kubernetes.io/ingress.class”. The parameter –controller-class has precedence over this. |
ingress-class-by-name | TODO | TODO | Define if Ingress Controller should watch for Ingress Class by Name together with Controller Class |
internal-logger-address | TODO | 127.0.0.1:11514 | Address to be used when binding internal syslogger |
kubeconfig | 连接api server的信息 | - | Path to a kubeconfig file containing authorization and API server information. |
length-buckets | TODO | - | Set of buckets which will be used for prometheus histogram metrics such as RequestLength, ResponseLength. ([10.000000,20.000000,30.000000,40.000000,50.000000,60.000000,70.000000,80.000000,90.000000,100.000000]) |
log_backtrace_at | TODO | 0 | when logging hits line file:N, emit a stack trace |
log_dir | 日志目录 | - | If non-empty, write log files in this directory (no effect when -logtostderr=true) |
log_file | 日志文件名 | - | If non-empty, use this log file (no effect when -logtostderr=true) |
log_file_max_size | 日志文件最大值,单位:MB | 1800MB | Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. |
logtostderr | 日志输出到终端 | true | log to standard error instead of files |
maxmind-edition-ids | TODO | - | Maxmind edition ids to download GeoLite2 Databases. (default “GeoLite2-City,GeoLite2-ASN”) |
maxmind-license-key | TODO | - | Maxmind license key to download GeoLite2 Databases. |
maxmind-mirror | TODO | - | Maxmind mirror url (example: http://geoip.local/databases |
maxmind-retries-count | TODO | 1 | Number of attempts to download the GeoIP DB. |
maxmind-retries-timeout | TODO | 0s | Maxmind downloading delay between 1st and 2nd attempt, 0s - do not retry to download if something went wrong. |
metrics-per-host | TODO | true | Export metrics per-host |
monitor-max-batch-size | TODO | 10000 | Max batch size of NGINX metrics |
one_output | TODO | TODO | If true, only write logs to their native severity level |
post-shutdown-grace-period | TODO | 10 | Seconds to wait after the nginx process has stopped before controller exits. |
profiler-port | 控制器对外提供的profiler端口地址 | 10245 | Port to use for expose the ingress controller Go profiler when it is enabled. |
profiling | 是否开启pprof | true | Enable profiling via web interface host:port/debug/pprof/ |
publish-service | 各个 ingress.status 的 Address 地址,监听命名空间下服务,格式为:“namespace/name”,一般仅在公有云环境使用 | TODO | Service fronting the Ingress controller. Takes the form “namespace/name”. When used together with update-status, the controller mirrors the address of this service’s endpoints to the load-balancer status of all Ingress objects it satisfies. |
publish-status-address | 功能同"publish-service",有人工预先分配 | TODO | Customized address (or addresses, separated by comma) to set as the load-balancer status of Ingress objects this controller satisfies. Requires the update-status parameter. |
report-node-internal-ip-address | 功能同"publish-service",使用当前 controler 部署节点的IP,一般在私有云使用 | TODO | Set the load-balancer status of Ingress objects to internal Node addresses instead of external. |
report-status-classes | TODO | TODO | Use status classes (2xx, 3xx, 4xx and 5xx) instead of status codes in metrics |
shutdown-grace-period | TODO | TODO | Seconds to wait after receiving the shutdown signal, before stopping the nginx process. |
size-buckets | TODO | TODO | Set of buckets which will be used for prometheus histogram metrics such as BytesSent (default [10.000000,100.000000,1000.000000,10000.000000,100000.000000,1000000.000000,10000000.000000]) |
skip_headers | TODO | TODO | If true, avoid header prefixes in the log messages |
skip_log_headers | TODO | TODO | If true, avoid headers when opening log files (no effect when -logtostderr=true) |
ssl-passthrough-proxy-port | TODO | 442 | Port to use internally for SSL Passthrough. |
status-port | TODO | 10246 | Port to use for the lua HTTP endpoint configuration. |
status-update-interval | TODO | 60 | Time interval in seconds in which the status should check if an update is required. Default is 60 seconds |
stderrthreshold | TODO | 2 | logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) |
stream-port | TODO | 10247 | Port to use for the lua TCP/UDP endpoint configuration. |
sync-period | TODO;默认关闭 | - | Period at which the controller forces the repopulation of its local object stores. |
sync-rate-limit | TODO | 0.3 | Define the sync frequency upper limit |
tcp-services-configmap | nginx stream tcp代理 | tcp-services | Name of the ConfigMap containing the definition of the TCP services to expose. The key in the map indicates the external port to be used. The value is a reference to a Service in the form “namespace/name:port”, where “port” can either be a port number or name. |
time-buckets | TODO | TODO | Set of buckets which will be used for prometheus histogram metrics such as RequestTime, ResponseTime (default [0.005000,0.010000,0.025000,0.050000,0.100000,0.250000,0.500000,1.000000,2.500000,5.000000,10.000000]) |
udp-services-configmap | nginx stream udp代理 | udp-services | Name of the ConfigMap containing the definition of the UDP services to expose. The key in the map indicates the external port to be used. The value is a reference to a Service in the form “namespace/name:port”, where “port” can either be a port name or number. |
update-status | TODO | true | Update the load-balancer status of Ingress objects this controller satisfies. Requires setting the publish-service parameter to a valid Service reference. |
update-status-on-shutdown | TODO | true | Update the load-balancer status of Ingress objects when the controller shuts down. Requires the update-status parameter. |
v | 日志级别 | - | number for the log level verbosity |
validating-webhook | 准入控制器验证ingress的配置 | TODO | The address to start an admission controller on to validate incoming ingresses. Takes the form “ |
validating-webhook-certificate | 准入控制器的证书 | TODO | The path of the validating webhook certificate PEM. |
validating-webhook-key | 准入控制器的证书 | TODO | The path of the validating webhook key PEM. |
vmodule | TODO | TODO | comma-separated list of pattern=N settings for file-filtered logging |
watch-ingress-without-class | TODO | TODO | Define if Ingress Controller should also watch for Ingresses without an IngressClass or the annotation specified |
watch-namespace | TODO | TODO | Namespace the controller watches for updates to Kubernetes objects. This includes Ingresses, Services and all configuration resources. All namespaces are watched if this parameter is left empty. |
watch-namespace-selector | TODO | TODO | Selector selects namespaces the controller watches for updates to Kubernetes objects. |
ConfigMap 配置参数
可以通过这个定制 nginx.conf
文件内容,里面填写的键值对对照数据结构 config.go
配置,由于 “ConfigMap” 里面只能是 string
类型,所以任何值需使用引号包含起来,如:"128"
。如果是数组类型,则通过逗号分隔,如:"192.168.30.0/24, 192.168.31.0/24"
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
data:
access-log-path: "/var/log/nginx/access.log"
error-log-path: "/var/log/nginx/error.log"
名称 | 默认值 | 可取值 | 说明 |
---|---|---|---|
allow-backend-server-header | “true” | “true” or “false” | 是否以后端返回的 “Server” 响应头来代替nginx ingress的值 |
allow-snippet-annotations | “true” | “false” or “true” | 开启ingress配置 *-snippet 更改 nginx.conf 内容,如果用户不可信则不开放 |
annotation-value-word-blocklist | "" | 字符串数组,见建议值 | 定义哪些关键字不能提供给用户配置 annotation 使用,有安全风险 |
hide-headers | "" | 字符串数组 | 定义哪些请求头不返回给客户端 |
access-log-params | "" | access_log | nginx access_log 额外的一些参数 |
access-log-path | “/var/log/nginx/access.log” 指向 “/dev/stdout” | http 与 stream 共同使用 | 客户端访问日志 |
http-access-log-path | "" | http 访问日志,优先级高 | http 访问日志 |
stream-access-log-path | "" | stream 访问日志,优先级高 | http 访问日志 |
enable-access-log-for-default-backend | “false” | “true” or “false” | 是否开启未匹配后端ingress的请求日志记录 |
error-log-path | “/var/log/nginx/error.log” 指向 “/dev/stderr” | "" | nginx 错误日志 |
enable-modsecurity | “false” | “true” or “false” | 是否开启 modsecurity 功能 |
enable-owasp-modsecurity-crs | “false” | “true” or “false” | 同上 |
modsecurity-snippet | "" | "" | TODO; 同上 |
client-header-buffer-size | “1k” | "" | 客户端请求header缓存大小 |
client-header-timeout | “60” | "" | - |
client-body-buffer-size | “8k” | "" | - |
client-body-timeout | “60” | "" | - |
disable-access-log | “false” | “true” “false” | 是否关闭请求日志 |
disable-ipv6 | “false” | “true” or “false” | 是否关闭ipv6监听 |
disable-ipv6-dns | “false” | “true” or “false” | 关闭nginx对ipv6的解析 |
enable-underscores-in-headers | “false” | “true” or “false” | 客户端提交下划线"_“的请求头是否忽略,不做传递至后端 |
enable-ocsp | “false” | “true” or “false” | TODO |
ignore-invalid-headers | “true” | “true” or “false” | 忽略异常请求头 |
retry-non-idempotent | “false” | “true” or “false” | 对非幂等的请求(POST、LOCK、PATCH),如果后端错误将不进行重试 |
error-log-level | “notice” | 见nginx error_log | 错误日志级别 |
hsts | “true” | “true” or “false” | 告诉浏览器必须使用https进行访问 |
hsts-include-subdomains | “true” | “true” or “false” | TODO |
hsts-max-age | - | - | - |
hsts-preload | “false” | - | - |
keep-alive | “75” | "” | 客户端与服务端保持连接时长,避免频繁建立tcp,设置为0则关闭 |
keep-alive-requests | “100” | "" | TODO |
large-client-header-buffers | “4 8k” | "" | |
log-format-escape-json | “false” | “true” or “false” | 如果日志以json格式输出,则对一些格式进行转换 |
log-format-upstream | 见日志格式默认值 | "" | 客户端请求日志格式 |
log-format-stream | 见stream日志格式默认值 | "" | 客户端请求日志格式 |
enable-multi-accept | “treu” | “true” or “false” | TODO |
max-worker-connections | “16384” | "" | TODO |
max-worker-open-files | “0” | "" | TODO |
map-hash-bucket-size | “64” | "" | TODO |
proxy-real-ip-cidr | “0.0.0.0/0” | 字符串数组 | 配置proxy中间层地址并过滤, 用于获取真实客户端IP |
proxy-set-headers | "" | "" | 自定义传输后段的请求头 |
server-name-hash-max-size | “1024” | "" | TODO |
server-name-hash-bucket-size | "" | "" | TODO |
proxy-headers-hash-max-size | “512” | "" | TODO |
proxy-headers-hash-bucket-size | “64” | "" | TODO |
reuse-port | “true” | “true” or “false” | TODO |
plugins | "" | "" | TODO |
server-tokens | “false” | “true” or “false” | 是否返回客户端nginx的版本 |
use-proxy-protocol | “false” | “true” or “false” | 是否使用 PROXY 协议,可以获取客户端IP |
proxy-protocol-header-timeout | “5s” | "" | TODO |
use-gzip | “false” | “true” or “false” | 针对 HTTP 响应是否开启 gzip 压缩 |
gzip-level | “1” | "" | gzip 压缩级别 |
use-geoip | “true” | “true” or “false” | 开启 geoip |
use-geoip2 | “false” | “true” or “false” | 开启 geoip |
enable-brotli | “false” | “true” or “false” | 使用 brotli 模块压缩 |
user-http2 | “false” | “true” or “false” | 开启 http2 支持 |
gzip-min-length | “256” | "" | TODO |
gzip-types | 见gzip默认压缩类型 | "" | 需要压缩的类型 |
worker-processes | “auto” | "" | 开启nginx的进程数,默认等于cpu核心数 |
load-balance | “round_robin” | “round_robin” or “ewma” | TODO; |
upstream-keepalive-connections | - | - | - |
proxy-read-timeout | 60s | x | proxy读取等待后端响应体返回的最大时间 |
proxy-next-upstream-tries | 3 | x | proxy读取、发送后端如果超时,重试的次数 |
compute-full-forwarded-for | false | “true” or “false” | 将 remote address 附加到 X-Forwarded-For,新增X-Original-Forwarded-For 记录旧值,一般用于解决 xff 伪造 |
- ingress关闭建议值
"load_module,lua_package,_by_lua,location,root,proxy_pass,serviceaccount,{,},',\""
- 日志格式默认值
$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
- stream日志格式默认值
[$remote_addr] [$time_local] $protocol $status $bytes_sent $bytes_received $session_time
- gzip默认压缩类型
application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component
各个配置例子
有三种方式可以自定义你的Ingress Nginx:
-
通过ConfigMap
更改全局的ConfigMap配置"nginx-configuration",默认由参数"–configmap"控制。
-
通过Annotations
通过各个ingress的配置文件添加特定注解,控制各自的行为,注解前缀由"–annotations-prefix"控制。
-
自定义 nginx.tmpl 模版
如果以上两种方式还无法满足需要,可以通过更改nginx.conf的模版文件。
自定义Nginx模版
- 拷贝ingress-nginx镜像内的模版内容
/etc/nginx/template/nginx.tmpl
- 以nginx.tmpl创建ConfigMap资源
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-template
namespace: kube-system
data:
nginx.tmpl: |
{{ $all := . }}
{{ $servers := .Servers }}
{{ $cfg := .Cfg }}
{{ $IsIPV6Enabled := .IsIPV6Enabled }}
{{ $healthzURI := .HealthzURI }}
{{ $backends := .Backends }}
{{ $proxyHeaders := .ProxySetHeaders }}
{{ $addHeaders := .AddHeaders }}
# Configuration checksum: {{ $all.Cfg.Checksum }}
......
- 在Deployment或DaemonSet中加入模版
把官方镜像里的nginx.tmpl模版文件拷贝更改,并创建为ConfigMap资源挂载覆盖默认模版。
volumeMounts:
- name: nginx-template
mountPath: /etc/nginx/template
readOnly: true
......
volumes:
- name: nginx-template
configMap:
name: nginx-template
......
代理TCP与UDP流量
ingres是不包含tcp、udp这块流量规范,这里是ingress-nginx添加的功能。
- 创建tcp服务使用的ConfigMap
监听的cm名称由
--tcp-services-configmap
参数决定
kind: ConfigMap
apiVersion: v1
metadata:
name: tcp-services
data:
"1053": "kube-system/kube-dns:53"
开启1053端口,转发流量至"kube-system"命名空间下service为"kube-dns"的53端口。
- 在ingress-nginx自动生成的配置
/etc/nginx/nginx.conf
stream {
......
server {
preread_by_lua_block {
ngx.var.proxy_upstream_name="tcp-kube-system-kube-dns-53";
}
listen 1053;
proxy_timeout 600s;
proxy_next_upstream on;
proxy_next_upstream_timeout 600s;
proxy_next_upstream_tries 3;
proxy_pass upstream_balancer;
}
......
}
app-root
- ingress配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/app-root: "/test"
- nginx.tmpl模版
{{ if not (empty $location.Rewrite.AppRoot) }}
if ($uri = /) {
return 302 $scheme://$http_host{{ $location.Rewrite.AppRoot }};
}
{{ end }}
- nginx.conf生成内容
server {
if ($uri = /) {
return 302 $scheme://$http_host/test;
}
}
affinity
- ingress配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "HELLO"
- curl测试
< HTTP/1.1 200 OK
< Date: Mon, 12 Sep 2022 14:05:36 GMT
< Content-Type: text/html
< Content-Length: 4
< Connection: keep-alive
< Set-Cookie: HELLO=1662991537.226.193.550764|a6b1ec86db225f232b62b29085af45ff; Path=/; HttpOnly
< Last-Modified: Mon, 11 Dec 2017 03:18:39 GMT
具体逻辑由"rootfs/etc/nginx/lua/balancer/sticky.lua"实现。
auth
- 创建用户与密码文件
htpasswd -c http-auth.txt user1
# 用户: user1
# 密码: kubernetes
user1:$apr1$ue3Fu891$xnyqlJlwcM4iWtJrAN8ZW/
- 把 http-auth.txt 转化为 k8s secret 资源
cat http-auth.txt
当"nginx.ingress.kubernetes.io/auth-secret-type"为"auth-file"时,替换"auth"对应的值
apiVersion: v1
kind: Secret
metadata:
name: basic-auth
stringData:
auth: dXNlcjE6JGFwcjEkdWUzRnU4OTEkeG55cWxKbHdjTTRpV3RKckFOOFpXLwo=
type: Opaque
当"nginx.ingress.kubernetes.io/auth-secret-type"为"auth-map"时,替换下面"user1"行
apiVersion: v1
kind: Secret
metadata:
name: basic-auth
stringData:
user1: $apr1$ue3Fu891$xnyqlJlwcM4iWtJrAN8ZW/
type: Opaque
这里注意"secret"中的内容格式由"nginx.ingress.kubernetes.io/auth-secret-type"确定"。
canary
- 基于 HTTP 请求头
当仅设置 nginx.ingress.kubernetes.io/canary-by-header
请求头时,对应的值可取 “always” 或 “never” 分别表示流量至该副本或关闭。
如果需要自定义默认的 “always” 与 “never” 值,需在定义 nginx.ingress.kubernetes.io/canary-by-header-value
内容,然后请求匹配值才会调度。
日志格式
json日志
log-format-escape-json: "true"
log-format-upstream: '{"msec": "$msec", "remote_addr": "$remote_addr", "request_length": $request_length, "request_method": "$request_method", "host": "$host", "request_uri": "$request_uri", "server_name": "$server_name", "server_addr": "$server_addr", "server_port": $server_port, "uri": "$uri", "args": "$args", "server_protocol": "$server_protocol", "bytes_sent": $bytes_sent, "body_bytes_sent": $body_bytes_sent, "status": $status, "request_time": $request_time, "http_referer": "$http_referer", "http_user_agent": "$http_user_agent", "http_x_tr_user_id": "$http_x_tr_user_id", "http_x_tr_pv_id": "$http_x_tr_pv_id", "http_x_tr_request_id": "$req_id", "http_x_tr_rpc_id": "$http_x_tr_rpc_id", "proxy_upstream_name": "$proxy_upstream_name", "upstream_addr": "$upstream_addr", "upstream_response_length": "$upstream_response_length", "upstream_response_time": "$upstream_response_time", "upstream_status": "$upstream_status"}'
客户端通过snippet自定义nginx.conf配置
客户端是指通过在ingress中编写annotations可以很灵活的自定义nginx.conf配置,如果是不可信用户则相当危险。
功能开启或关闭是在 “nginx-configuration” 的configmap配置,“true"是开启状态:
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
data:
allow-snippet-annotations: "true"
可以通过以下几种注解分别自定义不同的配置:
nginx.ingress.kubernetes.io/configuration-snippet
nginx.ingress.kubernetes.io/server-snippet
nginx.ingress.kubernetes.io/stream-snippet
nginx.ingress.kubernetes.io/modsecurity-snippet
- 在各 “server” 下 “location” 自定义配置
ingress注解
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "x-tr-request-id: $req_id";
nginx.tmpl模版内容
http {
## start server {{ $server.Hostname }}
server {
......
location {{ $path }} {
{{/* Add any additional configuration defined */}}
{{ $location.ConfigurationSnippet }}
}
......
}
## end server {{ $server.Hostname }}
}
生成的内容
http {
server {
......
location / {
more_set_headers "Request-Id: $req_id";
}
......
}
}
- 在各 “server” 下添加自定义配置
ingress注解
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
set $agentflag 0;
if ($http_user_agent ~* "(Mobile)" ){
set $agentflag 1;
}
if ( $agentflag = 1 ) {
return 301 https://m.a-demo-web.site;
}
nginx.tmpl模版内容
http {
## start server {{ $server.Hostname }}
server {
......
{{ if not (empty $cfg.ServerSnippet) }}
# Custom code snippet configured in the configuration configmap
{{ $cfg.ServerSnippet }}
{{ end }}
......
}
## end server {{ $server.Hostname }}
}
生成的nginx.conf
http {
server {
# Custom code snippet configured for host api.a-demo-web.site
set $agentflag 0;
if ($http_user_agent ~* "(Mobile)" ){
set $agentflag 1;
}
if ( $agentflag = 1 ) {
return 301 https://m.a-demo-web.site;
}
}
}
- 在各 “stream” 下添加自定义配置
ingress注解
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/stream-snippet: |
server {
listen 8000;
proxy_pass 127.0.0.1:80;
}
nginx.tmpl模版内容
stream {
# TCP services
{{ range $tcpServer := .TCPBackends }}
server {
....
}
{{ end }}
# UDP services
{{ range $udpServer := .UDPBackends }}
server {
....
}
{{ end }}
# Stream Snippets
{{ range $snippet := .StreamSnippets }}
{{ $snippet }}
{{ end }}
}
- 在开启 “auth-url” 下添加自定义配置
ingress注解
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-url: http://a-demo-web.site/external-auth
nginx.ingress.kubernetes.io/auth-snippet: |
proxy_set_header Foo-Header 42;
nginx.tmpl模版内容
http {
## start server {{ $server.Hostname }}
server {
{{ if $authPath }}
location = {{ $authPath }} {
internal;
{{ if not (empty $externalAuth.AuthSnippet) }}
{{ $externalAuth.AuthSnippet }}
{{ end }}
}
}
## end server {{ $server.Hostname }}
}
- 在开启 “modsecurity” 下添加自定义配置
ingress注解
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/enable-modsecurity: "true"
nginx.ingress.kubernetes.io/modsecurity-snippet: |
SecRuleEngine On
SecDebugLog /tmp/modsec_debug.log
nginx.tmpl模版内容
http {
## start server {{ $server.Hostname }}
server {
......
location {{ $path }} {
{{ buildModSecurityForLocation $all.Cfg $location }}
}
......
}
## end server {{ $server.Hostname }}
}
# 各各站点的配置生成
# internal/ingress/controller/template/template.go
func buildModSecurityForLocation(cfg config.Configuration, location *ingress.Location) string {
isMSEnabledInLoc := location.ModSecurity.Enable
isMSEnableSetInLoc := location.ModSecurity.EnableSet
isMSEnabled := cfg.EnableModsecurity
......
if location.ModSecurity.Snippet != "" {
buffer.WriteString(fmt.Sprintf(`modsecurity_rules '
%v
';
`, location.ModSecurity.Snippet))
}
return buffer.String()
}
生成的nginx.conf
http {
server {
......
set $proxy_alternative_upstream_name "";
modsecurity on;
modsecurity_rules '
SecRuleEngine On
SecDebugLog /tmp/modsec_debug.log
';
client_max_body_size 20m;
......
}
}
服务端通过snippet自定义nginx.conf配置
服务端是通过"ingress-controller"启动参数--configmap=$(POD_NAMESPACE)/nginx-configuration
所关联的"ConfigMap"资源来实现。
可以通过以下几种注解分别自定义不同的配置:
main-snippet
http-snippet
server-snippet
stream-snippet
location-snippet
......
daemon off;
# main-snippet
{{ if not (empty $cfg.MainSnippet) }}
{{ $cfg.MainSnippet }}
{{ end }}
events {
}
http {
# http-snippet
{{ if not (empty $cfg.HTTPSnippet) }}
# Custom code snippet configured in the configuration configmap
{{ $cfg.HTTPSnippet }}
{{ end }}
## start server {{ $server.Hostname }}
server {
......
# 该模版内同样包含一个"server snippet",由客户端通过注解提交
# 以下属于 {{ template "SERVER" serverConfig $all $server }} 内容
{{ if not (empty $server.ServerSnippet) }}
# Custom code snippet configured for host {{ $server.Hostname }}
{{ $server.ServerSnippet }}
{{ end }}
location {{ $path }} {
# location-snippet
{{ if not (empty $all.Cfg.LocationSnippet) }}
# Custom code snippet configured in the configuration configmap
{{ $all.Cfg.LocationSnippet }}
{{ end }}
}
# 以上属于 {{ template "SERVER" serverConfig $all $server }} 内容
# server-snippet
{{ if not (empty $cfg.ServerSnippet) }}
# Custom code snippet configured in the configuration configmap
{{ $cfg.ServerSnippet }}
{{ end }}
{{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics $cfg.EnableModsecurity) }}
}
## end server {{ $server.Hostname }}
}
stream {
......
# stream-snippet
# 客户端通过ingress提交注解也在次
# Stream Snippets
{{ range $snippet := .StreamSnippets }}
{{ $snippet }}
{{ end }}
}
......
监听的几个端口
- 启动监听的端口
端口 | 协议 | 参数 | 用途描述 |
---|---|---|---|
80 | http | http-port | xxx |
443 | https | https-port | xx |
8181 | http | default-server-port | 默认服务 |
442 | https | ssl-passthrough-proxy-port | xxx |
10254 | http | healthz-port | /metrics, /healthz |
10245 | http | profiler-port | 仅可在 127.0.0.1 监听; /debug/pprof/ |
10246 | http | status-port | 仅可在 127.0.0.1 监听;/healthz, /is-dynamic-lb-initialized, /nginx_status, /configuration |
10247 | tcp | stream-port | 仅可在 127.0.0.1 监听;用于更新 tcp-services 与 udp-services 后端 |
rp := []int{
n.cfg.ListenPorts.HTTP,
n.cfg.ListenPorts.HTTPS,
n.cfg.ListenPorts.SSLProxy,
n.cfg.ListenPorts.Health,
n.cfg.ListenPorts.Default,
nginx.ProfilerPort,
nginx.StatusPort,
nginx.StreamPort,
}
- default-server-port
在nginx.conf模版中实现
# backend for when default-backend-service is not configured or it does not have endpoints
server {
listen 8181 default_server reuseport backlog=4096;
set $proxy_upstream_name "internal";
access_log off;
location / {
return 404;
}
}
- profiler-port
在go代码中实现
if conf.EnableProfiling {
go metrics.RegisterProfiler("127.0.0.1", nginx.ProfilerPort)
}
- status-port
在nginx.conf模版中实现
# default server, used for NGINX healthcheck and access to nginx stats
server {
listen 127.0.0.1:{{ .StatusPort }};
set $proxy_upstream_name "internal";
keepalive_timeout 0;
gzip off;
access_log off;
location {{ $healthzURI }} {
return 200;
}
location /is-dynamic-lb-initialized {
......
}
location {{ .StatusPath }} {
stub_status on;
}
location /configuration {
......
}
location / {
content_by_lua_block {
ngx.exit(ngx.HTTP_NOT_FOUND)
}
}
}
- stream-port
在go代码中实现
streams := make([]ingress.Backend, 0)
for _, ep := range TCPEndpoints {
var service *apiv1.Service
if ep.Service != nil {
service = &apiv1.Service{Spec: ep.Service.Spec}
}
key := fmt.Sprintf("tcp-%v-%v-%v", ep.Backend.Namespace, ep.Backend.Name, ep.Backend.Port.String())
streams = append(streams, ingress.Backend{
Name: key,
Endpoints: ep.Endpoints,
Port: intstr.FromInt(ep.Port),
Service: service,
})
}
for _, ep := range UDPEndpoints {
var service *apiv1.Service
if ep.Service != nil {
service = &apiv1.Service{Spec: ep.Service.Spec}
}
key := fmt.Sprintf("udp-%v-%v-%v", ep.Backend.Namespace, ep.Backend.Name, ep.Backend.Port.String())
streams = append(streams, ingress.Backend{
Name: key,
Endpoints: ep.Endpoints,
Port: intstr.FromInt(ep.Port),
Service: service,
})
}
buf, err := json.Marshal(streams)
hostPort := net.JoinHostPort("127.0.0.1", fmt.Sprintf("%v", nginx.StreamPort))
conn, err := net.Dial("tcp", hostPort)
_, err = conn.Write(buf)
配置404服务后端
如果请求域名未在集群中配置,则把流量返回至指定后端服务,比如官方默认的服务:
建议不要开启,当该后端服务不可用时,客户端需等待超时时间后才关闭,并以504返回; 客户等待的时间为:proxy-read-timeout * proxy-next-upstream-tries
kube-system/ingress-nginx-defaultbackend
- 镜像与代码
默认镜像
gcr.io/google-containers/defaultbackend:1.4
源代码
https://github.com/kubernetes/ingress-gce/tree/master/cmd/404-server
default backend 原始代码仓库为 ingress-nginx 之后被移到 ingress-gce 下面,参考
- controller 开启
在 /nginx-ingress-controller 添加 --default-backend-service
参数指定 namespace
下的 service
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/ingress-nginx-defaultbackend
- 响应示例:未配置任何404服务
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
- 响应示例:转发默认404服务
default backend - 404
- 响应示例:已配置404服务,但后端不可用
<html>
<head><title>504 Gateway Time-out</title></head>
<body>
<center><h1>504 Gateway Time-out</h1></center>
<hr><center>nginx</center>
</body>
</html>
需等待服务端配置的超时时间结束。
POD内核优化
- 未调整前
/etc/nginx $ sysctl -a | grep kernel.core_uses_pid
kernel.core_uses_pid = 0
/etc/nginx $
/etc/nginx $ sysctl -a | grep net.core.somaxconn
net.core.somaxconn = 4096
/etc/nginx $
/etc/nginx $ sysctl -a | grep net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768 60999
/etc/nginx $ ^C
URL重定向
- 需求
针对请求地址 api.a-demo-web.site/commons/cmdb/v1/host/search
到后端需变更为 /host/search
,也就是移除前缀路径 /commons/cmdb/v1/
。
- 实现
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/$1"
name: commons-api
spec:
ingressClassName: nginx
rules:
- host: api.a-demo-web.site
http:
paths:
- path: /commons/cmdb/v1/(.*)
backend:
serviceName: commons-cmdb-v1
servicePort: 10080
pathType: Prefix
主要添加 “rewrite-target” 注解,与 path 设置为正则,这里需注意下 ingress 的 “apiVersion”,不同版本间风格存在差异。
防止 xff 伪造
- 功能需求
客户端使用 “X-Forwarded-For” 自定了一些 ip 并提交了请求,此时服务端正常情况下会记录整个 ip 列表。
curl -v -H "X-Forwarded-For: 1.1.1.1, 2.2.2.2" https://www.baidu.com
服务端将会记录:“1.1.1.1, 2.2.2.2, 代理IP1, 代理IP2, ……",此时希望能排除客户端自定的ip,期望为:“代理IP1, 代理IP2, ……”
- 步骤实现
forwarded-for-header: "X-Forwarded-For"
use-forwarded-headers: "true"
compute-full-forwarded-for: "true"
proxy-real-ip-cidr: ""
配置 “compute-full-forwarded-for” 值为 “true”,则在 ingress-nginx 这里会把当前 “X-Forwarded-For” 请求头的值拷贝并新增至 “X-Original-Forwarded-For”,同时重制 “X-Forwarded-For” 并把此时 nginx 认为的 remote addr 写入覆盖该头。
- 原理分析
http {
......
{{ if and $cfg.UseForwardedHeaders $cfg.ComputeFullForwardedFor }}
# We can't use $proxy_add_x_forwarded_for because the realip module
# replaces the remote_addr too soon
map $http_x_forwarded_for $full_x_forwarded_for {
{{ if $all.Cfg.UseProxyProtocol }}
default "$http_x_forwarded_for, $proxy_protocol_addr";
'' "$proxy_protocol_addr";
{{ else }}
default "$http_x_forwarded_for, $realip_remote_addr";
'' "$realip_remote_addr";
{{ end}}
}
......
}
{{/* definition of server-template to avoid repetitions with server-alias */}}
{{ define "SERVER" }}
......
{{ if $authPath }}
location = {{ $authPath }} {
{{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }}
proxy_set_header X-Forwarded-For $full_x_forwarded_for;
{{ else }}
proxy_set_header X-Forwarded-For $remote_addr;
{{ end }}
}
{{ end }}
location {{ $path }} {
# 如果同时设置了 "use-forwarded-headers" 与 "compute-full-forwarded-for" 则不进行 xff 的替换。
{{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }}
{{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for;
{{ else }}
{{ $proxySetHeader }} X-Forwarded-For $remote_addr;
{{ end }}
}
......
{{ end }}