在讲contour之前,我们先讲什么是ingress?
Ingress 公开了从集群外部到集群内 services 的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
可以将 Ingress 配置为提供服务外部可访问的 URL、负载均衡流量、终止 SSL / TLS,以及提供基于名称的虚拟主机。
Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort 或者 Service.Type=LoadBalancer 类型的服务。
为了使Ingress资源正常工作,集群必须运行一个Ingress Controller。Ingress controller 通常负责通过负载均衡器来实现 Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。
而今天我们讲到的contour就是一个基于envoy的ingress controller。
Contour
架构
Contour Ingress controller 主要有两部分组成:
- Envoy,提供高性能的反向代理。
- Contour,充当Envoy的管理服务器并为其提供配置。
尽管可以进行其他配置,但这些容器是分开部署的,contour 通过deployment形式部署,Envoy通过daemonset 形式部署。
在Envoy Pods中,Contour在引导模式下作为initcontainer
运行,并将引导配置写入临时卷。该卷将传递到Envoy容器,并指示Envoy将Contour视为其管理服务器。
初始化完成后,Envoy容器启动,检索由Contour的引导模式编写的引导配置,并与Contour建立GRPC会话以接收配置。
如果管理服务器不可用,Envoy将正常重试,从而消除了任何容器启动订购问题。
Contour是Kubernetes API的客户端。 Contour监视Ingress,HTTPProxy,IngressRoute,Secret,Service和Endpoint对象,并通过将其对象的缓存转换为相关的JSON 来充当Envoy的管理服务器(Service objects for CDS, Ingress for RDS, Endpoint objects for SDS, and so on)。
从Kubernetes到Contour的信息传输是通过使用SharedInformer框架 Watch API来实现的。
对于Envoy,readiness probes 会检查Envoy是否已准备好接受连接。 将GET请求发送到Envoy管理端点中的/ready
。
对于Contour,liveness probes 会检查Pod的指标端口上运行的/healthz
。 readiness probes 是对gRPC端口是否打开的TCP检查。
以下是Contour如何在Kubernetes集群中工作的几个高层架构图,并显示了到后端Pod的请求的数据路径。
对projectcontour.io/blog
的请求通过负载平衡器路由到Envoy代理的实例,然后将该请求发送到Pod。
特性
Contour 作为一款高性能的ingress 控制器,具备如下特性:
- 动态更新负载均衡配置而无需drop 链接
- 支持多租户k8s集群
- 通过路由委托的方式支持跨命名空间的流量转发
- 无需注解就可以灵活地定义服务的权重和负载均衡策略
- TLS 证书委托(可以获取到其他命名空间的secret作为https 的证书,该功能对于证书的管理非常重要,实际场景中,我们可以把证书创建在管理命名空间中,其他空间通过委托来使用,减少了证书显露的风险)
那么contour 为什么要选择Envoy作为自己的数据层那?
- 通过api的方式进行配置文件更新
- 支持http2 和grpc
- 在生产环境已经被证明
部署
在开始之前,您需要:
- Kubernetes集群
- 配置了对集群的管理员访问权限的kubectl
- 必须在集群上启用RBAC
然后运行下面的命令,完成部署:
$ kubectl apply -f https://projectcontour.io/quickstart/contour.yaml
此命令创建:
- 新的名称空间projectcontour
- 名称空间中的两个Contour实例
- 在集群的每个节点上运行的Envoy(Daemonset 方式部署)在主机端口80/443上侦听
- 服务类型:LoadBalancer,它指向Contour的Envoy实例
示例
如果您尚未准备好与Contour一起运行的应用程序,则可以使用kuard。
运行以下命令:
$ kubectl apply -f https://projectcontour.io/examples/kuard.yaml
本示例为所有主机指定默认后端,以便您可以测试Contour安装。不过,建议您仅将其用于探索和测试,因为它会响应所有请求,而与映射的传入DNS无关。
有很多方法可以验证一切正常。第一种方法是使用Envoy服务的外部地址,第二种方法是将端口转发到Envoy Pod。
一些最佳实践
我大量在生产环境使用到了Contour。有一些注意点,需要大家注意。
1:Envoy 通过daemonset 方式部署是否是最佳实践?
使用daemonset 方式部署的好处是可以保证每个node一点运行一个Envoy,首先满足了高可用,同时也减少了扩缩Envoy的心智负担。
但是如果你的k8s运行在公有云上,而你使用到了node 级别的扩缩。那么我们知道node在缩容的时候,并不会驱赶daemonset部署的pod。所以做到Envoy优雅退出比较难。
那么通过deployment方式部署,无需担心优雅退出。但是容量规划又是一个问题。可以尝试使用HPA来解决。另外可以设置POD的硬反亲和来实现一台主机只运行一个Envoy的目标。
2:接受流量的服务外部流量策略选择Local
主要为了高性能,可以避免流量的二跳。当然如果你的Pod网络是类似于ENI,负载均衡器的流量直接到POD,而不是nodeport ,那么可以忽视这点。
3:对于某些应用并发比较高,需要额外设置
Kubernetes服务映射到Envoy集群。 Envoy群集具有许多设置来控制特定行为。这些注释允许访问其中一些设置。
-
projectcontour.io/max-connections
:单个Envoy实例允许与Kubernetes服务的最大连接数;默认为1024。 -
projectcontour.io/max-pending-requests
:单个Envoy实例允许给Kubernetes服务的最大挂起请求数;默认为1024。 -
projectcontour.io/max-requests
:单个Envoy实例向Kubernetes服务允许的最大并行请求;默认为1024。
当你的应用QPS比较高,必须设置一下这几个参数。
4:做好可观察性工作
主要是涉及到metrics和access log。
此处通过metrics 可以获取到应用的p99等延迟指标,但是该指标是一个sum,并不能获取到具体到某个POD。
那么我们可以通过对access log的分析,得到具体到Pod的延迟分析。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。