定义
官方定义:管理外部请求(如典型的Http)对集群内服务访问的API对象
Ingress提供了负载均衡、SSL中断以及虚拟域名的服务
什么是Ingress
Ingress对外暴露Http和Https的路由,使得外部服务能够访问集群内的服务。路由规则则可以被定义Ingress的资源中。
Ingress流量转发示意图
Ingress能够为集群内服务提供外部可达的URLs,负载均衡控制,SSL/TSL的终端,以及基于名字的虚拟域名。而Ingress Controller则负责Ingress的实现,通常采用一种负载均衡器来实现,但也能够被用于配置边缘路由(edge router)或者前端路由。
Ingress不会暴露任意的端口和协议,通常情况下,在暴露除Http和Https协议外的服务时候往往采用类型为NodePort或者LoadBalancer的服务。
Ingress资源
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
上面的代码块为Ingress的一个最小化实现,可以看到一共由apiVersion、kind、metadata、spec组成。此外,Ingress的名字必须为一个合法的DNS子域名。Ingress采用annotation来打通Ingress Controller,一般的配置都写在annotation中被Ingress Controller解读。如上述代码的"nginx.ingress.kubernetes.io/rewrite-target: /",但是不同的Ingress Controller支持的annotation也不尽相同。
Ingress的spec部分包含了所有随负载均衡器或者代理服务器的配置薪资。最重要的是该部分规定了外部请求的路由规则。Ingress资源仅仅支持Http或Https的直接流量。
如果ingressClassName缺失了,则会采用默认的Ingress Class。
此外一些Ingress Controller能够在不定义默认IngressClass的情况下工作。如Ingress-Nginx支持一个叫做--watch-ingress-without-class的盘配置。尽管如此,官方仍然建议还是定义一个默认的IngressClass。
Ingress Rules
一条Http(s)的路由规则包含以下三类配置:
- 可供的域名。当不配置域名时,rule将对所有访问Ingress IP的Http(s)请求生效,而当配置了域名(如*.abc.com),rule将匹配请求域名。
- 一个路径列表,当配置了host和路径时,需要路径和host同时被满足,才能请求到该规则对应的后端服务。此外要注意的是,Ingress采用的匹配逻辑是最长匹配。当请求路径为/test/abc/,而有rule1 路径为/ ,rule2路径为/test,此时该请求会被转发到rule2对应的后端服务。
- 后端服务,该处需要填写服务名称以及端口。
通常情况下Ingress还会配置一个defaultBackend,用来处理那些没有匹配上任何规则的请求。
Path Types
pathType顾名思义为路径匹配的类型,当前Ingress支持以下三种pathType:
- ImplementationSpecific:该类型的路径匹配取决于IngressClass的实现,其实现可能为前缀匹配,亦可能为精准匹配。
- Exact:精准匹配。
- Prefix:前缀匹配,要注意Ingress采用最长匹配原则。
域名通配符
Ingress支持域名以通配符的形式进行匹配,譬如*.abc.com,当请求域名为test.abc.com, good.abc.com都符合上述通配。但是foo.bar.abc.com,这是因为Ingress的*通配符只能够单个DNS标签,即被.分割的一个单词。
Ingress Class
通常情况下,IngressClass的实现和配置取决于不同的Ingress Controller。每一个Ingress都应该指定一个对IngressClass资源的引用,IngressClass资源则定义了用于实现IngressClass的IngressController的名称。
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb
其中.spec.parameters引用了另外资源,该资源被用来配置IngressClass
而.spec.contoller则指定了用于实现IngressClass的IngressController的名称
一般情况下IngressClass的作用域为集群级别,但IngressClass也可以指定作用域为某个命名空间。在使用命名空间为作用域的IngressClass时候,需要在.spec.parameters.scope处配置作用域为Namespace,并且在spec.parameters.namespace处填入具体命名空间。
命名空间级别的IngressClass的好处
- 每个团队只用关系自己命名空间下的IngressClass的配置
- 可以使用kubernetes的RBAC进行管控,实现精细化的权限控制
集群级别IngressClass
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-1
spec:
controller: example.com/ingress-controller
parameters:
# The parameters for this IngressClass are specified in a
# ClusterIngressParameter (API group k8s.example.net) named
# "external-config-1". This definition tells Kubernetes to
# look for a cluster-scoped parameter resource.
scope: Cluster
apiGroup: k8s.example.net
kind: ClusterIngressParameter
name: external-config-1
命名级别IngressClass
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-2
spec:
controller: example.com/ingress-controller
parameters:
# The parameters for this IngressClass are specified in an
# IngressParameter (API group k8s.example.com) named "external-config",
# that's in the "external-configuration" namespace.
scope: Namespace
apiGroup: k8s.example.com
kind: IngressParameter
namespace: external-configuration
name: external-config
Ingress的类型
单服务的Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80
如上的Ingres实际上绑定了一个服务名为service,端口为80的后端服务。通过kubectl apply -f可以创建该Ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress external-lb * 203.0.113.123 80 59s
其中203.0.113.123为Ingress Contoler用于实现该Ingress的IP。
简单的多播(Simple fanout)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
上面的配置为上面的图片的实现,可以看到这里配置两个路径规则,满足前缀为/foo的将被转发到service1的4200端口,满足前缀为/bar的将被转发到service2的8080端口。
通过执行
kuberctl describe ingress simple-fanout-example
可以看到
Name: simple-fanout-example
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
只要service1和service2存在且合法,IngressController就会为这个Ingress创建一个负载均衡器来实现该资。
基于名字的虚拟域名(name based virtual hosting)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
根据上述配置,Ingress将会根据请求的域名来讲流量转发到对应后端。
此外当存在如下配置,service3对应rule没有配置域名,当请求同时不满足serice1和service2对应的rule是,service3的rule才生效。也就是当请求的host不为first.bar.com和second.bar.com时,流量才被转发到service3。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress-no-third-host
spec:
rules:
- host: first.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: second.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
- http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service3
port:
number: 80
TLS
在启用Ingress的TLS套件前,需要先创建一下的Secret用于保存证书。此外Ingress资源只支持端口为443的TLS端口,并Ingress为Https的终点(即服务到pod的流量是明文的)。如果Ingress中的TLS配置部分指定了不同的主机,则根据通过SNI TLS扩展指定的主机名(前提是Ingress控制器支持SNI),这些主机将在同一端口上多路传输。TLS机密必须包含名为TLS.crt和TLS.key的密钥,它们包含用于TLS的证书和私钥。例如:
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
type: kubernetes.io/tls
一个典型的启用了TLS的Ingress资源定义如下
为了确保TLS的生效,在tls部分配置的域名需要尽可能覆盖rule中配置的域名,即rule中的域名尽量是tls hosts中的域名或者子域名
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
此外,每个IngressController的TLS实现细节也存在一定差异,需要在使用时候详细了解
负载均衡
Ingress控制器使用一些应用于所有Ingress的负载平衡策略设置进行引导,例如负载平衡算法、后端权重方案等。更高级的负载平衡概念(例如,持久会话、动态权重)尚未通过Ingress公开。相反,您可以通过用于服务的负载均衡器来获得这些功能。
同样值得注意的是,尽管健康检查不是直接通过Ingress公开的,但Kubernetes中存在类似的概念,如就绪探针,可以实现相同的最终结果。请查看控制器特定的文档,了解它们如何处理健康检查(例如:nginx或GCE)。