kubernetes(K8s)学习笔记(第七期):网络与服务暴露

kubernetes(K8s)学习笔记(第七期):网络与服务暴露

本笔记为 Kubernetes 系列第七期,聚焦集群网络与服务暴露的核心机制。涵盖:Service 概述与基本管理、Service 三种发现方式、五种 Service 类型、会话保持与金丝雀发布、kube-proxy 的 iptables 与 IPVS 两种工作模式详解、Ingress 控制器部署与生产级规则实践(多域名、多路径、重写、TLS、限流、跨域等 10+ 种注解)。所有命令和 YAML 示例均已经过整理和注释。全文约 4700 字 ,包含 35+ YAML 示例80+ 命令示例18 张对比表格,是 Kubernetes 网络与服务暴露的完整指南。
--- Compiled and Authored by Whisky --- June 29th, 2026

目录

  1. Service 概述与基本管理
  2. Service 发现
  3. Service 类型
  4. Service 高级特性
  5. kube-proxy 工作原理
  6. Ingress 概述与控制器部署
  7. Ingress 规则实践
  8. 总结与知识点一览表

一、Service 概述与基本管理

1.1 为什么需要 Service?

在 Kubernetes 中,Pod 是临时的、动态的资源:

  • 每个 Pod 有自己的 IP 地址(由网络插件分配)
  • Pod 可能因故障、滚动更新、扩缩容而被销毁和重建
  • 每次重建后 IP 地址会变化

这就带来一个问题:前端应用如何找到并连接到后端 Pod?

答案是 Service

Service 的核心作用

  • 固定 IP 和 DNS 名称:无论后端 Pod 如何变化,Service 的 IP 和 DNS 不变
  • 负载均衡:将流量分发到多个后端 Pod
  • 服务发现:通过 DNS 或环境变量让应用自动发现服务

通俗比喻:Service 就像"前台总机"。每个员工(Pod)都有分机号(IP),分机号经常变动。但客户只需要打总机号码(Service IP),前台会自动转接到可用的员工(Pod)。

1.2 Service 与 Endpoints 的关系

Service 通过标签选择器(selector) 匹配后端 Pod,被匹配的 Pod IP 和端口会记录在 Endpoints 对象中。

bash 复制代码
root@master30:~# kubectl create deployment web --image=httpd --replicas=3
root@master30:~# kubectl expose deployment web --port=8080 --target-port=80
root@master30:~# kubectl get svc
NAME   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
web    ClusterIP   10.103.19.150   <none>        8080/TCP   6m58s

root@master30:~# kubectl describe svc web
Name:              web
IP:                10.103.19.150
Port:              8080-80  8080/TCP
TargetPort:        80/TCP
Endpoints:         10.224.193.67:80,10.224.193.68:80,10.224.41.131:80

root@master30:~# kubectl get endpoints
NAME   ENDPOINTS                                      AGE
web    10.224.193.67:80,10.224.193.68:80,10.224.41.131:80   7m

关键理解:Endpoints 是 Service 和 Pod 之间的桥梁。Service 不直接连接 Pod,而是通过 Endpoints 获取所有匹配 Pod 的地址列表。当 Pod 发生变动时,Endpoints 会自动更新,Service 无需任何配置变更即可感知新 Pod。

1.3 通过 YAML 创建 Service

bash 复制代码
root@master30:~# kubectl create service clusterip web --tcp=8080:80 -o yaml --dry-run=client > svc-web.yaml
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  labels:
    app: web
  name: web
spec:
  ports:
  - name: web-8080-80
    port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    app: web
  type: ClusterIP

注意spec.selector 中指定的标签必须与 Pod 的标签完全匹配,否则 Service 将无法发现后端 Pod,Endpoints 列表将为空。

二、Service 发现

所谓 Service 发现,是指集群内应用如何访问 Service。我们介绍三种方式:

方式 说明 适用场景
IP 访问 直接使用 Service 的 ClusterIP 临时调试、硬编码(不推荐)
环境变量 Pod 启动时注入 Service 信息 简单场景,但需注意创建顺序
DNS 访问 通过 DNS 名称访问(CoreDNS) 生产环境推荐

2.1 通过 IP 访问 Service

