01
写在之前
今天记录一下Nginx Ingress的常用参数配置,如果你还没有安装过,可以参考之前学习记录的文档链接:同一kubernetes部署多个Nginx Ingress Controller。
众所周知,Nginx 参数很多,但在Nginx Ingress上面如何配置呢,安装完后,都是使用的默认参数,这些参数如果想修改,应该如何修改呢?这里整理下如何修改Nginx Ingress默认参数配置,清晰并快速掌握配置Nginx Ingress的整体脉络,记录一下。
其实Ingress存在的本质原因,是不想让我们直接修改Nginx Ingress Controller,或者说只能通过Ingress规则去修改,但往往事与愿违,很多默认的参数不能满足我们的需求。
02
实例需求
手机APP上面访问服务时,每次请求都带有一个traceID,如果请求Header中没有traceID信息的话,在APP网关(APP接入层 Nginx)上面通过lua或第三方插件自动生成,说到这里,大家应该都清楚了,这是为链路追踪而设计的,之前我们在Nginx服务器上面,通过获取Header头信息,然后再proxy_set_header到上游服务器,一层一层的传递下去,在kubernetes上面,应该如何实现呢?
默认情况下Nginx Ingress配置不支持自定义的Heaer,需要简单配置,然后把此信息以proxy_set_header的形式传递到上游服务器,最近通过实验,做下记录;
03
实例架构图
从上面图中,我们可以看出,Nginx Ingress Controller工作原理,它是以deployment资源类型部署的,主动监听ingress 资源的变化,ingress发现变化后,他立即生成若干server片段,每个server片段反向代理到ingress规则对应service后面的Pod上面 ,所有配置最终生成到nginx.conf并自动加载,不需要人为重启(主要是因为nginx ingress甚于openresty开发的)。
04
Nginx Ingress 参数说明
下面是nginx ingress controller的部分配置
containers:
- args:
- nginx-ingress-controller
- --default-backend-service=kubeops/outroute-nginx-ingress-default-backend
- --election-id=ingress-controller-leader
- --ingress-class=outroute
- --configmap=kubeops/outroute-nginx-ingress-controller
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
image: hub.k8s.vip/kubernetes/nginx-ingress-controller-timezone8:0.28.0
imagePullPolicy: IfNotPresent复制
–-configmap:kubeops/outroute-nginx-ingress-controller,这是官方还有很多网上文档说的,使用configmap的方式配置nginx,这里要注意一下,这里只是允许配置http段的各种配置项,configmap配置应用后,就会覆盖默认的参数值;官方参数链接:https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/configmap.md,如日志格式、worker数目、keepalive参数等等;
--ingress-class=outroute,不同的nginx-ingress就是通过此参数进行隔离的,这个是kubernetes的内置资源,或者说是集群资源,同一集群部署多个隔离的nginx ingress controller就是通过此参数区分;
默认情况下nginx ingress只是提供http/https反向代理的功能,但是我们知道nginx目前已经支持了tcp/udp代理,那么nginx ingress应该如何支持呢?其实也是通过configmap的形式,
–tcp-services-configmap、–udp-services-configmap,具体配置可参考官网:https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/exposing-tcp-udp-services.md
还有很多默认参数,比如–-annotations-prefix=nginx.ingress.kubernetes.io,这个参数大家需要了解一下,刚才简单提到了nginx ingress controller工作原理,ingress规则把定义的配置生成到server段中,如果我们想修改server段的内容怎么办呢?就需要在定义ingress时通过配置annotations来修改各种配置,它们必须遵循这个前缀才能被nginx-ingress识别;
定义ingress规则时annotations可以修改的参数有哪些呢?官方链接:https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md,你可以定义proxy-connect-timeout、proxy-send-timeout、proxy-set-header等等;
通过分析nginx ingress配置,我们得出一个结论,如果你想修改的是http段的默认参数,你可以通过configmap的形式修改,如果你修改的是server段的默认参数,你需要通过定义ingress规则时,通过annotations配置;
05
traceID配置
配置Nginx Ingress
这里简单修改下 nginx ingress 日志格式,根据上面的结论,nginx日志格式需要定义在http段,所以我们需要修改--configmap=kubeops/outroute-nginx-ingress-controller这里的configmap,我们定义一个outroute_log.yaml,内容如下
apiVersion: v1
data:
worker-processes: 'auto'
log-format-upstream: '$time_iso8601 $remote_addr $http_host $scheme $request_method $uri $request_id $status $upstream_addr $upstream_status $request_time $upstream_response_time $upstream_connect_time $upstream_header_time $req_id '
http-snippet: |
map $http_trace_header_id $req_id {
default $http_trace_header_id;
"" $request_id;
}
kind: ConfigMap
metadata:
name: 'outroute-nginx-ingress-controller'
namespace: 'kubeops'复制
这里我们除了修改了下日志格式,我们还定义了一个http-snippet片段,主要功能是把trace_header_id取到,如果为空,使用request_id,熟悉nginx的同学,这个很简单;
应用配置
[root@master01 modiy_logformat]# kubectl apply -f outroute_log.yaml
configmap/outroute-nginx-ingress-controller unchanged
[root@master01 modiy_logformat]#复制
验证配置
...
log_format upstreaminfo '$time_iso8601 $remote_addr $http_host $scheme $request_method $uri $request_id $status $upstream_addr $upstream_status $request_time $upstream_response_time $upstream_connect_time $upstream_header_time $req_id ';
...
map $http_trace_header_id $req_id {
default $http_trace_header_id;
"" $request_id;
}
....复制
定义Ingress规则
我们创建一个Demo,这个Demo是使用nginx,方便打出header信息,日志格式的最后加上'$http_trace_header_id';
apiVersion: apps/v1
kind: Deployment
metadata:
name: test3-deployment-nginx
namespace: test
spec:
replicas: 1
selector:
matchLabels:
run: test3-deployment-nginx
template:
metadata:
labels:
run: test3-deployment-nginx
spec:
containers:
- name: test3-deployment-nginx
image: hub.k8s.vip/kubernetes/nginx-header-test:v1
ports:
- containerPort: 80
command: ["/bin/sh","-c","/data/nginx/sbin/nginx && tail -f dev/null"]
---
apiVersion: v1
kind: Service
metadata:
name: test3-svc-nginx
namespace: test
spec:
selector:
run: test3-deployment-nginx
type: ClusterIP
ports:
- name: svc-nginx-port
port: 80
targetPort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: default-ingress-nginx5
namespace: test
annotations:
kubernetes.io/ingress.class: "outroute"
nginx.ingress.kubernetes.io/proxy-body-size: 1000m
nginx.ingress.kubernetes.io/rewrite-target:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
add_header trace-header-id $req_id;
proxy_set_header trace-header-id $req_id;
spec:
rules:
- host: e.k8s.vip
http:
paths:
- path:
backend:
serviceName: test3-svc-nginx
servicePort: svc-nginx-port复制
上面创建的deployment、service、ingress,配置都很简单,不做说明,这里重点说下
nginx.ingress.kubernetes.io/configuration-snippet: |
add_header trace-header-id $req_id;
proxy_set_header trace-header-id $req_id;
根据前面的总结,知道server块中的配置,需要在Ingress规则中配置,这里我们定义了add_header(向客户端Header中添加 trace-header-id),也定义了proxy_set_header(向上游服务中添加trace-header-id);
不过这里再次强制一点:ingress的namespace必须与它反向代理service所处的namespace一致。
再次验证配置
进入nginx ingress pod,查看e.k8s.vip片段,发现这两个参数已经修改
add_header trace-header-id $req_id;
proxy_set_header trace-header-id $req_id;复制
06
验证traceID
[root@master01 ~]# curl -H "Host: e.k8s.vip" -H "trace-header-id: 123456678" http://master01/ -i
HTTP/1.1 200 OK
Server: nginx/1.17.7
Date: Sat, 15 Feb 2020 12:56:51 GMT
Content-Type: application/octet-stream
Content-Length: 10
Connection: keep-alive
trace-header-id: 123456678
BBBBBBBBBB[root@master01 ~]#
[root@master01 ~]#
[root@master01 ~]# curl -H "Host: e.k8s.vip" http://master01/ -i
HTTP/1.1 200 OK
Server: nginx/1.17.7
Date: Sat, 15 Feb 2020 12:57:10 GMT
Content-Type: application/octet-stream
Content-Length: 10
Connection: keep-alive
trace-header-id: 3401f0e4808ed5a12cd0840beb2e9643
BBBBBBBBBB[root@master01 ~]#
[root@master01 ~]#复制
第一次访问,我们指定了trace-header-id: 123456678,第二次使用了ingress controller自动产生的,现在通过日志查看验证下,日志字段最后一个为trace-header-id
[root@master01 ~]# kubectl logs --tail=2 outroute-nginx-ingress-controller-59f548d7d-g7fwc -n kubeops
2020-02-15T20:56:51+08:00 100.73.16.108 e.k8s.vip http GET a68b2b8e3b770345654de57caf2e2707 200 172.19.184.6:80 200 0.001 0.000 0.000 0.000 123456678
2020-02-15T20:57:10+08:00 100.73.16.108 e.k8s.vip http GET 3401f0e4808ed5a12cd0840beb2e9643 200 172.19.184.6:80 200 0.001 0.001 0.001 0.001 3401f0e4808ed5a12cd0840beb2e9643
[root@master01 ~]#复制
通过查看最后两行日志中最后字段是123456678,3401f0e4808ed5a12cd0840beb2e9643,与访问时一致;
现在我们再去查看下应用Pod上面的日志,是否有这两个trace-header-id
[root@master01 ~]# kubectl exec -it test3-deployment-nginx-8ddffb97b-9j87d -n test bin/bash
[root@test3-deployment-nginx-8ddffb97b-9j87d ]# tail -n 2 data/logs/access.log
e.k8s.vip 100.73.16.108 [15/Feb/2020:12:56:51 +0000] "GET HTTP/1.1" 200 10 "-" "curl/7.29.0" "100.73.16.108" "-" 0.000 - - - 123456678
e.k8s.vip 100.73.16.108 [15/Feb/2020:12:57:10 +0000] "GET HTTP/1.1" 200 10 "-" "curl/7.29.0" "100.73.16.108" "-" 0.000 - - - 3401f0e4808ed5a12cd0840beb2e9643
[root@test3-deployment-nginx-8ddffb97b-9j87d /]#复制
通过查看trace-header-id与客户端一致,说明traceID通过ingress已经正常传到后端(上游)服务器,这样一来,就可以把传统HTTP服务的整个链路串起来。
07
总结
通过以上实例,自定义了日志格式,手机APP上面的header信息经过ingress传到后端应用Pod中,此过程相对简单,这里需要理解Ingress配置的要点,多查官方文档,其实很容易就可以实现。
您的关注是我写作的动力
往期分享