Kubernetes Ingresses (1)

在连接上一个 K8S cluster 后执行下面的命令可以看到系统中的 ingressclasses。这篇文字用来帮助自己理解下面几行简单的输出。

╰─$ kubectl get ingressclass
NAME       CONTROLLER                     PARAMETERS                             AGE
awslb      ingress.k8s.aws/alb            IngressClassParams.elbv2.k8s.aws/alb   20d
nginx      nginx.org/ingress-controller   <none>                                 30d
os-nginx   k8s.io/ingress-nginx           <none>                                 30d

Mental Model

在 Kubernets 里经常会提到 Pod,Service,Ingress,Ingress Controller, Ingress Class,那他们之间有什么逻辑关系呢?

Pod

Pod 用于把几个相关的 containers 封装在一起对外提供业务服务,containers 之间可以直接通过 localhost 通讯。而如果想访问 POD 服务只能凭借 POD 的 IP,这个 IP 也是 K8S 集群内部可见,而 POD 的 IP 在每次重建后都会变化,这显然是不可接受的。

Service

Service 就是为了解决这个问题而生,通过 service.yaml 可以定义 1)这个 service 的 name/namespace;2)由 selector 定义这个 service 对应的 PODs;3)再通过定义 service port 和 pod port 的映射关系,就可以通过 Service 的名称访问 PODs 提供的服务了。Service 借助自己对 Pod 自动发现的能力、服务名到 POD IP 的解析能力、简单的负载均衡能力,成为在 Kubernets 集群内部暴露 Pod 的不二之选。

Ingress / Ingress Controller / Ingerss Class

Service 解决了我们在 k8s 集群内部访问‘服务’的问题。如果想从集群外部访问‘服务’呢?这正是“Ingress 机制”七层路由存在的意义。这里的 Ingress 机制由 Ingress Controller、Ingress 这两个概念组成。
作为码农,接触较多的一般是 Ingress。这是因为 Ingress Controller 一旦部署到 Kubernetes Cluster 就很少会再去改动,而需要经常改动的应用路由规则都是在 Ingress 这个 Kubernets API 对象(或者说是在 ingress.yaml 文件)完成的。实际上,Ingress Controller 实例才是真正执行将用户请求路由到 Service 进而到 Pod的部件。Ingress 只是我们定义请求到 Service 的路由规则的对象。

既然“ingress“的核心功能就是 7 层路由/反向代理,那么借助早已存在的 Nginx、HAProxy 等产品实现 IngressController 就是很自然的想法了。另一个 ingress controller 的实现类别可以划分到 service mesh 阵营,比如 Istio Ingerss、Gloo 等。
k8s 官网列出的一些 Ingerss Controller 实现
这篇文章详细讲解了各种 Ingress Controller 的特性以方便我们根据自己项目的需求做出选择。直接贴上文章的干货图片:
kubernetes-ingress-comparison

在一个 Kubernets 集群里可以定义多个不同 Ingress Controller 实现/类型,那么 Ingress 对象如何知道自己的数据是提供给哪个 Ingress Controller 的呢?

在 Kubernetes 1.18 之前,是通过在 Ingress 的一个annotation kubernets.io/ingress.class 来声明。
在 Kubernetes 1.18 正式引入了一个新的k8s 资源对象 IngressClass帮助 Ingress 定义它绑定到哪个 IngressController
下面是一个官网的 IngressClass 对象定义示例,spec.controll定义了 IngressController 的实现, spec.parameters 相当于定义了你可以在 Ingerss 对象里可以向这个 IngressController 对象能够传递的参数,当然这些参数也是这种 IngressControll 必须支持的。不同的 Ingress Controller 实现其需要的 parameter 肯定是不同的,而 k8s 1.18 之前通过 annoation 给 IngerssController 传递参数的方式就显得比较随意无章可循了,这应该也是 IngressClass 出现的一个原因。

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: external-lb
spec:
  controller: example.com/ingress-controller
  parameters:
    apiGroup: k8s.example.com
    kind: IngressParameters
    name: external-lb

有了 IngressClass,那么在 Ingress 中只要设置 spec.ingressClassName 为某个 IngerssClass 的名字,那么就意味着这个 Ingress 的配置就会被这个 IngerssClass 所对应的 IngressController 所获取并被这个 IngressControll 生成为对应的路由 rules,从而完成把一个集群外请求路由到 Service 的功能。

