Kubernetes——Ingress 资源

Ingress 资源

  Kubernetes 提供了两种内建的云端负载均衡机制(cloud load balancing)用于发布公共应用,一种是工作于传输层的 Service 资源,它实现的是 "TCP负载均衡器",另一种是 Ingress 资源,它实现的是 "HTTP(S)负载均衡器"。

一、Ingress 和 Ingress Controller

  Kubernetes 中,Service 资源和 Pod 资源的 IP 地址仅能用于集群网络内部的通信,所有的网络流量都无法穿透边界路由器(Edge Router)以实现集群内外通信。

  尽管可以为 Service 使用 NodePort 或 LoadBalancer 类型通过节点引入外部流量,但它依然是 4层 流量转发,可用的负载均衡器也位传输层负载均衡机制。

  Ingress 是 Kubernetes API 的标准资源类型之一,它其实就是一组基于 DNS 名称(host)或 URL 路径把请求转发至指定的 Service 资源的规则,用于将集群外部的请求流量转发至集群内部。然而,Ingress 资源自身并不能进行 "流量穿透",它仅仅是一组路由规则的集合,这些规则要想真正发挥作用还需要其他功能的辅助,如监听某套接字,然后根据这些规则的匹配机制路由请求流量。这种能够为 Ingress 资源监听的套接字并转发流量的组件称为 Ingress 控制器(Ingress Controller)。

注意:
不同于 Deployment 控制器等,Ingress 控制器并不直接运行为 kube-controller-manager 的一部分,它是 Kubernetes 集群的一个重要附件,类似于 CoreDNS,需要在集群上单独部署。

  Ingress 控制器可以由任何具有反向代理(HTTP/HTTPS)功能的服务程序实现,如 Nginx、Envoy、HAProxy、Vulcand 和 Traefik 等。Ingress 控制器自身也是运行于集群中的 Pod 资源对象,它与被代理的运行为 Pod 资源的应用运行于同一网络中,下图讲述了 ingress-nginx 与 pod1、pod2等的关系示意图:

  上图中,Ingress 规则需要由一个 Service 资源对象辅助识别相关的所有 Pod 对象,但 ingress-nginx 控制器可经由 wap.xxx.com 规则的定义直接将请求流量调度至 pod1 和 pod2,而无须经由 Service 对象 API 的再次转发,www 相关规则的作用方式与此类似。

  另外一方面,使用 Ingress 资源进行流量分发时,Ingress 控制器可基于某 Ingress 资源定义的规则将客户端的请求流量直接转发至与 Service 对应的后端 Pod 资源之上,这种转发机制会绕过 Service 资源,从而省去了 由 kube-proxy 实现的端口代理开销。

二、创建 Ingress 资源

  Ingress 资源是基于 HTTP 虚拟主机或 URL 的转发规则,它在资源配置清单的 spec 字段中嵌套了 rules、backend 和 tls 等字段进行定义。

[root@mh-k8s-master-247-10 ~]# kubectl explain ingress
KIND:     Ingress
VERSION:  extensions/v1beta1

DESCRIPTION:
     Ingress is a collection of rules that allow inbound connections to reach
     the endpoints defined by a backend. An Ingress can be configured to give
     services externally-reachable urls, load balance traffic, terminate SSL,
     offer name based virtual hosting etc. DEPRECATED - This group version of
     Ingress is deprecated by networking.k8s.io/v1beta1 Ingress. See the release
     notes for more information.

FIELDS:
   apiVersion	<string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind	<string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   spec	<Object>
     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

   status	<Object>
     Status is the current state of the Ingress. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

[root@mh-k8s-master-247-10 ~]# 

  ingress.spec 字段:

[root@mh-k8s-master-247-10 ~]# kubectl explain ingress.spec
KIND:     Ingress
VERSION:  extensions/v1beta1

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:
   backend	<Object>
     A default backend capable of servicing requests that don't match any rule.
     At least one of 'backend' or 'rules' must be specified. This field is
     optional to allow the loadbalancer controller or defaulting logic to
     specify a global default.

   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.

