Kubernetes Ingress 与容器网络
实验环境:Kubernetes v1.30,containerd,Calico CNI,ingress‑nginx,MetalLB LoadBalancer
一、Ingress 七层代理
1.1 Ingress 简介
Ingress 为 Service 提供外部可访问的 HTTP/HTTPS URL、负载均衡、SSL 终止、基于域名虚拟主机等 7 层能力。
⚠️关键点:
- Ingress本身只是配置规则资源,不会自己工作 ,必须部署 Ingress Controller(控制器);
- Ingress 只处理 HTTP、HTTPS;TCP/UDP 四层暴露使用
NodePort/LoadBalancer类型 Service。
ingress‑nginx 工作流程
- 部署 Ingress‑nginx Controller Pod(本质是一组 Nginx 代理)
- 创建 Ingress YAML(k8s 资源,等价写 Nginx 配置片段)
- Controller 监听 apiserver,拉取全部 Ingress 规则
- 将规则转换成真实 nginx.conf 配置写入 Pod 内部
- reload nginx,完成流量转发
Ingress 本质就是 K8s 集群内部的7 层 HTTP 反向代理。
1.2 ingress‑nginx 部署前提
- 集群有可用 LoadBalancer(本实验使用 MetalLB 提供外部 IP)
- 必须部署 ingress‑nginx 控制器,Ingress 资源才会生效
1.3 部署 ingress‑nginx‑controller
wget https://laoma.cloud/class/course-materials/softwares/stage03/ingress-nginx-controller-v1.11.2.tar.gz
tar -xf ingress-nginx-controller-v1.11.2.tar.gz
# 查看原始镜像
grep image: ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml|uniq
# 替换镜像为私有harbor
sed -ir 's#@sha256.*##;s/registry.k8s.io/hub.laoma.cloud/' ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml
# 部署
kubectl apply -f ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml
# 查看资源
kubectl get all -n ingress-nginx
输出示例:
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-create-xhvp9 0/1 Completed 0 8m14s
pod/ingress-nginx-admission-patch-j47tm 0/1 Completed 2 8m14s
pod/ingress-nginx-controller-596db54d7-cgbdd 1/1 Running 0 8m14s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller LoadBalancer 10.107.255.83 10.1.8.40 80:30973/TCP,443:32344/TCP 14s
service/ingress-nginx-controller-admission ClusterIP 10.106.37.158 <none> 443/TCP 8m15s
EXTERNAL‑IP即为 Ingress 对外访问 IP,后续域名解析指向这个 IP。
1.4 Ingress 规则实践
前置环境准备
kubectl create ns ingress
kubectl config set-context --current --namespace ingress
# 部署两套httpd测试业务
# webapp01
kubectl create deployment webapp01 --image=hub.laoma.cloud/library/httpd --replicas=2
kubectl exec -it $(kubectl get pods -l app=webapp01 -o name|head -n1) -- bash -c "echo hello webapp01 pod1 > htdocs/index.html"
kubectl exec -it $(kubectl get pods -l app=webapp01 -o name|tail -n1) -- bash -c "echo hello webapp01 pod2 > htdocs/index.html"
kubectl expose deployment webapp01 --port=80 --target-port=80
# webapp02
kubectl create deployment webapp02 --image=hub.laoma.cloud/library/httpd --replicas=2
kubectl exec -it $(kubectl get pods -l app=webapp02 -o name|head -n1) -- bash -c "echo hello webapp02 pod1 > htdocs/index.html;mkdir -p htdocs/games;echo hello webapp02 game1 > htdocs/games/index.html"
kubectl exec -it $(kubectl get pods -l app=webapp02 -o name|tail -n1) -- bash -c "echo hello webapp02 pod2 > htdocs/index.html;mkdir -p htdocs/games;echo hello webapp02 game2 > htdocs/games/index.html"
kubectl expose deployment webapp02 --port=80 --target-port=80
示例 1:多域名虚拟主机(多 host)
同一个 Ingress,不同域名转发到不同 Service
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
ingressClassName: nginx
rules:
- host: webapp01.laoma.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp01
port:
number: 80
- host: webapp02.laoma.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp02
port:
number: 80
kubectl apply -f multi-host-ingress.yaml
kubectl describe ingress multi-host-ingress
本地 hosts 增加解析:
10.1.8.40 webapp01.laoma.cloud
10.1.8.40 webapp02.laoma.cloud
测试:
curl webapp01.laoma.cloud
curl webapp02.laoma.cloud
示例 2:同一域名多 path 路径路由
同一个域名,不同 URL 路径转发不同后端服务
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-path-ingress
spec:
ingressClassName: nginx
rules:
- host: www.laoma.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp01
port:
number: 80
- path: /games
pathType: Prefix
backend:
service:
name: webapp02
port:
number: 80
kubectl apply -f multi-path-ingress.yaml
curl www.laoma.cloud
curl www.laoma.cloud/games/
pathType 三种类型
Prefix:前缀匹配;Exact:严格完整路径匹配;ImplementationSpecific:交由 ingress 控制器自行实现,正则重写场景使用。
示例 3:路径重写裁剪(rewrite‑target)
访问
/webapp01/xxx,转发后端去掉/webapp01,直接访问/xxx,等价 nginxproxy_pass /
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-trimming-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
ingressClassName: nginx
rules:
- host: www.laoma.cloud
http:
paths:
- path: /webapp01/(.*)
pathType: ImplementationSpecific
backend:
service:
name: webapp01
port:
number: 80
- path: /webapp02/(.*)
pathType: ImplementationSpecific
backend:
service:
name: webapp02
port:
number: 80
kubectl apply -f path-trimming-ingress.yaml
curl www.laoma.cloud/webapp01/
curl www.laoma.cloud/webapp02/
示例 4:TLS HTTPS + 80 强制跳转 443
生成自签名证书,存入 k8s secret:
openssl genrsa -out www.key 2048
openssl req -new -key www.key -out www.csr -subj "/C=CN/ST=JS/L=NJ/O=LM/OU=DEVOPS/CN=www.laoma.cloud/emailAddress=webadmin@laoma.cloud"
openssl x509 -req -days 3650 -in www.csr -signkey www.key -out www.crt
kubectl create secret tls www-tls --cert=./www.crt --key=./www.key
Ingress TLS 配置:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- www.laoma.cloud
secretName: www-tls
rules:
- host: www.laoma.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp01
port:
number: 80
测试:
curl -Lk http://www.laoma.cloud
curl -k https://www.laoma.cloud
1.5 ingress‑nginx 常用注解速查表
| 注解 | 功能说明 |
|---|---|
nginx.ingress.kubernetes.io/force-ssl-redirect: "true" |
HTTP 80 强制跳转 HTTPS 443 |
nginx.ingress.kubernetes.io/rewrite-target: /$1 |
URL 路径重写,裁剪前缀 |
nginx.ingress.kubernetes.io/whitelist-source-range: "10.1.8.0/24" |
IP 访问白名单 |
nginx.ingress.kubernetes.io/limit-rps: "20" |
单 IP 每秒请求数限流,防刷 |
nginx.ingress.kubernetes.io/enable-cors: "true" |
开启跨域,前后端分离项目 |
nginx.ingress.kubernetes.io/proxy-read-timeout: "60" |
代理后端接口超时时间 |
nginx.ingress.kubernetes.io/x-forwarded-for: "true" |
向后端透传真实客户端 IP |
nginx.ingress.kubernetes.io/canary: "true" canary‑weight: "10" |
金丝雀灰度,按百分比切流量 |
清理 ingress 实验环境
kubectl delete ns ingress
二、Kubernetes 容器网络体系
2.1 Underlay 与 Overlay 概念
- Underlay:底层物理网络直连,无报文封装,性能高;节点之间直接路由 Pod 网段
- Overlay:隧道封装,原始数据包外层再套一层宿主机 IP 头;对底层网络无要求,有少量性能开销
2.2 主流 CNI 方案对比
| CNI 方案 | 网络模式 | 是否隧道 | 支持 NetworkPolicy | 适用场景 |
|---|---|---|---|---|
| Flannel | host‑gw(Underlay)/VXLAN(Overlay) | VXLAN 封装;host‑gw 无封装 | ❌不支持网络策略 | 追求简单,不需要 Pod 防火墙 |
| Calico | BGP(Underlay) / IPIP/VXLAN(Overlay) | IPIP/VXLAN 封装;BGP 无封装 | ✅原生支持 | 企业最常用,需要 Pod 网络隔离策略 |
| WeaveNet | UDP 隧道 Overlay | UDP 封装 | ✅支持 | 小规模测试环境 |
| Macvlan | Underlay 二层直连物理网卡 | ❌无封装 | 依赖配套插件 | Pod 需要拿到局域网独立 IP,追求极低延迟 |
Calico 两大隧道模式对比 | 项目 | IPIP 隧道 | VXLAN 隧道 | |---|---|---| | 协议 | IP 协议号 4|UDP 4789 端口 | | 虚拟网卡 | tunl0|vxlan.calico| | 是否带二层 MAC | 不带,纯三层 IP 包 | 完整二层帧,支持广播组播 | | 公有云兼容性 | 很多云厂商封禁协议 4,容易不通 | UDP 端口一般放行,公有云更稳 |
ipipMode /vxlanMode 三种取值:
Always:全部跨节点流量都走隧道;Never:关闭隧道,BGP 发布 Pod 路由,Underlay 直连;CrossSubnet混合模式:同子网不走隧道,跨子网自动启用隧道。
查看当前 Calico IPPool 配置
kubectl get ippool -o yaml |egrep 'ipip|vxlan'
# 宿主机看路由,dev tunl0代表IPIP隧道模式
ip route
修改 IPPool 隧道模式(生产建议业务低峰操作)
kubectl get ippool default-ipv4-ippool -o yaml > ippool-backup.yaml
kubectl edit ippool default-ipv4-ippool
2.3 CNI 与 CNM 网络模型
- CNM(Docker libnetwork):Docker 原生网络模型,Sandbox (netns)、Endpoint (veth‑pair)、Network (bridge);绑定 dockerd 守护进程。
- CNI(Container Network Interface) :Google+CoreOS 制定,Kubernetes 标准网络接口;不依赖守护进程,插件可插拔,分为 CNI 插件(配置网络)、IPAM 插件(分配 PodIP)。
CNI 工作对象是Pod,CNM 工作对象是容器。
三、NetworkPolicy 网络策略(Pod 防火墙)
⚠️前提条件:CNI 插件必须支持 NetworkPolicy,本实验 Calico 支持;Flannel 原生不支持。
3.1 基础概念
- 默认状态:集群所有 Pod 之间全部互通,没有任何隔离。
- NetworkPolicy 作用对象:Pod,控制 Pod 的入站 Ingress、出站 Egress 流量。
- NetworkPolicy 是白名单机制:一旦 Pod 被 NetworkPolicy 选中,没有被规则允许的流量全部拒绝。
policyTypes: [Ingress,Egress]显式声明要管控的流量方向。
重要:访问连通需要两端同时放行: 源 Pod 的 Egress 出站策略允许出去,目标 Pod 的 Ingress 入站策略允许进来,连接才能建立。
3.2 四种选择器
podSelector:选择同一个命名空间内的 Pod;namespaceSelector:选择其他整个命名空间;namespaceSelector + podSelector:组合,选中其他命名空间下指定标签 Pod;ipBlock:基于 IP 网段 CIDR 过滤,多用于集群外部 IP。
3.3 实验示例
准备实验环境
kubectl create ns web
kubectl create ns laoma
# web命名空间
kubectl run web1 -n web --image=hub.laoma.cloud/library/nginx
kubectl run web2 -n web --image=hub.laoma.cloud/library/nginx
kubectl expose pod web1 -n web --port=80
kubectl expose pod web2 -n web --port=80
# laoma命名空间
kubectl run test -n laoma --image=hub.laoma.cloud/library/nginx
示例 1:仅同命名空间指定标签 Pod 可以访问 web1
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: test
ports:
- protocol: TCP
port: 80
示例 2:允许本命名空间所有 Pod 访问目标 Pod
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
ports:
- protocol: TCP
port: 80
示例 3:根据命名空间标签放行访问
给 namespace 打标签:
kubectl label namespaces laoma project=myproject
网络策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
ports:
- protocol: TCP
port: 80
示例 4:基于 IP 网段 ipBlock 放行
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 10.1.8.0/24
except:
- 10.1.8.128/26
ports:
- protocol: TCP
port: 80
示例 5:默认拒绝全部入站流量(命名空间全局隔离)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: web
spec:
podSelector: {}
policyTypes:
- Ingress
示例 6:默认拒绝全部入站 + 全部出站
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: web
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
注意 NetworkPolicy 做不到的事情:
- 无法写显式拒绝规则,只有白名单允许;
- 不能针对整个集群所有 namespace 全局生效;
- Pod 内部localhost本地回环流量无法拦截。
网络策略环境清理
kubectl delete ns web laoma
小结
- Ingress‑nginx 实现 k8s 集群 7 层 HTTP 反向代理,支持域名、路径、重写、HTTPS、限流、灰度;
- CNI 分为 Overlay 隧道封装与 Underlay 底层直连;Calico 支持 BGP/IPIP/VXLAN 多种模式,支持 NetworkPolicy;
- NetworkPolicy 为 Pod 提供防火墙,白名单模型,可以基于 Pod 标签、Namespace 标签、IP 网段做访问控制;
- 连通需要 Ingress 入站、Egress 出站两端同时放行。