文章目录
- ingress-nginx 的模板解读
- server 段
- SERVER template
- 测试修改 ingress-nginx template
- 测试访问 ingress-nginx 的静态资源
- version: nginx-ingress-controller:0.29.0
ingress-nginx 的模板解读
本文简单介绍了 ingress-nginx template,并稍做修改,像原生一样使用 ingress-nginx 来处理静态资源的请求。
根据Custom NGINX template中的说明,其模板位于 /etc/nginx/template/nginx.tmpl
。
使用 kubectl cp
将其cp到外面进行查看。
server 段
# server 段中使用了 template 语句,所有的虚拟主机都是用 SERVER 模板生成的
{{ range $server := $servers }}
...
{{ template "SERVER" serverConfig $all $server }}
...
{{ end}}
# 其中 serverConfig 是一个函数在 internal/ingress/controller/template/template.go 中
"serverConfig": func(all config.TemplateConfig, server *ingress.Server) interface{} {
return struct{ First, Second interface{} }{all, server}
}
# 函数的作用就是把 $all $server 变成一个结构体,分别对应 First, Second
# 所以在 {{ define "SERVER" }} 中的前两行也只是得到 $all $server 这两个值
{{ $all := .First }}
{{ $server := .Second }}
全局变量 $all
和 $servers
# all 就是 .
{{ $all := . }}
# $server 是遍历 $servers 的
{{ range $server := $servers }}
# $servers 是 .Servers
{{ $servers := .Servers }}
SERVER template
# SERVER 开始 775 行,
# 这里的 path 是遍历 server.Locations ,即使没有 / 时也会自动加上,这个是实践出来的, 而其他的 location 就是 ingress 中的 path 了, 每一个 host 会生成一个虚拟主机的配置,即一个 server 段
{{ range $location := $server.Locations }}
...
{{ $path := buildLocation $location $enforceRegex }}
...
location {{ $path }}
...
{{ end }}
测试修改 ingress-nginx template
现在的目的是修改 location {{ $path }}
处,为其增加一个判断,如果 nginx.ingress.kubernetes.io/server-snippet
中有 location / {}
的配置时,就跳过 location /
的生成。这样可以使用自己指定的 location /
,就可以实现 ingress-nginx
处理静态请求了。
要不然的话,使用 nginx.ingress.kubernetes.io/app-root: /test
是生成一个 302 的跳转:
如创建ingress资源如下:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
labels:
app: test1
env: test
tier: frontend
name: test1
namespace: default
annotations:
nginx.ingress.kubernetes.io/server-alias: test2.mytest.com
# 这里使用此注释指向 /test1
nginx.ingress.kubernetes.io/app-root: /test1/
nginx.ingress.kubernetes.io/server-snippet: |
listen 8032;
# 这里定义了静态资源的location
location /test1 {
root /data/apps/opt/web;
index index.html;
}
spec:
rules:
- host: test1.mytest.com
http:
paths:
- backend:
serviceName: sample-app
servicePort: 8080
path: /sample
生成的nginx配置如下:
# SERVER template 中的定义
if ($uri = /) {
return 302 {{ $location.Rewrite.AppRoot }};
}
# 渲染后的结果
if ($uri = /) {
return 302 $scheme://$http_host/test1/;
}
访问效果如下:
# curl -i -H 'host: test1.mytest.com' http://10.111.32.9
HTTP/1.1 302 Moved Temporarily
Date: Mon, 28 Sep 2020 05:30:13 GMT
Content-Type: text/html
Content-Length: 138
Connection: keep-alive
Location: http://test1.mytest.com/test1/
HTTP/1.1 200 OK
Server: nginx/1.17.8
Date: Mon, 28 Sep 2020 05:30:13 GMT
Content-Type: text/html
Content-Length: 15
Last-Modified: Mon, 28 Sep 2020 04:45:25 GMT
Connection: keep-alive
ETag: "5f716a65-f"
Accept-Ranges: bytes
<h1>test1</h1>
或者自己使用 rewrite 生成一个规则,也都是类似的情况,反正你的 /
不能直接处理静态请求。
其默认加载的函数中有 contains: strings.Contains
, 但是这个函数并不完全准确,比如说 location / {
中多一个空格的话,就会检测失败。
- 如果
location / {
中间的空格多了,是不行的 - 这种判断太粗糙了,如果是
# location /
也是会被匹配到的,然而实际上这是注释的
在 location 前添加判断
{{ if contains $server.ServerSnippet "location / {" }}
{{ if eq $path "/" }}
{{ $path = "/nolocation" }}
{{ end }}
{{ end }}
location {{ $path }} {
...
}
这样过后,如果有如下的ingress资源,那么就可以正常的处理 /
的请求了(静态资源需要自己预先挂载)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
labels:
app: test1
env: test
tier: frontend
name: test1
namespace: default
annotations:
nginx.ingress.kubernetes.io/server-alias: test2.mytest.com
#nginx.ingress.kubernetes.io/app-root: /test1
nginx.ingress.kubernetes.io/server-snippet: |
listen 8032;
location / {
root /data/apps/opt/web;
index index.html;
}
spec:
rules:
- host: test1.mytest.com
http:
paths:
- backend:
serviceName: sample-app
servicePort: 8080
path: /sample
测试访问 ingress-nginx 的静态资源
# 使用虚拟主机
# curl -i -H 'host: test1.mytest.com' http://10.111.32.9
HTTP/1.1 200 OK
Server: nginx/1.17.8
Date: Mon, 28 Sep 2020 05:59:13 GMT
Content-Type: text/html
Content-Length: 15
Last-Modified: Mon, 28 Sep 2020 04:45:25 GMT
Connection: keep-alive
ETag: "5f716a65-f"
Accept-Ranges: bytes
<h1>test1</h1>
# 使用端口
# curl -i http://10.111.32.9:8032
HTTP/1.1 200 OK
Server: nginx/1.17.8
Date: Mon, 28 Sep 2020 05:59:21 GMT
Content-Type: text/html
Content-Length: 15
Last-Modified: Mon, 28 Sep 2020 04:45:25 GMT
Connection: keep-alive
ETag: "5f716a65-f"
Accept-Ranges: bytes
<h1>test1</h1>
参考
- : K8S 源码探秘 之 nginx-ingress 工作原理分析
- https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/custom-template/ : Custom NGINX template