系列目录html
向外网暴露集群内服务,以使客户端可以访问,有如下几种方法,本文重点描述Ingress。node
LoadBalancer通常由云服务供应商提供或者用户自定义,运行在集群以外。在建立service时为其配置LoadBalancer相关参数,当从外网访问集群内servcie时,用户直接链接到LoadBalancer服务器,LoadBalancer服务器再将流量转发到集群内service。Loadbalancer配置及使用方法与各云服务供应商有关,本文不详细描述。nginx
这种方式要求集群中部分节点有被外网访问的能力。Kubernetes为每一个NodePort类型的服务在集群中的每一个节点上分配至少一个主机网络端口号。客户经过能被外网访问的节点IP加上节点端口的方式访问服务。大多数状况下不会经过这种方式向集群外暴露服务,缘由有四。git
其一:大多状况下,为了安全起见,集群中的节点位于彻底内网环境中,不该该有被外网直接访问的能力。通常外网访问集群中的节点都是经过边界服务器如网关、跳板等,而这种边界服务器须要经过各类方式进行安全加固。github
其二:若是集群内节点能够从外网直接访问的话,则会将集群内节点地址、服务名称、端口号等信息直接暴露在外,很是不安全。api
其三:服务端口号通常由系统自动分配,并不是固定,而服务名称也可能发生变动,此时外部客户端须要跟踪变动并修改,属于重试耦合。安全
其四:这种方式,每一个服务至少向外网暴露一个端口号,当服务不少时不易于管理。服务器
Ingress不是某种产品、组件的名称,它应该是kubernetes向集群外暴露服务的一种思路、技术,用户彻底能够根据这种思路提供本身的Ingress实现,固然kubernetes提供了默认Ingress实现还有其它第三方实现,通常无需本身开发。它的思路是这样的,首先在集群内运行一个服务或者pod也能够是容器,不论是什么它至少应该有一个外网能够访问的IP,至少向外网开放一个端口号,让它充当反向代理服务器。当外网想要访问集群内service时,只需访问这个反向代理服务器并指定相关参数,代理服务器根据请求参数并结合内部规则,将请求转发到service。这种思路与LoadBalancer的不一样之处是它就位于集群内,而LoadBalancer位于集群外。与NodePort的不一样之处是集群只向外暴露一个服务或者pod等,而NodePort是暴露所有service。网络
Kubernetes用nginx实现反向代理服务器,称为Ingress Controller,是pod类型资源。同时提供了Ingress类型对象,经过建立Ingress对象配置nginx反向代理服务器的转发规则。Nginx反向代理服务器收到来自外网的请求后,用请求的URL地址、请求头字段区别不一样service,而后转发请求。app
在Kubernetes中,Ingress Controller典型是pod类型资源,其部署方式与普通pod相同,经过Deployment、DaemonSet等副本控制器部署,其中更值推荐的是DaemonSet方式。Ingress Controller须要部署在具有连通外网能力的节点上,首先在目标节点打上Ingress Controller专用标签,而后在DaemonSet的配置文件中配置节点选择器选中此类标签,控制pod实例能够部署的节点,经过为节点增减相关标签控制Ingress Controller的pod实例个数。Ingress Controller通常占用两个节点主机端口,http用80,https用443。详细参考:这里。外网经过http://节点外网ip:80/...或者https://节点外网ip:80/...就能够访问内部服务了,当前首先须要建立Ingress对象配置访问策略。
本节经过建立各类Ingress对象,展现Ingress的各类典型用法。
配置文件:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test-ingress spec: backend: serviceName: testsvc servicePort: 80
而后经过kubectl create -f
建立对象,这同建立通常对象并无不少区别,前面已经屡次提到过,这里再也不详细描述
查看对象:
$ kubectl get ing NAME RULE BACKEND ADDRESS test-ingress - testsvc:80 107.178.254.228
以上配置中没有具体的rule,因此诸如http(s)://107.178.254.228/xxx之类的请求都转发到testsvc的80端口。
假如要实现如下目标:
foo.bar.com -> 178.91.123.132 -> / foo s1:80 / bar s2:80
其中foo.bar.com是http请求体头部中的host字段,178.91.123.132是Ingress Controller外网地址,当请求路径与/foo匹配时转发到s1服务的80端口,当与/bar匹配时转发到s2服务的80端口,其最核心逻辑是用URL区分不一样服务。
配置以下:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: foo.bar.com http: paths: - path: /foo backend: serviceName: s1 servicePort: 80 - path: /bar backend: serviceName: s2 servicePort: 80
查看对象:
$ kubectl get ing NAME RULE BACKEND ADDRESS test - foo.bar.com /foo s1:80 /bar s2:80
实现以下目录:
foo.bar.com --| |-> foo.bar.com s1:80 | 178.91.123.132 | bar.foo.com --| |-> bar.foo.com s2:8
这种方式的核心逻辑是用http请求中的host字段区分不一样服务,而不是URL。如host: foo.bar.com的请求被转发到s1服务80端口,如host: bar.foo.com的请求被转发到s2服务80端口。
配置:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test spec: rules: - host: foo.bar.com http: paths: - backend: serviceName: s1 servicePort: 80 - host: bar.foo.com http: paths: - backend: serviceName: s2 servicePort: 80
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test spec: rules: - host: foo.bar.com http: paths: - backend: serviceName: s1 servicePort: 80 - host: bar.foo.com http: paths: - backend: serviceName: s2 servicePort: 80
利用Secret类型对象为Ingress Controller提供私钥及证书,对通讯链路加密。
Secret配置:
apiVersion: v1 data: tls.crt: base64 encoded cert tls.key: base64 encoded key kind: Secret metadata: name: testsecret namespace: default type: Secret
在Ingress对象中引用
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: no-rules-map spec: tls: - secretName: testsecret backend: serviceName: s1 servicePort: 80
使用kubectl edit命令编辑Ingress实时对象:
$ kubectl get ing NAME RULE BACKEND ADDRESS test - 178.91.123.132 foo.bar.com /foo s1:80 $ kubectl edit ing test
在弹出的编辑器中修改:
spec: rules: - host: foo.bar.com http: paths: - backend: serviceName: s1 servicePort: 80 path: /foo - host: bar.baz.com http: paths: - backend: serviceName: s2 servicePort: 80 path: /foo ..
保存关稍后确认更新:
$ kubectl get ing NAME RULE BACKEND ADDRESS test - 178.91.123.132 foo.bar.com /foo s1:80 bar.baz.com /foo s2:80
参考:
$ kubectl get ing NAME RULE BACKEND ADDRESS test - 178.91.123.132 foo.bar.com /foo s1:80 bar.baz.com /foo s2:80
问题现场:
配置好Ingress以后能够经过Ingress正常访问系统,可是输入用户名密码以后登录失败。可是经过NodePort暴露服务时能够正常访问和登陆。接下来进过调试发现是在获取用户信息时出错,没法从Request header中取到自定义的用户信息字段。
参考此文章发现,NginX默认会将用户自定义的header过滤掉,除非开启 underscores_in_headers ,通过测试,在NginX中开启 underscores_in_headers 以后系统登陆正常。那么如何在Ingress-NginX中开启此项呢:
kind: ConfigMap apiVersion: v1 metadata: name: nginx-configuration namespace: ingress-nginx labels: app: ingress-nginx data: enable-underscores-in-headers: "true"