ingress的安装、资源讲解、为什么需要ingress资源

前言

环境:centos7.9 docker-ce-20.10.9 kubernetes-version v1.22.6

本篇来讲解k8s中ingress资源。

什么是ingress资源,为什么需要ingress资源

Kubernetes 中,为了使外部的应用能够访问集群内的service,最为常用的是使用 NodePortLoadBalancer 两种类型的service,但它们在使用上还是有一些限制:如,对外提供访问时,NodePort 类型需要在外部搭建额外的负载均衡,比如F5或nginx反向代理,NodePort方式最大的缺点是会占用很多集群机器的端口;而 LoadBalancer 要求 Kubernetes 必须跑在支持的 Cloud Provider 上,由云厂商提供公网IP地址,同时当存在多个LoadBalancer 的类型service时,就会占用大量公网ip地址,而ingress正是为解决以上这种问题而存在的。

NodePort的缺点

这种方式的service要求集群中部分节点有被外网访问的能力。Kubernetes为每一个NodePort类型的服务在集群中的每一个节点上分配至少一个主端口号。客户经过能被外网访问的节点IP加上节点端口的方式访问服务。大多数状况下不会经过这种方式向集群外暴露服务,缘由有四:
1、大多状况下,为了安全起见,集群中的节点位于完全封闭的内网环境中,不该有被外网直接访问的能力。通常外网访问集群中的节点都是经过边界服务器如网关、跳板等,而这种边界服务器须要经过各类方式进行层层安全加固;
2、若是集群内节点能够被外网直接访问的话,将会使集群内节点地址、服务名称、端口号等信息直接暴露在外,很不安全;
3、服务端口号通常由系统自动分配,并不是固定,而服务名称也可能发生变动,此时外部客户端须要跟踪变动并修改,属于重试耦合;
4、NodePort这种类型的service,每一个服务都会在node节点起一个端口号,当创建的service很多时会占用很多集群节点机器的端口。

LoadBalancer 的缺点

LoadBalancer通常由云服务供应商提供或者用户自定义,运行在集群以外。在建立service时为其配置LoadBalancer相关参数,当从外网访问集群内servcie时,用户直接链接到LoadBalancer服务器,LoadBalancer服务器再将流量转发到集群内service。Loadbalancer配置及使用方法与各云服务供应商有关,本文不详细描述。

ingress资源(简写ing)

除了使用NodePortLoadBalancer来暴露service,k8s还支持使用ingress资源来暴露service,想要使用ingress,首先必须先创建ingress -controller,即ingress控制器,ingress控制器有很多种,目前k8s官方的ingress控制器是ingress-nginx-controller,由此可见ingress其实也是使用了nginx的7层反向代理来实现的。

ingress的简写为ing,ingress可以实现暴露多个service,即当外部客户端向一个ingress发送连接请求时,ingress会根据请求的主机和路径来决定将请求转发给对应的service。
;

Ingress包含的组件

Ingress ControllerIngress控制器,具体实现反向代理即负载均衡的程序,实现七层转发的Edge Router,通过调用k8s的api动态感知集群中Pod的变化而动态更新配置文件并重载, Controller需要部署在k8s集群中以实现和集群中的pod通信,通常以DaemonSetsDeployments的形式部署,并对外暴露80和443端口,对于DaemonSets来说,一般是以hostNetwork或者hostPort的形式暴露,Deployments则以NodePort的方式暴露,Ingress控制器的多个节点则借助外部负载均衡ExternalLB以实现统一接入;

Ingress资源对象:配置规则,即定义如何转发到service的规则;

ingress(以nginx为例)的工作原理

1、用户编写ingress规则,说明哪个域名对应kubernetes集群中的哪个service;
2、ingress控制器动态感知ingress服务的规则的变化,然后生成一段对应的nginx配置;
3、ingress控制器会将生成的nginx配置写入到一个运行着的nginx服务中,并动态更新;
4、到此为止,其实真正工作的就是一个nginx了,内部配置了用户定义的请求转发规则;

方法一、安装ingress-nginx-controller

根据官网的yaml文件来部署即可,不过yaml文件使用的k8s官网的镜像,可能下载不到。

https://kubernetes.github.io/ingress-nginx/deploy

这种部署方式其实是使用DaemonSets 来部署的,同时配置了 ingress-nginx Pod 使用它们运行的​​主机的网络,而不是专用的网络命名空间。 这种方法的好处是 NGINX Ingress 控制器可以将端口 80 和 443 直接绑定到 Kubernetes 节点的宿主机网络接口,而无需 NodePort 服务强加的额外网络转换。

# 从官网下载下俩的yaml文件,需要修改下面这两点:
  dnsPolicy: ClusterFirstWithHostNet 		#默认是ClusterFirst,如果hostNetwork: true则必须改为ClusterFirstWithHostNet
  hostNetwork: true							#使用宿主机网络,表示直接将端口绑定到主机上