实验:部署 MySQL Service,使用 IP 访问。

bash 复制代码
# 1. 创建 MySQL Pod
root@master30:~# kubectl run mysql --image=mysql \
    --env=MYSQL_ROOT_PASSWORD=redhat \
    --env=MYSQL_USER=tom \
    --env=MYSQL_PASSWORD=redhat \
    --env=MYSQL_DATABASE=blog

# 2. 创建 Service
root@master30:~# kubectl expose pod mysql --port=3306 --target-port=3306
root@master30:~# kubectl get svc mysql
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
mysql   ClusterIP   10.111.69.45   <none>        3306/TCP   25m

# 3. 测试连接
root@master30:~# apt install -y mysql-client
root@master30:~# mysql -u tom -predhat -h 10.111.69.45 -e 'show databases;'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| blog               |
+--------------------+

2.2 通过环境变量访问 Service

当 Pod 启动时,Kubernetes 会自动注入所有 Service 的环境变量。

bash 复制代码
root@master30:~# kubectl run test --rm -it --image=busybox sh
/ # env | grep MYSQL
MYSQL_PORT_3306_TCP_ADDR=10.111.69.45
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_SERVICE_HOST=10.111.69.45
MYSQL_SERVICE_PORT=3306
MYSQL_PORT=tcp://10.111.69.45:3306
/ # exit

环境变量命名规则

  • <SERVICE_NAME>_SERVICE_HOST:Service IP
  • <SERVICE_NAME>_SERVICE_PORT:Service 端口
  • <SERVICE_NAME>_PORT_<port>_TCP_ADDR:具体端口对应的 IP

⚠️ 前提条件 :Service 必须在 Pod 之前创建,否则环境变量不会注入。如果 Service 后创建,Pod 需要重启才能获取环境变量。

实验:WordPress 通过环境变量连接 MySQL。

bash 复制代码
root@master30:~# kubectl run wordpress \
    --image=wordpress \
    --env=WORDPRESS_DB_USER=tom \
    --env=WORDPRESS_DB_PASSWORD=redhat \
    --env=WORDPRESS_DB_NAME=blog \
    --env=WORDPRESS_DB_HOST='$(MYSQL_SERVICE_HOST)'

2.3 通过 DNS 名称访问 Service(推荐)

Kubernetes 集群默认部署 CoreDNS 作为 DNS 服务器。

bash 复制代码
root@master30:~# kubectl get svc -n kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   3d2h

DNS 记录格式<service-name>.<namespace>.svc.cluster.local

