
一、MetalLB基本概念
1. MetalLB概述
MetalLB是面向裸金属、虚拟机等非云环境Kubernetes集群的负载均衡组件,由Controller、Speaker两大核心组件构成。支持ARP/NDP二层模式和BGP三层模式,可以为集群内LoadBalancer类型Service分配公网IP并向全网宣告。MetalLB组件弥补了自建集群原生不支持LoadBalancer服务的缺陷,不仅实现外网正常访问集群业务,还可以解决Nginx Ingress控制器外网地址一致处于Pending的问题。
2. Controller
部署形态:Deployment,集群内一般仅单个实例运行。
Controller持续监听LoadBalancer类型Service的生命周期变化,从预设IP地址池中选取可用IP分配给对应服务,同步更新服务状态字段以解除外网地址Pending状态,当服务删除后自动回收IP资源。
3. Speaker
部署形态:DaemonSet,每个节点默认运行一个。
Speaker负责将Controller分配的外部IP地址宣告至物理网络,实现外网正常访问。Speaker支持Layer2和BGP两种工作模式。
3.1 Layer 2
特点:部署配置简单,无需改动现有网络设备,缺点是同一时刻仅单个节点承担业务流量。
基于IPv4的ARP协议、IPv6的NDP协议实现。集群内所有Speaker会选举出一个主节点,虚拟IP(VIP)会被绑定至该节点。局域网内访问VIP的流量,会通过ARP/NDP解析指向主节点,再由节点内的kube-proxy转发至后端Pod。当主节点异常时,其余Speaker会重新选举,实现VIP秒级漂移切换。
3.2 BGP
特点:性能强、支持多活、路由策略灵活,缺点是要求网络设备兼容BGP。
Speaker与物理路由器建立BGP邻居,将虚拟IP通告为路由条目。路由器借助ECMP分摊流量,达成多活负载均衡。
4. 部署MetalLB
如果无法正常下载,可以访问我提供的百度云链接下载。MetalLB组件包
链接: https://pan.baidu.com/s/1XxPL_Q_lPU3MHc6FPcdIkQ?pwd=r6v5
提取码: r6v5
[Step1] 下载metallb描述文件,其实也可以使用“kubectl apply -f”一步下载和导入,但是为了方便区分安装错误的原因,这里将下载和导入步骤分开进行。
root@k8s-master:~# wget https://gh-proxy.org/https://raw.githubusercontent.com/metallb/metallb/v0.15.3/config/manifests/metallb-native.yaml
[Step2] 安装metallb。
root@k8s-master:~# kubectl apply -f metallb-native.yaml
[Step3] 验证:查看metallb-system命名空间是否存在,如果存在则证明安装成功。
root@k8s-master:~# kubectl get namespaces metallb-system
[Step4] 验证:查看metallb核心组件的状态,状态均为Running。
root@k8s-master:~# kubectl get pods -n metallb-system
5. 部署MetalLB负载均衡
[Step1] 本地新建YAML清单,定义MetalLB可分配的IP地址池,用于为集群内LoadBalancer类型的Service自动分配外部访问地址。
root@k8s-master:~# vim metallb-pool.yml
# 写入下列内容
apiVersion: metallb.io/v1beta1 # 固定配置
kind: IPAddressPool # 资源类型
metadata:
name: metallb-pool-192-168-8-100-110
namespace: metallb-system # 指定命名空间
spec:
addresses: # 地址池包含的IP范围
# 可以分配为Service的外部IP段:100~110
- 192.168.8.100-192.168.8.110[Step2] 基于YAML清单向Kubernetes集群声明式创建IPAddressPool资源。
root@k8s-master:~# kubectl create -f metallb-pool.yml[Step3] 验证:查看metallb-system命名空间内MetalLB负载均衡器的IP地址池信息。
root@k8s-master:~# kubectl get ipaddresspools.metallb.io -n metallb-systemNAME:地址池名称
AUTO ASSIGN:自动分配IP功能已开启,默认开启
AVOID BUGGY IPS:是否分配网络地址(.0)和广播地址(.255),默认为false也就是正常分配
ADDRESSES:地址池范围

