k8s随笔 – nginx-ingress配置原理

如题,今天剖析一下nginx-ingress的配置原理,帮助大家快速搞清楚整体脉络。

几个概念

nginx-ingress作为K8S集群对外的流量入口,充当K8S集群内各个service的反向代理。

  • ingress:K8S内置资源类型,用于配置应用Domain与后端service的关联关系,提供给ingress-controller使用。
  • nginx-ingress-controller:ingress-controller的其中一种实现,利用openresty开发,基于deployments部署;其监听ingress资源变化,根据ingress配置生成若干server段,每一个server段对应一个应用的Domain,反向代理到对应service的若干POD,所有配置均生成到nginx.conf并自动热加载。

前提

我已经部署了1个项目,并且创建了其service:

该项目监听在809端口,内部利用nginx提供了5个不同域名的服务。

创建nginx-ingress-controller

这个YAML的目的就是创建nginx-ingress-controller的deployment。

我们需要关注nginx-ingress-controller的启动参数:

这个deployment跑在ingress-nginx namespace。

  • –configmap:让其加载ingress-nginx/nginx-configuration这个configmap配置文件,从而允许我们修改nginx的http段的各种配置项覆盖nginx的默认值:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/,这就是官方说的configmap方式配置nginx。
  • –tcp-services-configmap:又是一个configmap,因为ingress只是拿来提供http/https反向代理用的概念,而nginx额外提供了4层TCP反向代理的能力,这需要通过单独的configmap配置,而不是用ingress对象配置,具体参考:https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services/
  • –udp-services-configmap:nginx提供udp反向代理能力,也是通过独立的configmap配置。
  • –publish-service:配置为了ingress-nginx/ingress-nginx对象,意思就是指定ingress-controller对外暴露用的service的名字,我们稍后创建nginx-ingress的service时就得用这个名字,否则nginx-ingress就会因为报错。这个配置的意义在于,在describe ingress对象的时候可以通过查看这个service来打印出nginx-ingress的POD列表。
  • –annotations-prefix:刚才说过ingress是配置nginx.conf中的server的,ingress可以配置annotations来修改server段中的各种配置项,但是它们必须遵循这个前缀才能被nginx-ingress识别。

所有的命令行参数在这里查看:https://kubernetes.github.io/ingress-nginx/user-guide/cli-arguments/

我个人认为值得关注的其他参数包括:

  • –ingress-class:默认是nginx,也就是说这个nginx-ingress只会响应annotation中ingress.class=nginx的ingress对象。如果我们部署了不同的nginx-ingress,那么就需要通过class来隔离ingress配置。

创建ingress

接下来就是配置反向代理了,看看就明白了:

上述ingress对象,配置了5个Domain,全部反向代理到了zhongce-service。

这里我们关注到annotations配置了class,从而归属于之前部署的那个nginx-ingress-controller。

可以通过annotations配置这5个server段的详细参数,比如:proxy_connect_timeout,详细参见:https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md#custom-timeouts,这些annotations只有使用nginx-ingress-controller启动时指定的前缀nginx.ingress.kubernetes.io才会被nginx-ingress-controller识别。

讲到这里,我们应该做一个总结:

1)ingress的目标就是让我们不需要手动维护nginx配置。

2)修改nginx配置的方法需要区分对待:1,server段(也就是虚拟主机)是通过ingress配置的; 2,非server段(http段以及http段之外的配置项,例如:worker数量)是通过configmap配置的。

如果我们有更多的domain要配置,那么就创建更多的Ingress对象好了,不需要都写在一个yaml中。

特别注意,ingress的命名空间必须与它反向代理的service所处的命名空间一致。

nginx-ingress的service

为了让nginx-ingress暴露到K8S集群外,可以采用nodePort service的方式实现:

这里service的label selector是依据nginx-ingress-controller的label配置的,从而筛选出nginx-ingress-controller的POD。

对外暴露了2个nodePort,一个是http的80端口,一个是https的443端口,流量一旦进入到nginx-ingress就可以proxy到各个内部service完成调用了。

特别注意,这个service必须和nginx-ingress-controller的namespace一致,默认安装就是ingress-nginx。

配置文件

在nginx-ingress的yaml里已经创建了configmap,我们只需要在里面配置key-value对即可对nginx进行配置修改:

问题

基于nodePort暴露的ingress,其可以通过K8S集群的任意机器的nodePort端口访问到,因此在我尝试执行kubectl get ingress -o wide的时候,address入口地址显式为空:

有Issue提到在使用nodePort的情况下就是如此:https://github.com/kubernetes/ingress-nginx/issues/1467

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~