【Kubernetes系列七】Ingress资源对象
k8s提供了两种内建的云端负载均衡机制用于发布公共应用,一种是工作于传输层的service资源,它实现的是TCP负载均衡器,另一种是Ingress资源,它实现的是HTTP(S)负载均衡器。
TCP负载均衡器
无论是iptables还是ipvs模型的service资源都配置于Linux内核中的netfilter之上进行四层调度,是一种类型更为通用的调度器,支持调度HTTP、MYSQL等应用层服务。不过,也正是由于工作于传输层从而使得它无法做到类似卸载https种的ssl会话等一类操作,也不支持基于url的请求调度机制,而且,k8s也不支持为此类负载均衡器配置任何类型的健康检查机制
HTTP(S)负载均衡器
HTTP(S)负载均衡器是应用层负载均衡机制的一种,支持根据环境做出更好的调度决策。与传输层调度器相比,它提供了诸如可自定义url映射和tls卸载等功能,并支持多种类型的后端服务器监控状态检测机制。
1. Ingress和Ingress Controller
service资源和pod资源的IP地址仅能用于集群网络内部的通信,所有的网络流量都无法穿透边界路由器以实现集群内外通信。尽管可以为service使用NodePort或LoadBalancer类型通过节点引入外部流量,但它依然是4层流量转发,可用的负载均衡器也为传输层负载均衡机制。
Ingress是k8s的标准资源类型之一,它其实就是一组基于DNS名称或URL路径把请求转发至指定的service资源的规则,用于将集群外部的请求流量转发至集群内部完成服务发布。然而,Ingress资源自身并不能进行流量穿透,它仅是规则的集合,这些规则要想真正发挥作用还需要其他功能的辅助,如监听某套接字,然后根据这些规则的匹配机制路由请求流量。这种能够为Ingress资源监听套接字并转发流量的组件称为Ingress控制器。
Ingress控制器可以由任何具有反向代理功能的服务程序实现,如Nginx、Envoy和Traefik等。Ingress控制器自身也是运行于集群中的pod资源对象,它与被代理的运行为pod资源的应用运行于同一网络中。使用Ingress资源进行流量分发时,Ingress控制器可基于某Ingress资源定义的规则将客户端的请求流量直接转发至与service对应的后端pod资源之上,这种转发机制会绕过service资源,从而省去了由kube-proxy实现的端口代理开销。Ingress规则需要由一个service资源对象辅助识别相关的所有pod对象,但Ingress-nginx控制器可经由api.ilinux.io规则的定义直接将请求流量调度至后端pod上,而无须经由service对象api的再次转发。
2. 创建Ingress资源
Ingress资源是基于http虚拟主机或url的转发规则,它在资源配置清单的spec字段中嵌套了rules、backend和tls等字段的定义:
示例: 把发往www.ilinux.io的请求代理给名为myapp-svc的service资源
~]# cat my-ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: www.libux.io
http:
paths:
- backend:
serviceName: myapp-svc
servicePort: 80
资源清单中annotation用于识别其所属的Ingress控制器的类型,这一点在集群中部署有多个Ingress控制器时尤为重要。
Ingress spec中的字段是定义Ingress资源的核心组成部分:
rules:用于定义当前Ingress资源的转发规则列表;未由rules定义规则,或者没有匹配到任何规则时,所有流量都会转发到由backend定义的默认后端。
backend:默认的后端用于服务那些没有匹配到任何规则的请求;定义Ingress资源时,至少应该定义backend或rules两者之一;此字段用于让负载均衡器指定一个全局默认的后端。
tls:TLS配置,目前仅支持通过默认端口443提供服务,如果要配置指定的列表成员指向了不同的主机,则须通过SNI TLS扩展机制来支持此功能。
backend对象的定义由两个必选的内嵌字段组成:serviceName和servicePort,分别用于指定流量转发的后端目标service资源的名称和端口。
rules对象由一系列配置Ingress资源的host规则组成,这些host规则用于将一个主机上的某个url路径映射至相关的后端service对象。
spec:
rules:
- host: <String>
http:
paths:
- backend:
serviceName: <String>
servicePort: <String>
path: <String>
注意:spec.rules.host属性值目前不支持使用IP地址,也不支持后跟端口号,且字段值留空表示通配所有的主机名。
tls对象由两个内嵌字段组成,仅在定义tls主机的转发规则时才需要定义此类对象:
hosts:包含于使用的tls证书之内的主机名称字符串列表,因此,此处使用的主机名必须匹配tlsSecret中的名称
secretName:用于引用SSL会话的secret对象名称,在基于SNI实现多主机路由的场景中,此字段可选。
3. Ingress资源类型
基于http暴露的每个service资源均可发布于一个独立的FQDN主机名之上,如www.ik8s.io;也可发布于某主机的URL路径之上,从而将它们整合到同一个web站点,如www.ik8s.io/frafana。至于是否需要发布为https类型的应用则取决于用户的业务需求。
(1) 单service资源型Ingress
暴露单个服务的方法有很多种,如服务类型中的NodePort、LoadBalancer等,不过一样可以考虑Ingress来暴露服务,此时只需要为Ingress指定default.backend即可
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
backend:
serviceName: my-svc
servicePort: 80
Ingress控制器会为其分配一个IP地址接入请求流量,并将它们转至后端。
(2) 基于url路径进行流量分发
垂直拆分或微服务架构中,每个小的应用都有其专用的service资源暴露服务,但在对外开放的站点上,它们可能时财经、新闻、电商即可等一类的独立应用,可通过主域名的url路径分别接入,用于发布集群内名称为API和WAP的service资源。于是,可对应地创建一个如下的Ingress资源:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
anotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: www.ilinux.io
http:
paths:
- path: /wap
backend:
serviceName: wap
servicePort: 80
- path: /api
backend:
serviceName: api
servicePort: 80
(3) 基于主机名称的虚拟主机
将多个FQDN解析至同一IP地址
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: api.ik8s.io
http:
paths:
- backend:
serviceName: api
servicePort: 80
- host: wap.ik8s.io
http:
paths:
- backend:
serviceName: wap
servicePort: 80
(4) TLS类型的Ingress资源
这种类型用于以https发布service资源,基于一个含有私钥和证书的secret对象即可配置TLS协议的Ingress资源,目前来说,Ingress资源仅支持单TLS端口,并且还会卸载TLS会话,在Ingress资源中引用此secret即可让Ingress控制器加载并配置为https服务
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: no-rules-map
spec:
tls:
- secretName: ikubernetesSecret
backend:
serviceName: homesite
servicePort: 80
4.部署Ingress控制器(使用Nginx)
运行为pod资源的Ingress控制器进程接入外部的请求流量常用的有两种解决方案:
第一种:以deployment控制器管理Ingress控制器的pod资源,并通过NodePort或LoadBalancer类型的service对象为其接入集群外部的请求流量,这就意味着,定义一个Ingress控制器时,必须在其前端定义一个专用的service资源
第二种:借助于DaemonSet控制器,将Ingress控制器的pod资源各自以单一实例的方式运行于集群的所有或部分工作节点之上,并配置这类pod对象以hostPort或hostNetwork的方式在当前节点接入外部流量。
例子:发布tomcat应用实践
(1) 创建Ingress控制器
Ingress控制器把ingress规则转换为nginx配置文件,然后创建一个service,为ingress控制器提供入口,采用nodeport
~]# wget https://github.com/kubernetes/ingress-nginx/tree/master/deploy/static/mandatory.yaml
~]# kubectl get nodes --show-labels #查看node的标签
NAME STATUS ROLES AGE VERSION LABELS
master.ilinux.io Ready master 98d v1.12.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master.ilinux.io,node-role.kubernetes.io/master=
node01.ilinux.io Ready <none> 98d v1.12.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=node01.ilinux.io
node02.ilinux.io NotReady <none> 98d v1.12.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node02.ilinux.io
node03.ilinux.io NotReady <none> 97d v1.12.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node03.ilinux.io
需要修改mandatory.yaml文件中的nodeSelector符合上述节点标签对应
~]# vi mandatory.yaml
spec --> spec --> nodeSelector --> beta.kubernetes.io/os: linux
~]# kubectl apply -f mandatory.yaml
上述操作创建ingress-nginx名称空间及ingress-nginx控制器
(2) 定义一个service,作为Ingress控制器的service资源入口,此处为NodePort 类型
~]# cat nginx-ingress-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
spec:
type: NodePort
clusterIP: 10.99.99.99
ports:
- port: 80
name: http
nodePort: 30080
- port: 443
name: https
nodePort: 30443
selector:
app.kubernetes.io/name: ingress-nginx
此时,可以通过node节点IP的30080端口测试,结果为404即为成功
(3) 创建testing名称空间,部署tomcat应用
~]# kubectl create namespace testing
~]# cat tomcat-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-deploy
namespace: testing
spec:
replicas: 2
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- name: tomcat
image: tomcat:8.0.50-jre8-alpine
ports:
- containerPort: 8080
name: httpport
- containerPort: 8009
name: ajpport
~]# kubectl get pods -n testing
NAME READY STATUS RESTARTS AGE
tomcat-deploy-5b9cfbdcb4-7hd4c 1/1 Running 0 10m
tomcat-deploy-5b9cfbdcb4-ph459 1/1 Running 0 10m
(4) 为tomcat实例提供service资源
~]# cat tomcat-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: tomcat-svc
namespace: testing
labels:
app: tomcat-svc
spec:
selector:
app: tomcat
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
(5) 为service提供ingress资源,编写规则
~]# cat tomcat-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: tomcat
namespace: testing
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: tomcat.ilinux.io
http:
paths:
- path:
backend:
serviceName: tomcat-svc
servicePort: 80
~]# kubectl get ingress -n testing
NAME HOSTS ADDRESS PORTS AGE
tomcat tomcat.ilinux.io 80 24h
此时,本地绑定hosts(ingress域名,node节点IP),可以访问域名的30080端口即可访问
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现