6. L2模式通告配置
[Step1] 本地新建YAML清单,配置MetalLB的L2通告策略,使集群可以通过ARP/NDP协议对外宣告服务IP,确保本地网络能够正常解析并访问集群暴露的外部IP。
root@k8s-master:~# vim metallb-l2advertisement.yml
# 写入下列内容
apiVersion: metallb.io/v1beta1 # 固定配置
kind: L2Advertisement # 资源类型
metadata:
name: metallb-l2advertisement
namespace: metallb-system # 命名空间需要与地址池一致
spec:
ipAddressPools: # 关联对外广播的IP地址池
- metallb-pool-192-168-8-100-110 # 和上述定义的地址池名匹配[Step2] 基于YAML清单向Kubernetes集群声明式创建L2Advertisement资源。
root@k8s-master:~# kubectl create -f metallb-l2advertisement.ymlNAME:资源名称
IPADDRESSPOOLS:绑定的地址池
IPADDRESSPOOL SELECTORS:标签选择器动态匹配的IPAddressPool
INTERFACES:只在指定网卡接口发送ARP/NDP通告

二、Ingress基本概念
1. Ingress Controller
Ingress用于实现集群外部到内部服务的HTTP、HTTPS流量路由,转发规则由Ingress资源定义,支持流量负载均衡、SSL证书卸载、基于域名的虚拟主机托管等能力,可以配置外网访问地址,管控外网请求分发。
Ingress可以识别主机名、访问路径等应用层信息,依托Kubernetes API规则将外部流量转发至对应的后端服务,是管控集群外网HTTP类访问的API对象。资源生效依赖集群内运行的Ingress控制器,一般以负载均衡组件作为实际转发载体。非HTTP、HTTPS类型的外网服务暴露,通常采用NodePort或LoadBalancer类型Service实现,Ingress不会对外开放其它端口与协议。
目前Kubernetes已经冻结Ingress API,不再迭代更新功能,但是该接口具备版本稳定性保障,官方暂时没有移除的计划,现阶段更推荐使用Gateway作为替代方案。

