4.4 路径类型(pathType)
对于每条规则(rule
)中的路径(path
),都必须设置一个相应的路径类型, 目前支持以下3种类型。
- ImplementationSpecific:系统默认,由
IngressClass
控制器提供具体实现; - Exact:精确匹配
URL
路径,区分大小写。 - Prefix:匹配
URL
路径的前缀,区分大小写,路径由“/
”符号分隔为一个个元素,匹配规则为逐个元素进行前缀匹配。如果路径中的最后一个元素是请求路径中最后一个元素的子字符串,则不会判断为匹配,例如/foo/bar
是路 径/foo/bar/baz
的前缀,但不是路径/foo/barbaz
的前缀。
如表所示是常见的路径类型匹配规则示例:
路径类型 | 在ingress中配置的路径 | 请求路径 | 是否匹配 |
Prefix | / | (all paths) | 是 |
Exact | /foo | /foo | 是 |
Exact | /foo | /bar | 否 |
Exact | /foo | /foo/ | 否 |
Exact | /foo/ | /foo | 否 |
Prefix | /foo | /foo,/foo/ | 是 |
Prefix | /foo/ | /foo,/foo/ | 是 |
Prefix | /aaa/bb | /aaa/bbb | 否 |
Prefix | /aaa/bbb | /aaa/bbb | 是 |
Prefix | /aaa/bbb/ | /aaa/bbb | 是,忽略结尾的“/” |
Prefix | /aaa/bbb | /aaa/bbb/ | 是,匹配结尾的“/” |
Prefix | /aaa/bbb | /aaa/bbb/ccc | 是,匹配子路径 |
Prefix | /aaa/bbb | /aaa/bbbxyz | 否,无匹配前缀 |
Prefix | /,/aaa | /aaa/ccc | 是,匹配的是/aaa前缀 |
Prefix | /,/aaa,/aaa/bbb | /aaa/bbb | 是,匹配的是/aaa/bbb前缀 |
Prefix | /,/aaa,/aaa/bbb | /ccc | 是,匹配了"/" |
Prefix | /aaa | /ccc | 否 |
Exact+Prefix配合 | /foo(Prefix), /foo(Exact) | /foo | 是,优先匹配Exact |
在某些情况下,Ingress中的多个路径都会匹配一个请求路径。在这种情况 下,将优先考虑最长的匹配路径。如果两个匹配的路径仍然完全相同,则Exct类 型的规则优先于Prefix类型的规则生效。
4.5 host通配符设置
在规则(rule
)中设置的host
用于匹配请求中的域名(虚拟主机名),设置为完整的字符串表示精确匹配,例如:“foo.bar.com
”。
Kubernetes从1.18版本开始支 持为host设置通配符“
*
”,例如“*.foo.com
”。
- 精确匹配要求HTTP请求头中host参数的值必须与Ingress host设置的值完全一致 ;
- 通配符匹配要求HTTP请求头中host参数的值需要与Ingress host设置的值的后缀一致,并且仅支持一层DNS匹配。
下面是常见的一些host通配符匹配规则示例:
ingress host 配置 | 请求头中的host值 | 是否匹配 |
*.foo.com | bar.foo.com | 否 |
*.foo.com | baz.bar.foo.com | 否,不是一层DNS匹配 |
*.foo.com | foo.com | 否,不是一层DNS匹配 |
下例中的 Ingress包含精确匹配host"foo.bar.com" 和 通配符匹配 host"*.foo.com"两条规则:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-wildcard-host spec: rules: - host: "foo.bar.com" http: paths: - pathType: Prefix path: "/bar" backend: service: name: service1 port: number: 80 - host: "*foo.com" http: paths: - pathType: Prefix path: "/foo" backend: service: name: service2 port: number: 80
4.6 ingressClassName和ingressClass资源对象
在一个Kubernetes集群内,用户可以部署多个不同类型的Ingress Controller 同时提供服务,此时需要在Ingress资源上注明该策略由哪个Controller管理。
Kubernetes在1.18版本之前,可以在
Ingress
资源上设置一个名为kubernetes.io/ingress.class
的annotation
进行声明。但annotation
的定义没有标准规范,Kubernetes从1.18版本开始引入一个新的资源对象IngressClass
对其进行规范定义。在IngressClass
中除了可以设置Ingress
的管理Controller
,还可以配置更加丰富的参数信息(通过parameters
字段进行设置)。
例如下面的IngressClass
定义了一个名为“example.com/ingress--controller‘
”的Controller
和一组参数:
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
然后在Ingress
资源对象的定义中通过ingressClassName
字段引用该IngressClass
,标明使用其中指定的Ingress Controller
和相应的参数:
apiversion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress spec: ingressclassName: external-lb rules: - host: "*example.com" http: paths: - path: /example pathType: Prefix backend: service: name: example-service port: number: 80
05 ingress策略配置
为了实现灵活的路由转发策略,Ingress
策略可以按多种方式进行配置,下面对几种常见的Ingress
转发策略进行说明。
5.1 转发到单个后端服务
基于这种设置,客户端发送到Ingress Controller的访问请求都将被转发到后端的唯一服务,在这种情况下,Ingress无须定义任何rule,只需设置一个默认的 后端服务(defaultBackend)。
通过如下所示的设置,对Ingress Controller的访问请求都将被转发到 “myweb:8080”这个服务:
# ingress-single-backend-service.yaml apiversion: networking.k8s.io/v1 kind: Ingress metadata: name: test-ingress spec: defaultBackend: service: name: webapp port: number: 8080
通过kubectl create命令创建后,查看ingress详情,可以看到系统为其设置了正确的后端目标地址:
5.2 将同一域名的不同URL路径转发到不同的服务(Simple Fanout)
这种配置常用于一个网站通过不同的路径提供不同的服务的场景,例如/web 表示访问Web页面,/api表示访问API接口,对应到后端的两个服务,只需在Ingress规则定义中设置将同一域名的不同URL路径转发到不同的后端服务,如图所示:
通过如下所示的设置,对"mywebsite.com/web
"的访问请求将被转发到"web- service:80
"服务,对"mywebsite.com/api
"的访问请求将被转发到"api-service: 80
"服务:
# ingress-simple-fanout.yaml apiversion: networking.k8s.io/v1 kind: Ingress metadata: name: simple-fanout-example spec: rules: - host: mywebsite.com http: paths: - path: /web pathType: ImplementationSpecific backend: service: name: web-service port: number: 8080 - path: /api pathType: ImplementationSpecific backend: service: name: api-service port: number: 8081
通过kubectl create创建之后,查看ingress详情,可以看到系统为不同的path设置了转发规则:
5.3 将不同的域名(虚拟主机名)转发到不同的服务
这里 指基于host域名的Ingress规则将客户端发送到同一个IP地址的HTTP请求,根据不同的域名转发到后端不同的服务,例如foo.bar.com域名由service1提供服务,bar.foo.com域名由service2提供服务,如图所示:
通过如下所示的设置,请求头中host=foo.bar.com的访问请求将被转发到“service1:80”服务,请求头中host=bar.foo.com的访问请求将被转发到 “service2:80”服务:
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
5.4 不使用域名的转发规则
如果在Ingress中不定义任何host域名,Ingress Controller则将所有客户端请求都转发到后端服务。
例如下面的配置为将"<ingress-controller-ip>/demo
"的访问请求转发到"webapp:8080/demo
"服务:
apiversion: networking.k8s.io/v1 kind: Ingress metadata: name: test-ingress spec: rules: - http: paths: path: /demo pathType: Prefix backend: service: name: webapp port: number: 8080
06 ingress的TLS安全设置
Kubernetes支持为Ingress设置TLS安全访问机制,通过为Ingress的host(域名)配置包含TLS私钥和证书的Secret进行支持。
Ingress
资源仅支持单个TLS
端口号443,并且假设在Ingress
访问点(Ingress Controller
)结束TLS
安全机制,向后端服务转发的流量将以明文形式发送。- 如果
Ingress
中的TLS
配置部分指定了不同的host
,那么它们将根据通过SNI TLS
扩展指定的虚拟主机名(这要求Ingress Controller
支持SNI
)在同一端口进行复用。
TLS Secret中的文件名必须为“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
然后,需要在Ingress资源对象中引用该Secret,这将通知Ingress Controller
使用TLS加密客户端到负载均衡器的网络通道。
用户需要确保在
TLS
证书(tls.crt
)中包含相应host
的全限定域名(FQDN
)被包含在其CN
(Common Name
)配置中。
TLS
的功能特性依赖于Ingress Controller
的具体实现,不同Ingress Controller
的实现机制可能不同,用户需要参考各个Ingress Controller
的文档。
下面以Nginx Ingress为例,对Ingress的TLS配置进行说明,步骤如下:
- 创建自签名的密钥和SSL证书文件;
- 将证书保存到Kubernetes的Secret资源对象中;
- 在Ingress资源中引用该Secret。
6.1 生成秘钥和证书
下面通过OpenSSL
工具生成密钥和证书文件,将参数-subj
中的/CN
设置为host
全限定域名(FQDN
) “mywebsite.com”:
通过以上命令将生成tls.key
和tls.crt
两个文件。
6.2 创建secret资源对象
然后根据tls.key和tls.crt文件创建secret资源对象,有以下两种方法。
方法一:使用kubectl create secret tl
s命令直接通过tls.key
和tls.crt
文件创建secret
对象
方法二:编辑mywebsite-ingress-secret.yaml
文件,将tls.key
和tls.crt
文件的内容经过BASE64
编码的结果复制进去,使用kubectl create
命令进行创建
# mywebsite-ingress-secret.yaml apiVersion: v1 kind: Secret metadata: name: mywebsite-ingress-secret type: kubernetes.io/tls data: tls.crt: MIIDAzCC....... tls.key: MIIEV......
然后使用kubectl create命令创建即可。
6.3 多个域名的配置
如果需要配置TLS的host域名有多个,例如前面第3种Ingress策略配置方式, 则SSL证书需要使用额外的一个x509 v3配置文件辅助完成,在[alt_names
]段中完成多个DNS域名的设置。
首先编写openssl.cnf文件,内容如下:
[req] req_extensions = v3_req distinguished_name = req_distinguished_name [req distinguished name] [v3 req] basicConstraints = CA:FALSE keyusage = nonRepudiation,digitalSignature,keyEncipherment subjectAltName = @alt_names [alt names] DNS.1 = mywebsite.com DNS.2 = mywebsite2.com
接着使用OpenSSL工具完成密钥和证书的创建,生成自签名CA证书:
# openssl genrsa -out ca.key 2048 Generating RSA private key,2048 bit long modulus (2 primes) ·······················++++++++++++ ············++++++++++++ e is 65537(0x10001) # openssl req -x509 -new -nodes -key ca.key -days 5000 -out ca.crt -subj "/CN=mywebsite.com"
基于openssl.cnf和CA证书生成Ingress TLS证书:
# openssl genrsa -out ingress.key 2048 Generating RSA private key,2048 bit long modulus (2 primes) ·······················++++++++++++ ············++++++++++++ e is 65537(0x10001) # openssl req -new -key ingress.key -out ingress.csr -subj "/CN=mywebsite.com" -config openss1.cnf # openssl x509 -req -in ingress.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out ingress.crt -days 5000 -extensions v3 req -extfile openssl.cnf Signature ok subject=/CN=mywebsite.com Getting CA Private Key
然后根据ingress.key
和ingress.crt
文件创建secret资源对象,同样可以通过 kubectl create secret tls
命令或YAML文件生成。这里通过命令行直接生成:
$ kubectl create secret tls mywebsite-ingress-secret --key ingress.key --cert ingress.crt secret "mywebsite-ingress-secret"created
至此,Ingress
的TLS
证书和密钥就成功创建到Secret
对象中了, 下面创建Ingress
对象,在tls
段引用刚刚创建好的Secret
对象:
# mywebsite-ingress-tls.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: mywebsite-ingress-tls spec: tls: - hosts: - mywebsite.com secretName: mywebsite-ingress-secret rules: - host: mywebsite.com http: paths: - path: /demo pathType: Prefix backend: service: name: webapp port: number: 8080
成功创建该Ingress资源之后,就可以通过HTTPS安全访问Ingress了。
以使用curl命令行工具为例,访问Ingress Controller的URL"https:/192.168.18.3/demo/":