[root@mh-k8s-master-247-10 ~]# 

  下面的示例中定义了一个 Ingress 资源,它包含了一个转发规则,把发往 www.xxx.com 的请求代理给名为 myapp-svc 的 Service 资源:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: www.xxx.com
    http:
	  paths:
	  - backend:
	      serviceName: myapp-svc
		  servicePort: 80

  上面资源清单中的 annotations 用于识别其所属的 Ingress 控制器的类别,这一点在集群上部署有多个 Ingress 控制器时尤为重要。Ingress Spec 中的字段是定义 Ingress 资源的核心组成部分,它主要嵌套如下四个字段:

FIELDS:
   backend	<Object>
     A default backend capable of servicing requests that don't match any rule.
     At least one of 'backend' or 'rules' must be specified. This field is
     optional to allow the loadbalancer controller or defaulting logic to
     specify a global default.

   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.

  我们再看看 backend 对象的定义,该对象由两个必须的内嵌字段组成:

[root@mh-k8s-master-247-10 ~]# kubectl explain ingress.spec.rules.http.paths.backend
KIND:     Ingress
VERSION:  extensions/v1beta1

RESOURCE: backend <Object>

DESCRIPTION:
     Backend defines the referenced service endpoint to which the traffic will
     be forwarded to.

     IngressBackend describes all endpoints for a given service and port.

FIELDS:
   resource	<Object>
     Resource is an ObjectRef to another Kubernetes resource in the namespace of
     the Ingress object. If resource is specified, serviceName and servicePort
     must not be specified.

   serviceName	<string>
     Specifies the name of the referenced service.

   servicePort	<string>
     Specifies the port of the referenced service.

[root@mh-k8s-master-247-10 ~]# 

  rules 对象由一系列配置 Ingress 资源的 host 规则组成,这些 host 规则用于将一个主机上的某 URL 路径映射至相关的后端 Service 对象,它的定义格式如下:

[root@mh-k8s-master-247-10 ~]# kubectl explain ingress.spec.rules
KIND:     Ingress
VERSION:  extensions/v1beta1

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@mh-k8s-master-247-10 ~]# 

  注意,ingress.spec.rules.host 属性目前不支持使用 IP 地址,也不支持后跟 ":PORT" 格式的端口号,且此字段值留空表示通配所有的主机名。

  tls 对象由两个内嵌字段组成,仅在定义 TLS 主机的转发规则时才需要定义此类对象,定义如下:

[root@mh-k8s-master-247-10 ~]# kubectl explain ingress.spec.tls
KIND:     Ingress
VERSION:  extensions/v1beta1

RESOURCE: tls <[]Object>

DESCRIPTION:
     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.

     IngressTLS describes the transport layer security associated with an
     Ingress.

FIELDS:
   hosts	<[]string>
     Hosts are a list of hosts included in the TLS certificate. The values in
     this list must match the name/s used in the tlsSecret. Defaults to the
     wildcard host setting for the loadbalancer controller fulfilling this
     Ingress, if left unspecified.

   secretName	<string>
     SecretName is the name of the secret used to terminate SSL traffic on 443.
     Field is left optional to allow SSL routing based on SNI hostname alone. If
     the SNI host in a listener conflicts with the "Host" header field used by
     an IngressRule, the SNI host is used for termination and value of the Host
     header is used for routing.

[root@mh-k8s-master-247-10 ~]# 

三、Ingress 资源类型

  基于 HTTP 暴露的每个 Service 资源均可发布于一个独立的 FQDN 主机名之上,如 "www.baidu.com";也可以发布于某主机的 URL 路径之上,从而将它们整合到同一个 Web 站点,如 "www.xxx.com/grafana"。至于是否需要发布为 HTTPS 类型的应用则取决于用户的业务需求。

