k8s Ingress——外部流量转发
前言
Kubernetes 中,Ingress 是管理外部流量接入集群内部服务的核心组件,通过统一入口,依据主机名和 URL 路径将流量路由到不同 Service,简化外部访问复杂度。其功能实现依赖 Ingress 规则(定义路由策略)和 Ingress Controller(执行路由逻辑)的协同。
1 Igress 的概念
- Ingress 是解决外部流量如何接入集群内部服务这一问题的核心组件之一
- 作为统一流量入口,根据请求的 主机名(Host) 和 URL 路径,将流量智能地路由到不同的 Service
- 简化了外部访问的复杂性
2 Igress 的组成
Ingress 的实现依赖于两个协同工作的部分:
- Ingress(规则定义)
- 以 YAML 配置的 API 对象,定义请求如何转发到 service 的规则
- 能提供:外部 URL、负载均衡、SSL/TLS、基于域名的反向代理
- 具体功能需 Ingress Controller 实现
- Ingress Controller(规则执行)
- 接收外部流量,并根据 Ingress 规则进行负载均衡、反向代理
- 一个 Pod 内同时运行守护进程(监控集群并生成配置)与反向代理程序(如 Nginx)
3 Igress 的工作原理
- Ingress Controller 与 APIServer 交互,动态的去感知 Ingress 规则变化;
- 读取规则并按自定义模板生成配置文件(如 Nginx);
- 再写到nginx-ingress-controller的pod里,这个ingress-controller的pod里运行着一个Nginx服务,控制器会把生成的 nginx配置写入 /etc/nginx.conf文件中
- 执行 reload 使配置生效,实现按域名分流与动态更新。
4 部署 Ingress-Controller
以下示例以 ingress-nginx 为例,展示多种对外暴露方式。
4.1 准备与获取清单
mkdir -p /opt/ingress && cd /opt/ingress
# 官方:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.25.0/deploy/static/mandatory.yaml
# 国内镜像:
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.25.0/deploy/static/mandatory.yaml
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml
说明:mandatory.yaml文件中包含了很多资源的创建,包括namespace、ConfigMap、role,ServiceAccount等等所有部署ingress-controller需要的资源。。
4.2 修改 ClusterRole 资源配置
在 mandatory.yaml 中将 Ingress 资源权限加入 networking.k8s.io(0.25 版本开始):
vim mandatory.yaml
------------------------------------------------------------------------------------------------------------
# RBAC相关资源从1.17版本开始改用rbac.authorization.k8s.io/v1,rbac.authorization.k8s.io/v1beta1在1.22版本即将弃用
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
- "networking.k8s.io" # (0.25版本)增加 networking.k8s.io Ingress 资源的 api
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
- "networking.k8s.io" # (0.25版本)增加 networking.k8s.io/v1 Ingress 资源的 api
resources:
- ingresses/status
verbs:
- update
5 Ingress 暴露服务的三种方式***
| 方式 | 适用场景 | 核心优势 | 关键依赖 |
|---|---|---|---|
| Deployment + LoadBalancer | 公有云生产环境、高可用需求 | 云厂商托管负载均衡、自动容错 | 云平台 LoadBalancer 支持 |
| DaemonSet + HostNetwork + nodeSelector | 私有集群、高性能需求、边缘节点部署 | 低延迟、网络路径短 | 节点标签管理、端口独占 |
| Deployment + NodePort | 测试环境、小规模集群、无负载均衡器 | 通用兼容、部署简单 | 节点网络可达性 |
5.1 数据流向

