本文接k8s之Service 。
在k8s之Service 一文中我们分析了service API对象,该API对象能够实现多个POD的负载均衡访问,以及服务的自动发现,但是这是一种基于四层的负载均衡方式,只支持基于IP地址的负载均衡,而现在业务几乎都是基于http、https的七层协议,即需要能够根据域名,域名后缀,甚至请求头等信息来负载均衡,为了解决这个问题k8s在Service API的基础上又扩展出来了ingress API对象(但其实ingress仅仅是一个路由配置规则,并不负责规则的解析,但大家习惯上都称这种基于七层协议的负载均衡机制为ingress,后面我们也会看到这些内容)
。下面我们就开始吧!
ingress API对象如下:
dongyunqi@mongodaddy:~/k8s$ kubectl api-resources|egrep -w 'Ingress|KIND'
NAME SHORTNAMES APIVERSION NAMESPACED KIND
ingresses ing networking.k8s.io/v1 true Ingress
从networking.k8s.io/v1
可以看到其是属于k8s网络系统相关的API对象,它在网络系统中的作用就是来定义路由规则,如xxx.com/
访问Service1,xxx.com/user
访问service2,xxx.com/customer
访问service3这样。但其也仅仅是给出相关的规则定义,并没有具体规则的解析以及流量的转发机制,那么为什么ingress不增加这个功能呢?还是因为单一职责
的原则,为此,k8s又专门定义了另一个API对象ingress controller,所以准确来说ingress controller才是核心,因为它是流量的入口。如此重要的一个AP对象按道理来讲k8s应该自己来开发才是,但不知道出于什么原因,将这个关键点
交给了社区开发,只要符合ingress规则即可,即能够解析ingress定义的规则,并按照此规则来转发流量。目前比较主流的ingress controller实现包括:
社区的 Kubernetes Ingress Controller(https://github.com/kubernetes/ingress-nginx)、
Nginx 公司自己的 Nginx Ingress Controller(https://github.com/nginxinc/kubernetes-ingress)、
基于 OpenResty 的 Kong Ingress Controller(https://github.com/Kong/kubernetes-ingress-controller)
本文以Nginx公司开发实现的 Ingress Controller 为例,来进行说明,此时结构如下图:
到这里应该就告一段了,k8s的ingres就可以安安心心
的对外提供服务了,但是现实总是让你不得安生
,在用户的实际使用过程中,因为k8s仅仅支持一个ingress controller,一些问题就暴露了,如下:
1:一个ingress controller,当ingress规则比较多时,规则解析压力会比较大,可能成为性能瓶颈
2:因为业务需要,确实需要多个ingress controller
3:各种路由规则都混杂在一个ingress中,造成路由规则的维护成本过高
核心问题就是不能只支持一个ingress controller
,那么为了解决这个问题,k8s又引入了一个新的API对象,即ingress class,该对象的作用就是档
在ingress controller和ingress中间,起一个转换器
的作用。所以最后的结构就是这样子的:
其中红色半透明区域多组
来支持多个ingress controller,但实际上我们一般只会使用一个ingress controller,这样ingress主要结构我们就介绍完成了,接下来看下实际的操作。
首先我们来定义路由规则,访问本文 已经定义好的service,生成yaml模板如下:
dongyunqi@mongodaddy:~/k8s$ export out="--dry-run=client -o yaml" && kubectl create ing ngx-ing --rule="ngx.test/=ngx-svc:80" --class=ngx-ink $out
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
creationTimestamp: null
name: ngx-ing
spec:
ingressClassName: ngx-ink
rules:
- host: ngx.test
http:
paths:
- backend:
service:
name: ngx-svc
port:
number: 80
path: /
pathType: Exact
status:
loadBalancer: {}
ingressClassName: ngx-ink
定义要使用ingress class是ngx-ink(后面会定义)
,- host: ngx.test
设置规则的主域名是ngx.test
,path: /
访问的路径是/
,即将访问http://ngx.test/
时会匹配到该规则。name: ngx-svc
使用名称为ngx-svc的service,number: 80
后端服务的端口号为80,pathType: Exact
代表使用精准匹配。这里用到了ingress class,只有一个比较关键的controller配置,用来设置具体的ingress controller,这里为了简单起见将ingress和ingress class的yaml定义在一起,如下:
dongyunqi@mongodaddy:~/k8s$ cat ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ngx-ing
spec:
ingressClassName: ngx-ink
rules:
- host: ngx.test
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: ngx-svc
port:
number: 80
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: ngx-ink
spec:
controller: nginx.org/ingress-controller
ingress class定义的controller是nginx.org/ingress-controller
,这是个固定的名称。apply应用,之后查看二者:
dongyunqi@mongodaddy:~/k8s$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ngx-ing ngx-ink ngx.test 80 20h
dongyunqi@mongodaddy:~/k8s$ kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
ngx-ink nginx.org/ingress-controller 20h
重点describe下ingress看下路由信息是否生效:
nqi@mongodaddy:~/k8s$ kubectl decribe ingress ngx-ing
error: unknown command "decribe" for "kubectl"
Did you mean this?
describe
dongyunqi@mongodaddy:~/k8s$ kubectl describe ingress ngx-ing
Name: ngx-ing
Labels:
Namespace: default
Address:
Default backend: default-http-backend:80 ()
Rules:
Host Path Backends
---- ---- --------
ngx.test
/ ngx-svc:80 (10.10.1.10:80,10.10.1.9:80)
Annotations:
Events:
从Rules:
可以看出当完整路径为ngx.test/
时匹配的后端服务是ngx-svc:80 (10.10.1.10:80,10.10.1.9:80)
,后端服务的POD信息也都列举了出来。此时结构可以参考下图:
ingress controller的定义相对就要麻烦一些,首先需要先安装依赖的相关信息,如congigmap,secret等,相关的文件可以从这里 下载,然后执行如下命令:
kubectl apply -f common/ns-and-sa.yaml
kubectl apply -f rbac/rbac.yaml
kubectl apply -f common/nginx-config.yaml
kubectl apply -f common/default-server-secret.yaml
kubectl apply -f crds/k8s.nginx.org_globalconfigurations.yaml
kubectl apply -f crds/k8s.nginx.org_policies.yaml
kubectl apply -f crds/k8s.nginx.org_transportservers.yaml
kubectl apply -f crds/k8s.nginx.org_virtualserverroutes.yaml
kubectl apply -f crds/k8s.nginx.org_virtualservers.yaml
然后我们可以从这里 下载ingress controller的yaml,然后就可以应用yaml了:
kubectl apply -f kic.yml
然后查看(注意此时要带上命名空间,否则从default命名空间是找不到的)
:
dongyunqi@mongodaddy:~/k8s$ kubectl get deploy -n nginx-ingress
NAME READY UP-TO-DATE AVAILABLE AGE
ngx-kic-dep 1/1 1 1 7h50m
dongyunqi@mongodaddy:~/k8s$ kubectl get pod -n nginx-ingress
NAME READY STATUS RESTARTS AGE
ngx-kic-dep-67c7cf6d5f-7v7kw 1/1 Running 0 7h50m
可以看到ingress controller也是已pod来运行的(这似乎是句废话!)
,此时结构如下图:
但是因为POD是无法直接在外部访问的,所以我们方便起见使用port-forward
直接映射端口到Node节点(port-forward在测试的时候用处还是比较大的)
,如下:
kubectl port-forward -n nginx-ingress ngx-kic-dep-8859b7b86-cplgp 8080:80 &
因为ingress是基于域名ngx.test
来解析的,所以我们需要配置host来映射到127.0.0.1
,但是方便起见这里直接直接使用curl --resolve ngx.test:8080:127.0.0.1 http://ngx.test:8080
,测试如下:
dongyunqi@mongodaddy:~/k8s$ curl --resolve ngx.test:8080:127.0.0.1 http://ngx.test:8080
Handling connection for 8080
srv : 1111111111110.10.1.10:80
host: ngx-dep-name-dcc8b7bfd-97x94
uri : GET ngx.test /
date: 2023-01-14T11:46:08+00:00
dongyunqi@mongodaddy:~/k8s$ curl --resolve ngx.test:8080:127.0.0.1 http://ngx.test:8080
Handling connection for 8080
srv : 1111111111110.10.1.9:80
host: ngx-dep-name-dcc8b7bfd-4v4dx
uri : GET ngx.test /
date: 2023-01-14T11:46:09+00:00
到这里就结束了。
本文分析了基于http/https七层协议来提供负载均衡的ingress,ingress controller,ingress class,并分析了每种API对象的作用,并提到了ingress controller的各种实现,最后给出了一个具体的实战例子。希望本文能够帮助到你。