在连接上一个 k8s cluster 后执行下面的命令可以看到系统中的ingressclasses。这篇文字用来帮助自己理解下面几行简单的输出。
╰─$ kubectl get ingressclass NAME CONTROLLER PARAMETERS AGEawslb ingress.k8s.aws/alb IngressClassParams.elbv2.k8s.aws/alb 20dnginx nginx.org/ingress-controller <none> 30dos-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实现 https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/。
而这篇文章 https://blog.palark.com/comparing-ingress-controllers-for-kubernetes/ 详细讲解了各种Ingress Controller的特性以方便我们根据自己项目的需求做出选择。直接贴上文章的干货图片:
在一个Kubernets集群里可以定义多个不同Ingress Controller实现/类型,那么Ingress对象如何知道自己的数据是提供给哪个Ingress Controller的呢?
在Kubernetes 1.18之前,是通过在Ingress的一个annotation`kubernets.io/ingress.class` 来声明。
在Kubernetes 1.18正式引入了一个新的[k8s资源对象 IngressClass](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) 来帮助Ingress定义它绑定到哪个IngressController。
下面是一个官网的IngressClass对象定义示例,`spec.controll`定义了IngressController的实现, `spec.parameters` 相当于定义了你可以在Ingerss对象里可以向这个IngressController对象能够传递的参数,当然这些参数也是这种IngressControll必须支持的。不同的Ingress Controller实现其需要的parameter肯定是不同的,而k8s 1.18之前通过annoation给IngerssController传递参数的方式就显得比较随意无章可循了,这应该也是IngressClass出现的一个原因。
代码语言:javascript复制 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](https://github.com/kubernetes/ingress-nginx) [doc](https://kubernetes.github.io/ingress-nginx/)。
Nginx版自己又分为免费的基于开源Nginx的IngressController实现和商业版。Nginx开源版[code](https://github.com/nginxinc/kubernetes-ingress) [doc](https://docs.nginx.com/nginx-ingress-controller/)。
所以就开源的版本来说,一个是Kubernets社区版,一个是Nginx开源版,两个都是基于开源的Nginx实现的,只是owner不通。表现在IngressClass的定义中,就是字段 `spec.controller` 的值一个是Kubernets社区版的 `k8s.io/ingress-nginx`, 一个是nginx开源版的 `nginx.org/ingress-controller`
下面这个表格 https://gist.github.com/grigorkh/f8e4fd73e99f0fde06a51e2ed7c2156c 列出了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 |
现在再回到文章开头的命令输出,是不是看到的东西更多了?
代码语言:javascript复制 ╰─$ 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](https://kubernetes.io/docs/concepts/services-networking/ingress/)
[2]: [IngressController](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/)
[3]: [IngressClass](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class)
[4]: [Comparing Ingress Controllers for Kubernetes](https://blog.palark.com/comparing-ingress-controllers-for-kubernetes/)
[5]: [基于Nginx的Ingress Controller在社区和商业版之间的比较](https://www.nginx.com/blogguide-to-choosing-ingress-controller-part-4-nginx-ingress-controller-options/)
[6]: [Kubernetes社区版](https://kubernetes.github.io/ingress-nginx/)
[7]: [Nginx开源版](https://kubernetes.github.io/ingress-nginx/)
[8]: [Nginx Ingress Controll社区版和Nginx开源版的比较](https://grigorkh.medium.com/there-are-two-nginx-ingress-controllers-for-k8s-what-44c7b548e678)