如果还是无法理解Ingress的应用场景,可以代入Apache中的“Virtual Hosts”,通过定义多个虚拟主机,实现单个入口地址对应多项后端服务的访问分发。
<VirtualHost *:80>
ServerName www.example.com
DocumentRoot "/www/domain"
</VirtualHost>
<VirtualHost *:80>
ServerName other.example.com
DocumentRoot "/www/otherdomain"
</VirtualHost>2. Ingress路径类型
Ingress每条路由路径必须指定路径类型(Path Type),未配置该参数的路径校验不通过。目前共支持三类路径类型:
ImplementationSpecific:匹配规则由IngressClass决定,可以独立判断,也可以等效为前缀或精确匹配
Exact:精确匹配URL路径,且区分大小写
Prefix:以斜杠分割路径层级作前缀匹配,区分大小写,按层级逐段校验。请求路径每一级均匹配规则路由前缀,才算匹配成功。
3. Ingress安装
如果无法正常下载,可以访问我提供的百度云链接下载。Ingress组件包
链接: https://pan.baidu.com/s/19uTFX0F0R32tbw1O3DR3qg?pwd=yar4
提取码: yar4
[Step1] 下载Ingress-nginx描述文件,其实也可以使用“kubectl apply -f”一步下载和导入,但是为了方便区分安装错误的原因,这里将下载和导入步骤分开进行。
root@k8s-master:~# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml
[Step2] Ingress-nginx依赖controller和kube-webhook-certgen两个镜像,这里可以通过第三方镜像加速器正常拉取镜像。如果该加速器已失效,可以访问我的百度云链接手动导入镜像。
root@k8s-master:~# crictl pull m.daocloud.io/registry.k8s.io/ingress-nginx/controller:v1.6.3
root@k8s-master:~# crictl pull m.daocloud.io/registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343[Step3] 修改已下载镜像的标签,需要与Ingress-nginx描述文件中的“image”字段保持一致。
root@k8s-master:~# ctr -n k8s.io image tag m.daocloud.io/registry.k8s.io/ingress-nginx/controller:v1.6.3 registry.k8s.io/ingress-nginx/controller:v1.6.3
root@k8s-master:~# ctr -n k8s.io image tag m.daocloud.io/registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343 registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343[Step4] 在工作节点k8s-worker1上也拉取镜像,修改镜像标签。
root@k8s-worker1:~# crictl pull m.daocloud.io/registry.k8s.io/ingress-nginx/controller:v1.6.3
root@k8s-worker1:~# crictl pull m.daocloud.io/registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343
root@k8s-worker1:~# ctr -n k8s.io image tag m.daocloud.io/registry.k8s.io/ingress-nginx/controller:v1.6.3 registry.k8s.io/ingress-nginx/controller:v1.6.3
root@k8s-worker1:~# ctr -n k8s.io image tag m.daocloud.io/registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343 registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343[Step5] 在工作节点k8s-worker2上也拉取镜像,修改镜像标签。
root@k8s-worker2:~# crictl pull m.daocloud.io/registry.k8s.io/ingress-nginx/controller:v1.6.3
root@k8s-worker2:~# crictl pull m.daocloud.io/registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343
root@k8s-worker2:~# ctr -n k8s.io image tag m.daocloud.io/registry.k8s.io/ingress-nginx/controller:v1.6.3 registry.k8s.io/ingress-nginx/controller:v1.6.3
root@k8s-worker2:~# ctr -n k8s.io image tag m.daocloud.io/registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343 registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343[Step6] 编辑Ingress-nginx描述文件,删除三处“image”字段中“@”字符以后的镜像摘要内容。镜像摘要用于校验镜像完整性并唯一标识镜像版本。
# 原字段
image: registry.k8s.io/ingress-nginx/controller:v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f
# 修改后字段
image: registry.k8s.io/ingress-nginx/controller:v1.6.3
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343[Step7] 安装Ingress-nginx。
root@k8s-master:~# kubectl apply -f deploy.yaml
[Step8] 验证:查看“ingress-nginx”命名空间下的全部Pod,admission相关Pod状态为Completed即为正常。
root@k8s-master:~# kubectl get pods -n ingress-nginx
4. Ingress基础案例配置
[Step1] 本地新建YAML清单,定义Deployment资源描述模板。
root@k8s-master:~# vim nginx-ingress-deployment.yml
# 写入下列内容
apiVersion: apps/v1 # 固定配置
kind: Deployment # 资源类型
metadata:
name: nginx-ingress-deployment
labels: # 定义标签
app: nginx-ingress-deployment # 自定义标签(键和值均可自定义)
spec:
replicas: 3 # 预期数量为3
selector:
matchLabels: # 标签匹配模式:精确匹配
app: nginx-ingress-deployment # 匹配的标签值
template: # 根据此模板来新建Pod
metadata:
labels: # 给Pod加上标签,需要和selector定义一致
app: nginx-ingress-deployment
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80[Step2] 基于YAML清单向Kubernetes集群声明式地创建Deployment资源。
root@k8s-master:~# kubectl create -f nginx-ingress-deployment.yml[Step3] 验证:查看当前集群中的所有Deployment资源。
root@k8s-master:~# kubectl get deployments.apps
[Step4] 本地新建YAML清单,定义ClusterIP类型的Service资源描述模板。
root@k8s-master:~# vim nginx-ingress-service.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: Service # 资源类型
metadata:
name: nginx-ingress-service
spec:
# Service类型,裸机需要借助MetalLB来分配IP
# 如果没有MetalLB,后续Ingress的ADDRESS字段会为空
type: LoadBalancer
selector: # 标签选择器,匹配后端Pod
# 匹配后端Pod的标签,需要和上述Deployment名称对应
app: nginx-ingress-deployment
ports:
- protocol: TCP # 使用TCP协议
port: 8084 # Service自己暴露的端口
targetPort: 80 # 后端Pod实际监听的端口[Step5] 基于YAML清单向Kubernetes集群声明式地创建Service资源。
root@k8s-master:~# kubectl create -f nginx-ingress-service.yml[Step6] 验证:查看当前命名空间下的所有Service资源。
root@k8s-master:~# kubectl get service
[Step7] 验证:查看Service关联的后端Pod IP与端口信息。
root@k8s-master:~# kubectl get endpoints
[Step8] 本地新建YAML清单,定义Ingress资源描述模板。
root@k8s-master:~# vim nginx-ingress.yml
# 写入下列内容
apiVersion: networking.k8s.io/v1 # 固定配置
kind: Ingress # 资源类型
metadata:
name: nginx-ingress
spec:
ingressClassName: nginx # 指定使用nginx-ingress-controller
rules: # 路由规则
- host: www.meaauf.com # 当访问www.meaauf.com时,转发到后端服务
http:
paths:
- pathType: Prefix # 路径匹配规则:前缀匹配
path: "/" # 匹配以/开头的路径,也就是全部路径
backend: # 匹配成功后,流量转发到哪
service: # 转发到Service
name: nginx-ingress-service # Service的名称
port: # 端口配置
number: 8084 # 转发Service的8084端口[Step2] 基于YAML清单向Kubernetes集群声明式地创建Ingress资源。
root@k8s-master:~# kubectl create -f nginx-ingress.yml[Step3] 验证:查看创建的所有的Ingress。
root@k8s-master:~# kubectl get ingress
[Step4] 验证:本地临时添加域名解析,将域名指向ADDRESS。然后通过域名访问,能够正常显示Nginx测试页。
root@k8s-master:~# echo "192.168.8.100 www.meaauf.com" >> /etc/hosts
三、Gateway基本概念
1. Gateway API概述
Kubernetes Gateway API是新一代网关标准,旨在提供一种在Kubernetes中管理网关和负载均衡器的标准方法,作为传统Ingress API的升级替代方案,具有更强的功能丰富度与扩展能力。Gateway基于可扩展、角色导向、协议感知的设计理念构建网络服务配置体系。核心组件如下:
GatewayClass:网关类,用于定义同类型网关集合,由专属网关控制器统一管理。
Gateway:网关实例,代表实际承载流量的基础设施,如云负载均衡器
Route:路由规则,基于不同协议定义流量的转发策略,实现网关请求到集群Service的路由映射。目前HTTPRoute已正式稳定,TCPRoute、UDPRoute、GRPCRoute、TLSRoute等路由资源仍然在迭代完善中。
1.1 Gateway反向代理模式完整请求数据流转过程
客户端构造并发起访问“http://www.meaauf.com”的HTTP请求
客户端调用DNS解析服务,查询域名,获取Gateway绑定的IP地址列表
客户端向Gateway IP推送请求,反向代理读取请求“Host”头部,结合Gateway及HTTPRoute规则完成配置匹配
可选环节:依据HTTPRoute匹配策略,校验请求头、请求路径
可选环节:依据HTTPRoute过滤规则,对请求头进行新增、移除等改写操作
反向代理将处理完成的请求转发至对应后端服务集群