简化写法

  • 同 Namespace:直接使用 Service 名称(如 wordpress
  • 跨 Namespace:使用 <service>.<namespace>(如 wordpress.default
bash 复制代码
root@master30:~# kubectl run busybox --rm -it --image=busybox sh
/ # cat /etc/resolv.conf
nameserver 10.96.0.10
search service.svc.cluster.local svc.cluster.local cluster.local
/ # wget -q -O- wordpress:80
<html><body><h1>It works!</h1></body></html>

三、Service 类型

Kubernetes Service 支持以下五种类型:

类型 说明 访问范围
ClusterIP(默认) 集群内部 IP 仅集群内
NodePort 节点端口映射 集群内外均可(通过节点 IP+端口)
LoadBalancer 外部负载均衡器 IP 集群内外均可(通过 LB IP)
ExternalName DNS CNAME 映射 集群内(DNS 级别)
Headless ClusterIP=None 直接访问 Pod IP

3.1 ClusterIP(默认)

ClusterIP 是默认类型,只能在集群内部访问。

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: ClusterIP
  ports:
  - port: 8080
    targetPort: 80
  selector:
    app: web

3.2 NodePort

NodePort 在每个节点上打开一个端口(默认范围 30000-32767),将流量转发到 Service。

bash 复制代码
root@master30:~# kubectl expose deployment web --type=NodePort --port=8080 --target-port=80
root@master30:~# kubectl get svc
NAME   TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
web    NodePort   10.110.40.0   <none>        8080:31917/TCP   48s

三个端口的关系

端口 含义 示例
nodePort 节点上监听的端口(用户访问入口) 31917
port ClusterIP 上监听的端口 8080
targetPort Pod 监听的端口 80

NodePort 端口分配机制

  • Kubernetes 从 --service-node-port-range 标志指定的范围内分配端口
  • 默认范围:30000-32767
  • 如果用户没有指定,系统自动分配一个空闲端口
  • 用户也可以手动指定,但需确保端口不冲突
bash 复制代码
root@client:~# curl http://10.1.8.30:31917   # 通过任意节点 IP 访问
root@client:~# curl http://10.1.8.31:31917
root@client:~# curl http://10.1.8.32:31917

指定固定 NodePort

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 80
    nodePort: 30080   # 固定端口,需在 30000-32767 范围内
  selector:
    app: web

3.3 LoadBalancer

LoadBalancer 类型需要外部负载均衡器支持。在裸金属环境中,可以使用 MetalLB

部署 MetalLB

bash 复制代码
root@master30:~# wget http://192.168.42.200/course-materials/softwares/stage03/metallb-0.14.8.tar.gz
root@master30:~# tar -xf metallb-0.14.8.tar.gz
root@master30:~# sed -i 's/quay.io/hub.whisky.cloud/g' metallb-0.14.8/config/manifests/metallb-native.yaml
root@master30:~# kubectl apply -f metallb-0.14.8/config/manifests/metallb-native.yaml

# 等待所有 Pod 正常运行
root@master30:~# kubectl get all -n metallb-system

配置 IP 地址池

yaml 复制代码
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.1.8.40-10.1.8.80   # 可用的 IP 范围

配置 L2 通告

yaml 复制代码
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: example
  namespace: metallb-system

创建 LoadBalancer Service

bash 复制代码
root@master30:~# kubectl expose deployment web --type=LoadBalancer --port=80 --target-port=80
root@master30:~# kubectl get svc
NAME   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
web    LoadBalancer   10.109.101.67   10.1.8.40     80:32101/TCP     5s

[root@client ~]# curl 10.1.8.40:80
<html><body><h1>It works!</h1></body></html>

MetalLB 工作流程图

text 复制代码
客户端 → MetalLB VIP (10.1.8.40) → 节点 kube-proxy → Service → 后端 Pod

MetalLB 只做 ARP 宣告 + IP 占坑,实际的流量转发由 kube-proxy 完成。

3.4 ExternalName

ExternalName 将 Service 映射到外部 DNS 名称,在 DNS 级别返回 CNAME 记录。

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: ExternalName
  externalName: database.example.com

访问 my-service.prod.svc.cluster.local 会被解析为 database.example.com

适用场景:将集群内服务访问透明地重定向到外部服务,无需修改应用代码。

3.5 Headless Service

当不需要负载均衡和 ClusterIP 时,可以将 clusterIP 设为 None

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: headless-web
spec:
  clusterIP: None
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 80

行为差异

  • 带 selector:DNS 返回 Pod IP 列表(A 记录),适合 StatefulSet 直接访问 Pod
  • 无 selector:需要手动配置 Endpoints,适合接入外部服务

四、Service 高级特性

4.1 会话保持(sessionAffinity)

默认情况下,Service 将请求轮询分发到所有后端 Pod。如果希望同一客户端的请求始终发往同一 Pod,可以启用会话保持。

bash 复制代码
# 默认无会话保持
root@master30:~# for i in {1..20}; do curl -s 10.111.90.183; done | sort | uniq -c
     10 web-6db76cb4fc-5gbx2
     10 web-6db76cb4fc-b8f7l

# 启用会话保持(基于 ClientIP)
root@master30:~# kubectl patch svc web -p '{"spec":{"sessionAffinity":"ClientIP"}}'

# 再次测试:所有请求都发往同一个 Pod
root@master30:~# for i in {1..20}; do curl -s 10.111.90.183; done | sort | uniq -c
     20 web-6db76cb4fc-5gbx2

会话保持与 IPVS 的关系

  • Service 配置 sessionAffinity: ClientIP → kube-proxy 自动使用 IPVS 的 SH(源地址哈希) 算法
  • 默认情况下,IPVS 使用 rr(轮询) 算法
  • 超时时间:.spec.sessionAffinityConfig.clientIP.timeoutSeconds(默认 10800 秒,即 3 小时)

配置超时时间示例

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 7200   # 2 小时
  selector:
    app: web
  ports:
  - port: 80

4.2 金丝雀发布

利用 Service 标签选择器 的灵活性,可以实现金丝雀发布------同时运行稳定版和测试版,通过调整副本数控制流量比例。

核心思想 :同一个 Service 匹配多个 Deployment(它们有相同的 apptier 标签,但 track 不同)。

bash 复制代码
# 创建 ConfigMap
root@master30:~# echo "hello nginx 1.28" > web/index28.html
root@master30:~# echo "hello nginx 1.29" > web/index29.html
root@master30:~# kubectl create configmap web --from-file=./web

# 部署稳定版(track: stable)
root@master30:~# kubectl apply -f webapp-1.28.yaml
# 部署金丝雀版(track: canary)
root@master30:~# kubectl apply -f webapp-1.29.yaml

# 创建 Service(匹配 app: web, tier: frontend)
root@master30:~# kubectl apply -f webapp-svc.yaml

# 调整副本数控制流量比例
root@master30:~# kubectl scale deployment web-28 --replicas=8
root@master30:~# kubectl scale deployment web-29 --replicas=2
root@master30:~# for i in {1..50}; do curl -s 10.98.235.36; done | sort | uniq -c
     39 hello nginx 1.28
     11 hello nginx 1.29

五、kube-proxy 工作原理

kube-proxy 是 Kubernetes 网络的核心组件,负责实现 Service 到后端 Pod 的流量转发与负载均衡。

5.1 三种工作模式对比

模式 地位 性能 适用场景
iptables 默认模式 中(服务数 < 1000) 小规模集群
IPVS 推荐模式 极高(服务数 10w+) 中大规模生产环境
Userspace 已废弃 仅测试、兼容旧版

5.2 iptables 模式详解

iptables 模式是 kube-proxy 的默认模式。它利用 Linux 内核的 netfilter 框架,通过动态生成 iptables 规则实现流量转发。

工作原理

客户端访问 Service IP → 进入 KUBE-SERVICES 链 → 匹配到 KUBE-SVC-XXX 链 → 随机概率选择 KUBE-SEP-XXX 链 → DNAT 到后端 Pod

iptables-save 分析

bash 复制代码
# 保存防火墙规则
root@master30:~# iptables-save > iptables.list

# 1. 服务入口链:匹配 ClusterIP
-A KUBE-SERVICES -d 10.103.143.120/32 -p tcp --dport 80 -j KUBE-SVC-7D76YWGERGEPC4GC

# 2. 服务调度链:负载均衡(概率匹配)
-A KUBE-SVC-7D76YWGERGEPC4GC -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-HYZM2VM7RCC7M2HX
-A KUBE-SVC-7D76YWGERGEPC4GC -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CHPZVFCOFL4YLCYM
-A KUBE-SVC-7D76YWGERGEPC4GC -j KUBE-SEP-HM7RLUR2RXSQ3D6F

# 3. 后端端点链:DNAT 到 Pod
-A KUBE-SEP-HYZM2VM7RCC7M2HX -p tcp -j DNAT --to-destination 10.224.113.164:80

iptables 模式流程图

ini 复制代码
┌─────────────────────────────────────────────────────────────────────────────┐
│                    iptables 模式流量转发全链路                             │
└─────────────────────────────────────────────────────────────────────────────┘

  客户端
    │  访问 ClusterIP 10.103.143.120:80
    ▼
  ┌─────────────────────────────────────────────────────────────────────────┐
  │ ① PREROUTING 链 (nat 表)                                               │
  │    拦截所有进入本机的数据包                                             │
  └─────────────────────────────────────────────────────────────────────────┘
    │
    ▼
  ┌─────────────────────────────────────────────────────────────────────────┐
  │ ② KUBE-SERVICES(服务总入口链)                                        │
  │    匹配条件:目的 IP = 10.103.143.120,目的端口 = 80                    │
  │    动作:跳转到 KUBE-SVC-7D76YWGERGEPC4GC                              │
  └─────────────────────────────────────────────────────────────────────────┘
    │
    ▼
  ┌─────────────────────────────────────────────────────────────────────────┐
  │ ③ KUBE-SVC-XXX(Service 专属调度链)                                   │
  │                                                                         │
  │     ┌───────────────────────────────────────────────────────────────┐   │
  │     │  检查:源 IP 是否在 Pod 网段(10.224.0.0/16)内?            │   │
  │     │  否 → SNAT 标记(跳转 KUBE-MARK-MASQ)后继续处理             │   │
  │     └───────────────────────────────────────────────────────────────┘   │
  │                                    │                                    │
  │                    ┌───────────────┼───────────────┐                    │
  │                    │               │               │                    │
  │                    ▼               ▼               ▼                    │
  │             ┌─────────────┐ ┌─────────────┐ ┌─────────────┐           │
  │             │  分支 1     │ │  分支 2     │ │  分支 3     │           │
  │             │  概率 1/3   │ │  概率 1/3   │ │  概率 1/3   │           │
  │             │ KUBE-SEP-A  │ │ KUBE-SEP-B  │ │ KUBE-SEP-C  │           │
  │             └─────────────┘ └─────────────┘ └─────────────┘           │
  └─────────────────────────────────────────────────────────────────────────┘
    │              │              │
    ▼              ▼              ▼
  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
  │ ④ DNAT      │ │ ④ DNAT      │ │ ④ DNAT      │
  │ 转发到:    │ │ 转发到:    │ │ 转发到:    │
  │ Pod 1       │ │ Pod 2       │ │ Pod 3       │
  │ 10.224      │ │ 10.224      │ │ 10.224      │
  │ .113.164:80 │ │ .113.165:80 │ │ .19.38:80   │
  └─────────────┘ └─────────────┘ └─────────────┘

缺点:服务数超过 1000 时,规则链膨胀,CPU 占用飙升,延迟显著增加。

5.3 IPVS 模式详解(生产推荐)

IPVS(IP Virtual Server)是 Linux 内核的负载均衡模块,使用哈希表存储规则,查找效率为 O(1)。

切换为 IPVS 模式

bash 复制代码
# 1. 修改 kube-proxy ConfigMap
root@master30:~# kubectl edit configmap -n kube-system kube-proxy
# 将 mode: "" 改为 mode: "ipvs"

# 2. 重启 kube-proxy
root@master30:~# kubectl rollout restart daemonset -n kube-system kube-proxy

# 3. 验证模式
root@master30:~# kubectl logs -n kube-system kube-proxy-72b7j | grep Using
I0415 13:22:14.052593       1 server_linux.go:233] "Using ipvs Proxier"

IPVS 内核模块要求

bash 复制代码
# 加载 IPVS 内核模块
root@master30:~# modprobe ip_vs
root@master30:~# modprobe ip_vs_rr
root@master30:~# modprobe ip_vs_wrr
root@master30:~# modprobe ip_vs_lc
root@master30:~# modprobe ip_vs_sh
root@master30:~# modprobe nf_conntrack

验证 IPVS 规则

bash 复制代码
root@master30:~# ipvsadm -Lnt 10.103.143.120:80
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.103.143.120:80 rr
  -> 10.224.19.38:80              Masq    1      0          0
  -> 10.224.113.164:80            Masq    1      0          0
  -> 10.224.113.165:80            Masq    1      0          0

IPVS 调度算法

算法 说明 适用场景
rr 轮询 默认,通用场景
wrr 加权轮询 节点性能不均
lc 最少连接 长连接、WebSocket
sh 源地址哈希 配合 sessionAffinity
sed 最短预期延迟 低延迟场景
nq 最少队列 公平分配

IPVS vs iptables 性能对比

对比项 iptables IPVS
规则查找 O(n) 线性 O(1) 哈希
服务数上限 ~1000 100000+
规则同步延迟 随规则数增加 恒定
调度算法 仅随机概率 8 种算法

六、Ingress 概述与控制器部署

6.1 什么是 Ingress?

Ingress 是 Kubernetes 中用于管理外部访问集群服务的 API 对象,提供 HTTP/HTTPS 路由能力。

Ingress vs Service

对比项 Service(NodePort/LoadBalancer) Ingress
协议 TCP/UDP HTTP/HTTPS(7 层)
路由能力 仅端口映射 域名、路径、SSL 等
成本 每个服务一个 LB IP 多个服务共享一个 LB IP

Ingress 架构

text 复制代码
客户端 → Ingress Controller (Nginx) → Service → Pod

Ingress 资源 定义路由规则,Ingress Controller 负责执行这些规则。

6.2 ingress-nginx 部署

前提:集群中已部署 MetalLB(用于提供 LoadBalancer IP)。

bash 复制代码
root@master30:~# kubectl apply -f ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml

查看部署状态

bash 复制代码
root@master30:~# kubectl get all -n ingress-nginx
NAME                                           READY   STATUS
pod/ingress-nginx-controller-596db54d7-cgbdd   1/1     Running

NAME                                         TYPE           CLUSTER-IP      EXTERNAL-IP
service/ingress-nginx-controller             LoadBalancer   10.107.255.83   10.1.8.40

七、Ingress 规则实践

7.1 基础规则

规则一:多域名虚拟主机(多 host 路由)

场景:不同域名转发到不同 Service。

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-host-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: webapp01.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp01
            port:
              number: 80
  - host: webapp02.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp02
            port:
              number: 80
规则二:同一域名多路径路由(path 分流)

场景:同一个域名,不同路径转发给不同 Service。

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-path-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: www.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp01
            port:
              number: 80
      - path: /games
        pathType: Prefix
        backend:
          service:
            name: webapp02
            port:
              number: 80

7.2 生产级注解规则

规则三:路径重写(rewrite-target)

场景 :前端访问 /webapp01/api,后端只识别 /api,需要剥离前缀。

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rewrite-ingress
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  ingressClassName: nginx
  rules:
  - host: www.whisky.cloud
    http:
      paths:
      - path: /webapp01/(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: webapp01
            port:
              number: 80

原理说明rewrite-target: /$1 表示将正则表达式中第一个括号匹配的内容作为新路径。例如 /webapp01/api/hello 会被重写为 /api/hello 转发给后端。

规则四:TLS 证书绑定 + 强制 HTTPS
bash 复制代码
# 1. 生成自签名证书
root@master30:~# openssl genrsa -out www.key 2048
root@master30:~# openssl req -new -key www.key -out www.csr -subj "/CN=www.whisky.cloud"
root@master30:~# openssl x509 -req -days 3650 -in www.csr -signkey www.key -out www.crt

# 2. 创建 Secret
root@master30:~# kubectl create secret tls www-tls --cert=./www.crt --key=./www.key
yaml 复制代码
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.whisky.cloud
    secretName: www-tls
  rules:
  - host: www.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp01
            port:
              number: 80

验证

bash 复制代码
[root@client ~]# curl -Lk http://www.whisky.cloud/   # 自动跳转 HTTPS
[root@client ~]# curl -k https://www.whisky.cloud/
规则五:限流与防刷
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rate-limit-ingress
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "20"
    nginx.ingress.kubernetes.io/limit-connections: "50"
spec:
  ingressClassName: nginx
  rules:
  - host: www.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp01
            port:
              number: 80
规则六:自定义超时时间
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: timeout-ingress
  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"
spec:
  ingressClassName: nginx
  rules:
  - host: www.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp01
            port:
              number: 80
规则七:跨域配置
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cors-ingress
  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"
    nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization"
spec:
  ingressClassName: nginx
  rules:
  - host: api.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp01
            port:
              number: 80
规则八:IP 白名单
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: whitelist-ingress
  annotations:
    nginx.ingress.kubernetes.io/whitelist-source-range: "10.1.8.0/24,127.0.0.1/32"
spec:
  ingressClassName: nginx
  rules:
  - host: admin.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp01
            port:
              number: 80
规则九:透传真实客户端 IP
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: xff-ingress
  annotations:
    nginx.ingress.kubernetes.io/x-forwarded-for: "true"
    nginx.ingress.kubernetes.io/proxy-real-ip-cidr: "10.0.0.0/8"
spec:
  ingressClassName: nginx
  rules:
  - host: www.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp01
            port:
              number: 80
规则十:金丝雀发布(权重分流)
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-ingress
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
  - host: www.whisky.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp01-canary
            port:
              number: 80

说明 :此规则需要与稳定版的 Ingress 配合使用。稳定版 Ingress 没有 canary: "true" 注解,金丝雀版添加此注解和权重,10% 的流量会进入金丝雀 Service。

7.3 生产高频注解速查表

注解 作用 示例
ssl-redirect: "true" 80 端口强制跳转 HTTPS nginx.ingress.kubernetes.io/ssl-redirect: "true"
rewrite-target 路径重写,裁剪前缀 nginx.ingress.kubernetes.io/rewrite-target: /$1
use-regex 启用正则表达式匹配 nginx.ingress.kubernetes.io/use-regex: "true"
limit-rps 单 IP 每秒请求数限制 nginx.ingress.kubernetes.io/limit-rps: "20"
limit-connections 单 IP 最大并发连接数 nginx.ingress.kubernetes.io/limit-connections: "50"
enable-cors 启用跨域 nginx.ingress.kubernetes.io/enable-cors: "true"
cors-allow-origin 跨域允许的源 nginx.ingress.kubernetes.io/cors-allow-origin: "*"
whitelist-source-range IP 白名单 nginx.ingress.kubernetes.io/whitelist-source-range: "10.1.8.0/24"
proxy-read-timeout 读取超时时间 nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
x-forwarded-for 透传真实客户端 IP nginx.ingress.kubernetes.io/x-forwarded-for: "true"
canary 启用金丝雀发布 nginx.ingress.kubernetes.io/canary: "true"
canary-weight 金丝雀流量权重 nginx.ingress.kubernetes.io/canary-weight: "10"

八、总结与知识点一览表

8.1 Service 类型对比

类型 ClusterIP NodePort LoadBalancer ExternalName Headless
访问范围 集群内 节点 IP+端口 外部 LB IP DNS CNAME 集群内
负载均衡
适用场景 内部服务 简单外部暴露 生产外部暴露 外部服务别名 StatefulSet

8.2 Service 发现方式对比

方式 优点 缺点
IP 简单直接 IP 变化,硬编码不推荐
环境变量 自动注入 依赖创建顺序
DNS 灵活、动态 需要 CoreDNS

8.3 kube-proxy 模式对比

模式 性能 规则结构 调度算法 适用场景
iptables 线性链表 随机概率 小规模集群
IPVS 极高 哈希表 rr/wrr/lc/sh 等 大规模生产环境

8.4 Ingress 注解分类速查

分类 注解
路由 rewrite-target, use-regex
安全 ssl-redirect, whitelist-source-range
限流 limit-rps, limit-connections
跨域 enable-cors, cors-allow-origin
超时 proxy-read-timeout, proxy-connect-timeout
灰度 canary, canary-weight
客户端 x-forwarded-for

8.5 常见错误排查

错误 原因 解决方法
Connection refused Service 端口或 targetPort 不匹配 检查 porttargetPort
No endpoints Service selector 不匹配任何 Pod 检查 Pod 标签
ExternalIP 不通 MetalLB 未配置 检查 IPAddressPool 和 L2Advertisement
Ingress 404 路径匹配规则不正确 检查 pathType 和路径格式
Ingress 证书错误 TLS Secret 不存在或格式错误 检查 Secret 名称和 key 名称
kube-proxy 切换 IPVS 失败 内核未加载 IPVS 模块 modprobe ip_vs
限流不生效 未正确配置注解 确认注解拼写,查看 Ingress Controller 日志

8.6 生产环境最佳实践

实践 说明
优先使用 DNS 发现 避免硬编码 IP 和依赖创建顺序
生产环境使用 IPVS 模式 性能更优,支持更多调度算法
Ingress 统一管理入口 多个服务共享一个 LB,降低成本
配置合理的限流 防止单 IP 攻击和流量突增
启用 TLS/HTTPS 生产环境必须加密传输
使用路径重写适配后端 保持前后端路由一致性
金丝雀发布验证新版本 降低上线风险

下一期预告:Kubernetes 调度与资源管理------节点亲和性、Pod 亲和性/反亲和性、污点与容忍、资源请求与限制、Horizontal Pod Autoscaler(HPA)。
--- Compiled and Authored by Whisky --- June 29th, 2026