本文永久链接: https://www.xtplayer.cn/kubernetes/ingress-configuration-demo/

本文列举一些常用的 ingress 功能配置,并持续更新。

Ingress 配置修改方法

通过 Rancher UI 配置

依次进入 system 项目|配置映射,然后在 ingress-nginx 命名空间部分找到 nginx-configuration配置映射并编辑 nginx-configuration。

然后在 配置映射 中以键值对形式添加参数,比如: server-tokens=false

注意: 配置映射设置的参数是作用于全局,如果想局部生效,可通过对应的 注释 去配置相应参数,配置方法文章后面会说明。

通过 kubectl 命令行修改

执行以下命令进入配置映射文件的编辑模式

kubectl -n ingress-nginx  edit configmaps nginx-configuration

然后在 data 字段中添加相应参数,比如: server-tokens: "false",注意双引号。

kubectl ingress-nginx plugin

ingress 大概从 0.26.0(或 v0.24.0)版本开始不再支持在 nginx.conf 配置文件中直接显示 backend。

参考链接: https://github.com/kubernetes/ingress-nginx/blob/e825af86e11790a335e0e4b4360d52ce13cd7a9c/rootfs/etc/nginx/template/nginx.tmpl#L456

upstream upstream_balancer {
### Attention!!!
#
# We no longer create "upstream" section for every backend.
# Backends are handled dynamically using Lua. If you would like to debug
# and see what backends ingress-nginx has in its memory you can
# install our kubectl plugin https://kubernetes.github.io/ingress-nginx/kubectl-plugin.
# Once you have the plugin you can use "kubectl ingress-nginx backends" command to
# inspect current backends.
#
###

server 0.0.0.1; # placeholder

balancer_by_lua_block {
balancer.balance()
}

backend 数据保存在内存中,将通过 Lua 动态的去生成 Nginx 配置文件。为了 debug ingress 的配置,ingress 推出了一款 kubectl 插件,可以通过此插件查看相应的配置信息。

安装 krew

Krew 可以理解为 kubectl 插件的包管理工具。借助 Krew,可以轻松地使用 kubectl plugin 查询、安装和管理插件,使用类似 apt、dnf 或 brew。

  • macOS/Linux
  1. 需要提前安装 git 工具

  2. 在终端中运行以下命令以下载并安装 krew

    (
    set -x;
    cd "$(mktemp -d)" &&
    curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew.{tar.gz,yaml}" &&
    tar zxvf krew.tar.gz &&
    KREW=./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" &&
    "$KREW" install --manifest=krew.yaml --archive=krew.tar.gz &&
    "$KREW" update
    )
  3. .bashrc.zshrc 文件中添加以下内容将 $HOME/.krew/bin 目录添加到 PATH 环境变量。

  4. 运行 kubectl krew 验证命令是否运行正常。

    export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"

    其他运行环境请参考:https://krew.sigs.k8s.io/docs/user-guide/setup/install/

安装 kubectl ingress-nginx plugin

  1. 运行以下命令安装 kubectl ingress-nginx plugin

    kubectl krew install ingress-nginx
  2. 安装完成后,可通过以下命令查看插件安装是否正常

    kubectl ingress-nginx --help

    A kubectl plugin for inspecting your ingress-nginx deployments

    Usage:
    ingress-nginx [command]

    Available Commands:
    backends Inspect the dynamic backend information of an ingress-nginx instance
    certs Output the certificate data stored in an ingress-nginx pod
    conf Inspect the generated nginx.conf
    exec Execute a command inside an ingress-nginx pod
    general Inspect the other dynamic ingress-nginx information
    help Help about any command
    info Show information about the ingress-nginx service
    ingresses Provide a short summary of all of the ingress definitions
    lint Inspect kubernetes resources for possible issues
    logs Get the kubernetes logs for an ingress-nginx pod
    ssh ssh into a running ingress-nginx pod

    Flags:
    --as string Username to impersonate for the operation
    --as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
    --cache-dir string Default HTTP cache directory (default "/Users/hxl/.kube/http-cache")
    --certificate-authority string Path to a cert file for the certificate authority
    --client-certificate string Path to a client certificate file for TLS
    --client-key string Path to a client key file for TLS
    --cluster string The name of the kubeconfig cluster to use
    --context string The name of the kubeconfig context to use
    -h, --help help for ingress-nginx
    --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
    --kubeconfig string Path to the kubeconfig file to use for CLI requests.
    -n, --namespace string If present, the namespace scope for this CLI request
    --request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
    -s, --server string The address and port of the Kubernetes API server
    --tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
    --token string Bearer token for authentication to the API server
    --user string The name of the kubeconfig user to use

    Use "ingress-nginx [command] --help" for more information about a command.

kubectl ingress-nginx plugin 用法

注意: 因为 rancher 或 rke 创建的集群中,ingress 控制器是以 DaemonSet 的方式运行。kubectl ingress-nginx plugin 查看配置时需要指定资源,默认只支持 --deployment。在 rancher 或 rke 创建的 ingress 默认都有 app=ingress-nginx 标签,所以这里用标签来指定资源。

  • 查看 Nginx 配置

    kubectl ingress-nginx --kubeconfig=xxxx -n ingress-nginx -l app=ingress-nginx conf

    以上的命令将会输出全部规则的配置,可以通过指定域名来输出指定配置的配置。

    kubectl ingress-nginx --kubeconfig=xxxx -n ingress-nginx -l app=ingress-nginx conf --host <配置的域名>
  • 查看 backends

    kubectl ingress-nginx --kubeconfig=xxxx  -n ingress-nginx -l app=ingress-nginx backends

永久重定向状态码 (http-redirect-code)

ingress 中重定向的状态码默认是 308,某些情况下我们可能需要 301 状态码,可以按照以下方法配置。

全局配置

可通过在配置映射中添加 http-redirect-code=301 来修改全局重定向状态码,修改后所有 ingress 规则的重定向状态码都将是 301

参考链接:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#http-redirect-code

局部配置

如果只想某个域名使用 301 状态码,那可以编辑对应的 ingress 规则添加以下注释

nginx.ingress.kubernetes.io/permanent-redirect-code: '301' # 默认 308

参考链接:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#permanent-redirect-code

代理外部应用(域名(http、https)或 ip + 端口)

创建外部服务

假设有一个外部应用,是通过域名 123.com 进行访问。现在想在 ingress 中通过新的域名 abc.com 去代理这个外部应用。那么需要先把外部域名通过外部服务的方式引入 K8S 集群中,然后 ingress 去调用这个外部服务。

  1. 服务发现页面,添加 一条 DNS 记录(或者叫新建一个 SVC)

  2. DNS 记录配置详情

    • DNS 记录名称

      名称可以随意填写,但是不能以数字开头,不能大写

    • 命名空间

      DNS 记录所在的命名空间

    • 解析类型

      选择解析类型,可以选择外部域名或者外部 ip

    • 填写目标域名或者目标 ip (这里不用写端口)

    • 端口映射

      这个参数很重要,需要根据外部服务访问的真实端口来配置。比如你的服务访问是通过 http://123.com:9000 来访问的,那么这里就需要填写 9000 端口。如果是通过 http://123.com 或者 https://123.com 访问,80 或 443 端口也需要填写。

Ingress 规则创建

  1. 在负载均衡页面添加一条新的 ingress 规则。如下图,添加 目标后端 的时候先删除默认的后端规则,然后点击服务

  2. 因为只有选择 服务 此处才能选择之前创建的 DNS 记录

  3. 最后点击保存

http 域名或者 ip + 端口

编辑刚刚创建的 ingress 规则,在 标签/注释 中为 ingress 规则添加 annotations,通过 annotations 指定后端应用的访问地址。

nginx.ingress.kubernetes.io/upstream-vhost: 123.com 或者 ip+端口

https

对于外部服务为 https 访问又有两种情况,一种是权威的 ssl 证书,一种是自签名的 ssl 证书。不同类型需要添加不同的 annotations 配置。

  • 权威 ssl 证书

    nginx.ingress.kubernetes.io/upstream-vhost: 123.com
    nginx.ingress.kubernetes.io/secure-backends: "true"
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
  • 自签名 ssl 证书

    nginx.ingress.kubernetes.io/upstream-vhost: 123.com
    nginx.ingress.kubernetes.io/secure-backends: "true"
    nginx.ingress.kubernetes.io/proxy-ssl-verify: "off"
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS

外部服务后端重写

如果外部服务是以 http(s)://123.com/path 的 url 形式访问,那么需要为其配置后端重写才能保证能通过 abc.com 这种形式访问。

配置方法请参考 后端重写

后端重写

后端重写 主要有两种使用场景:

  1. 有多个后端应用,但是当前只有一个可用域名,那么需要通过 <单域名>/<Path> 的方式来区分。
  2. 多个应用通过子目录的方式部署在一个 web server 下,需要通过多个域名来访问应用。

单域名 + Path

如上图,可用配置多个 Path 来区分多个服务。 但是当访问 <单域名>/<Path> 的时候,可能会出现 404 错误。因为当访问 <单域名>/<Path> 的时候会是去后端服务页面中找 Path 路径,可能 Path 是随意设置的,后端服务页面并不存在此页面,所以会提示 404 错误。并且我们要求访问 <单域名>/<Path> 的时候是访问后端服务的根目录,而不是子目录,所以需要通过后端重写的方式将请求转发到根目录。

在 ingress 可通过配置以下注释达到预期要求:

nginx.ingress.kubernetes.io/rewrite-target: /

多域名 + Path

如果多个应用是以子目录的方式部署在同一个 web 服务器中,这种情况其实是可通过 <域名>/<Path> 的方式来访问的。但是有时候可能需要不加 Path 后缀,直接通过域名访问。这种需求也需要通过 后端重写 的方式来设置,其配置方法正好与 单域名 + Path 相反。

注意: 如果请求的资源不是全部在子站点中,那么页面重写过去之后,可能存在一些静态资源无法加载的问题,因此需要根据实际的应用架构来确定是否采用这种后端重写。

  1. 在 ingress 规则中添加以下注释来实现页面重写:

    nginx.ingress.kubernetes.io/rewrite-target: /test
  2. Path 处设置为 /(.*)

  3. 完整 ingress yaml 示例:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /test/$1
name: test-domain
namespace: default
spec:
rules:
- host: www.test.local
http:
paths:
- backend:
serviceName: ingress-541fa2c5687afb7ccb3c7c9a13fa7119
servicePort: 80
path: /(.*)

参考链接:https://kubernetes.github.io/ingress-nginx/examples/rewrite/

隐藏 Ingress - Nginx 版本号

Ingress 是内置 NGINX 来提供负载均衡服务,默认显示 nginx 版本号。为了安全有时候会要求关闭版本号显示,可通过修改配置映射来隐藏版本号。

在配置映射中设置:

  1. Rancher UI 配置 server-tokens=false
  2. YAML 配置 server-tokens: "false"

参考链接:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#server-tokens

自定义 http 和 https 端口

在 Rancher 部署的 K8S 集群中,默认部署了 ingress 控制器。ingress 控制器以 DaemonSet 类型部署,并且以 host 网络模式运行。ingress 控制器默认会监听 80443 两个端口来提供 web 服务,所以如果主机上原来已经有服务监听了 80 或者 443 端口,那么 ingress 控制器部署将会出现端口冲突。

根据部署方式的不同,大概有以下几种修改方式:

更新工作负载修改 http 和 https 端口

  1. 依次进入 目标集群|system 项目,在工作负载中找到 nginx-ingress-controller,点击右侧省略号菜单,选择编辑。

  2. 在配置详情页面中,点击右下角 显示高级选项,然后打开 命令 选项卡

  3. 在命令配置栏中添加配置参数,比如: --http-port=8880 --https-port=8443

RKE 配置文件修改

如果使用 rke 创建 K8S 集群,那么可以在 rke 配置文件中指定 ingress 的端口参数。

ingress:
provider: nginx
options:
map-hash-bucket-size: "128"
ssl-protocols: SSLv2
extra_args:
enable-ssl-passthrough: ""
http-port: 8880
https-port: 8443

Rancher 自定义集群

与 rke 集群相似,可以编辑集群的 YAML 配置文件,然后添加对应参数。

自定义 client_max_body_size 大小

编辑 ingress 规则,在注释中添加:

nginx.ingress.kubernetes.io/proxy-body-size: 32m

如果想全局配置 proxy-body-size 大小,则在配置映射文件中添加 proxy-body-size=32m

自定义 Proxy buffering 大小

  1. 默认情况下,ingress 配置中禁用 Proxy buffering 。所以需要配置以下设置开启:

    nginx.ingress.kubernetes.io/proxy-buffering: "on"

    如果想全局开启 Proxy buffering ,则在配置映射文件中添加 proxy-buffering=on

  2. 默认情况下,Proxy buffering 大小设置为 4k,可通过以下配置修改大小:

    nginx.ingress.kubernetes.io/proxy-buffer-size: "8k"

    如果想全局配置 Proxy buffering 大小,则在配置映射文件中设置 proxy-buffer-size=8k

开启 TLS/HTTPS

默认情况下,如果 ingress 规则对象入口启用了 TLS/HTTPS,则 ingress-controller 将使用 308 永久重定向将 HTTP 请求重定向到 HTTPS 请求。如果需修改 308 为 301,请参考:永久重定向状态码 (http-redirect-code)

某些情况下可能希望 http 和 https 同时使用,那么就需要禁止 TLS 自动重定向。可以在 ingress 规则中添加以下注释来禁止重定向:

nginx.ingress.kubernetes.io/ssl-redirect: "false"

如果想全局禁止 TLS 自动重定向,可以在配置映射文件中配置: ssl-redirect=false 来禁止。

记录客户端地址

跨域配置

nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers:"DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"

白名单

nginx.ingress.kubernetes.io/whitelist-source-range: 192.168.1.0/24,192.168.2.8

请求速率限制

nginx.ingress.kubernetes.io/limit-rps: '100'

websocket 配置

nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Upgrade "websocket";
proxy_set_header Connection "Upgrade";
nginx.ingress.kubernetes.io/proxy-read-timeout 3600;
nginx.ingress.kubernetes.io/proxy-send-timeout 3600;

自定义 header

全局配置 header

  1. 复制以下内容创建自定义 header ConfigMap 文件

    apiVersion: v1
    data:
    X-Different-Name: "true"
    X-Request-Start: t=${msec}
    X-Using-Nginx-Controller: "true"
    x-custom-headers: xxxxx
    kind: ConfigMap
    metadata:
    name: custom-headers
    namespace: ingress-nginx

    配置效果:

  2. system 项目|配置映射 下找到 nginx-configuration 配置映射并编辑它,添加如下配置:

    enable-underscores-in-headers=true
    proxy-set-headers=ingress-nginx/custom-headers

    配置效果:

  3. 注意:如果配置一直没有更新,则需要重启 ingress 控制器 Pod,以触发配置更新。

单个 ingress 规则配置自定义 header

  1. system 项目|配置映射 下找到 nginx-configuration 配置映射并编辑它,添加如下配置:

    enable-underscores-in-headers=true
  2. 编辑 ingress 规则的 YAML 配置,添加如下配置:

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
    more_set_headers "Hello: World";
    more_set_headers "Hello1: World1";

    配置效果:

自定义日志输出格式

更多参数参考

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#configuration-options/

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/