Kubernetes Service
学习参考:Service
环境准备
bash
root@master30 ~ 10:20:01# kubectl create ns services
root@master30 ~ 10:20:05# kubectl config set-context --current --namespace services
Service 类型
Kubernetes Service 共支持五类服务类型:
- ClusterIP:仅允许集群内部发起访问。
- NodePort:依托物理节点开放端口实现访问,集群内所有节点会复用同一个端口号。
- LoadBalancer:提供负载均衡能力,绑定独立的物理网段外网 IP。
- ExternalName:用于配置集群内部域名 CNAME 解析记录。
- Headless:仅提供服务域名,不会分配独立集群 IP。
若业务应用需要将服务暴露至集群外部访问,Kubernetes 提供两种实现方案:NodePort 与 LoadBalancer。
环境准备
创建 Deployment 资源
bash
root@master30 ~ 10:20:06# kubectl create deployment web --image=hub.laoma.cloud/library/httpd --replicas=2
deployment.apps/web created
ClusterIP
ClusterIP 会分配集群内部专用 IP 对外暴露服务,采用该类型时服务仅能在集群内部访问,同时这也是 Service 的默认类型。
- ClusterIP 的 IP 地址从集群预留的专用地址段中分配,其余几类 Service 均基于 ClusterIP 底层能力拓展实现。
- 创建 Service 时,可通过
.spec.clusterIP字段手动指定自定义集群 IP;若将该字段值设为"None",Kubernetes 将不再为此服务分配集群 IP。 - 自定义的 IP 地址必须为合法 IPv4/IPv6 地址,且归属 API 服务配置的
service-cluster-ip-range网段。若填写非法集群 IP,API 服务会返回 422 状态码提示参数不合法。
更多细节可参考前文「服务发现」相关章节。
NodePort
- 若将 Service 的
type字段设置为NodePort,Kubernetes 控制平面会从--service-node-port-range参数划定的端口区间自动分配端口(默认区间:30000-32767 ),分配完成后端口号会记录在.spec.ports[*].nodePort字段中。 - NodePort 类型服务会借助集群所有节点的 IP 与分配端口对外提供访问入口;为保证节点端口可正常转发流量,Kubernetes 会同步为该服务分配 ClusterIP,集群全部节点都会监听该统一端口,并将接收的请求转发至对应 Service。
实操示例:
bash
root@master30 ~ 10:20:16# kubectl expose deployment web --type NodePort --port=8080 --target-port=80 -o yaml --dry-run=client > service-NodePort.yaml
root@master30 ~ 10:20:25# vim service-NodePort.yaml
bash
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
status:
loadBalancer: {}
bash
# 创建NodePort类型Service
root@master30 ~ 10:20:32# kubectl apply -f service-NodePort.yaml
service/web created
# 查看节点分配的对外端口31917
root@master30 ~ 10:20:39# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web NodePort 10.100.38.69 <none> 8080:30389/TCP 7s
# 参数说明:
# 1. EXTERNAL-IP 显示为<none>,代表可通过集群任意节点的物理IP访问当前服务。
# 2. PORT(S) 字段格式为8080:31917:8080是ClusterIP监听端口,31917是宿主机节点监听端口。
# Kubernetes 会从30000~32767区间选取空闲端口,集群所有节点统一监听该端口并转发请求至Service
# 访问集群任意节点完成连通性测试
root@master30 ~ 10:20:46# curl http://10.1.8.30:30389
<html><body><h1>It works!</h1></body></html>
root@master30 ~ 10:20:59# curl http://10.1.8.31:30389
<html><body><h1>It works!</h1></body></html>
root@master30 ~ 10:21:03# curl http://10.1.8.32:30389
<html><body><h1>It works!</h1></body></html>
内核防火墙转发规则解析:
bash
root@master30 ~ 10:21:35# iptables-save |grep 30389
-A KUBE-NODEPORTS -p tcp -m comment --comment "services/web" -m tcp --dport 30389 -j KUBE-EXT-7D76YWGERGEPC4GC
root@master30 ~ 10:21:56# iptables-save |grep KUBE-EXT-7D76YWGERGEPC4GC
:KUBE-EXT-7D76YWGERGEPC4GC - [0:0]
-A KUBE-EXT-7D76YWGERGEPC4GC -m comment --comment "masquerade traffic for services/web external destinations" -j KUBE-MARK-MASQ
-A KUBE-EXT-7D76YWGERGEPC4GC -j KUBE-SVC-7D76YWGERGEPC4GC
-A KUBE-NODEPORTS -p tcp -m comment --comment "services/web" -m tcp --dport 30389 -j KUBE-EXT-7D76YWGERGEPC4GC
root@master30 ~ 10:22:15# iptables-save |grep KUBE-SVC-7D76YWGERGEPC4GC
:KUBE-SVC-7D76YWGERGEPC4GC - [0:0]
-A KUBE-EXT-7D76YWGERGEPC4GC -j KUBE-SVC-7D76YWGERGEPC4GC
-A KUBE-SERVICES -d 10.100.38.69/32 -p tcp -m comment --comment "services/web cluster IP" -m tcp --dport 8080 -j KUBE-SVC-7D76YWGERGEPC4GC
-A KUBE-SVC-7D76YWGERGEPC4GC ! -s 10.224.0.0/16 -d 10.100.38.69/32 -p tcp -m comment --comment "services/web cluster IP" -m tcp --dport 8080 -j KUBE-MARK-MASQ
-A KUBE-SVC-7D76YWGERGEPC4GC -m comment --comment "services/web -> 10.224.133.122:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-6KP5PMO4XMNPF6TB
-A KUBE-SVC-7D76YWGERGEPC4GC -m comment --comment "services/web -> 10.224.218.136:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-554EDXQBQCQ25NV6
-A KUBE-SVC-7D76YWGERGEPC4GC -m comment --comment "services/web -> 10.224.218.161:80" -j KUBE-SEP-Z2E2SH65MYX7M5GX
root@master30 ~ 10:22:32# iptables-save |grep KUBE-SEP-Z2E2SH65MYX7M5GX
:KUBE-SEP-Z2E2SH65MYX7M5GX - [0:0]
-A KUBE-SEP-Z2E2SH65MYX7M5GX -s 10.224.218.161/32 -m comment --comment "services/web" -j KUBE-MARK-MASQ
-A KUBE-SEP-Z2E2SH65MYX7M5GX -p tcp -m comment --comment "services/web" -m tcp -j DNAT --to-destination 10.224.218.161:80
-A KUBE-SVC-7D76YWGERGEPC4GC -m comment --comment "services/web -> 10.224.218.161:80" -j KUBE-SEP-Z2E2SH65MYX7M5GX
NodePort 默认自动随机分配端口,也可通过 nodePort 字段手动指定固定端口。
bash
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
ports:
- port: 8080
protocol: TCP
# 手动指定宿主机固定监听端口
nodePort: 30080
targetPort: 80
selector:
app: web
type: NodePort
status:
loadBalancer: {}
端口字段释义:
- nodePort:宿主机节点对外开放的监听端口。
- port:ClusterIP 集群内部监听端口。
- targetPort:后端 Pod 内部业务容器监听端口。
资源清理
bashroot@master30 ~ 10:42:42# kubectl delete svc web service "web" deleted
LoadBalancer
Kubernetes 原生并未内置负载均衡实现,需要借助第三方组件完成,典型方案为 MetalLB。
每一个 LoadBalancer 类型 Service 都会分配独立的外网 IP,仅需将 Service 的 type 字段修改为 LoadBalancer 即可创建该类型服务。
下文将基于 MetalLB 演示完整部署流程。
官方文档地址: https://metallb.universe.tf/
GitHub 开源地址:https://github.com/metallb/metallb
部署 MetalLB
bash
root@master30 ~ 10:46:08# wget http://192.168.46.200/class/course-materials/softwares/stage03/metallb-0.14.8.tar.gz
--2026-08-11 11:10:51-- http://192.168.46.200/class/course-materials/softwares/stage03/metallb-0.14.8.tar.gz
Connecting to 192.168.46.200:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 14835368 (14M) [application/octet-stream]
Saving to: 'metallb-0.14.8.tar.gz'
metallb-0.14.8.tar.gz 100%[=========================>] 14.15M 3.24MB/s in 4.4s
2026-08-11 11:10:55 (3.24 MB/s) - 'metallb-0.14.8.tar.gz' saved [14835368/14835368]
root@master30 ~ 11:10:55# tar -xf metallb-0.14.8.tar.gz
# 查看镜像配置
root@master30 ~ 11:11:04# grep image metallb-0.14.8/config/manifests/metallb-native.yaml image: quay.io/metallb/controller:v0.14.8
image: quay.io/metallb/speaker:v0.14.8
# 根据内网镜像仓库替换镜像地址
root@master30 ~ 11:11:25# sed -i 's/quay.io/hub.laoma.cloud/g' metallb-0.14.8/config/manifests/metallb-native.yaml
root@master30 ~ 11:11:35# kubectl apply -f metallb-0.14.8/config/manifests/metallb-native.yaml
namespace/metallb-system created
customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created
...
# 等待全部Pod进入正常运行状态后再执行后续操作
root@master30 ~ 11:12:25# kubectl get all -n metallb-system
NAME READY STATUS RESTARTS AGE
pod/controller-d6499775f-48q5x 1/1 Running 0 32s
pod/speaker-4tv4k 1/1 Running 0 32s
pod/speaker-j8l97 1/1 Running 0 32s
pod/speaker-q6xsq 1/1 Running 0 32s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/metallb-webhook-service ClusterIP 10.107.23.110 <none> 443/TCP 32s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/speaker 3 3 3 3 3 kubernetes.io/os=linux 32s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/controller 1/1 1 1 32s
NAME DESIRED CURRENT READY AGE
replicaset.apps/controller-d6499775f 1 1 1 32s
配置 IP 地址分配池
bash
root@master30 ~ 11:12:35# cat << 'EOF' > ippool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 10.1.8.40-10.1.8.80
EOF
root@master30 ~ 11:12:51# kubectl apply -f ippool.yaml
ipaddresspool.metallb.io/first-pool created
配置二层广播宣告模式
bash
root@master30 ~ 11:12:58# cat << 'EOF' > L2.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
EOF
root@master30 ~ 11:13:11# kubectl apply -f L2.yaml
功能验证
bash
root@master30 ~ 11:13:22# kubectl expose deployment web --type LoadBalancer --port=80 --target-port=80 -o yaml --dry-run=client > service-LoadBalancer.yaml
root@master30 ~ 11:13:59# cat service-LoadBalancer.yaml
bash
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
type: LoadBalancer
status:
loadBalancer: {}
bash
root@master30 ~ 11:14:07# kubectl apply -f service-LoadBalancer.yaml
service/web created
root@master30 ~ 11:14:21# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web LoadBalancer 10.97.78.201 10.1.8.40 80:32306/TCP 6s
# 访问测试需使用Service暴露的80端口,而非节点分配的32101端口
root@master30 ~ 11:14:27# curl -s http://10.1.8.40:80
<html><body><h1>It works!</h1></body></html>
核心总结
- 客户端流量完整转发链路:用户请求 → MetalLB 虚拟负载均衡 IP → 节点 kube-proxy 组件 → Service 负载均衡调度 → 后端业务 Pod。
- ✅ MetalLB 仅负责 ARP 广播宣告与 IP 地址占用,实际流量转发逻辑完全依赖 kube-proxy 与 Service 机制实现。
- MetalLB 搭配 LoadBalancer 类型 Service 是 Kubernetes 集群标准负载均衡落地方案。
完整流量流程图
访问 LB VIP:10.1.8.40
客户端用户
ARP 寻址 → 流量进入集群任意节点
节点内核拦截 Service IP 流量
kube-proxy 处理 iptables/IPVS 规则
Service 负载均衡:选择一个健康 Pod
通过 CNI 网络转发到 Pod 所在节点
流量进入 Pod 网络命名空间
目标 Pod 接收并响应请求
#mermaid-svg-4nxKIKAjpQGPpK4J{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4nxKIKAjpQGPpK4J .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4nxKIKAjpQGPpK4J .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4nxKIKAjpQGPpK4J .error-icon{fill:#552222;}#mermaid-svg-4nxKIKAjpQGPpK4J .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4nxKIKAjpQGPpK4J .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4nxKIKAjpQGPpK4J .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4nxKIKAjpQGPpK4J .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4nxKIKAjpQGPpK4J .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4nxKIKAjpQGPpK4J .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4nxKIKAjpQGPpK4J .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4nxKIKAjpQGPpK4J .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4nxKIKAjpQGPpK4J .marker.cross{stroke:#333333;}#mermaid-svg-4nxKIKAjpQGPpK4J svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4nxKIKAjpQGPpK4J p{margin:0;}#mermaid-svg-4nxKIKAjpQGPpK4J .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4nxKIKAjpQGPpK4J .cluster-label text{fill:#333;}#mermaid-svg-4nxKIKAjpQGPpK4J .cluster-label span{color:#333;}#mermaid-svg-4nxKIKAjpQGPpK4J .cluster-label span p{background-color:transparent;}#mermaid-svg-4nxKIKAjpQGPpK4J .label text,#mermaid-svg-4nxKIKAjpQGPpK4J span{fill:#333;color:#333;}#mermaid-svg-4nxKIKAjpQGPpK4J .node rect,#mermaid-svg-4nxKIKAjpQGPpK4J .node circle,#mermaid-svg-4nxKIKAjpQGPpK4J .node ellipse,#mermaid-svg-4nxKIKAjpQGPpK4J .node polygon,#mermaid-svg-4nxKIKAjpQGPpK4J .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4nxKIKAjpQGPpK4J .rough-node .label text,#mermaid-svg-4nxKIKAjpQGPpK4J .node .label text,#mermaid-svg-4nxKIKAjpQGPpK4J .image-shape .label,#mermaid-svg-4nxKIKAjpQGPpK4J .icon-shape .label{text-anchor:middle;}#mermaid-svg-4nxKIKAjpQGPpK4J .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4nxKIKAjpQGPpK4J .rough-node .label,#mermaid-svg-4nxKIKAjpQGPpK4J .node .label,#mermaid-svg-4nxKIKAjpQGPpK4J .image-shape .label,#mermaid-svg-4nxKIKAjpQGPpK4J .icon-shape .label{text-align:center;}#mermaid-svg-4nxKIKAjpQGPpK4J .node.clickable{cursor:pointer;}#mermaid-svg-4nxKIKAjpQGPpK4J .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4nxKIKAjpQGPpK4J .arrowheadPath{fill:#333333;}#mermaid-svg-4nxKIKAjpQGPpK4J .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4nxKIKAjpQGPpK4J .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4nxKIKAjpQGPpK4J .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4nxKIKAjpQGPpK4J .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4nxKIKAjpQGPpK4J .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4nxKIKAjpQGPpK4J .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4nxKIKAjpQGPpK4J .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4nxKIKAjpQGPpK4J .cluster text{fill:#333;}#mermaid-svg-4nxKIKAjpQGPpK4J .cluster span{color:#333;}#mermaid-svg-4nxKIKAjpQGPpK4J div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4nxKIKAjpQGPpK4J .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4nxKIKAjpQGPpK4J rect.text{fill:none;stroke-width:0;}#mermaid-svg-4nxKIKAjpQGPpK4J .icon-shape,#mermaid-svg-4nxKIKAjpQGPpK4J .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4nxKIKAjpQGPpK4J .icon-shape p,#mermaid-svg-4nxKIKAjpQGPpK4J .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4nxKIKAjpQGPpK4J .icon-shape .label rect,#mermaid-svg-4nxKIKAjpQGPpK4J .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4nxKIKAjpQGPpK4J .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4nxKIKAjpQGPpK4J .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4nxKIKAjpQGPpK4J :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 访问 LB VIP:10.1.8.40
客户端用户
ARP 寻址 → 流量进入集群任意节点
节点内核拦截 Service IP 流量
kube-proxy 处理 iptables/IPVS 规则
Service 负载均衡:选择一个健康 Pod
通过 CNI 网络转发到 Pod 所在节点
流量进入 Pod 网络命名空间
目标 Pod 接收并响应请求
访问 LB VIP:10.1.8.40
客户端用户
ARP 寻址 → 流量进入集群任意节点
节点内核拦截 Service IP 流量
kube-proxy 处理 iptables/IPVS 规则
Service 负载均衡:选择一个健康 Pod
通过 CNI 网络转发到 Pod 所在节点
流量进入 Pod 网络命名空间
目标 Pod 接收并响应请求
- 客户端发起访问:用户通过浏览器或业务程序访问 MetalLB 分配的负载均衡虚拟 IP(示例:10.1.8.200)。
- ARP 寻址转发流量至集群节点:MetalLB 工作在二层模式,通过 ARP 广播声明虚拟 IP 归属,客户端流量会转发至集群任意一台节点。
- 节点内核捕获目标流量:宿主机内核识别访问目标为负载均衡 IP,将流量交由内核网络子系统处理。
- kube-proxy 匹配转发规则:kube-proxy 匹配内核中预生成的 iptables/IPVS 转发规则,定位流量归属的 Service 资源。
- Service 完成负载均衡调度:从 Service 绑定的就绪端点列表中,按预设调度策略选择一台健康后端 Pod。
- CNI 插件跨节点转发:若目标 Pod 不在当前接收流量的节点,流量将通过 Calico、Flannel 等 CNI 网络插件跨节点传输。
- 流量送入 Pod 网络命名空间:目标节点通过 veth-pair 虚拟网卡设备,将流量转发至 Pod 独立网络命名空间。
- 业务 Pod 处理并返回响应:容器内业务程序接收请求处理后,沿原链路将响应数据返回客户端。
ExternalName
ExternalName 类型服务用于将集群内服务映射至外部域名,映射逻辑由 externalName 字段定义(示例域名:api.foo.bar.example)。该配置会修改集群 DNS 解析,对外返回对应外部域名的 CNAME 解析记录,集群不会为此服务创建任何流量代理转发规则。
示例:将 prod 命名空间下 my-service 服务映射至外部数据库域名database.example.com
bash
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: database.example.com
当程序解析域名 my-service.prod.svc.cluster.local 时,集群 DNS 会返回一条 CNAME 记录,指向 database.example.com。访问该服务的调用方式与常规 Service 完全一致,核心差异在于域名重定向逻辑由 DNS 解析层完成,不存在内核代理转发流程。
Headless Services
部分业务场景无需负载均衡能力,也不需要分配独立集群 IP,此时可通过将 ClusterIP 显式设置为 None 创建无头服务(Headless Service)。
无头服务不会分配集群 IP,kube-proxy 不会为其生成转发规则,集群也不会提供负载均衡与路由转发能力。
DNS 解析规则会根据 Service 是否配置标签选择器分为两种逻辑:
-
配置标签选择器的无头服务:Kubernetes 控制平面会在 API 中生成 EndpointSlice 资源,并修改集群 DNS 配置,直接返回后端 Pod 对应的 IPv4/A 或 IPv6/AAAA 解析记录。
-
未配置标签选择器的无头服务
:控制平面不会创建 EndpointSlice 资源,集群 DNS 执行逻辑区分两种场景:
-
若服务类型为
type: ExternalName,生成对应 CNAME 解析记录; -
其余服务类型,会读取服务就绪端点的全部 IP 并生成 A/AAAA 解析记录(IPv4 生成 A 记录,IPv6 生成 AAAA 记录)。
定义无选择器的无头服务时,
port端口值必须与targetPort完全一致。
-
Service 会话保持
会话保持基础介绍
若需要保证同一客户端的全部请求始终转发至同一台后端 Pod,可将 Service 的 .spec.sessionAffinity 字段设置为 ClientIP,开启基于客户端源 IP 的会话粘性,默认配置为 None(关闭会话保持)。
同时可通过 .spec.sessionAffinityConfig.clientIP.timeoutSeconds 配置会话粘性的最大超时时间,默认值 10800 秒(3 小时)。
底层工作逻辑:
- 客户端首次发起服务访问时,Service 将请求转发至某一台 Pod,并记录客户端 IP 与目标 Pod 的绑定关系。
- 该客户端后续所有请求,都会匹配绑定记录转发至同一台 Pod。
该特性更适配有状态业务场景(如 Java Web 应用、WebSocket 长连接、游戏服务端),典型收益:
- 用户登录会话状态不会丢失
- 购物车数据保持一致
- 长连接链路稳定不中断
测试环境准备
bash
root@master30 ~ 11:14:48# kubectl create deployment web --image=hub.laoma.cloud/library/httpd --replicas=2
root@master30 ~ 11:40:05# kubectl expose deployment web --port 80
root@master30 ~ 11:40:44# for pod in $(kubectl get pods -o name | awk -F/ '{print $2}'); do kubectl exec -it $pod -- bash -c "echo $pod > htdocs/index.html"; done
root@master30 ~ 11:41:04# kubectl get svc web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web LoadBalancer 10.97.78.201 10.1.8.40 80:32306/TCP 27m
root@master30 ~ 11:41:48# for i in {1..20};do curl -s 10.97.78.201;done|sort |uniq -c
9 web
10 web-5885dfff8c-qvfnf
1 web-5885dfff8c-vmj6r
开启会话保持配置
bash
root@master30 ~ 11:42:07# kubectl patch svc web -p '{"spec":{"sessionAffinity":"ClientIP"}}'
service/web patched
# 重复访问验证会话粘性效果
root@master30 ~ 11:42:38# for i in {1..20};do curl -s 10.97.78.201;done|sort |uniq -c
20 web-5885dfff8c-vmj6r
会话保持与 kube-proxy IPVS 模式关联逻辑
1. Service 的 sessionAffinity 配置优先级最高
当 Service 配置 ClientIP 会话粘性时,kube-proxy 会自动启用 IPVS 的 SH 调度算法
- SH 全称 Source Hashing,即源地址哈希算法
- 保障同一客户端 IP 的请求固定转发至同一后端 Pod
2. 未配置 sessionAffinity 的默认逻辑
kube-proxy 会采用 IPVS 预设的全局调度算法,可选策略:
- rr:轮询调度
- lc:最少连接调度
- wrr:加权轮询调度
金丝雀发布
学习参考:金丝雀部署
环境初始化:
bashroot@master30 ~ 13:26:50# mkdir web mkdir: cannot create directory 'web': File exists root@master30 ~ 13:46:25# echo hello nginx 1.28 > web/index28.html root@master30 ~ 13:46:34# echo hello nginx 1.29 > web/index29.html root@master30 ~ 13:46:41# kubectl create configmap web --from-file=./web configmap/web created root@master30 ~ 13:46:48# kubectl get configmaps web -o yaml |grep ^data -A4 data: index28.html: | hello nginx 1.28 index29.html: | hello nginx 1.29
金丝雀发布用于灰度上线新版本应用,上线过程中保留旧版本服务同时承接部分生产真实流量,可在全量发布前完成新版本稳定性验证。
实操中可借助 track 标签区分应用不同版本:
-
稳定线上版本配置
track: stablebashroot@master30 ~ 13:46:57# vim webapp-1.28.yamlbashapiVersion: apps/v1 kind: Deployment metadata: labels: app: web name: web-28 spec: replicas: 10 selector: matchLabels: app: web tier: frontend track: stable template: metadata: labels: app: web tier: frontend track: stable spec: containers: - image: hub.laoma.cloud/library/nginx:1.28 name: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80 volumeMounts: - name: webcontent mountPath: "/usr/share/nginx/html" volumes: - name: webcontent configMap: name: web items: - key: index28.html path: index.htmlbashroot@master30 ~ 13:47:23# kubectl apply -f webapp-1.28.yaml deployment.apps/web-28 created -
创建统一接入 Service 资源
bashroot@master30 ~ 13:47:39# vim webapp-svc.yamlbashapiVersion: v1 kind: Service metadata: labels: app: web name: web spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: web tier: frontendbashroot@master30 ~ 13:48:02# kubectl apply -f webapp-svc.yaml service/web configured root@master30 ~ 13:48:18# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE web ClusterIP 10.97.78.201 <none> 80/TCP 154m -
部署灰度新版本,新版本配置
track: canarybashroot@master30 ~ 13:48:26# vim webapp-1.29.yamlbashapiVersion: apps/v1 kind: Deployment metadata: labels: app: web name: web-29 spec: replicas: 1 selector: matchLabels: app: web tier: frontend track: canary template: metadata: labels: app: web tier: frontend track: canary spec: containers: - image: hub.laoma.cloud/library/nginx:1.29 name: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80 volumeMounts: - name: webcontent mountPath: "/usr/share/nginx/html" volumes: - name: webcontent configMap: name: web items: - key: index29.html path: index.htmlbashroot@master30 ~ 13:48:47# kubectl apply -f webapp-1.29.yaml deployment.apps/web-29 created验证流量分配比例:
bashroot@master30 ~ 13:49:09# kubectl scale deployment web-28 --replicas 8 deployment.apps/web-28 scaled root@master30 ~ 13:49:30# kubectl scale deployment web-29 --replicas 2 deployment.apps/web-29 scaled root@master30 ~ 13:49:39# for i in {1..50}; do curl -s 10.97.78.201; done | sort -n|uniq -c 38 hello nginx 1.28 12 hello nginx 1.29 -
总 Pod 数量保持不变,逐步缩减旧版本副本、扩容新版本副本完成全量灰度:
bashroot@master30 ~ 13:50:09# kubectl scale deployment web-28 --replicas 6 deployment.apps/web-28 scaled root@master30 ~ 13:50:47# kubectl scale deployment web-29 --replicas 4 deployment.apps/web-29 scaled root@master30 ~ 13:50:55# for i in {1..50}; do curl -s 10.97.78.201; done | sort -n|uniq -c 31 hello nginx 1.28 19 hello nginx 1.29
环境资源清理
bash
root@master30 ~ 13:51:00# kubectl delete ns services
kube-proxy
kube-proxy 是 Kubernetes 集群负责 Pod 网络转发的核心组件,核心职责是实现 Service 服务到后端 Endpoint 业务 Pod 的流量转发与负载均衡调度。
环境准备
bash
root@master30 ~ 13:51:05# kubectl create ns services
root@master30 ~ 13:51:10# kubectl config set-context --current --namespace services
工作模式类型
kube-proxy 共提供三类工作模式,对比信息如下:
| 模式 | 定位 | 性能表现 | 适用业务场景 | 核心特性 |
|---|---|---|---|---|
| iptables | 默认内置模式 | 中等(服务数量低于 1000) | 小规模测试集群、稳定静态环境 | 依赖内核 netfilter 模块,服务数量增多后规则匹配存在性能损耗 |
| IPVS | 生产环境推荐模式 | 极高(支持十万级服务) | 中大型线上生产集群 | 基于内核 IPVS 模块,底层采用哈希表检索,转发性能大幅优于 iptables |
| Userspace | 废弃兼容模式 | 性能低下 | 仅旧版本兼容、临时测试 | 全部转发逻辑运行在用户态,转发效率极差,K8s 1.25 及以上版本已彻底移除 |
✅ 线上生产集群强制选用 IPVS 模式,搭配 Calico CNI 网络插件,兼顾转发性能与集群稳定性。
工作模式切换操作
查看当前生效工作模式
bash
root@master30 ~ 14:11:14# kubectl get cm -n kube-system kube-proxy -o yaml|grep mode
mode: ""
# mode字段为空代表未手动指定模式
# 查看kube-proxy容器运行日志确认实际模式
root@master30 ~ 14:17:56# kubectl get pods -n kube-system -l k8s-app=kube-proxy -o name
pod/kube-proxy-dqpfk
pod/kube-proxy-kv6sb
pod/kube-proxy-r57jz
root@master30 ~ 14:18:27# kubectl logs -n kube-system kube-proxy-dqpfk |grep Using
I0811 00:49:00.834031 1 server_linux.go:69] "Using iptables proxy"
I0811 00:49:00.901237 1 server_linux.go:165] "Using iptables Proxier"
# 日志输出"Using iptables proxy",说明当前默认启用iptables转发模式
修改切换工作模式
bash
# 步骤1:编辑kube-proxy全局配置ConfigMap
root@master30 ~ 14:18:59# kubectl edit configmaps -n kube-system kube-proxy
# 找到mode配置项,修改为目标模式(示例切换为ipvs)
....
metricsBindAddress: ""
mode: "ipvs"
....
# 步骤2:滚动重启kube-proxy DaemonSet使配置生效
root@master30 ~ 14:19:40# kubectl rollout restart daemonset -n kube-system kube-proxy
daemonset.apps/kube-proxy restarted
# 步骤3:验证模式切换结果
root@master30 ~ 14:20:33# kubectl get pods -n kube-system -l k8s-app=kube-proxy -o name
pod/kube-proxy-6zffc
pod/kube-proxy-gnssn
pod/kube-proxy-wqp7w
root@master30 ~ 14:21:09# kubectl logs -n kube-system kube-proxy-6zffc | grep Using
I0811 06:20:03.684316 1 server_linux.go:233] "Using ipvs Proxier"
# 日志输出"Using ipvs Proxier",代表IPVS模式已成功启用
IPVS 模式详解
IPVS 转发模式基于 netfilter 回调机制实现,底层数据结构采用哈希表存储转发规则,全部逻辑运行在内核空间。对比 iptables 模式,IPVS 具备更低的流量转发延迟,同步更新转发规则时性能损耗更小,同时可承载更高并发流量。
IPVS 内置多种负载均衡调度算法,适配不同业务需求:
rr:轮询调度lc:最少连接调度(优先选择当前活跃连接数最少的后端)dh:目标地址哈希调度sh:源地址哈希调度(用于会话保持)sed:最短预期延迟调度nq:最少队列调度
底层工作原理
kube-proxy 会在宿主机内核中创建 IPVS 虚拟服务实例,并将所有后端业务 Pod 注册为 Real Server 真实服务节点。IPVS 依托哈希表存储转发规则,检索匹配时间复杂度为 O (1)。流量抵达宿主机后,IPVS 根据预设调度算法直接完成转发,规避了 iptables 多层规则链遍历带来的性能开销。
流量通信流程图:
#mermaid-svg-gce4lZ4qGE5ZEaqn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gce4lZ4qGE5ZEaqn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gce4lZ4qGE5ZEaqn .error-icon{fill:#552222;}#mermaid-svg-gce4lZ4qGE5ZEaqn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gce4lZ4qGE5ZEaqn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gce4lZ4qGE5ZEaqn .marker.cross{stroke:#333333;}#mermaid-svg-gce4lZ4qGE5ZEaqn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gce4lZ4qGE5ZEaqn p{margin:0;}#mermaid-svg-gce4lZ4qGE5ZEaqn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gce4lZ4qGE5ZEaqn .cluster-label text{fill:#333;}#mermaid-svg-gce4lZ4qGE5ZEaqn .cluster-label span{color:#333;}#mermaid-svg-gce4lZ4qGE5ZEaqn .cluster-label span p{background-color:transparent;}#mermaid-svg-gce4lZ4qGE5ZEaqn .label text,#mermaid-svg-gce4lZ4qGE5ZEaqn span{fill:#333;color:#333;}#mermaid-svg-gce4lZ4qGE5ZEaqn .node rect,#mermaid-svg-gce4lZ4qGE5ZEaqn .node circle,#mermaid-svg-gce4lZ4qGE5ZEaqn .node ellipse,#mermaid-svg-gce4lZ4qGE5ZEaqn .node polygon,#mermaid-svg-gce4lZ4qGE5ZEaqn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gce4lZ4qGE5ZEaqn .rough-node .label text,#mermaid-svg-gce4lZ4qGE5ZEaqn .node .label text,#mermaid-svg-gce4lZ4qGE5ZEaqn .image-shape .label,#mermaid-svg-gce4lZ4qGE5ZEaqn .icon-shape .label{text-anchor:middle;}#mermaid-svg-gce4lZ4qGE5ZEaqn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gce4lZ4qGE5ZEaqn .rough-node .label,#mermaid-svg-gce4lZ4qGE5ZEaqn .node .label,#mermaid-svg-gce4lZ4qGE5ZEaqn .image-shape .label,#mermaid-svg-gce4lZ4qGE5ZEaqn .icon-shape .label{text-align:center;}#mermaid-svg-gce4lZ4qGE5ZEaqn .node.clickable{cursor:pointer;}#mermaid-svg-gce4lZ4qGE5ZEaqn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gce4lZ4qGE5ZEaqn .arrowheadPath{fill:#333333;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gce4lZ4qGE5ZEaqn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gce4lZ4qGE5ZEaqn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gce4lZ4qGE5ZEaqn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gce4lZ4qGE5ZEaqn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gce4lZ4qGE5ZEaqn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gce4lZ4qGE5ZEaqn .cluster text{fill:#333;}#mermaid-svg-gce4lZ4qGE5ZEaqn .cluster span{color:#333;}#mermaid-svg-gce4lZ4qGE5ZEaqn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gce4lZ4qGE5ZEaqn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gce4lZ4qGE5ZEaqn rect.text{fill:none;stroke-width:0;}#mermaid-svg-gce4lZ4qGE5ZEaqn .icon-shape,#mermaid-svg-gce4lZ4qGE5ZEaqn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gce4lZ4qGE5ZEaqn .icon-shape p,#mermaid-svg-gce4lZ4qGE5ZEaqn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gce4lZ4qGE5ZEaqn .icon-shape .label rect,#mermaid-svg-gce4lZ4qGE5ZEaqn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gce4lZ4qGE5ZEaqn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gce4lZ4qGE5ZEaqn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gce4lZ4qGE5ZEaqn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 访问 Service IP:Port
哈希查找+调度算法
直接路由/隧道
客户端 Pod
宿主机网卡
内核 IPVS 虚拟服务器
选择最优后端 Pod
后端 Pod IP:Port
响应流量直接返回
IPVS 模式核心优势:
- 支持多种精细化调度算法,包含轮询、加权轮询、最少连接等策略。
- 转发性能不受集群服务总量影响,可稳定支撑十万级 Service 规模。
- 内置端点健康检测机制,与 Kubernetes Endpoint 资源状态实时联动。
原理实操验证
前置环境要求
- 宿主机已安装 IPVS 配套工具(
ipvsadm、ipset)并加载对应内核模块。 - kube-proxy 组件已切换至 IPVS 转发模式。
分步验证流程
1. 调整测试资源副本数量
bash
root@master30 ~ 14:22:17# kubectl scale deployment web-28 --replicas 2
deployment.apps/web-28 scaled
root@master30 ~ 14:26:01# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/web 1/1 Running 1 (5h37m ago) 21h
pod/web-28-7c6ffdbbd7-2k6rb 1/1 Running 0 26m
pod/web-28-7c6ffdbbd7-rwsv7 1/1 Running 0 26m
pod/web-29-5546565fbd-fhn44 1/1 Running 0 35m
pod/web-29-5546565fbd-mmbvw 1/1 Running 0 35m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/web ClusterIP 10.97.78.201 <none> 80/TCP 3h11m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/web-28 2/2 2 2 26m
deployment.apps/web-29 2/2 2 2 37m
NAME DESIRED CURRENT READY AGE
replicaset.apps/web-28-7c6ffdbbd7 2 2 2 26m
replicaset.apps/web-29-5546565fbd 2 2 2 37m
2. 查看内核 IPVS 转发规则
在集群任意节点执行,示例操作节点为 master30,查询 kube-proxy 生成的 IPVS 虚拟服务规则:
bash
# 列出指定Service的IPVS虚拟服务配置
root@master30 ~ 14:26:17# ipvsadm -Ln -t 10.97.78.201:80
执行后输出内容示例,其中 10.97.78.201 为 Service 集群 IP,80 为服务端口:
bash
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.97.78.201:80 rr
-> 10.224.133.73:80 Masq 1 0 0
-> 10.224.133.109:80 Masq 1 0 0
-> 10.224.218.167:80 Masq 1 0 0
-> 10.224.218.184:80 Masq 1 0 0
验证结论:IPVS 已为目标 Service 成功创建虚拟服务,并绑定全部后端业务 Pod 作为真实转发节点。
3. 验证负载均衡分发效果
在集群内部或外部持续访问 Service,观察流量是否均匀分发至不同 Pod 实例:
bash
# 连续发起50次访问请求
root@master30 ~ 14:40:10# for i in {1..50}; do curl -s 10.97.78.201; done | sort -n|uniq -c
25 hello nginx 1.28
25 hello nginx 1.29
预期结果:新旧版本 Pod 各承接 25 次请求,证明 IPVS 轮询(rr)调度算法正常生效。
Kubernetes Ingress
学习参考:Ingress
环境准备
bash
root@master30 ~ 14:48:46# kubectl create ns ingress
root@master30 ~ 14:49:50# kubectl config set-context --current --namespace ingress
Ingress 介绍
Ingress 能够为 Service 提供公网可访问的 URL 地址、实现流量负载均衡、终止 SSL/TLS 加密连接,同时支持基于域名的虚拟主机托管等核心能力。Ingress 控制器 是实现 Ingress 全部功能的核心组件,通常依托负载均衡器、边缘网关或前端代理完成流量处理工作。Ingress 不会直接对外开放非 HTTP/HTTPS 协议端口。若需要将其他协议服务暴露至公网,一般采用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的 Service 实现。
Ingress 控制器
集群中必须部署并正常运行 Ingress 控制器,Ingress 资源才能生效。
与内置在 kube-controller-manager 中的其他控制器不同,Ingress 控制器不会随 Kubernetes 集群自动部署启动。你可根据集群环境,选择适配的 Ingress 控制器实现方案。
Kubernetes 官方目前维护并支持 AWS、GCE、Nginx 三款 Ingress 控制器,对应项目地址如下:
ingress-nginx 工作流程
本次实验选用 ingress-nginx 控制器作为实践载体。
项目地址:ingress-nginx。
ingress-nginx 的完整工作流程如下:
- 部署 Ingress Controller 实体,该组件本质是前置 Nginx 代理服务
- 创建 Ingress 自定义资源,对应 Nginx 的路由配置文件
- Ingress Controller 与 Kubernetes APIServer 持续交互,动态拉取集群内所有 Ingress 规则;对规则完成解析后,生成代理服务对应的配置(即 Nginx 配置)
- 将生成的配置写入运行 Nginx 的 Pod,配置文件存放路径为
/etc/nginx/nginx.conf - 重载 Nginx 服务,使新路由规则立即生效
Ingress 本质是七层 HTTP/HTTPS 反向代理组件。
ingress-nginx 部署前提
项目地址: kubernetes/ingress-nginx
- 本实验环境采用负载均衡组件处理前端流量,需提前部署 Metallb 等 LoadBalancer 实现方案
- 集群必须部署配套 Ingress 控制器,本教程使用 ingress-nginx
ingress-nginx 版本
| Supported | Ingress-NGINX version | k8s supported version | Alpine Version | Nginx Version | Helm Chart Version |
|---|---|---|---|---|---|
| 🔄 | v1.11.2 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.11.2 |
| 🔄 | v1.11.1 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.11.1 |
| 🔄 | v1.11.0 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.11.0 |
| 🔄 | v1.10.2 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.10.2 |
| 🔄 | v1.10.1 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.19.1 | 1.25.3 | 4.10.1 |
| 🔄 | v1.10.0 | 1.29, 1.28, 1.27, 1.26 | 3.19.1 | 1.25.3 | 4.10.0 |
| ... |
ingress-nginx 部署
bash
root@master30 ~ 14:49:53# wget http://192.168.46.200/class/course-materials/softwares/stage03/ingress-nginx-controller-v1.11.2.tar.gz
--2026-08-11 15:09:54-- http://192.168.46.200/class/course-materials/softwares/stage03/ingress-nginx-controller-v1.11.2.tar.gz
Connecting to 192.168.46.200:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3902473 (3.7M) [application/octet-stream]
Saving to: 'ingress-nginx-controller-v1.11.2.tar.gz'
ingress-nginx-controll 100%[=========================>] 3.72M --.-KB/s in 0.04s
2026-08-11 15:09:54 (91.9 MB/s) - 'ingress-nginx-controller-v1.11.2.tar.gz' saved [3902473/3902473]
root@master30 ~ 15:10:41# tar -xf ingress-nginx-controller-v1.11.2.tar.gz
ingress-nginx 部署配置文件 deploy.yaml 包含四部分核心资源:
-
创建独立命名空间 ingress-nginx
-
创建 ConfigMap
ConfigMap 用于统一存储通用配置变量,作用等效配置文件。它可将分布式系统各模块所需环境变量统一管理,区别于本地配置文件的是,该资源托管于集群内部,且支持 Kubernetes 标准资源操作。
Pod 启动时可绑定 ConfigMap,容器内应用能够直接读取其中配置。ConfigMap 常见使用场景包括:注入环境变量、设置程序启动参数、挂载生成配置文件,本质是为业务运行环境统一封装配置项。
- Ingress 相关 RBAC 权限管控,依次创建 ServiceAccount、ClusterRole、Role、RoleBinding、ClusterRoleBinding 全套权限资源
- 部署 ingress-controller,前文提到该组件会实时读取新增 Ingress 规则,并转换为 Nginx 代理配置
bash
# 查看资源使用的镜像
root@master30 ~ 15:10:49# grep image: ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml|uniq
image: registry.k8s.io/ingress-nginx/controller:v1.11.2@sha256:d5f8217feeac4887cb1ed21f27c2674e58be06bd8f5184cacea2a69abaf78dce
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.3@sha256:a320a50cc91bd15fd2d6fa6de58bd98c1bd64b9a6f926ce23a600d87043455a3
# 替换镜像
root@master30 ~ 15:13:06# sed -ir 's#@sha256.*##;s/registry.k8s.io/hub.laoma.cloud/' ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml
# 创建 Ingress
root@master30 ~ 15:13:58# kubectl apply -f ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
== 注意 == :registry.k8s.io 官方镜像仓库国内无法直接拉取,需配置镜像加速服务;也可从 该地址 获取对应镜像。
查看部署的资源
bash
root@master30 ~ 15:18:56# kubectl get all -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-create-plk2q 0/1 Completed 0 5m5s
pod/ingress-nginx-admission-patch-xn265 0/1 Completed 0 5m5s
pod/ingress-nginx-controller-8659885ffd-gfcmp 1/1 Running 0 5m5s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller LoadBalancer 10.103.179.59 10.1.8.40 80:31688/TCP,443:32641/TCP 5m6s
service/ingress-nginx-controller-admission ClusterIP 10.98.172.241 <none> 443/TCP 5m6s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 5m6s
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-nginx-controller-8659885ffd 1 1 1 5m5s
NAME STATUS COMPLETIONS DURATION AGE
job.batch/ingress-nginx-admission-create Complete 1/1 4s 5m5s
job.batch/ingress-nginx-admission-patch Complete 1/1 4s 5m5s
Ingress 规则实践
Ingress 规则说明
规则示例
-
示例 1: 无路由规则,配置默认后端
通过指定
defaultBackend实现兜底转发,所有访问该负载均衡入口的流量,都会统一转发至配置内的 Kubernetes Service。bashapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: test-ingress spec: defaultBackend: service: name: testsvc port: number: 80 -
示例 2:虚拟主机配置,单域名匹配根路径
bashapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myingress spec: ingressClassName: nginx rules: - host: www.laoma.cloud http: paths: - path: / pathType: Prefix backend: service: name: www port: number: 80 - host: web.laoma.cloud http: paths: - path: / pathType: Prefix backend: service: name: web port: number: 80 -
示例 3:单域名多路径分流
bashapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myingress spec: ingressClassName: nginx rules: - host: www.laoma.cloud http: paths: - path: / pathType: Prefix backend: service: name: web port: number: 80 - path: /laoma pathType: Prefix backend: service: name: web port: number: 80 -
示例 4:HTTPS 流量透传场景
若后端 Service 自身提供 HTTPS 服务,可配置 TLS 透传,让 Ingress 不做解密操作,直接将原始 HTTPS 流量转发至后端 Service。
bashapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myingress annotations: # 关键:透传 TLS,Ingress 不解密 nginx.ingress.kubernetes.io/ssl-passthrough: "true" nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" spec: ingressClassName: nginx rules: - host: www.laoma.cloud http: paths: - path: / pathType: Prefix backend: service: name: web port: number: 443
配置说明
与 Kubernetes 其他资源配置规范一致,Ingress 配置文件必须包含 apiVersion、kind、metadata 基础字段。
Ingress 的 spec 字段包含负载均衡与反向代理所需的全部配置信息,核心为一组用于匹配前端请求的路由规则,当前 Ingress 仅支持 HTTP 协议路由。
单条 HTTP 路由规则包含以下信息:
host域名配置(例如 www.laoma.cloud,默认值为通配符*)paths路径匹配列表(例如/laoma),每条路径绑定一组后端service:port服务。负载均衡转发流量前,会优先匹配请求的 Host 与 Path。
IngressClass
集群中可部署多款不同实现的 Ingress 控制器,各自拥有独立配置逻辑,每条 Ingress 资源都需指定对应的 IngressClass。IngressClass 资源存储控制器专属配置,同时定义该类规则由哪一款控制器处理。
支持将某一条 IngressClass 设置为集群默认类:为对应 IngressClass 添加注解 ingressclass.kubernetes.io/is-default-class: true 后,所有未填写 ingressClassName 字段的 Ingress 资源,都会自动绑定该默认 IngressClass。
路径匹配
Ingress 内每一条路径都必须声明路径类型(Path Type),未指定 pathType 的配置无法通过集群合法性校验。
当前官方定义三种路径匹配类型:
Prefix:基于/分隔的 URL 路径前缀匹配,匹配区分大小写,逐段校验路径分隔元素。仅当请求路径每一段都匹配规则前缀时,才算匹配成功。Exact:严格完整匹配 URL 路径,区分大小写。ImplementationSpecific:匹配逻辑由对应 IngressClass 的控制器实现决定,控制器可自定义匹配规则,或等效复用 Prefix/Exact 逻辑。
示例
| 类型 | 路径 | 请求路径 | 匹配与否? |
|---|---|---|---|
| Prefix | / |
(所有路径) | 是 |
| Exact | /foo |
/foo |
是 |
| Exact | /foo |
/bar |
否 |
| Exact | /foo |
/foo/ |
否 |
| Exact | /foo/ |
/foo |
否 |
| Prefix | /foo |
/foo, /foo/ |
是 |
| Prefix | /foo/ |
/foo, /foo/ |
是 |
| Prefix | /aaa/bb |
/aaa/bbb |
否 |
| Prefix | /aaa/bbb |
/aaa/bbb |
是 |
| Prefix | /aaa/bbb/ |
/aaa/bbb |
是,忽略尾部斜线 |
| Prefix | /aaa/bbb |
/aaa/bbb/ |
是,匹配尾部斜线 |
| Prefix | /aaa/bbb |
/aaa/bbb/ccc |
是,匹配子路径 |
| Prefix | /aaa/bbb |
/aaa/bbbxyz |
否,字符串前缀不匹配 |
| Prefix | /, /aaa |
/aaa/ccc |
是,匹配 /aaa 前缀 |
| Prefix | /, /aaa, /aaa/bbb |
/aaa/bbb |
是,匹配 /aaa/bbb 前缀 |
| Prefix | /, /aaa, /aaa/bbb |
/ccc |
是,匹配 / 前缀 |
| Prefix | /aaa |
/ccc |
否,使用默认后端 |
| 混合 | /foo (Prefix), /foo (Exact) |
/foo |
是,优选 Exact 类型 |
多重匹配
在某些情况下,Ingress 中会有多条路径与同一个请求匹配。这时匹配路径最长者优先。 如果仍然有两条同等的匹配路径,则精确路径类型优先于前缀路径类型。
主机名匹配
Host 域名支持两种匹配模式:精确匹配、通配符匹配。精确匹配要求 HTTP 请求 Host 头部与配置字段完全一致;通配符匹配仅校验域名后缀段是否吻合。
| 主机 | host 头部 | 匹配与否? |
|---|---|---|
*.foo.com |
bar.foo.com |
匹配,后缀域名段一致 |
*.foo.com |
baz.bar.foo.com |
不匹配,通配符仅覆盖单级 DNS 域名标签 |
*.foo.com |
foo.com |
不匹配,通配符仅覆盖单级 DNS 域名标签 |
Ingress 规则实践
本节主要讲解生产环境中 ingress-nginx 高频使用的路由配置方案。
环境准备
站点 webapp01
bash
# 创建Deployment
root@master30 ~ 15:40:33# kubectl create deployment webapp01 --image=hub.laoma.cloud/library/httpd --replicas=2
deployment.apps/webapp01 created
# 查看pod标签
root@master30 ~ 15:53:43# kubectl get pod -L app
NAME READY STATUS RESTARTS AGE APP
webapp01-587d58c655-jssqn 1/1 Running 0 17s webapp01
webapp01-587d58c655-s8kvk 1/1 Running 0 17s webapp01
# 准备pod主页内容
root@master30 ~ 15:54:00# kubectl exec -it webapp01-587d58c655-jssqn -- bash -c "echo hello webapp01 pod1 > htdocs/index.html"
root@master30 ~ 15:56:19# kubectl exec -it webapp01-587d58c655-s8kvk -- bash -c "echo hello webapp01 pod2 > htdocs/index.html"
root@master30 ~ 15:57:03# kubectl expose deployment webapp01 --port=80 --target-port=80
service/webapp01 exposed
站点 webapp02
bash
# 创建Deployment
root@master30 ~ 15:57:16# kubectl create deployment webapp02 --image=hub.laoma.cloud/library/httpd --replicas=2
deployment.apps/webapp02 created
# 查看pod标签
root@master30 ~ 15:57:36# kubectl get pod |grep webapp02
webapp02-56cfd678d6-5wlt9 1/1 Running 0 13s
webapp02-56cfd678d6-skjkf 1/1 Running 0 13s
# 准备pod主页内容
root@master30 ~ 15:57:49# kubectl exec -it webapp02-56cfd678d6-5wlt9 -- bash -c "echo hello webapp02 pod1 > htdocs/index.html
mkdir htdocs/games
echo hello webapp02 game1 > htdocs/games/index.html"
root@master30 ~ 15:58:30# kubectl exec -it webapp02-56cfd678d6-skjkf -- bash -c "echo hello webapp02 pod2 > htdocs/index.html
mkdir htdocs/games
echo hello webapp02 game2 > htdocs/games/index.html"
root@master30 ~ 15:58:32# kubectl expose deployment webapp02 --port=80 --target-port=80
service/webapp02 exposed
基础通用规则
多域名虚拟主机(多 host 路由)
场景:多个独立域名分别转发至不同业务后端
bash
root@master30 ~ 15:58:58# vim ingress.yaml
bash
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
# 这里一定要指定ingressClassName为nginx
ingressClassName: nginx
rules:
- host: webapp01.liu.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp01
port:
number: 80
- host: webapp02.liu.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp02
port:
number: 80
bash
root@master30 ~ 15:59:38# kubectl apply -f ingress.yaml
ingress.networking.k8s.io/multi-host-ingress created
root@master30 ~ 15:59:50# kubectl describe ingress multi-host-ingress
Name: multi-host-ingress
Labels: <none>
Namespace: ingress
Address:
Ingress Class: nginx
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
webapp01.liu.cloud
/ webapp01:80 (10.224.133.106:80,10.224.218.158:80)
webapp02.liu.cloud
/ webapp02:80 (10.224.133.115:80,10.224.218.162:80)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 15s nginx-ingress-controller Scheduled for sync
访问验证
bash
# 如果有多个域名,建议使用配置DNS-wild匹配
root@master30 ~ 16:00:05# echo '10.1.8.40 webapp01.liu.cloud'>> /etc/hosts
root@master30 ~ 16:00:52# echo '10.1.8.40 webapp02.liu.cloud'>> /etc/hosts
# 注意: 这里我们直接访问域名,没有加端口号
root@master30 ~ 16:01:00# curl webapp01.liu.cloud
hello webapp01 pod2
root@master30 ~ 16:10:17# curl webapp01.liu.cloud
hello webapp01 pod1
root@master30 ~ 16:10:19# curl webapp02.liu.cloud
hello webapp02 pod2
root@master30 ~ 16:10:25# curl webapp02.liu.cloud
hello webapp02 pod1
删除 ingress
bash
root@master30 ~ 16:25:36# kubectl delete ingress multi-host-ingress
ingress.networking.k8s.io "multi-host-ingress" deleted
同一域名多路径路由(path 分流)
场景:单一域名下,不同 URL 路径转发至对应微服务
bash
root@master30 ~ 16:32:58# vim ingress.yaml
bash
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-path-ingress
spec:
ingressClassName: nginx
rules:
- host: www.liu.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp01
port:
number: 80
- path: /games
pathType: Prefix
backend:
service:
name: webapp02
port:
number: 80
bash
root@master30 ~ 16:35:36# kubectl apply -f ingress.yaml
ingress.networking.k8s.io/multi-path-ingress created
root@master30 ~ 16:35:57# kubectl describe ingress multi-path-ingress
Name: multi-path-ingress
Labels: <none>
Namespace: ingress
Address:
Ingress Class: nginx
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
www.liu.cloud
/ webapp01:80 (10.224.133.106:80,10.224.218.158:80)
/games webapp02:80 (10.224.133.115:80,10.224.218.162:80)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 16s nginx-ingress-controller Scheduled for sync
访问验证
bash
# 修改www.laoma.cloud解析,确保客户端能解析该名称
# 如果有多个域名,建议使用配置DNS-wild匹配
root@master30 ~ 16:36:13# echo '10.1.8.40 www.liu.cloud'>> /etc/hosts
# 注意: 这里我们直接访问域名,没有加端口号
root@master30 ~ 16:37:57# curl www.liu.cloud
hello webapp01 pod1
root@master30 ~ 16:38:54# curl www.liu.cloud
hello webapp01 pod2
root@master30 ~ 16:39:12# curl www.li.cloud/games/
hello webapp02 game1
root@master30 ~ 16:39:24# curl www.liu.cloud/games/
hello webapp02 game2
删除 ingress
bash
root@master30 ~ 16:39:26# kubectl delete ingress multi-path-ingress
ingress.networking.k8s.io "multi-path-ingress" deleted
生产核心:路径重写
路径裁剪(等价 Nginx proxy_pass /)
场景 :前端请求携带 /api 统一前缀,后端程序仅识别去除前缀后的路径,通过重写规则剥离前缀
bash
root@master30 ~ 16:39:59# vim ingress.yaml
bash
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-path-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
ingressClassName: nginx
rules:
- host: www.liu.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
bash
root@master30 ~ 16:40:54# kubectl apply -f ingress.yaml
ingress.networking.k8s.io/multi-path-ingress created
root@master30 ~ 16:41:11# kubectl describe ingress multi-path-ingress
Name: multi-path-ingress
Labels: <none>
Namespace: ingress
Address: 10.1.8.40
Ingress Class: nginx
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
www.liu.cloud
/webapp01/(.*) webapp01:80 (10.224.133.106:80,10.224.218.158:80)
/webapp02/(.*) webapp02:80 (10.224.133.115:80,10.224.218.162:80)
Annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/use-regex: true
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 3s (x2 over 20s) nginx-ingress-controller Scheduled for sync
访问验证
bash
root@master30 ~ 16:41:31# curl www.liu.cloud/webapp01/
hello webapp01 pod1
root@master30 ~ 16:41:57# curl www.liu.cloud/webapp01/
hello webapp01 pod2
root@master30 ~ 16:42:09# curl www.liu.cloud/webapp02/
hello webapp02 pod2
root@master30 ~ 16:42:10# curl www.liu.cloud/webapp02/
hello webapp02 pod1
删除 ingress
bash
root@master30 ~ 16:42:12# kubectl delete ingress multi-path-ingress
ingress.networking.k8s.io "multi-path-ingress" deleted
HTTPS 强制 & TLS 证书
绑定 TLS 证书 + 强制 HTTPS
环境准备
bash
oot@master30 ~ 16:42:41# openssl genrsa -out www.key 2048
root@master30 ~ 16:42:50# openssl req -new -key www.key -out www.csr -subj "/C=CN/ST=JS/L=NJ/O=LM/OU=DEVOPS/CN=www.liu.cloud/emailAddress=webadmin@liu.cloud"
root@master30 ~ 16:43:15# openssl x509 -req -days 3650 -in www.csr -signkey www.key -out www.crt
Certificate request self-signature ok
subject=C = CN, ST = JS, L = NJ, O = LM, OU = DEVOPS, CN = www.liu.cloud, emailAddress = webadmin@liu.cloud
root@master30 ~ 16:43:24# kubectl create secret tls www-tls --cert=./www.crt --key=./www.key
secret/www-tls created
生产标配:访问 80 端口自动跳转 443 HTTPS 加密端口
bash
root@master30 ~ 16:43:54# vim ingress.yaml
bash
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.liu.cloud
secretName: www-tls
rules:
- host: www.liu.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp01
port:
number: 80
bash
root@master30 ~ 16:44:33# kubectl apply -f ingress.yaml
ingress.networking.k8s.io/tls-ingress created
root@master30 ~ 16:44:47# kubectl describe ingress tls-ingress
Name: tls-ingress
Labels: <none>
Namespace: ingress
Address:
Ingress Class: nginx
Default backend: <default>
TLS:
www-tls terminates www.liu.cloud
Rules:
Host Path Backends
---- ---- --------
www.liu.cloud
/ webapp01:80 (10.224.133.106:80,10.224.218.158:80)
Annotations: nginx.ingress.kubernetes.io/force-ssl-redirect: true
nginx.ingress.kubernetes.io/ssl-redirect: true
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 10s nginx-ingress-controller Scheduled for sync
访问验证
bash
# 使用 -L 跟随 301/302/307/308 所有重定向
root@master30 ~ 16:45:18# curl -Lk http://www.liu.cloud/
hello webapp01 pod2
root@master30 ~ 16:45:21# curl -Lk http://www.liu.cloud/
hello webapp01 pod1
# 访问https站点
root@master30 ~ 16:45:22# curl -k https://www.liu.cloud/
hello webapp01 pod1
root@master30 ~ 16:45:34# curl -k https://www.liu.cloud/
hello webapp01 pod2
删除 ingress
bash
root@master30 ~ 16:45:35# kubectl delete ingress tls-ingress
ingress.networking.k8s.io "tls-ingress" deleted
限流、防刷、超时优化
连接数限流、单 IP 限速
bash
annotations:
# 单IP最大并发连接
nginx.ingress.kubernetes.io/limit-connections: "50"
# 单IP每秒请求数
nginx.ingress.kubernetes.io/limit-rps: "20"
自定义超时时间
bash
annotations:
nginx.ingress.kubernetes.io/proxy-connect-timeout: "10"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
跨域配置(前后端分离必备)
全局跨域放行
bash
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET,POST,PUT,DELETE,OPTIONS"
白名单访问控制(内网 / 后台系统)
限制指定 IP 段访问
场景:管理后台、内部业务系统,仅允许企业内网 IP 接入
bash
annotations:
# 只放行 10.1.8.0/24 网段
nginx.ingress.kubernetes.io/whitelist-source-range: "10.1.8.0/24,127.0.0.1/32"
静态资源缓存、请求头透传
透传真实客户端 IP
bash
annotations:
nginx.ingress.kubernetes.io/x-forwarded-for: "true"
nginx.ingress.kubernetes.io/proxy-real-ip-cidr: "10.0.0.0/8"
静态资源缓存优化
bash
annotations:
nginx.ingress.kubernetes.io/proxy-cache: "true"
nginx.ingress.kubernetes.io/proxy-cache-valid: "200 302 10m"
灰度 / 权重分流(金丝雀发布)
权重流量拆分
场景:线上灰度发布,90% 流量分配至稳定版本,10% 流量分发至测试新版本
bash
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
错误页面、自定义配置
自定义后端错误页、关闭目录浏览
bash
annotations:
nginx.ingress.kubernetes.io/custom-http-errors: "404,500,502,503"
生产高频注解 速查表
| 注解 | 作用 |
|---|---|
force-ssl-redirect: true |
80 端口强制跳转 HTTPS |
rewrite-target |
实现路径重写、路由前缀裁剪 |
whitelist-source-range |
配置访问 IP 白名单 |
limit-rps / limit-connections |
防 CC 攻击、请求限流 |
enable-cors |
开启前后端跨域支持 |
proxy-read-timeout |
解决长接口请求超时断开问题 |
x-forwarded-for |
后端服务获取真实客户端 IP |
环境清理
bash
root@master30 ~ 16:49:19# kubectl get all
No resources found in ingress namespace.