k8s之ingress

写在前面

本文接k8s之Service 。

k8s之ingress_第1张图片
在k8s之Service 一文中我们分析了service API对象,该API对象能够实现多个POD的负载均衡访问,以及服务的自动发现,但是这是一种基于四层的负载均衡方式,只支持基于IP地址的负载均衡,而现在业务几乎都是基于http、https的七层协议,即需要能够根据域名,域名后缀,甚至请求头等信息来负载均衡,为了解决这个问题k8s在Service API的基础上又扩展出来了ingress API对象(但其实ingress仅仅是一个路由配置规则,并不负责规则的解析,但大家习惯上都称这种基于七层协议的负载均衡机制为ingress,后面我们也会看到这些内容)。下面我们就开始吧!

1: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之ingress_第2张图片

到这里应该就告一段了,k8s的ingres就可以安安心心的对外提供服务了,但是现实总是让你不得安生,在用户的实际使用过程中,因为k8s仅仅支持一个ingress controller,一些问题就暴露了,如下:

1:一个ingress controller,当ingress规则比较多时,规则解析压力会比较大,可能成为性能瓶颈
2:因为业务需要,确实需要多个ingress controller
3:各种路由规则都混杂在一个ingress中,造成路由规则的维护成本过高

核心问题就是不能只支持一个ingress controller,那么为了解决这个问题,k8s又引入了一个新的API对象,即ingress class,该对象的作用就是在ingress controller和ingress中间,起一个转换器的作用。所以最后的结构就是这样子的:
k8s之ingress_第3张图片
其中红色半透明区域多组来支持多个ingress controller,但实际上我们一般只会使用一个ingress controller,这样ingress主要结构我们就介绍完成了,接下来看下实际的操作。

2:实战

2.1:定义ingress路由规则和ingress class

首先我们来定义路由规则,访问本文 已经定义好的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信息也都列举了出来。此时结构可以参考下图:

k8s之ingress_第4张图片

2.2:定义ingress controller

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来运行的(这似乎是句废话!),此时结构如下图:

k8s之ingress_第5张图片

但是因为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的各种实现,最后给出了一个具体的实战例子。希望本文能够帮助到你。

参考文章列表

你可能感兴趣的:(k8s,kubernetes,docker,ingress,七层负载)