1、单 Servcie 资源型 Ingress

  暴露单个服务的方法有很多,如服务类型中的 NodePort、LoadBalancer 等,不过一样可以考虑使用 Ingress 来暴露服务,此时只需要为 Ingress 指定 "defalut backend" 即可。例如下面的例子:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: myapp-svc
    servicePort: 80

  Ingress 控制器会为其分配一个 IP 地址接入请求流量,并将它们转至示例中的 my-svc 后端。

2、基于 URL 路径进行流量分发

  垂直拆分或微服务架构中,每个小的应用都有其专用的 Service 资源暴露服务,但在对外开放的站点上,它们可能是财经、新闻、无线端或者 API 接口等一类的独立应用,可通过主域名的 URL 路径(path)分别接入,例如,www.xxx.com/api、www.xxx.com/wap 等,用于发布集群内名称为 API 和 WAP 的 Services 资源。

  于是,可对应地创建一个如下的 Ingress 资源,它将对 www.xxx.com/api 的请求都转发至 API Server 资源,将对 www.xxx.com/wap 的请求转发至 WAP Service 资源:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: www.xxx.com
    http:
	  paths:
	  - path: /wap
	    backend:
          serviceName: wap
		  servicePort: 80  
	  - path: /api
	    backend:
          serviceName: api
		  servicePort: 80  

3、基于主机名称的虚拟主机

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
spec:
  rules:
  - host: www.aaa.com
    http:
      path:
      - path: /wap
        backend:
          serviceName: wap
          servicePort: 80  
      - path: /api
        backend:
          serviceName: api
          servicePort: 80 
  - host: www.bbb.com
    http:
      paths:
      - path: /wap
        backend:
          serviceName: wap
		  servicePort: 80  
      - path: /api
        backend:
          serviceName: api
          servicePort: 80 		  

4、TLS 类型的 Ingress 资源

  这种类型用于以 HTTPS 发布 Service 资源,基于一个含有私钥和证书的 Secret 对象即可配置 TLS 协议的 Ingress 资源。在 Ingress 资源中引用此 Secret 即可让 Ingress 控制器加载并配置为 HTTPS 服务。

  下满是一个简单的 TLS 类型的 Ingress 资源示例:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: no-rules-map
spec:
  tls:
  - secretName: www.xxx.comSecret
  backend:
    serviceName: homesite
	servicePort: 80

四、部署 Ingress 控制器(Nginx)

  Ingress 控制器自身是运行于 Pod 中的容器应用,一般是 Nginx 或 Envoy 一类的具有代理及负载均衡功能的守护进程,它监视着来自于 API Server 的 Ingress 对象状态,并以其规则生成相应的应用程序专有格式的配置文件通过重载或重启守护进程而使新配置生效。

  例如,对于 Nginx 来说,Ingress 规则需要转换为 Nginx 的配置信息。简单的来说,Ingress 控制器其实就是托管于 Kubernetes 系统之上的用于实现在应用层发布服务的 Pod 资源,它将跟踪 Ingress 资源并实时生成配置规则。那么,同样运行为 Pod 资源的 Ingress 控制器进程又该如何接入外部的请求流量呢?常用的解决方案有如下两种:

  • 以 Deployment 控制器管理 Ingress 控制器的 Pod 资源,并通过 NodePort 或 LoadBalancer 类型的 Servcie 对象为其接入集群外部的请求流量,这意味着,定义一个 Ingress 控制器时,必须在其前端定义一个专用的 Service 资源。
  • 借助于 DaemonSet 控制器,将 Ingress 控制器的 Pod 资源各自以单一实例的方式运行于集群的所有或部分工作节点之上,并配置这类 Pod 对象以 hostPort 或 hostNetwork 的方式在当前节点接入外部流量。
posted @ 2022-06-21 15:17  左扬  阅读(365)  评论(0编辑  收藏  举报
levels of contents