技术流ken

运维拯救世界

kubernetes(k8s)之Ingress资源(十八)–技术流ken

介绍

 

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

 

( 1) TCP 载均衡器

无论是 iptables 还是ipvs 模型的 Service 资源都配置于 Linux 内核中的 Netfilter 之上进行四层调度,是一种类型更为通用的调度器, 支持调度 HTTP、MySQL 应用层服务。不过,也正是由于 作于传输层从而使得它无法做到类似卸载 HTTPS 中的 SSL 会话等一类作,也不支持基于 URL 的请求调度机制,而且, Kubernetes 也不支持为此类负载均衡器配置任何类型的健康状态检查机制

( 2) HTTP(S )负载均衡器

HTTP(S )负载均衡器是应用层负载均衡机制的 种,支持根据环境做出更好的调度决策。与传输层调度器相比,它提供了诸如可自定义 URL 映射和 TLS 卸载 功能,并支持多种类型 的后端服务器健康状态检查机制

Ingress和Ingess Controller

 

Kubernetes 中, Service 资源和 Pod 资源的 IP 地址仅能用于集群网络内部的通信,所有的网络流量都无法穿透边界路由器( Edge Rout )以 现集群内外通信。尽管可以为Service 使用 NodePort LoadBalancer 类型通过节点引人外部流 ,但它依然是4层流量流发,可用的负载均衡器也为传输层负载均衡机制。

 

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

 

注意:

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

 

 

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

 

另一方面,使用 Ingress 资源进行流量分发时, Ingress 控制器可基于某 Ingress 资源定义的规则将客户端的请求流 直接转发至与 Service 应的后端 Pod 资源之上,这种转发机制会绕过 service 资源,从而省去了由 kube proxy实现的端口代理开销 如上图所示,Ingress 规则需要由一个 Service 资源对象辅助识别相关的所有 Pod 象,但 ingress-nginx控制器可经由 api.ilinux.io 规则的定义直接将请求流量调度至 pod3或者pod4 ,而无须经由Service对象API 再次转发, WAP关规则的作用方式与此类同。

 

创建 Ingress 资源

 

Ingress 资源是基于 HTTP 虚拟主机或 URL 的转发规则, 它在资源配置清单的 spec中嵌套了rules、backend、tls 等字段进行定义。下面的示例中定义了 Ingress 资源,它包含了一个转发规则,把发往 www. ilinux.io 请求代理给名为 myapp-svc的Service 资源:

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

  •  rules <Object> :用于定义当前Ingress 资源的转发规则列表;未由 rules 定义规则,或者没有匹配到任何规则时,所有流量都会转发到由 backend 定义的默认后端
  • backend <Object>: 默认的后端用于服务那些没有匹配到任何规则的请求;定义Ingress 源时,至少应该定义 backend或者rules 两者之一;此字段用于让负载均衡器指定一个全局默认的后端。
  • tls <Object> : TLS ,目前仅支持通过 认端口 443 提供服务;如果要配置指定的列表成员指向了不同的主机,则必须通过 SNI TLS 扩展机制来支持此功能

 

 

backend 对象的定义由两个必选的内嵌 段组成: serviceName和servicePort ,分别用于指定流量转发的后端目标 Service 资源的名称和端口。

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

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

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

  • host :包含于使用的 TLS 证书之内的主机名称字符串列表,因此,此处使用的主机

名必须匹配 tlsSecret 中的名称

  • secretName :用于引用 SSL 会话的 secret 象名 称,在基于 SNI 实现多主机路由的

场景中,此字段为可选

 

Ingress 资源类型

 

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

 

1.单Service 资源型 Ingress

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

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

 

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

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

 

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

上面类型2中描述的需求,也可以将每个应用分别以独立的 FQDN 主机名进行输出,如:wap.ik8s.io和api.ik8s.io ,这两个主机名解析到 external LB (如上图所示)的 IP 地址之上,分别用于发布集群 部的 WAP和API 两个 Servic 资源 这种实现方案其实就是Web 站点部署中的 “基于主 机名的虚拟主机”,将多个 FQDN 解析至同一个 IP 地址, 然后根据“主机头”( Host header )进行转发。下面是以独立 FQDN 主机形式发布服务的 Ingress资源示例:

 