2. 部署Gateway
如果无法正常下载,可以访问我提供的百度云链接下载。Gateway组件包
链接: https://pan.baidu.com/s/1GMu1udls38G0G4_V2GhC4g?pwd=f17x
提取码: f17x
[Step1] 下载Gateway描述文件,其实也可以使用“kubectl apply -f”一步下载和导入,但是为了方便区分安装错误的原因,这里将下载和导入步骤分开进行。
root@k8s-master:~# wget https://gh-proxy.org/https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.1/standard-install.yaml
[Step2] 部署Gateway。
root@k8s-master:~# kubectl apply -f standard-install.yaml
3. 部署NGINX Gateway Fabric
如果无法正常下载,可以访问我提供的百度云链接下载。Gateway组件包
链接: https://pan.baidu.com/s/1GMu1udls38G0G4_V2GhC4g?pwd=f17x
提取码: f17x
[Step1] 下载NGINX Gateway Fabric自定义资源描述文件,此文件用于创建CRD,不涉及任何镜像。NGINX Gateway Fabric由NGINX公司退出,基于Kubernetes官方Gateway API标准的开源网关实现,用Nginx做数据平面,替代传统Ingress Controller,提供更强大的流量治理能力。
root@k8s-master:~# wget https://gh-proxy.org/https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/v2.5.1/deploy/crds.yaml
[Step2] 安装NGINX Gateway Fabric自定义资源。
root@k8s-master:~# kubectl create -f crds.yaml
[Step3] 下载NGINX Gateway Fabric运行时描述文件,依赖nginx和nginx-gateway-fabric两个镜像。
root@k8s-master:~# wget https://gh-proxy.org/https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/v2.5.1/deploy/default/deploy.yaml
[Step4] 安装NGINX Gateway Fabric运行时。
root@k8s-master:~# kubectl apply -f deploy.yaml
[Step5] 验证:查看命名空间nginx-gateway下的Pod,能够看到有Pod在运行则证明部署成功。
root@k8s-master:~# kubectl get pods -n nginx-gateway
[Step6] 验证:系统会自动创建基于nginx的GatewayClass。
root@k8s-master:~# kubectl get gatewayclasses.gateway.networking.k8s.io
4. Gateway基础案例配置
[Step1] 本地新建YAML清单,分别定义Deployment和Service资源描述模板。
root@k8s-master:~# vim deployment-service.yml
# 写入下列内容
apiVersion: apps/v1 # 固定配置
kind: Deployment # 资源类型
metadata:
name: gateway-deployment
labels: # 定义标签
app: gateway-deployment # 自定义标签(键和值均可自定义)
spec:
replicas: 3 # 预期数量为3
selector:
matchLabels: # 标签匹配模式:精确匹配
app: gateway-deployment # 匹配的标签值
template: # 根据此模板来新建Pod
metadata:
labels: # 给Pod加上标签,需要和selector定义一致
app: gateway-deployment
spec:
containers:
- name: httpd
image: httpd:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1 # 固定配置
kind: Service # 资源类型
metadata:
name: gateway-service
spec:
type: ClusterIP
selector: # 标签选择器,匹配后端Pod
# 匹配后端Pod的标签,需要和上述Deployment名称对应
app: gateway-deployment
ports:
- protocol: TCP # 使用TCP协议
port: 8085 # Service自己暴露的端口
targetPort: 80 # 后端Pod实际监听的端口[Step2] 基于YAML清单向Kubernetes集群声明式地创建Deployment和Service资源。
root@k8s-master:~# kubectl create -f deployment-service.yml[Step3] 验证:查看当前集群中的所有Deployment和Service资源。
root@k8s-master:~# kubectl get deployments.apps,service
[Step4] 本地新建YAML清单,定义一个NGINX网关入口,监听80端口并接收以“meaauf.com”结尾的域名访问,将流量转发给集群里的服务。Gateway是实际入口,负责监听端口、协议和域名。
root@k8s-master:~# vim gateway.yml
# 写入下列内容
apiVersion: gateway.networking.k8s.io/v1 # 固定配置
kind: Gateway # 资源类型
metadata:
name: meaaufgateway # 网关的名称
spec:
# 使用NGINX作为网关驱动,也就是“kubectl get gatewayclasses.gateway.networking.k8s.io”显示的nginx
gatewayClassName: nginx
listeners: # 定义一个监听器,监听器可以指定协议(HTTP、HTTPS)、端口、域名范围
- name: default # 监听入口名称为default
hostname: "*.meaauf.com" # 处理以“.meaauf.com”结尾的域名
port: 80 # 监听80端口
protocol: HTTP # 监听HTTP请求
allowedRoutes: # 允许绑定到这个网关的路由
namespaces: # 允许的命名空间
from: All # 允许所有命名空间[Step5] 基于YAML清单向Kubernetes集群声明式地创建Gateway资源。
root@k8s-master:~# kubectl create -f gateway.yml[Step6] 验证:查询集群中所有网关资源的状态,能够看到刚刚我们创建的Gateway,且已经正常分配地址。
root@k8s-master:~# kubectl get gateways.gateway.networking.k8s.io
[Step7] 本地新建YAML清单,定义NGINX网关入口,监听80端口并接收以“meaauf.com”结尾的域名访问,将流量转发给集群里的服务。HTTPRoute是Gateway的子资源,用于定义具体的流量转发规则。通过匹配Host、路径、Header等条件,将请求转发到后端服务。一个Gateway可以关联多个HTTPRoute,一个HTTPRoute也可以被多个Gateway引用。
root@k8s-master:~# vim httproute.yml
# 写入下列内容
apiVersion: gateway.networking.k8s.io/v1 # 固定配置
kind: HTTPRoute # 资源类型
metadata:
name: meaauf-httproute
spec:
parentRefs: # 绑定到名为meaaufgateway的网关
- name: meaaufgateway
hostnames: ['www.meaauf.com'] # 只处理域名www.meaauf.com
#
rules: # 路由规则
- matches: # 匹配条件
- path: # 按照URL路径匹配
type: PathPrefix # 匹配方式:路径前缀匹配
value: / # 所有路径以/开头,也就是匹配所有请求
# 将流量转发给后端名为gateway-service的Service,端口为8085
backendRefs:
- name: gateway-service
port: 8085[Step8] 基于YAML清单向Kubernetes集群声明式地创建HTTPRoute资源。
root@k8s-master:~# kubectl create -f httproute.yml[Step9] 验证:查看当前集群中所有HTTP路由规则,能够看到上述我们创建的规则。
root@k8s-master:~# kubectl get httproutes.gateway.networking.k8s.io
[Step10] NGINX Gateway Fabric会监听Gateway、HTTPRoute资源变更,自动同步并更新NGINX配置。同时还会将HTTPRoute规则转换为NGINX配置文件,不用修改NGINX配置文件和重启NGINX就能随时修改路由。新版本的NGINX将对外暴露的VIP地址从Service移动到Gateway资源上,控制平面的Service修改为ClusterIP只做内部通信,真正的入口IP统一在Gateway的ADDRESS字段。
root@k8s-master:~# kubectl get service -n nginx-gateway
root@k8s-master:~# kubectl get gateways.gateway.networking.k8s.io
[Step11] 验证:本地临时添加域名解析,将域名指向网关的ADDRESS。通过域名访问,能够正常显示Apache测试页。
root@k8s-master:~# echo "192.168.8.102 www.meaauf.com" >> /etc/hosts