5.2 Deployment + LoadBalancer
-
适合公有云:LB 自动创建并绑定公网;将域名解析指向该地址即可对外暴露。
详细:如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个 type为 LoadBalancer 的 service 关联这组 pod。大部分公有云,都会为 LoadBalancer 的 service 自动创建一个负载均衡器,通常还绑定了公网地址。 只要把域名解析指向该地址,就实现了集群服务的对外暴露
5.3 DaemonSet + HostNetwork + nodeSelector
-
在特定节点以 DaemonSet 方式部署 Controller,并使用 HostNetwork 与宿主机网络打通;
-
直接占用宿主机 80/443;
-
链路最短、性能最好;一个 node 仅能运行一个 Controller Pod;适合大并发生产。
详解:用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。 比较适合大并发的生产环境使用。
5.3.1 选择指定节点运行
# 给 node 打标签,仅在 node02 运行
kubectl label node node02 ingress=true
kubectl get nodes --show-labels
5.3.2 设置配置
-
命名空间:创建了独立的
ingress-nginx命名空间,隔离 Ingress 相关资源 -
配置存储:ConfigMap 管理核心配置文件
-
权限控制:绑定 ClusterRole 和 Role 授予控制器访问集群资源(如 Ingress、Service、Pod 等)的权限
-
控制器部署:
-
DaemonSet 确保每个节点运行一个控制器(若指定,则仅在该指定节点上添加控制器)
-
开启
hostNetwork: true,直接使用宿主机网络,便于接收外部流量。 -
通过
nodeSelector: ingress: "true"限制仅在标记为ingress: true的节点上运行
-
vim mandatory.yaml
------------------------------------------------------------------------------------------------------------
...
apiVersion: apps/v1
# 修改 kind
# kind: Deployment
kind: DaemonSet
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
# 删除Replicas
# replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
annotations:
prometheus.io/port: "10254"
prometheus.io/scrape: "true"
spec:
# 使用主机网络
hostNetwork: true
# 选择节点运行
nodeSelector:
ingress: "true"
serviceAccountName: nginx-ingress-serviceaccount
......
5.3.3 加载镜像
# 在所有 node 上传镜像并加载
cd /opt/ingress
# 假设已有压缩包 ingree.contro.tar.gz
tar zxvf ingree.contro.tar.gz
docker load -i ingree.contro.tar
5.3.4 启动 Ingress Controller
# 创建配置
kubectl apply -f mandatory.yaml
# 查看
kubectl get pod -n ingress-nginx -o wide
kubectl get cm,daemonset -n ingress-nginx -o wide
netstat -lntp | grep nginx
# 期望监听:80 / 443 / 8181 / 10254
说明:
8181为默认 backend 端口(未匹配到规则时流量进入此处)。若需高可用,可在多节点部署,并在前面加 LVS + keepalived 做负载均衡。
5.3.5 部署服务
# 创建一个 Deployment 和 svc
vim service-nginx.yaml
------------------------------------------------------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-app-svc
spec:
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: nginx
5.3.6 创建 Ingress 规则
vim ingress-app.yaml
------------------------------------------------------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-app-ingress
spec:
rules:
- host: www.benet.com
http:
paths:
- path: /
pathType: Prefix # 也可使用 Exact
backend:
service:
name: nginx-app-svc
port:
number: 80
路径匹配:
Prefix:基于前缀匹配,如/ky37可匹配/ky37、/ky37/xyk、/ky37/xyk/xz。Exact:完全匹配,如/ky39只能匹配/ky39。
5.3.7 测试
kubectl apply -f service-nginx.yaml
kubectl apply -f ingress-app.yaml
kubectl get ingress
# /etc/hosts 添加解析:
# 192.168.10.21 www.benet.com
curl www.benet.com
可进入 Controller Pod 查看生成的
/etc/nginx/nginx.conf,确认server www.benet.com段落
5.4 Deployment + NodePort
- 以 Deployment 部署 Controller,并创建 NodePort Service 暴露
- 由于 NodePort 是随机端口,通常前置一层负载均衡
- 多一层 NAT,大流量场景可能影响性能
5.4.1 设置配置
- 命名空间:创建了独立的
ingress-nginx命名空间,隔离 Ingress 相关资源 - 配置存储:ConfigMap 管理核心配置文件
- 权限控制:绑定 ClusterRole 和 Role 授予控制器访问集群资源(如 Ingress、Service、Pod 等)的权限
- 控制器部署:通过 Deployment 控制器来控制 Ingress-Controller
# 创建目录
mkdir -p /opt/ingress-nodeport && cd /opt/ingress-nodeport
# 清单获取
// 官方下载地址:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
# 或国内镜像:
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
# 在所有 node 节点上传镜像包 ingress-controller-0.30.0.tar 到 /opt/ingress-nodeport 目录,并加载镜像
docker load -i ingress-controller-0.30.0.tar
# 启动 Controller 与 NodePort Service
kubectl apply -f mandatory.yaml
kubectl apply -f service-nodeport.yaml
------------------------------------------------------------------------------------------------------------
#如果K8S Pod 调度失败,在 kubectl describe pod资源时显示:
# Warning FailedScheduling ... didn't match node selector
# 解决:
# 1) 按 YAML 中的 nodeSelector 给节点加标签
kubectl label nodes <node_name> kubernetes.io/os=linux
# 2) 或删除 YAML 中的 nodeSelector
kubectl get pod,svc -n ingress-nginx
5.4.2 部署服务 和 制定ingress规则
vim ingress-nginx.yaml
------------------------------------------------------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
replicas: 2
selector:
matchLabels:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-test
spec:
rules:
- host: www.benet.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
部署与测试:
kubectl apply -f ingress-nginx.yaml
kubectl get svc -n ingress-nginx
# 假设 NodePort 为 80:32383/TCP
# hosts 添加:192.168.10.21 www.benet.com
curl http://www.benet.com:32383
可以在两个 Pod 内修改
index.html以区分返回:this is web1/web2。
5.4.3 示例:HTTPS 代理访问
# 创建目录
mkdir -p /opt/ingress-nodeport/https && cd /opt/ingress-nodeport/https
# 生成自签证书
openssl req -x509 -sha256 -nodes -days 365 \
-newkey rsa:2048 -keyout tls.key -out tls.crt \
-subj "/CN=nginxsvc/O=nginxsvc"
# 创建 secret
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
# 以 yaml 格式查看
kubectl get secret tls-secret -o yaml
vim ingress-https.yaml
------------------------------------------------------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
replicas: 2
selector:
matchLabels:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc-01
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-https
spec:
tls:
- hosts:
- www3.benet.com
secretName: tls-secret
rules:
- host: www3.benet.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-svc-01
port:
number: 80
kubectl apply -f ingress-https.yaml
kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.96.67.119 <none> 80:32383/TCP,443:32133/TCP 3h41m
测试:
# NodePort 假设 443:32133
# hosts 添加:192.168.10.21 www3.benet.com
# 浏览器访问:https://www3.benet.com:32133
示例:BasicAuth 认证
# 创建目录
mkdir -p /opt/ingress-nodeport/basic-auth && cd /opt/ingress-nodeport/basic-auth
# 生成 basic auth 文件(文件名需为 auth)
yum -y install httpd
htpasswd -c auth zhangsan
# 存为 secret
kubectl create secret generic basic-auth --from-file=auth
vim ingress-auth.yaml
------------------------------------------------------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-auth
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - zhangsan'
spec:
rules:
- host: auth.benet.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
参考:https://kubernetes.github.io/ingress-nginx/examples/auth/basic/
示例:重写(Rewrite)
- 常用注解:
nginx.ingress.kubernetes.io/rewrite-target: <字符串>:重定向目标 URI(必填)nginx.ingress.kubernetes.io/ssl-redirect: <bool>:是否仅允许 SSL(Ingress 含证书时默认true)nginx.ingress.kubernetes.io/force-ssl-redirect: <bool>:即使未启用 TLS 也强制跳转 HTTPSnginx.ingress.kubernetes.io/app-root: <字符串>:定义应用根路径重定向nginx.ingress.kubernetes.io/use-regex: <bool>:路径是否使用正则
vim ingress-rewrite.yaml
------------------------------------------------------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-rewrite
annotations:
nginx.ingress.kubernetes.io/rewrite-target: http://www1.benet.com:32383
spec:
rules:
- host: re.benet.com
http:
paths:
- path: /
pathType: Prefix
backend:
# 仅用于跳转,svc 名可随意
service:
name: nginx-svc
port:
number: 80
测试:
# hosts 添加:192.168.10.21 re.benet.com
# 浏览器访问:http://re.benet.com:32383
6 总结
Ingress 作为 K8s 流量网关,通过规则与控制器协作,实现外部流量的统一接入、分流和负载均衡。
三种部署方式各有适用场景:
- Deployment + LoadBalancer:适合公有云生产环境,依赖云厂商负载均衡服务,高可用且易维护。
- DaemonSet + HostNetwork + nodeSelector:适用于私有集群或高性能需求场景,链路短、性能好,需节点标签管理。
- Deployment + NodePort:适合测试或小规模集群,部署简单,大流量场景可能影响性能,通常需前置负载均衡。
此外,Ingress 还支持 HTTPS 配置、身份认证、路径重写等实用功能,满足多样化流量管理需求。
更多推荐


所有评论(0)