4.TLS 类型的 Ingress 资源

这种类型用于以 HTTPS发布Service 资源, 基于一个含有私钥和证书的 Secret对象,即可配 TLS 协议的 Ingress 资源,目前来说, Ingress 资源仅支持单 TLS 端口, 并且还会卸载 TLS会话。在 Ingress 资源中引用此 Secret 即可让 Ingress控制器加载并配置为 HTTPS服务。

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

 

部署 Ingress 控制器( Nginx)

 

Ingress 控制器自身是运行 Pod 中的容器应用,一般是 Nginx或Envoy -类的具有代理及负载均衡功能的守护进程,它监视着来自于API Server的Ingress 对象状态,并以其规则生成相应的应用程序专有格式的配置文件并通过重载或开启守护进程而使新配置生效。例如,对于 Nginx 来说,Ingress 规则需要转换为 Nginx 的配置信息,简单来说, Ingress 控制器其实就是托管于Kubemetes 系统之上的用于实现在应用层发布服务的Pod 资源,它将跟跟踪Ingress 资源并实时生成配置规则。那么,同样运行为 Pod 资源的 Ingress 控制器进程又该如何接入外部的请求流量那? 常用的解决方案有如下两种:

  1. 以 Deployment 控制器管理Ingress 控制器的 Pod 资源,并通过 NodePort或Load Balancer 类型的 Service 对象为其接入集群外部的请求流量,这就意味着,定义一个Ingress 控制器时,必须在其前端定义一个专用的 Service 资源:如图 所示

 

2.借助于 DaemonSet 控制器,将 Ingress控制器的 Pod 资源各自以单一实例的方式运行于集群的所有或部分工作节点之上,并配置这类Pod对象以hostPort(如图a)或 hostNetwork (如图b)的方式在当前节点接入外部流量

 

以ingress-nginx 项目为例,部署Ingress Nginx 控制器的配置文件被切割存放在了多个不同的文件中 ,并集中存储于其源码 deploy 子目录下,同时,为了方便用户部署,它还将所需的资源全部集成为一个配置文件 mandatory.yaml:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

 

因为需要下载相关的镜像文件,因此前面部署过程中的 Pod 资源的创建需要等待一段时间才能完成,具体时长要取决于网络的可用状况。

 

在线的配置清单采用了基于 Deployment 控制器部署 Ingress Nginx 的方式,因此接入外部流量之前还需要手动为其创建相关的 NodePort或LoadBalancer 类型的 Service 资源对象,下面的配置清单示例中对类型定义了 NodePort ,并明确指定了易记的端口和 IP 地址,以方便使用:

apiVers on vl 
kind : Se ce
metadata: 
   name : nginx-ingress-controller 
   namespace: ingress-nginx 
spec :
   type : NodePort 
   clusterIP : 10.99.99.99 
   ports: 
   - port : 80 
    name : http 
    nodePort : 30080 
  - port : 443 
    name : https 
    nodePort : 30443 
  selector . 
   app . kubernetes.io/name: ingress-nginx

 

将上面的配置信息保存于文件中,如 nginx-ingress-service.yaml ,而后执行如下命令完成资源的创建。注意 ,其标签选择器应该与 mandatory. yaml配置清单中的 Deployment 控制

nginx-ingress-controller 选择器保持一致:

kubectl apply -f nginx-ingress-service.yaml

 

确认 Service对象nginx-ingress-controller 的状态没有问题后即可于集群外部对其发起访问测试,目标 URL为http://<NodelP> :30080 或http ://<NodelP> :30443 ,确认可收到响应报文后 表示 Ingress Nginx 部署完成,不过,本示例中尚且缺少一个可用的外部负载均衡器,如图 6-13 中所示的“ external-LB ”,因 此,访问测试时暂时还只能使用http ://<Nodelp>: <NodePort>进行

发表评论

电子邮件地址不会被公开。