在Kubernetes中,服务和Pod的IP地址仅可以在集群网络内部使用,对于集群外的应用是不可见的。为了使外部的应用能够访问集群内的服务,在Kubernetes 目前 提供了以下几种方案:
这三种方案中,考虑到NodePort
是直接开放外部端口,这样需要管理所有服务开放的端口,跟我们原本使用k8s的初衷略有违背,我们初衷是希望对外是服务访问,对内可以不针对每个服务所在的服务器以及端口进行管理,在降低运维压力同时,实现负载均衡
,因此一般不选择这种方案实现对外暴露服务,而LoadBalancer
需要云端服务支持,就是一般是需要付费
,考虑成本也是不在参考范围里面的,因此最后的Ingress
这根稻草,在安全与成本
的方向的考虑,满足了大部分人的需求,基础部署参考:helm3.0部署nginx-ingress.
在kubernetes集群中,我们知道service和pod的ip仅在集群内部访问。如果外部应用要访问集群内的服务,集群外部的请求需要通过负载均衡转发到service在Node上暴露的NodePort上,然后再由kube-proxy组件将其转发给相关的pod。 而Ingress就是为进入集群的请求提供路由规则的集合,通俗点就是
提供外部访问集群的入口
,将外部的HTTP或者HTTPS请求转发到集群内部service
上。
Ingress代理的并不是pod的service,而是pod,之所以在配置的时候是配置的service,是为了通过service来获取所有pod的信息。
Ingress通常使用http://domain/path
的方式暴露服务,对于生产环境,是已经配置了一层Nginx代理,通过80/443
端口对外开放应用入口
具体访问原理如下:
当服务部署到k8s之后,能不能用原本的方案呢?
具体实现逻辑如下:
这个需要一个前提条件是由于是生产环境,域名是必须能够公网IP进行DNS解析,也就是Nginx-Ingress所在的服务器必须进行DNS解析才可以实现直接对外暴露服务,但是nginx-ingress是通过k8s部署,在正常情况下,我们都不会指定节点去部署,因为指定节点部署就可能会出现单点故障问题,且不能基于k8s进行动态分配服务器,也就是DNS解析这个除非全解析,不然不靠谱,鉴于时间问题以及风险问题,这种模式不考虑。
具体实现逻辑如下:
从图上面可以看到,相当于加了一层代理,只需要改变原有生成环境的反向代理服务地址就能把服务访问迁移到k8s的服务上面。这是一个相对比较合理跟成本较低的方案,在Nginx-Ingress这一层还是基于Ingress的规则统一开放k8s上面的应用服务,Nginx这一层反向代理Nginx-Ingress即可。
按照我们正常使用,nginx-ingress所在服务器集群式不开通外网,但是为了方便使用,我们通过externalIPs
将服务使用固定IP的方式对内网开放,其他服务/应用可以通过http/https://externalIPs/xxx
的方式即可访问nginx-ingress.
具体配置如下:
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 31314
- name: https
protocol: TCP
port: 443
targetPort: 443
nodePort: 30491
selector:
app: nginx-ingress
component: controller
release: nginx-ingress
clusterIP: 10.100.221.205
type: LoadBalancer
externalIPs:
- 192.168.1.123
sessionAffinity: None
externalTrafficPolicy: Cluster
编写一个Ingress规则,将服务通过ingress开放出去
注意这里跟普通的ingress规则差异的点在于spec.rules.host
这个选项,一般我们这个选项会填写我们的域名如www.test.com
,但是这里我们采用方案二
,因此不需要填写这个选项,按照以下的配置,访问test服务的时候,只需要通过我们上一步填写的IP即可访问,具体路径:http://192.168.1.123/test
,这样写就可以访问test服务,实现nginx-ingress通过统一IP访问服务
。我们把上述的服务地址配置到上游的nginx代理即可。
spec:
rules:
- http:
paths:
- path: /test
backend:
serviceName: test
servicePort: 8080
如果只有上面的操作,访问http://domain/path
的时候,页面会跳转不信任链接
,,报错308
原因是当我们的ingress规则不填写host
的时候,ingress-nginx默认要求https
,所以这时会遇到访问总是308跳转的问题。
针对这个问题,只需要修改nginx-ingress的参数如下:
打卡nginx-ingress的configmap:nginx-ingress-controller
设置 ssl-redirect: 'false'
data:
compute-full-forwarded-for: 'true'
enable-vts-status: 'false'
forwarded-for-header: X-Forwarded-For
ssl-redirect: 'false'
use-forwarded-headers: 'true'