[root@master ingress-nginx]# kubectl get ds -n ingress-nginx 
NAME                       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
ingress-nginx-controller   2         2         2       2            2           kubernetes.io/os=linux   15h
[root@master ingress-nginx]#
[root@master ingress-nginx]# kubectl get pods -n ingress-nginx   
NAME                             READY   STATUS    RESTARTS        AGE
ingress-nginx-controller-lv5m8   1/1     Running   1 (5h19m ago)   15h
ingress-nginx-controller-qcjsr   1/1     Running   1 (5h18m ago)   15h
[root@master ingress-nginx]# 

方法二、安装ingress-nginx-controller(新版本可参考这种方式安装ingress-nginx-controller)

新版的ingress-nginx-controller居然是使用deployment部署的,而且其副本数是一个pod:

#官网
https://kubernetes.github.io/ingress-nginx/deploy/
#注意不同的k8s版本对应不同的ingress-nginx版本,我这里属于测试环境,直接部署最新的版本
wget  https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/cloud/deploy.yaml		
#编辑文件,我们需要修改一些文件	
vim deploy.yml
dnsPolicy: ClusterFirstWithHostNet 		#默认是ClusterFirst,改为ClusterFirstWithHostNet

#方法一、在deployment下添加deployment.spec.template.spec.hostNetwork,表示将deployment的容器端口号绑定到宿主机上
#但是这样会有一个问题,那就是pod副本数只能是一个,不然多个pod在同一个宿主机上岂不是端口冲突了,除非你做pod反亲和性;这里官方的yaml文件pod副本数也是一个;

#方法二、修改service的类型为NodePort类型,默认是公有云上的LoadBalancer;同时,绑定nodePort端口,这里我指定了http的30080和https的30443这两个nodePort端口
#以上两者,我选择了方法二
#注意,当创建完成ingress-nginx-controller之后,只有ingress-nginx-controller-74696c6dbc-zlffh 这种pod跑在哪个节点上,从外部节点访问该节点时才能访问的通,如,假设ingress-nginx-controller-74696c6dbc-zlffh pod 位于master节点,则页面访问http://masterIP:30080 才能正常,这一点有点想不通,30080是service的nodeport端口,按理说该端口会在每个节点上的呀,怎么只有ingress-nginx-controller-74696c6dbc-zlffh pod的端口才能正常访问?不过,基于这一点,我们可以指定master节点为ingress的特定流量入口节点,即只需要将deployment配置节点选择器即可。

kubectl apply -f  deploy.yml	#创建资源

方法三、helm 安装ingress-nginx-controller

#添加仓库
helm repo add ingress-nginx  https://kubernetes.github.io/ingress-nginx
#由于kubernetes.github.io网站是国外的,所以访问很慢
#可以去https://www.ipaddress.com/site/kubernetes.github.io上搜索对应的ID做/etc/hosts域名解析

#搜索ingress-nginx的chart包
[root@master ~]# helm search repo ingress-nginx
NAME                       	CHART VERSION	APP VERSION	DESCRIPTION                                       
ingress-nginx/ingress-nginx	4.6.0        	1.7.0      	Ingress controller for Kubernetes using NGINX a...
#拉去chart包
helm pull ingress-nginx/ingress-nginx  --version=4.6.0
#解压chart包
tar  xf ingress-nginx-4.6.0.tgz
cd ingress-nginx/
vim values.yaml
工具内容修改
(待完善)

kubectl create namespace ingress-nginx
helm install ingress-nginx xx/

创建ingress资源对象

确保已经存在运行的ingress-nginx-controller了,下面来创建一个ingress对象。

[root@master ingress-nginx]# vim ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress								#创建一个ingress资源
metadata:
  name: my-ingress							#资源名称叫my-ingress
spec:
  rules:									#定义访问规则,-横杠表示下面可以是多个数组
  - host: www.lsp.com					#主机域名
    http:									#网络协议类型
      paths:
      - path: /lsp						#将访问/lsp的请求转发到lsp服务的80端口
        pathType: Exact
        backend:
          service:
            name: lsp					#service的名称
            port: 
              number: 80					#service的端口

#以上就创建一个单一规则的ingress

查看ingress

[root@master ingress-nginx]# kubectl  get ing			#ingress的简写为ing
NAME         CLASS    HOSTS             ADDRESS                           PORTS   AGE
my-ingress   <none>   www.lsp.com   192.168.118.132,192.168.118.133   80      24m
[root@master ingress-nginx]# 

#这样,windows进行www.lsp.com域名进行解析到192.168.118.132,然后浏览器就能进行www.lsp.com+端口+访问路径进行访问了

同一个主机的不同路径,映射到不同的service

