本章涵盖了
创建Ingress对象
部署和理解Ingress控制器
使用TLS加密ingresses
向Ingress添加额外的配置
安装多个控制器时使用IngressClasses
使用带有非服务后端的ingress
在前一章中,学习了如何使用Service对象公开一组具有稳定IP地址的pod。使用LoadBalancer服务类型时,该服务通过负载均衡器提供给集群外的客户端使用。如果只需要向外部公开单个服务,那么这种方法很好,但是对于大量的服务来说就有问题了,因为每个服务都需要自己的公共IP地址。
幸运的是,通过一个Ingress对象来公开这些服务,只需要一个IP地址。此外,Ingress还提供了其他一些服务对象无法提供的特性,比如HTTP身份验证、基于cookie的会话关联、URL重写等。
12.1 Ingresses简介注意
可以在以下地址找到本章的代码文件 kubernetes-in-action-2nd-edition/Chapter12 at master · luksa/kubernetes-in-action-2nd-edition · GitHub
在我解释Kubernetes的背景下什么是Ingress之前,首先定义术语Ingress是什么意思,这对于那些英语不是他们的第一语言的读者来说可能会很有帮助。
定义
Ingress(名词)----进入或进入的行为;进入权;进入的途径或地点;入口通道。
在Kubernetes中,Ingress是外部客户端访问集群中运行的应用程序的服务的一种方式。Ingress功能由以下三个组件组成:
Ingress API对象,用于定义和配置Ingress。
L7负载均衡器或反向代理,将流量路由到后端服务。
Ingress控制器,用于监控Ingress对象的Kubernetes API,并部署和配置负载均衡器或反向代理。
注意
L4和L7指开放系统互连模型(OSI模型)的第4层(传输层;TCP、UDP)和第7层(应用层;HTTP)。
注意
与转发代理不同,转发代理负责路由和过滤传出的流量,通常与所服务的客户端位于同一位置,而反向代理则负责处理传入的流量,并将其路由到一个或多个后端服务器。反向代理位于这些服务器附近。
在大多数网络内容中,术语ingress controller通常将负载均衡器/反向代理和实际控制器称为一个实体,但它们是两个不同的组件。因此,我在本章中分别提到它们。
我还使用术语proxy 来表示L7负载均衡器,这样您就不会将其与L4负载均衡器混淆,后者处理loadbalancer类型服务的流量。
12.1.1 Ingress对象类型简介当想要对外公开一组服务时,可以创建一个Ingress对象并引用其中的Service对象。Kubernetes使用这个Ingress对象来配置一个L7负载均衡器(一个HTTP反向代理),使得外部客户端可以通过一个公共入口点访问服务。
注意
如果通过Ingress公开Service ,通常可以将Service type设置为ClusterIP。然而,一些入口实现要求Service类型为NodePort。请参阅ingress控制器的文档,查看是否存在这种情况。
通过Ingress对象公开服务
虽然Ingress对象可以用于公开单个Service,但它通常与多个Service对象组合使用,如下图所示。该图显示了一个Ingress对象如何使外部客户端可以访问Kiada套件中的所有三个服务。
图12.1 Ingress 用于将外部流量转发给多个服务
Ingress对象包含基于HTTP请求中的信息将流量路由到这三个服务的规则。这些服务的公共DNS条目都指向同一个Ingress。Ingress从请求本身决定哪个服务应该接收请求。如果客户端请求指定主机kiada.example.com,则Ingress将其转发给属于 kiada 服务的pod,而指定主机 api.example.com 的请求则被转发到 quote or quiz 服务,具体取决于请求的路径。
在集群中使用多个Ingress对象
一个Ingress对象通常处理一个特定的Kubernetes命名空间中所有服务对象的流量,但是多个Ingress也是一个选项。通常,每个Ingress对象都有自己的IP地址,但有些Ingress实现会为集群中创建的所有Ingress对象使用一个共享的入口点。
12.1.2 Ingress控制器和反向代理简介并不是所有Kubernetes集群都支持开箱即用的Ingress。这个功能是由一个名为Ingress控制器的集群附加组件提供的。这个控制器是Ingress对象和实际的物理接入口(反向代理)之间的链路。通常,控制器和proxy作为同一个容器中的两个进程运行,或者作为同一个pod中的两个容器运行。这就是为什么人们使用术语ingress controller来表示这两者。
有时控制器或代理位于集群之外。例如,谷歌Kubernetes引擎提供了自己的Ingress控制器,该控制器使用谷歌云平台的L7负载均衡器为集群提供Ingress功能。
如果集群部署在多个可用zones中,一个ingress就可以处理所有的流量。例如,它根据客户端的位置将每个HTTP请求转发到最佳zone。
有很多Ingress控制器可供选择。Kubernetes社区维护了一个列表:Ingress Controllers | Kubernetes。其中最受欢迎的是Nginx Ingress控制器、Ambassador、Contour和Traefik。大多数Ingress控制器使用Nginx、HAProxy或Envoy作为反向代理,但也有一些使用自己的代理实现。
理解ingress控制器的角色
Ingress控制器是赋予Ingress对象生命的软件组件。如下图所示,控制器连接Kubernetes API服务器,监控Ingress、Service和Endpoints 或EndpointSlice对象。无论何时创建、修改或删除这些对象,控制器都会收到通知。它使用这些对象中的信息来提供和配置ingress的反向代理,如下图所示。
图12.2 Ingress控制器的角色
当创建Ingress对象时,控制器读取它的 spec部分,并将其与它引用的Service和EndpointSlice对象中的信息结合起来。控制器将此信息转换为反向代理的配置。然后,它使用这个配置设置一个新的代理,并执行额外的步骤,以确保从集群外部可以访问该代理。如果代理运行在集群内的pod中,这通常意味着创建一个 LoadBalancer 类型的服务,将代理公开在外部。
当更改Ingress对象时,控制器会更新代理的配置,当删除它时,控制器会停止并删除代理以及在一起创建的任何其他对象。
理解代理如何将流量转发给服务
反向代理(或L7负载平衡器)是处理传入HTTP请求并将其转发给services的组件。代理配置通常包含一个虚拟主机列表,以及每个虚拟主机的一个端点IP列表。该信息从Ingress、Service和Endpoints/EndpointSlice对象中获取。当客户端连接到代理时,代理将使用此信息将请求路由到端点(如pod),基于请求路径和请求头。
下图显示了客户端如何通过代理访问Kiada服务。客户端首先执行 kiada.example.com的DNS查找。DNS服务器返回反向代理的公网IP地址。然后客户端向代理发送一个HTTP请求,其中 Host 头部包含值kiada.example.com。代理将这个主机映射到Kiada pod中的一个IP地址,并将HTTP请求转发给它。请注意,代理并不将请求发送到service IP,而是直接发送到pod。这是大多数ingress实现的工作方式。
图12.3 通过Ingree访问pods
12.1.3 安装ingress控制器在开始创建ingress之前,需要确保在集群中运行了一个ingress控制器。正如在前一节中了解到的,并不是所有Kubernetes集群都有ingress控制器。
如果使用的是云提供商的托管集群,则已经有了一个ingress 控制器。在谷歌Kubernetes引擎中,ingress 控制器是GLBC (GCE L7 Load Balancer),在AWS中,Ingress 功能是由AWS Load Balancer Controller提供的,而Azure提供了AGIC(Application Gateway Ingress Controller)。查看云提供商的文档,看看是否提供了ingress 控制器,以及是否需要启用它。或者,可以自己安装ingress 控制器。
正如您已经知道的,有许多不同的ingress 实现可供选择。它们都提供了前一节中解释的流量路由类型,但都提供了不同的附加特性。在本章的所有例子中,我都使用了Nginx ingress controller。我建议您也使用它,除非您的集群提供了一个不同的方法。
注意
Nginx ingress 控制器有两种实现。一个是Kubernetes的维护者提供的,另一个是Nginx本身的作者提供的。如果你是Kubernetes的新手,你应该从前者开始。这是我用过的。
12.2 创建和使用Ingress对象安装nginx ingress 控制器
无论如何运行Kubernetes集群,都应该能够按照Installation Guide - NGINX Ingress Controller上的说明安装Nginx ingress 控制器。
如果使用kind工具创建了集群,可以运行以下命令安装控制器:
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml如果使用Minikube运行集群,可以如下方式安装控制器:
$ minikube addons enable ingress
上一节解释了Ingress对象和控制器的基础知识,以及如何安装Nginx的Ingress控制器。在本节中,将学习如何使用Ingress公开Kiada套件的服务。
在创建第一个Ingress对象之前,必须部署Kiada套件的pod和services。如果遵循了前一章的练习,它们应该已经在那里了。如果没有,可以通过创建 kiada 命名空间来创建它们,然后使用以下命令应用Chapter12/SETUP/目录中的所有清单:
$ kubectl apply -f SETUP/ --recursive12.2.1 通过Ingress公开service
一个Ingress对象引用一个或多个Service对象。第一个Ingress对象公开了在前一章中创建的 kiada 服务。在创建Ingress之前,请查看以下清单中的服务清单,以刷新记忆。
#清单12.1 kiada服务清单 apiVersion: v1 kind: Service metadata: name: kiada #注意服务名称,因为Ingress对象将通过名称引用服务。 spec: type: ClusterIP #这是一个ClusterIP服务,因此只能从集群内部访问。 selector: app: kiada ports: - name: http port: 80 targetPort: 8080 - name: https port: 443 targetPort: 8443
服务类型是ClusterIP,因为服务本身不需要被集群外的客户端直接访问,因为Ingress会处理这个问题。尽管该服务公开端口80和443,但Ingress只将流量转发到端口80。
创建Ingress对象
Ingress对象清单如下所示。可以在本书代码库的 Chapter12/ing.kiada-example-com.yaml 文件中找到。
#清单12.2一个在kiada.example.com上公开kiada服务的Ingress对象 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: kiada-example-com #虽然此对象的名称与主机匹配,但非必须。 可以给对象命名任何想要的名字。 spec: rules: - host: kiada.example.com #该Ingress规则匹配所有主机头部设置为kiada.example.com的HTTP请求。 http: paths: - path: / #该规则匹配所有请求,无论请求中的路径是什么。 pathType: Prefix backend: #请求被转发到kiada服务的80端口。 service: name: kiada port: number: 80
清单定义了一个名为 kiada-example-com的Ingress对象。虽然可以给对象任何想要的名称,但建议名称反映在入口规则中指定的主机和/或路径。
警告
在谷歌Kubernetes引擎中,Ingress名称不能包含点,否则在与Ingress对象关联的事件中会显示如下错误信息:
Error syncing to GCP: error running load balancer syncing routine: invalid loadbalancer name.
清单中的Ingress对象定义了一个规则。该规则规定,对主机kiada.example.com的所有请求都应该转发到kiada服务的端口80,而不管请求的路径是什么(由path和pathType字段表示)。如下图所示。
图12.4 kiada-example-com Ingress对象配置外部流量路由
检查Ingress对象,获取其公网IP地址
在使用kubectl apply创建了Ingress对象之后,可以通过kubectl get Ingress在当前命名空间中列出Ingress对象来查看它的基本信息,如下所示:
$ kubectl get ingresses NAME CLASS HOSTS ADDRESS PORTS AGE kiada-example-com nginx kiada.example.com 11.22.33.44 80 30s
注意
可以用ing作为ingress的缩写。
要详细查看Ingress对象,使用kubectl describe命令,如下所示:
$ kubectl describe ing kiada-example-com Name: kiada-example-com #Ingress对象的名称和命名空间。 Namespace: default Address: 11.22.33.44 #为该ingress处理请求的负载均衡器的IP地址。 Default backend: default-http-backend:80 (172.17.0.15:8080) #如果请求不匹配任何规则,它将被转发到此服务。 在12.2.4节中解释。 Rules: #对于每个规则,主机、路径、目标服务及其端点都显示出来。 Host Path Backends ---- ---- -------- kiada.example.com / kiada:80 (172.17.0.4:8080,172.17.0.5:8080,172.17.0.9:8080) Annotations:Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Sync 5m6s (x2 over 5m28s) nginx-ingress-controller Scheduled for sync
如您所见, kubectl describe 命令列出了Ingress对象中的所有规则。对于每个规则,不仅显示目标服务的名称,还显示其端点。如果看到与默认后端相关的错误消息,请暂时忽略它。你以后会解决的。
kubectl get和kubectl describe都显示Ingress的IP地址。这是L7负载均衡器或反向代理的IP地址,客户端应该向其发送请求。在回显中,IP地址为11.22.33.44,端口为80。
注意
地址可能不会立即显示。当集群在云中运行时,这是非常常见的。如果几分钟后没有显示该地址,说明没有ingress控制器处理过ingress对象。检查控制器是否运行。因为一个集群可以运行多个ingress控制器,如果没有指定哪个控制器应该处理它,它们可能会忽略你的ingress对象。检查选择的ingress控制器的文档,看看是否需要添加kubernetes.io/ingress.class注释,或者在ingress对象中设置spec.ingressClassName字段。稍后您将对这个领域有更多的了解。
也可以在Ingress对象的status字段中找到IP地址,如下所示:
$ kubectl get ing kiada -o yaml ... status: loadBalancer: ingress: - ip: 11.22.33.44 #ingress地址是主机名或者IP地址。
注意
有时显示的地址可能会误导。例如,如果使用Minikube并在虚拟机中启动集群,ingress 地址将显示为localhost,但这仅从虚拟机的角度来看是正确的。实际的ingress 地址是虚拟机的IP地址,可以通过minikube ip命令获取。
将ingress IP添加到DNS
将Ingress添加到生产集群后,下一步是将一条记录添加到Internet域的DNS服务器。在这些例子中,我们假设您拥有域名example.com。如果需要外部客户端通过ingress 访问您的服务,需要配置DNS服务器将域名kiada.example.com解析为入口IP 11.22.33.44。
在本地开发集群中,不必处理DNS服务器。因为您只能从自己的计算机访问服务,所以可以通过其他方式让它解析地址。下面将解释这一点,以及如何通过ingress访问服务的说明。
通过ingress访问服务
完整版请关注公众号 登峰大数据。