以上就是关于 Kubernetes 里 Ingerss 的几个基本概念。

有关 Nginx 的 IngressController

基于 Nginx 实现的 IngressController 分为Kubernets社区版Nginx版

Kubernets 社区版由 Kubernetes 社区和 F5 Nginx 工程师基于开源的 Nginx 实现,其官网 code doc

Nginx 版自己又分为免费的基于开源 Nginx 的 IngressController 实现和商业版。Nginx 开源版code doc

所以就开源的版本来说,一个是 Kubernets 社区版,一个是 Nginx 开源版,两个都是基于开源的 Nginx 实现的,只是 owner 不通。表现在 IngressClass 的定义中,就是字段 spec.controller 的值一个是 Kubernets 社区版的 k8s.io/ingress-nginx, 一个是 nginx 开源版的 nginx.org/ingress-controller

下面这个表格列出了 Nginx Ingress Controller 的 Kubernets 社区版和 Nginx 开源版的区别。可以看到,两者差别不大,k8s 社区版功能略好于 Nginx 开源版。而 Nginx 开源版因为没有使用 Lua 性能又好于 k8s 社区版。

Aspect or Feature kubernetes/ingress-nginx nginxinc/kubernetes-ingress with NGINX nginxinc/kubernetes-ingress with NGINX Plus
Fundamental
Authors Kubernetes community NGINX Inc and community NGINX Inc and community
NGINX version Custom NGINX build that includes several third-party modules NGINX official mainline build NGINX Plus
Commercial support N/A N/A Included
Implemented in Go/Lua (while Nginx is written in C) Go/Python Go/Python
Load balancing configuration via the Ingress resource
Merging Ingress rules with the same host Supported Supported via Mergeable Ingresses Supported via Mergeable Ingresses
HTTP load balancing extensions - Annotations See the supported annotations See the supported annotations See the supported annotations
HTTP load balancing extensions – ConfigMap See the supported ConfigMap keys See the supported ConfigMap keys See the supported ConfigMap keys
TCP/UDP Supported via a ConfigMap Supported via custom resources Supported via custom resources
Websocket Supported Supported via an annotation Supported via an annotation
TCP SSL Passthrough Supported via a ConfigMap Supported via custom resources Supported via custom resources
JWT validation Not supported Not supported Supported
Session persistence Supported via a third-party module Not supported Supported
Canary testing (by header, cookie, weight) Supported via annotations Supported via custom resources Supported via custom resources
Configuration templates See the template See the templates See the templates
Load balancing configuration via Custom Resources
HTTP load balancing Not supported See VirtualServer and VirtualServerRoute resources See VirtualServer and VirtualServerRoute resources
TCP/UDP load balancing Not supported See TransportServer resource See TransportServer resource
TCP SSL Passthrough load balancing Not supported See TransportServer resource See TransportServer resource
Deployment
Command-line arguments See the arguments See the arguments See the arguments
TLS certificate and key for the default server Required as a command-line argument/ auto-generated Required as a command-line argument Required as a command-line argument
Helm chart Supported Supported Supported
Operator Not supported Supported Supported
Operational
Reporting the IP address(es) of the Ingress controller into Ingress resources Supported Supported Supported
Extended Status Supported via a third-party module Not supported Supported
Prometheus Integration Supported Supported Supported
Dynamic reconfiguration of endpoints (no configuration reloading) Supported with a third-party Lua module Not supported Supported

再回到文章开头的命令输出,是不是看到的更多了些?

╰─$ kubectl get ingressclass
NAME       CONTROLLER                     PARAMETERS                             AGE
awslb      ingress.k8s.aws/alb            IngressClassParams.elbv2.k8s.aws/alb   20d
nginx      nginx.org/ingress-controller   <none>                                 30d
os-nginx   k8s.io/ingress-nginx           <none>                                 30d

References:
[1]: Ingress
[2]: IngressController
[3]: IngressClass
[4]: Comparing Ingress Controllers for Kubernetes
[5]: 基于 Nginx 的 Ingress Controller 在社区和商业版之间的比较
[6]: Kubernetes 社区版
[7]: Nginx 开源版
[8]: Nginx Ingress Controll 社区版和 Nginx 开源版的比较