实战:Ingress-2022.1.1
目录
文章目录
实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
k8s version:v1.22.2
containerd://1.5.5
实验软件
无
1、Ingress(对外暴露集群服务)
前面我们学习了在 Kubernetes 集群内部使用 kube-dns 实现服务发现的功能,那么我们部署在 Kubernetes 集群中的应用如何暴露给外部的用户使用呢?我们知道可以使用 NodePort
和 LoadBlancer
类型的 Service 可以把应用暴露给外部用户使用。除此之外,Kubernetes 还为我们提供了一个非常重要的资源对象可以用来暴露服务给外部用户,那就是 Ingress
。对于小规模的应用(或者测试的时候)我们使用 NodePort 或许能够满足我们的需求,但是当你的应用越来越多的时候,你就会发现对于 NodePort 的管理就非常麻烦了,这个时候使用 Ingress 就非常方便了,可以避免管理大量的端口。
注意:我们知道,NodePort它是要到我们节点上的ClusterIp,然后通过ClusterIp去帮我们做一下负载,其实它的调用链是多了一层。
2、资源对象
Ingress
资源对象是 Kubernetes 内置定义的一个对象,是从 Kuberenets 集群外部访问集群的一个入口,将外部的请求转发到集群内不同的 Service 上,其实就相当于 nginx、haproxy 等负载均衡代理服务器,可能你会觉得我们直接使用 nginx 就实现了,但是只使用 nginx 这种方式有很大缺陷,每次有新服务加入的时候怎么改 Nginx 配置?不可能让我们去手动更改或者滚动更新前端的 Nginx Pod 吧?那我们再加上一个服务发现的工具比如 consul 如何(然后利用consul-template去自动刷新我们的nginx配置)?貌似是可以,对吧?Ingress 实际上就是这样实现的,只是服务发现的功能自己实现了,不需要使用第三方的服务了,然后再加上一个域名规则定义,路由信息的刷新依靠 Ingress Controller 来提供。
注意:这里写的是
ingress
,但其实是ingress-controller在起作用。这里的路由规则可能是一个域名,或者是一个Path路径,都是可以去做一个路由的匹配。
Ingress Controller 可以理解为一个监听器,通过不断地监听 kube-apiserver,实时的感知后端 Service、Pod (当然也包括ingress)的变化,当得到这些信息变化后,Ingress Controller 再结合 Ingress 的配置,更新反向代理负载均衡器,达到服务发现的作用。其实这点和服务发现工具 consul、 consul-template 非常类似。
⚠️
我们刚才也说了,Ingress它是一种资源对象,但是Ingress-controller他其实就是一种……,我们前面和大家已经介绍了CRD ,operator了,我们自己是不是可以自己随意定义一些自定义资源对象。但是你自定义的这些资源对象是没有意义的,它只是可以在k8s里做一些增删改查,用kube-controller去做一些简单的管理而已。但你你创建出来这个资源对象,它有什么意义呢?它还是要依赖于它背后的一个控制器。所以这个ingress控制器其实你就可以把它认为是一个Operator,或者是一个我们所说的k8s里面通用的控制器。
所以说,如果要让大家自己去实现一个功能,就是说去把service的pod给它暴露到集群外部去,其实也相当于是去开发一个operator,或者说去开发一个控制器。只是说,这个自定义的资源对象可能它的一个规则是按照我们自己的一个规则,按我们自己定义的一个方式去做的。而k8s它提供一个资源对象ingress,可以认为它是把这一块的服务暴露给它做了一个规范。就是你其他一些第三方的ingress控制器可能都需要来实现一下,当然你不实现的话,也可以,只是说的话,可能,大家都认为市面上一些通用的控制器都会兼容k8s提供的这个默认内置的这个ingress资源对象。如果说你提供的一个新的ingress-controller,如果没去兼容它的话,可能使用的人就会有所顾虑吧。
当然你说你自己要去实现一个控制器,你就不用它的ingrss,当然也是可以的。其实,官方内置的ingress相当就是说约定俗成吧,基本上类似于一个通用的。
3、定义
一个常见的 Ingress 资源清单如下所示:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules: #rules下面是可以配置很多规则的
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
上面这个 Ingress 资源的定义,配置了一个路径为 /testpath
的路由,所有 /testpath/**
的入站请求,会被 Ingress 转发至名为 test 的服务的 80 端口的 /
路径下。可以将 Ingress 狭义的理解为Nginx 中的配置文件 nginx.conf
。
此外 Ingress 经常使用注解 annotations
来配置一些选项,当然这具体取决于 Ingress 控制器的实现方式,不同的 Ingress 控制器支持不同的注解。
⚠️另外需要注意的是当前集群版本是 v1.22
,这里使用的 apiVersion 是 networking.k8s.io/v1
,所以如果是之前版本的 Ingress 资源对象需要进行迁移。 Ingress 资源清单的描述我们可以使用 kubectl explain
命令来了解:
➜ kubectl explain ingress.spec
KIND: Ingress
VERSION: networking.k8s.io/v1
RESOURCE: spec <Object>
DESCRIPTION:
Spec is the desired state of the Ingress. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
IngressSpec describes the Ingress the user wishes to exist.
FIELDS:
defaultBackend <Object>
DefaultBackend is the backend that should handle requests that don't match
any rule. If Rules are not specified, DefaultBackend must be specified. If
DefaultBackend is not set, the handling of requests that do not match any
of the rules will be up to the Ingress controller.
ingressClassName <string>
IngressClassName is the name of the IngressClass cluster resource. The
associated IngressClass defines which controller will implement the
resource. This replaces the deprecated `kubernetes.io/ingress.class`
annotation. For backwards compatibility, when that annotation is set, it
must be given precedence over this field. The controller may emit a warning
if the field and annotation have different values. Implementations of this
API should ignore Ingresses without a class specified. An IngressClass
resource may be marked as default, which can be used to set a default value
for this field. For more information, refer to the IngressClass
documentation.
rules <[]Object>
A list of host rules used to configure the Ingress. If unspecified, or no
rule matches, all traffic is sent to the default backend.
tls <[]Object>
TLS configuration. Currently the Ingress only supports a single TLS port,
443. If multiple members of this list specify different hosts, they will be
multiplexed on the same port according to the hostname specified through
the SNI TLS extension, if the ingress controller fulfilling the ingress
supports SNI.
从上面描述可以看出 Ingress 资源对象中有几个重要的属性:defaultBackend
、ingressClassName
、rules
、tls
。
1.rules
其中核心部分是 rules
属性的配置,每个路由规则都在下面进行配置:
[root@master1 ~]#kubectl explain ingress.spec.rules
KIND: Ingress
VERSION: networking.k8s.io/v1
RESOURCE: rules <[]Object>:
DESCRIPTION:
A list of host rules used to configure the Ingress. If unspecified, or no
rule matches, all traffic is sent to the default backend.
IngressRule represents the rules mapping the paths under a specified host
to the related backend services. Incoming requests are first evaluated for
a host match, then routed to the backend associated with the matching
IngressRuleValue.
FIELDS:
host <string>
Host is the fully qualified domain name of a network host, as defined by
RFC 3986. Note the following deviations from the "host" part of the URI as
defined in RFC 3986: 1. IPs are not allowed. Currently an IngressRuleValue
can only apply to the IP in the Spec of the parent Ingress.
2. The `:` delimiter is not respected because ports are not allowed.
Currently the port of an Ingress is implicitly :80 for http and :443 for
https. Both these may change in the future. Incoming requests are matched
against the host before the IngressRuleValue. If the host is unspecified,
the Ingress routes all traffic based on the specified IngressRuleValue.
Host can be "precise" which is a domain name without the terminating dot of
a network host (e.g. "foo.bar.com") or "wildcard", which is a domain name
prefixed with a single wildcard label (e.g. "*.foo.com"). The wildcard
character '*' must appear by itself as the first DNS label and matches only
a single label. You cannot have a wildcard label by itself (e.g. Host ==
"*"). Requests will be matched against the Host field in the following way:
1. If Host is precise, the request matches this rule if the http host
header is equal to Host. 2. If Host is a wildcard, then the request matches
this rule if the http host header is to equal to the suffix (removing the
first label) of the wildcard rule.
http <Object>
[root@master1 ~]#
-
host
:可选字段,上面我们没有指定 host 属性,所以该规则适用于通过指定 IP 地址的所有入站 HTTP 通信,如果提供了 host 域名,则rules
则会匹配该域名的相关请求,此外host
主机名可以是精确匹配(例如foo.bar.com
)或者使用通配符来匹配(例如*.foo.com
)。 -
http.paths
:定义访问的路径列表,比如上面定义的/testpath
,每个路径都有一个由backend.service.name
和backend.service.port.number
定义关联的 Service 后端,在控制器将流量路由到引用的服务之前,host
和path
都必须匹配传入的请求才行。 -
backend
:该字段其实就是用来定义后端的 Service 服务的,与路由规则中host
和path
匹配的流量会将发送到对应的 backend 后端去。
⚠️ 此外一般情况下在 Ingress 控制器中会配置一个
defaultBackend
默认后端,当请求不匹配任何 Ingress 中的路由规则的时候会使用该后端。defaultBackend
通常是 Ingress 控制器的配置选项,而非在 Ingress 资源中指定。
2.Resource
backend
后端除了可以引用一个 Service 服务之外,还可以通过一个 resource
资源进行关联,Resource
是当前 Ingress 对象命名空间下引用的另外一个 Kubernetes 资源对象,但是需要注意的是 Resource
与 Service
配置是互斥的,只能配置一个。Resource
后端的一种常见用法是将所有入站数据导向带有静态资产的对象存储后端,如下所示:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-resource-backend
spec:
rules:
- http:
paths:
- path: /icons
pathType: ImplementationSpecific
backend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket #这个类似于对象存储的后端之类的。一般我们会把静态资源放到对象存储上面,然后前面加上cdn之类的。
name: icon-assets
该 Ingress 资源对象描述了所有的 /icons
请求会被路由到同命名空间下的名为 icon-assets
的 StorageBucket
资源中去进行处理。
但是你如果不用resource,你静态资源,一般的话,如果你用service,是不是还要用我们的nginx镜像去代理下我们的静态资源,比如我们的图片、css、js之类的。所以说,你如果用service的话也可以,你如果用service的,那么后面就可能要挂一个Nginx的镜像了。