Nginx Ingress的使用
Table of Contents
Kubernetes 暴露内部服务给外部使用的方式有三种:LoadBlancer Service、NodePort Service、Ingress
Ingress解决了什么问题
暴露k8s内部服务给外部使用会面临如下问题:
- pod IP动态变化的问题
Pod的IP是会动态变化的,那么如何把这个动态的Pod IP暴露出去?
这里借助于Service机制,以label的形式选定一组带有指定标签的Pod,并监控和自动负载他们的 Pod IP,向外只需要暴露Service IP即可;
这就是NodePort模式:即在每个节点上开起一个端口,然后转发到内部Pod IP上。
- 端口资源有限
使用NodePort模式的一个缺陷在于一个主机节点的端口资源是有限的,不适用于服务数量多的情况。
所以解决思路是:使用nginx在前端监听一个端口,然后按照域名(svc)向后转发。简单的实现就是使用DaemonSet在每个node上监听80端口,然后写好规则,因为 Nginx外面绑定了宿主机80端口(就像 NodePort),本身又在集群内,那么向后直接转发到相应Service IP就行了。
相当于Nginx充当k8s集群内外交互的桥梁。
- 域名变化和转发规则动态更新的问题
每次有新服务加入怎么改 Nginx 配置? 不可能每次都手工更改吧?
Ingress就是为解决这个问题而产生的。
原来需要改Nginx配置,然后配置各种域名对应哪个Service,现在把这个动作抽象出来,变成一个Ingress对象,你可以用yaml创建,每次不要去改Nginx了,直接改yaml文件,然后创建/更新即可。
通过创建/更新yaml来实现Nginx转发规则的更新。
Ingress的组成
Ingress由两部分组成:Ingress Controller 和 Ingress(此处指的是k8s的一种资源ingress)。
资源ingress定义了路径到k8s集群service的一种映射关系,即流量转发规则。
从而实现,外部用户只需访问ingress中定义的路径即可访问真正的pod应用。(ingress定义的路径–>service:port–>pod:port)
Ingress Controoler通过与Kubernetes API的交互,动态的去感知集群中Ingress规则的变化,然后读取它,按照固定模板生成一段Nginx 配置,再写到 Nginx Pod里,最后reload一下。
Kubernetes已经将Nginx与Ingress Controller合并为一个组件,所以只需要部署Ingress Controller即可
Ingress搭建
- 首先搭建好希望对外提供的业务服务,我们这里搭建的是一个etcd的集群, 可以看到其中一个节点的service name是
pod1,访问端口为2379
1 | [root@fqhnode01 yaml]# kubectl get pod |
可以发现,此时etcd集群是可以通过service IP来进行访问的。
- 搭建default-http-backend,定义Nginx不能正确转发时使用的后端,有如404 Not Found等页面。其中default-http-backend.yaml内容如下所示:
1 | apiVersion: extensions/v1beta1 |
- 搭建ingress controller,其中nginx-ingress-controller.yaml内容如下所示:
1 | apiVersion: extensions/v1beta1 |
注意--apiserver-host需要填apiserver运行的物理主机的IP地址
- 搭建Ingress,即声明域名到后面service的映射关系。my-ingress.yaml内容如下所示:
1 | apiVersion: extensions/v1beta1 |
需要注意的是namespace: default这个是和前面业务etcd集群一样的;而host: fqhnode这个则是host物理主机的域名;最后的serviceName 和 servicePort则是我们希望访问的service。
那么理论上,我们现在可以通过curl fqhnode/default/pod1/来访问之前搭建的etcd集群业务。
- 效果如下
1 | [root@fqhnode01 ingress]# curl fqhnode/default/pod1/v2/members |
- apply一下ingress.yaml,更改其中的path路径
1 | apiVersion: extensions/v1beta1 |
对应的访问方式是curl fqhnode/myetcd/v2/members
最后要说的是,如果需要在k8s集群外部访问的话,只需要在外部的客户端主机上/etc/hosts添加一个域名192.168.56.101 fqhnode即可。
通常可以使用对外使用多个域名,但后面用的都是同一个IP。
1 | foo.bar.com --| |-> foo.bar.com s1:80 |