创建一个ingress,将不同的service映射到相同主机的不同路径,如下:

[root@master ingress-nginx]# vim ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress								#创建一个ingress资源
metadata:
  name: my-ingress							#资源名称叫my-ingress
spec:
  rules:									#定义访问规则,-横杠表示下面可以是多个数组
  - host: www.lsp.com					#主机域名,下面是将同一个主机的不同访问路径映射到不同的service中去
    http:									#网络协议类型
      paths:
      - path: /lsp						#将访问www.lsp.com/lsp的请求转发到lsp服务的80端口
        pathType: Exact
        backend:
          service:
            name: lsp					#service的名称
            port: 
              number: 80					#service的端口
      - path: /dossier						#将访问路径www.lsp.com/dossier的请求转发到Tomcat服务的8080端口
        pathType: Exact
        backend:
          service:
            name: dossier					#service的名称
            port: 
              number: 8080					#service的端口


#以上,根据请求的URL中的路径,请求将发送到2个不同的服务,因此,客户端可以通过一个IP地址(ingress控制器的ip地址)访问2个不同的服务。

不同的主机,映射到不同的service

同理,也可以在一个ingress中定义不同的主机,来映射到不同的service,如下所示:

[root@master ingress-nginx]# vim ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress								#创建一个ingress资源
metadata:
  name: my-ingress							#资源名称叫my-ingress
spec:
  rules:									#定义访问规则,-横杠表示下面可以是多个数组
  - host: www.lsp.com					#第一个主机域名
    http:									#网络协议类型
      paths:
      - path: /lsp						#将访问www.lsp.com/lsp的请求转发到lsp服务的80端口
        pathType: Exact
        backend:
          service:
            name: lsp					#service的名称
            port: 
              number: 80					#service的端口
  - host: www.dossier.com 					#第二个主机域名
    http:  
      paths:
      - path: /dossier						#将访问路径www.dossier.com/dossier的请求转发到Tomcat服务的8080端口
        pathType: Exact
        backend:
          service:
            name: dossier					#service的名称
            port: 
              number: 8080					#service的端口

#以上,根据请求中的host头,请求将被分发到对应的主机的service中去,因此,客户端可以通过一个IP地址(ingress控制器的ip地址)访问多个主机/域名中的service。

更改ingress的默认80端口

前面我们在ingress的yaml文件中定义了访问域名,如www.lsp.com,然后在浏览器就能指定路径访问了,如:http://www.lsp.com/lsp,但是细心的人会发现,我们访问的时候并没有指定端口,这时http协议默认就是80端口,如果客户不给使用80端口,或者80端口已经被占用了,那这么办?这时就需要修改ingress的默认端口了,我们知道ingress使用的是nginx(官网推荐就是nginx),所以80端口其实就是ingress的默认端口,我们如果有需求要改变该端口,可以在ingress控制器中做修改,如下:

在这里插入图片描述
然后kubectl apply -f ingress-nginx-controller-deployment.yaml,pod就会被重新创建,然后页面访问就需要指定端口访问了,如:http://www.lsp.com:8012/lsp

配置ingress处理TLS传输(https)

https是需要秘钥和证书的,所以首先需要创建秘钥和证书,如下:

#创建证书
[root@master ingress-nginx]# openssl genrsa -out tls.key 2048
[root@master ingress-nginx]# openssl req -new -x509 -key tls.key -out tls.cert -days 365 -subj  /CN=www.lsp.com
#创建秘钥
[root@master ingress-nginx]# kubectl  create secret tls tls-secret --cert=tls.cert --key=tls.key
secret/tls-secret created
#创建一个使用https协议链接的ingress资源
[root@master ingress-nginx]# cat my-ingress-tls.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  tls:								#定义tls参数
  - hosts:
    - www.lsp.com				#指定访问的主机
    secretName: tls-secret			#指定使用的秘钥
  rules:							#下面这些和之前的保持不变
  - host: www.lsp.com
    http:
      paths:
      - path: /
        pathType: Exact
        backend:
          service:
            name: svc-nginx-clusterip-ingress2
            port:
             number: 8099
[root@master ingress-nginx]# 

此时,网页访问:https://www.lsp.com/ 就能正常访问了,https默认端口是443。

使用负载均衡器将流量负载到到多个ingress节点

ingress上定义了域名,那么客户端浏览器必须使用域名进行访问,生产中可以需要多个ingress节点接收流量,所以整个流程是这样的:

1、用户访问http://www.fuyu.com域名
2、LB解析了www.fuyu.com域名,所以请求到达LB服务器上,LB服务器可以是nginx或F5等软硬件;
3、LB服务器上根据域名配置了对多个node节点80端口进行请求转发;
4、80端口是ingress绑定的,所以ingress接收流量,并根据定义的规则转发给对应的service;
5、service将流量转发到后端的pod。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值