ingress与metallb 结合使用
ingress与metallb 结合使用
在 裸机(Bare Metal)Kubernetes 环境中,Ingress 需要 Ingress Controller(如 nginx-ingress),但裸机环境默认没有 LoadBalancer,因此 Metallb 可以为 Ingress 提供外部 IP,使其可以被外部访问。下面是 Ingress 与 Metallb 结合使用 的完整步骤。
1. 安装 Metallb
(1) 部署 Metallb
使用官方提供的 YAML 文件安装:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/main/config/manifests/metallb-native.yaml
等待 Metallb Pod 运行:
kubectl get pods -n metallb-system
(2) 配置 IP 地址池
Metallb 需要一个 IP 地址池 来分配外部 IP(确保该 IP 地址可以在你的网络中访问,例如 192.168.1.100-192.168.1.200)。
创建 metallb-config.yaml:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.100-192.168.1.110 # 这里改为你的可用 IP 段,注意,当ingress绑定一个IP后此IP不能再给其他ingress使用
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: first-advert
namespace: metallb-system
应用配置:
kubectl apply -f metallb-config.yaml
2. 安装 Ingress Controller
(1) 使用 Helm 安装 Nginx Ingress
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install nginx-ingress ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace
(2) 配置 Ingress Controller 使用 LoadBalancer
默认情况下,ingress-nginx 部署的 Service 是 NodePort 类型,我们需要手动修改为 LoadBalancer 类型,让 Metallb 分配外部 IP。
kubectl patch svc ingress-nginx-controller -n ingress-nginx -p '{"spec":{"type":"LoadBalancer"}}'
然后检查 Ingress Controller Service 是否获得了 Metallb 分配的 IP:
kubectl get svc -n ingress-nginx
示例输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
nginx-ingress-ingress-nginx-controller LoadBalancer 10.100.200.1 192.168.1.100 80:30678/TCP,443:30679/TCP
EXTERNAL-IP=192.168.1.100说明 Metallb 成功分配了 IP。
3. 部署应用 Service
创建 nginx-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
应用该 YAML 文件
kubectl apply -f nginx-deployment.yaml
4. 创建 Ingress 规则
创建 nginx-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: myapp.local # 这里按照子域名可以配置多个规则
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
# namespace: ns-app1 #目标命名空间,并根据namespace+svc的方式转发到不同的namespace中的service端口,此方法适用k8s的1.19之前的版本
port:
number: 80
应用该 YAML 文件
kubectl apply -f nginx-ingress.yaml
在k8s 1.19之后的版本中要实现一个ingress通用可以使用如下方法
✅ 方法 1:使用 ExternalName Service
由于 Ingress 不能直接跨 Namespace 访问 Service,可以在 default 命名空间中 创建一个 ExternalName 类型的 Service,指向目标命名空间的 Service。
步骤 1:在 default 命名空间创建 ExternalName Service
apiVersion: v1
kind: Service
metadata:
name: app1-service
namespace: default
spec:
type: ExternalName
externalName: app1-service.ns-app1.svc.cluster.local
- 这里
externalName: app1-service.ns-app1.svc.cluster.local让它指向ns-app1命名空间中的app1-service。
步骤 2:在 Ingress 中使用 default 里的 Service
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: subdomain-routing
namespace: default
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
rules:
- host: "app1.example.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app1-service # 指向 default 里的 ExternalName Service
port:
number: 80 # 原始服务的端口而不是ExternalName,在 Kubernetes ExternalName Service 的情况下,Service 本身不提供端口映射,而是直接解析为外部主机名
💡 这样 app1.example.com 访问时,会通过 ExternalName 方式路由到 ns-app1 里的 app1-service!
✅ 方法 2:使用 NGINX server-snippet(实验性)
如果你使用的是 NGINX Ingress Controller,可以利用 nginx.ingress.kubernetes.io/server-snippet 注解,手动定义 NGINX 代理规则。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: subdomain-routing
namespace: default
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
location / {
proxy_pass http://app1-service.ns-app1.svc.cluster.local;
}
spec:
ingressClassName: nginx
rules:
- host: "app1.example.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: dummy-service # 需要一个 dummy service,否则 YAML 解析会报错
port:
number: 80
⚠️ 注意:
server-snippet让 NGINX 直接代理流量到app1-service.ns-app1.svc.cluster.local,绕过Ingress限制。dummy-service只是为了让Ingress资源能被 Kubernetes 解析,并不会实际生效。
总结
❌ Ingress 不能 直接跨 Namespace 访问 Service,不能使用 backend.service.namespace
✅ 方法 1(推荐):使用 ExternalName 类型的 Service 进行 跨命名空间代理
✅ 方法 2(实验性):使用 nginx.ingress.kubernetes.io/server-snippet 让 Ingress 直接代理请求
5. 测试访问
(1) 确保 Ingress 规则生效
kubectl get ingress
示例输出:
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-ingress nginx myapp.local 192.168.1.100 80 10m
ADDRESS应该是 Metallb 分配的 IP(如192.168.1.100)。
(2) 修改 /etc/hosts
由于 Ingress 依赖 host 规则,浏览器访问时需要解析 myapp.local 到 Ingress 的 EXTERNAL-IP:
sudo echo "192.168.1.100 myapp.local" >> /etc/hosts
(3) 访问应用
在浏览器访问:
http://myapp.local
应该能看到 Nginx 欢迎页面 🎉。
6. (可选) 启用 HTTPS
如果需要 HTTPS + TLS 证书,可以使用 cert-manager 自动签发证书,或者手动创建 TLS 证书:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.local
secretName: myapp-tls
rules:
- host: myapp.local # 这里按照子域名可以配置多个规则
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
# namespace: ns-app1 #目标命名空间,并根据namespace+svc的方式转发到不同的namespace中的service端口,此方法适用k8s的1.19之前的版本
port:
number: 80
然后创建 myapp-tls 证书 Secret。
7.Ingress Annotations 介绍
在 Kubernetes v1.12.0 的 Ingress 资源中,Annotations(注解)用于配置 Ingress Controller 的额外行为。
不同 Ingress Controller(如 NGINX、Traefik、HAProxy 等)支持的 Annotations 可能有所不同,这里主要介绍 NGINX Ingress Controller v1.12.0 的 annotations 及其作用。
1. NGINX Ingress Controller v1.12.0 常用 Annotations
以下是 Ingress 的 常用 Annotations 及其功能:
1.1 基本路由配置
| Annotation | 作用 |
|---|---|
nginx.ingress.kubernetes.io/rewrite-target |
重新定义请求路径(例如,将 /foo 重写为 /) |
nginx.ingress.kubernetes.io/use-regex |
是否启用正则匹配路径 (true/false) |
nginx.ingress.kubernetes.io/force-ssl-redirect |
强制将 HTTP 请求重定向到 HTTPS (true/false) |
nginx.ingress.kubernetes.io/app-root |
访问 / 时重定向到指定路径 |
nginx.ingress.kubernetes.io/configuration-snippet |
允许插入自定义 nginx.conf 配置片段 |
示例:URL 重写
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
example.com/foo→example.com/
1.2 负载均衡 & 代理设置
| Annotation | 作用 |
|---|---|
nginx.ingress.kubernetes.io/load-balance |
负载均衡策略(round_robin、least_conn、ip_hash) |
nginx.ingress.kubernetes.io/proxy-body-size |
设置 client_max_body_size,限制请求体大小(默认 1m) |
nginx.ingress.kubernetes.io/proxy-connect-timeout |
代理连接超时(默认 5s) |
nginx.ingress.kubernetes.io/proxy-read-timeout |
代理读取超时(默认 60s) |
nginx.ingress.kubernetes.io/proxy-send-timeout |
代理发送超时(默认 60s) |
nginx.ingress.kubernetes.io/proxy-buffer-size |
定义 proxy_buffer_size 大小,减少响应数据拆分 |
nginx.ingress.kubernetes.io/proxy-buffering |
启用/禁用 proxy_buffering (on/off) |
示例:限制请求大小
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
- 限制单个请求体大小为 10MB
1.3 认证 & 安全
| Annotation | 作用 |
|---|---|
nginx.ingress.kubernetes.io/auth-type |
认证类型(basic / digest) |
nginx.ingress.kubernetes.io/auth-secret |
存储认证信息的 Secret 名称 |
nginx.ingress.kubernetes.io/auth-realm |
认证提示信息 |
nginx.ingress.kubernetes.io/enable-modsecurity |
启用 ModSecurity (true/false) |
nginx.ingress.kubernetes.io/modsecurity-snippet |
自定义 ModSecurity 规则 |
nginx.ingress.kubernetes.io/enable-owasp-modsecurity-crs |
启用 OWASP ModSecurity CRS 规则 |
示例:启用 Basic Auth
annotations:
nginx.ingress.kubernetes.io/auth-type: "basic"
nginx.ingress.kubernetes.io/auth-secret: "auth-secret"
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
- 认证信息存储在
auth-secret里
1.4 HTTPS & TLS 配置
| Annotation | 作用 |
|---|---|
nginx.ingress.kubernetes.io/ssl-redirect |
启用 HTTPS (true/false) |
nginx.ingress.kubernetes.io/ssl-passthrough |
直接透传 TLS,适用于 gRPC 或 TLS 终结 |
nginx.ingress.kubernetes.io/backend-protocol |
后端协议(HTTP、HTTPS、GRPC、GRPCS) |
nginx.ingress.kubernetes.io/hsts |
启用 HSTS (true/false) |
nginx.ingress.kubernetes.io/hsts-max-age |
HSTS 最大生命周期(秒) |
nginx.ingress.kubernetes.io/hsts-include-subdomains |
HSTS 适用于子域名 (true/false) |
nginx.ingress.kubernetes.io/hsts-preload |
启用 HSTS Preload (true/false) |
示例:强制 HTTPS + 启用 HSTS
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/hsts: "true"
nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
nginx.ingress.kubernetes.io/hsts-include-subdomains: "true"
nginx.ingress.kubernetes.io/hsts-preload: "true"
- 所有 HTTP 请求都会 自动跳转到 HTTPS
- 启用 HSTS,浏览器强制 HTTPS 访问
1.5 连接 & 限流
| Annotation | 作用 |
|---|---|
nginx.ingress.kubernetes.io/limit-rps |
限制 每秒请求数 |
nginx.ingress.kubernetes.io/limit-burst |
限制 突发请求数 |
nginx.ingress.kubernetes.io/limit-connections |
限制 最大并发连接数 |
nginx.ingress.kubernetes.io/whitelist-source-range |
允许访问的 IP 白名单(CIDR 格式) |
示例:限流 & 仅允许特定 IP 访问
annotations:
nginx.ingress.kubernetes.io/limit-rps: "5"
nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.1.0/24,10.0.0.0/8"
- 限制每个客户端 每秒最多 5 个请求
- 仅 192.168.1.0/24 和 10.0.0.0/8 网段 允许访问
2. 如何查看所有支持的 Annotations?
可以运行以下命令,检查 nginx-ingress-controller 的默认 Annotations:
kubectl describe pod -n ingress-nginx | grep ANNOTATION
或者查看 NGINX Ingress Controller 官方文档:
- 最新 NGINX Annotations
3. 总结
✅ nginx.ingress.kubernetes.io/rewrite-target → URL 重写
✅ nginx.ingress.kubernetes.io/proxy-body-size → 请求体大小限制
✅ nginx.ingress.kubernetes.io/auth-type → Basic 认证
✅ nginx.ingress.kubernetes.io/ssl-redirect → 强制 HTTPS
✅ nginx.ingress.kubernetes.io/whitelist-source-range → IP 访问控制
✅ nginx.ingress.kubernetes.io/limit-rps → 限流
这些 Annotations 可以帮助你灵活控制 Ingress 行为,让 Kubernetes 反向代理更安全高效! 🚀
总结
- 安装 Metallb,提供外部 LoadBalancer IP。
- 安装 Ingress Controller(如 Nginx Ingress)。
- 确保 Ingress Controller 使用
LoadBalancer类型,让 Metallb 分配 IP。 - 部署应用 Service,确保应用可以被 Ingress 访问。
- 创建 Ingress 规则,使用
host规则管理 HTTP 流量。 - 测试 Ingress 访问,通过 Metallb 分配的 IP 访问服务。
最终效果
http://myapp.local会被 Ingress 解析,并转发到nginx-service。- Metallb 分配的
192.168.1.100作为对外的 Ingress 入口。

浙公网安备 33010602011771号